ফর্মিক ফাংশনস - পিঁপড়ের রাণী হিল প্রতিযোগিতার


104

সরাসরি দেখুন | সক্রিয় উত্তর | নতুন উত্তর যুক্ত করুন | চ্যাট রুম | উত্স কোড | লিডারবোর্ড

যখনই দরকার হয় নতুন টুর্নামেন্ট। নতুন খেলোয়াড় এবং নতুন আপডেট খুব স্বাগত।

রঙিন টাইলস সহ নৃত্যের মেঝেতে রানী পিপীলিকা

আসল গেম ফুটেজ নয়।

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

১ players জন খেলোয়াড় একটি অঙ্গনে প্রতিযোগিতা করে। বিজয়ী রানী হলেন 30,000 টার্ন নেওয়ার পরে সর্বাধিক খাবার রাখছেন। ধরা পড়েছে যে পিঁপড়াগুলি কেবল আখড়া স্কোয়ারের রঙ পরিবর্তন করেই যোগাযোগ করতে পারে, যা প্রতিদ্বন্দ্বী পিঁপড়া দ্বারাও পরিবর্তন করা যেতে পারে ...

খেলা দেখছি

এটি একটি জাভাস্ক্রিপ্ট প্রতিযোগিতা, যার অর্থ আপনি নীচের লিঙ্কটি ক্লিক করে আপনার ব্রাউজারে গেম প্লে লাইভ আউট দেখতে পারেন।

খেলাটি সরাসরি খেলা হচ্ছে দেখতে এখানে ক্লিক করুন

অনেক ধন্যবাদ Helka Homba পার্বত্য প্রতিযোগিতায় মূল স্ট্যাক স্নিপেট রাজা, জন্য রেড বনাম ব্লু - পিক্সেল টিম Battlebots , এবং ব্লক বিল্ডিং বট ঝাঁকে ঝাঁকে , যা একটি ওয়েব ব্রাউজার এর ধারণা প্রদান করা KotH হোস্ট এবং প্রচন্ডভাবে এই এক কোড অবহিত।

স্যান্ডবক্সে এবং চ্যাটের দুর্দান্ত লোকদের কাছ থেকে সমস্ত প্রতিক্রিয়া এবং পরীক্ষার জন্যও বিশাল ধন্যবাদ।

লিডারবোর্ড

লিডারবোর্ডের শীর্ষ স্থানগুলির ছবি

(পূর্ণ লিডারবোর্ড এবং যৌথ জায়গাগুলির ব্যাখ্যা দেখতে চিত্রটিতে ক্লিক করুন - স্থান বাঁচাতে এখানে কেবল কয়েকজন খেলোয়াড় দেখানো হচ্ছে))

এই লিডারবোর্ডে খেলোয়াড়দের উপর ভিত্তি করে তৈরি হিসাবে তারা রবিবার 2 ছিল য় সেপ্টেম্বর 2018।

স্ক্রীনশট

কোনও খেলার শেষের দিকে আখড়াটি কীভাবে দেখায় তার কয়েকটি চিত্র। পূর্ণ আকার দেখতে ছবিতে ক্লিক করুন।

অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র অঙ্গনের চিত্র

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

আখড়া

রঙ্গভূমিটি স্কোয়ার সেলগুলির একটি টরোডিয়াল (প্রান্ত মোড়ানো) গ্রিড। এটির প্রস্থ 2500 এবং উচ্চতা 1000 রয়েছে All সমস্ত ঘর রঙ 1 হিসাবে শুরু হয়।

প্রাথমিকভাবে ঠিক 0.1% কোষে খাবার থাকবে। 2500 টুকরো খাবার এলোমেলোভাবে অভিন্নভাবে ছড়িয়ে দেওয়া হবে। গেম চলাকালীন নতুন কোনও খাবার চালু করা হবে না।

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

পিঁপড়া ক্ষমতা

  • দৃষ্টিশক্তি: প্রতিটি পিঁপড়া তার 3 বাই 3 পাড়ার 9 টি ঘর দেখে cells এটি এর আশেপাশের বাইরের কোনও পিঁপড়ার জ্ঞান নেই। এটি 9 টি কোষের প্রতিটি উপাদান (অন্যান্য পিঁপড়ো এবং খাবার) এবং প্রতিটি ঘরের রঙ দেখে
  • কোনও স্মৃতি নেই: প্রতিটি পিঁপড়া যা দেখেছে তার উপর ভিত্তি করে তার সিদ্ধান্ত নেয় - এটি আগের টার্নে কী করেছিল তা মনে রাখে না এবং আখেরার কোষগুলির রঙ ব্যতীত অন্য কোনও স্থানে রাষ্ট্র সংরক্ষণের কোনও উপায় নেই।
  • কোনও অভিমুখীকরণ নয়: একটি পিপীলিকা জানে না যে এটি কোথায় বা কোন পথে মুখোমুখি হয় - এটি উত্তর সম্পর্কে কোনও ধারণা নেই। 3 বাই 3 পাড়াটিকে এলোমেলোভাবে ঘোরানো ওরিয়েন্টেশনটিতে উপস্থাপিত করা হবে যা প্রতিটি পালা পরিবর্তিত করে যাতে এটি গাইড করার জন্য রঙ না থাকলে এটি সরলরেখায়ও হাঁটতে পারে না। (প্রতি বারে একই পদক্ষেপ গ্রহণের ফলে একটি সরলরেখার পরিবর্তে এলোমেলো হাঁটার ফলাফল আসবে))
  • , মুভিং রঙ উপলক্ষে ও কর্মীদের উত্পাদক: দেখুন আউটপুট কম।
  • অমরত্ব: এগুলি হাইল্যান্ড পিঁপড়া যা মারা যায় না। আপনি প্রতিদ্বন্দ্বী পিঁপড়ার চারপাশের রঙগুলি পরিবর্তন করে বিভ্রান্ত করতে পারেন, বা আপনার নিজের 8 পিঁপড়া দিয়ে তাদের চারপাশে ঘুরে বেড়াতে বাধা দিতে পারেন, তবে এগুলি ছাড়া তাদের কোনও ক্ষতি করা যায় না।
  • খাদ্য বহন করা: একজন শ্রমিক 1 পিস পর্যন্ত খাবার বহন করতে পারবেন। একটি রানী একটি নির্বিচার পরিমাণে খাবার বহন করতে পারে।
  • খাদ্যের স্থানান্তর: যদি কোনও শ্রমিক রানির সাথে সংলগ্ন হয় (8 টি দিকের যে কোনও একটিতে), নিম্নলিখিত পদ্ধতিগুলির মধ্যে একটি থেকে স্বয়ংক্রিয়ভাবে খাদ্য স্থানান্তরিত হবে:
    • নিজস্ব রানির সংলগ্ন একটি বোঝা শ্রমিক তার খাবারটিকে রানির কাছে স্থানান্তর করবে।
    • শত্রু রানীর সংলগ্ন একটি অপরিচ্ছন্ন কর্মচারী উপস্থিত থাকলে 1 পিস খাবার চুরি করবে।

একজন শ্রমিক শ্রমিকের কাছ থেকে চুরি করতে পারে না, এবং রানী কোনও রানী থেকে চুরি করতে পারে না। এছাড়াও একজন শ্রমিক তার নিজের রানীর কাছ থেকে খাবার নিতে পারে না এবং কোনও রানী শত্রু কর্মীর কাছ থেকে চুরি করতে পারে না।

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

আইনসংগ্রহ

একটি ফাংশন বডি সরবরাহ করুন

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

একটি জাভাস্ক্রিপ্ট ফাংশনটির শরীরে একটি কোড ব্লকযুক্ত একটি উত্তর পোস্ট করুন, এবং এটি স্বয়ংক্রিয়ভাবে নিয়ামকটিতে অন্তর্ভুক্ত হবে (কেবলমাত্র নিয়ামক পৃষ্ঠাটি রিফ্রেশ করুন)। প্লেয়ারটির নামটি ফর্মের উত্তরের শিরোনাম গঠন করে # PlayerName(যা নিয়ামক সারণীতে সর্বাধিক 40 টি অক্ষরে ছাঁটা হবে)।

কোন রাষ্ট্র, সময় নেই, এলোমেলো নয়

একটি ফাংশন অবশ্যই গ্লোবাল ভেরিয়েবল অ্যাক্সেস করতে হবে না এবং মোড়ের মধ্যে থাকা অবস্থায় স্টোর সংরক্ষণ করা উচিত নয়। এটি স্টোরেজ স্টেট জড়িত না এমন ফাংশনে অন্তর্নির্মিত ব্যবহার করতে পারে। উদাহরণস্বরূপ, এর ব্যবহারটি Math.abs()ভাল, তবে Date.getTime()অবশ্যই ব্যবহার করা উচিত নয়।

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

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

একটি পিঁপড়া ফাংশন তার শরীরের মধ্যে আরও ফাংশন ধারণ করার অনুমতি দেওয়া হয়। এটি কীভাবে কার্যকর হতে পারে তার উদাহরণগুলির জন্য বিদ্যমান উত্তরগুলি দেখুন ।

console.log

নতুন চ্যালেঞ্জার প্লেয়ারটি পরীক্ষা করার সময় আপনি কনসোলে লগইন করতে পারেন, তবে একবার উত্তর হিসাবে পোস্ট করার পরে প্লেয়ারটির কোনও অ্যাক্সেস থাকবে না console.log। এটি ব্যবহারের চেষ্টা করার ফলে সম্পাদিত হওয়া পর্যন্ত ত্রুটি এবং অযোগ্যতার ফলস্বরূপ। এটি লিডারবোর্ড টুর্নামেন্টগুলিকে দ্রুত রাখতে সহায়তা করবে, তবুও ডিবাগিং কোডটিকে নতুন চ্যালেঞ্জার পাঠ্য অঞ্চলে আটকানো অনুমতি দেওয়া উচিত।

ইনপুট এবং আউটপুট

ইনপুট

ইনপুটটির ওরিয়েন্টেশন প্রতিটি পিঁপড়ে এবং প্রতিটি টার্নের জন্য এলোমেলোভাবে বেছে নেওয়া হবে। ইনপুট 0, 90, 180 বা 270 ডিগ্রি দ্বারা আবর্তিত হবে, তবে কখনও প্রতিফলিত হবে না।

কক্ষগুলি ইংরেজী পাঠের ক্রমে সংখ্যাযুক্ত:

0 1 2
3 4 5
6 7 8

পিঁপড়ে ফাংশনটি view9 টি দৃশ্যমান কোষের প্রত্যেকটির জন্য একটি উপাদান সম্বলিত একটি অ্যারে নামে পরিচিত হবে । প্রতিটি বস্তুর নিম্নলিখিত থাকবে:

color: a number from 1 to 8
food: 0 or 1
ant: null if there is no ant on that cell, or otherwise an ant object

যদি কোনও কোষে একটি পিঁপড়া থাকে, পিপীলিকার বস্তুতে নিম্নলিখিতগুলি থাকে:

food: 0 or more (maximum 1 for a worker)
type: 1 to 4 for a worker, or 5 for a queen
friend: true or false

পিঁপড়া কেন্দ্রীয় কোষে পিপীলিকা দেখে তার নিজস্ব বিবরণ নির্ধারণ করতে পারে view[4].ant,। উদাহরণস্বরূপ, view[4].ant.typeরানির জন্য 5 বা কোনও শ্রমিকের 1 থেকে 4 নম্বর (এর ধরণটি নির্দেশ করে)।

আউটপুট

আউটপুটটি কোনও পদক্ষেপ গ্রহণের জন্য প্রতিনিধিত্ব করে তা ফিরিয়ে দেওয়া হয়। এতে নিম্নলিখিত যে কোনও একটি থাকতে পারে:

cell: a number from 0 to 8 (mandatory)
color: a number from 1 to 8 (optional)
type: a number from 1 to 4 (optional)

যদি colorএবং typeবাদ দেওয়া হয় বা শূন্য হয়, তবে cellঘরের দিকে যাওয়ার জন্য নির্দেশ করে।

যদি colorশূন্য নয়, তবে নির্দেশিত ঘরটি সেই রঙে সেট করা আছে।

যদি typeশূন্য হয় না, তবে সেই ধরণের একটি কর্মী পিপীলিকাটি নির্দেশিত ঘরে তৈরি করা হয়। কেবল রানীই একজন নতুন কর্মী তৈরি করতে পারে এবং কেবল তার যদি খাবার থাকে তবে তার জন্য প্রতি শ্রমিকের এক টুকরো খাবার ব্যয় হয়।

উদাহরণ ফলাফল:

{cell:0}: move to cell 0
{cell:4}: move to cell 4 (that is, do nothing, as 4 is the central cell)
{cell:4, color:8}: set own cell to color 8
{cell:6, type:1}: create a type 1 worker on cell 6
{cell:6, color:1}: set cell 6 to color 1
{cell:6, color:0}: equivalent to just `{cell:6}` - move rather than set color
{cell:6, type:0}: equivalent to just `{cell:6}` - move rather than create worker
{cell:6, color:0, type:0}: move to cell 6 - color 0 and type 0 are ignored

অবৈধ ফলাফল:

{cell:9}: cell must be from 0 to 8
{cell:0, color:9}: color must be from 1 to 8
{cell:0, type:5}: type must be from 1 to 4 (cannot create a new queen)
{cell:4, type:1}: cannot create a worker on a non-empty cell
{cell:0, color:1, type:1}: cannot set color and create worker in the same turn

একটি পিঁপড়া খাদ্য সমন্বিত একটি কোষের দিকে চলে যাওয়ায় স্বয়ংক্রিয়ভাবে খাবারের টুকরাটি বেছে নেবে।

শ্রমিকের ধরণ

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

কর্মী তৈরির সময় আপনার দ্বারা কর্মী টাইপ নম্বর বরাদ্দ করা হয় এবং এরপরে পরিবর্তন করা যায় না। আপনি উপযুক্ত দেখতে এটি ব্যবহার করুন।

টার্ন অর্ডার

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

খেলোয়াড়ের সংখ্যার সীমাবদ্ধতা

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

টার্ন প্রতি সময় সীমা

প্রতিবার পিঁপড়ের ফাংশনটি কল করার সময় এটি 15 মিলিসেকেন্ডের মধ্যে ফিরে আসবে। যেহেতু পিঁপড়ার ফাংশনের নিয়ন্ত্রণের বাইরে ওঠানামার কারণে সময়সীমা অতিক্রম করা হতে পারে, তাই একটি গড় গণনা করা হবে। যদি কোনও মুহুর্তে গড় 15 মিলিসেকেন্ডের উপরে হয় এবং নির্দিষ্ট কলসী ফাংশনটি এখন পর্যন্ত সমস্ত কলগুলিতে নেওয়া মোট সময় 10 সেকেন্ডের বেশি হয়, তবে সংশ্লিষ্ট খেলোয়াড়কে অযোগ্য ঘোষণা করা হবে।

অযোগ্যতা

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

কোনও খেলোয়াড় তার কোনও পিঁপড়ার (রানী বা কর্মী) জন্য নিম্নলিখিত যে কোনওটির জন্য অযোগ্য হবেন:

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

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

একাধিক উত্তর এবং সম্পাদনা

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

আপনি যখনই বেছে বেছে আপনার উত্তরগুলি সম্পাদনা করতে পারেন। আপনি কোনও নতুন উত্তর পোস্ট করেছেন বা বিদ্যমান উত্তরটি সম্পাদনা করছেন তা আপনার উপর নির্ভর করে। প্রদত্ত গেমটি অনেকগুলি নিকট-অভিন্ন বৈচিত্র সহ প্লাবিত না হয়, কোনও সমস্যা হওয়া উচিত নয়।

আপনি যদি অন্য ব্যক্তির উত্তরটির কোনও বৈকল্পিকতা তৈরি করেন তবে দয়া করে মনে রাখবেন যে তারা আপনার কাছ থেকে উত্তরটি যুক্ত করে তাদের ক্রেডিট দেবে।

স্কোরিং

প্রতিটি গেমের শেষে, একজন খেলোয়াড়ের স্কোর হ'ল অন্যান্য খেলোয়াড়ের সংখ্যা যাদের রানির দ্বারা কম খাবার বহন করা হয়। শ্রমিকদের বহন করা খাবার গণনা করা হয় না। এই স্কোরটি লিডারবোর্ডে যুক্ত করা হয় যা প্রতি খেলায় গড় স্কোরের জন্য প্রদর্শিত হয়।

যৌথ স্থানগুলি ইঙ্গিত দেয় যে খেলোয়াড়দের ক্রম এখনও অবধি গেমগুলির 6 টি উপসাগরের মধ্যে সামঞ্জস্যপূর্ণ নয়। গেমসের তালিকাকে subse টি উপ-বিভাগে বিভক্ত করা হয়েছে কারণ এটি ন্যূনতম সংখ্যা যা 5% এরও কম সম্ভাবনার সম্ভাবনা দেয় যে প্রদত্ত জোড়া খেলোয়াড়কে ভুল ক্রমে আলাদা স্থান দেওয়া হবে।

চ্যাট করুন

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

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


2
এই মন্তব্যগুলির মাধ্যমে যে কেউ পড়ছেন তার জন্য @ ডেসক্রটিবল লাইমন, আমি উত্তর দিয়েছি যে চ্যাট রুমে
ট্রাইকোপল্যাক্স


7
আরে, আমি একটা জিনিস বানিয়েছি ! আপনি এটি আকর্ষণীয় বলে মনে করতে পারেন যেহেতু এটি এই চ্যালেঞ্জ দ্বারা অনুপ্রাণিত হয়েছে এবং এতে ফর্মিক ফাংশন পরীক্ষার বাস্তবায়ন অন্তর্ভুক্ত রয়েছে ।
ডেভ

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

2
@ জিএনিক্ল্যাশ ধন্যবাদ; স্থির করেছি। এছাড়াও আমি দেখতে পাচ্ছি যে আপনার পিপড়া এখন খেলায় আধিপত্য বিস্তার করছে। চিত্তাকর্ষক!
ডেভ

উত্তর:


20

ফরেনসিক অ্যান্টস

আমার সমস্ত উত্তরগুলি একই স্তরের নিম্ন-স্তরের সহায়ক ফাংশনগুলি ভাগ করে নিচ্ছে। এই উত্তরের নির্দিষ্ট কোডটি দেখতে "উচ্চ-স্তরের যুক্তি এখানে সন্ধান করুন" অনুসন্ধান করুন।

// == Shared low-level helpers for all solutions ==

var QUEEN = 5;

var WHITE = 1;
var COL_MIN = WHITE;
var COL_LIM = 9;

var CENTRE = 4;

var NOP = {cell: CENTRE};

var DIR_FORWARDS = false;
var DIR_REVERSE = true;
var SIDE_RIGHT = true;
var SIDE_LEFT = false;

function sanity_check(movement) {
  var me = view[CENTRE].ant;
  if(!movement || movement.cell < 0 || movement.cell > 8) {
    return false;
  }
  if(movement.type) {
    if(movement.color) {
      return false;
    }
    if(movement.type < 1 || movement.type > 4) {
      return false;
    }
    if(view[movement.cell].ant || view[movement.cell].food) {
      return false;
    }
    if(me.type !== QUEEN || me.food < 1) {
      return false;
    }
    return true;
  }
  if(movement.color) {
    if(movement.color < COL_MIN || movement.color >= COL_LIM) {
      return false;
    }
    if(view[movement.cell].color === movement.color) {
      return false;
    }
    return true;
  }
  if(view[movement.cell].ant) {
    return false;
  }
  if(view[movement.cell].food + me.food > 1 && me.type !== QUEEN) {
    return false;
  }
  return true;
}

function as_array(o) {
  if(Array.isArray(o)) {
    return o;
  }
  return [o];
}

function best_of(movements) {
  var m;
  for(var i = 0; i < movements.length; ++ i) {
    if(typeof(movements[i]) === 'function') {
      m = movements[i]();
    } else {
      m = movements[i];
    }
    if(sanity_check(m)) {
      return m;
    }
  }
  return null;
}

function play_safe(movement) {
  // Avoid disqualification: no-op if moves are invalid
  return best_of(as_array(movement)) || NOP;
}

var RAND_SEED = (() => {
  var s = 0;
  for(var i = 0; i < 9; ++ i) {
    s += view[i].color * (i + 1);
    s += view[i].ant ? i * i : 0;
    s += view[i].food ? i * i * i : 0;
  }
  return s % 29;
})();

var ROTATIONS = [
  [0, 1, 2, 3, 4, 5, 6, 7, 8],
  [6, 3, 0, 7, 4, 1, 8, 5, 2],
  [8, 7, 6, 5, 4, 3, 2, 1, 0],
  [2, 5, 8, 1, 4, 7, 0, 3, 6],
];

function try_all(fns, limit, wrapperFn, checkFn) {
  var m;
  fns = as_array(fns);
  for(var i = 0; i < fns.length; ++ i) {
    if(typeof(fns[i]) !== 'function') {
      if(checkFn(m = fns[i])) {
        return m;
      }
      continue;
    }
    for(var j = 0; j < limit; ++ j) {
      if(checkFn(m = wrapperFn(fns[i], j))) {
        return m;
      }
    }
  }
  return null;
}

function identify_rotation(testFns) {
  // testFns MUST be functions, not constants
  return try_all(
    testFns,
    4,
    (fn, r) => fn(ROTATIONS[r]) ? ROTATIONS[r] : null,
    (r) => r
  );
}

function near(a, b) {
  return (
    Math.abs(a % 3 - b % 3) < 2 &&
    Math.abs(Math.floor(a / 3) - Math.floor(b / 3)) < 2
  );
}

function try_all_angles(solverFns) {
  return try_all(
    solverFns,
    4,
    (fn, r) => fn(ROTATIONS[r]),
    sanity_check
  );
}

function try_all_cells(solverFns, skipCentre) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i === CENTRE && skipCentre) ? null : fn(i)),
    sanity_check
  );
}

function try_all_cells_near(p, solverFns) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i !== p && near(p, i)) ? fn(i) : null),
    sanity_check
  );
}

function ant_type_at(i, friend) {
  return (view[i].ant && view[i].ant.friend === friend) ? view[i].ant.type : 0;
}

function friend_at(i) {
  return ant_type_at(i, true);
}

function foe_at(i) {
  return ant_type_at(i, false);
}

function foe_near(p) {
  for(var i = 0; i < 9; ++ i) {
    if(foe_at(i) && near(i, p)) {
      return true;
    }
  }
  return false;
}

function move_agent(agents) {
  var me = view[CENTRE].ant;
  var buddies = [0, 0, 0, 0, 0, 0];
  for(var i = 0; i < 9; ++ i) {
    ++ buddies[friend_at(i)];
  }

  for(var i = 0; i < agents.length; i += 2) {
    if(agents[i] === me.type) {
      return agents[i+1](me, buddies);
    }
  }
  return null;
}

function grab_nearby_food() {
  return try_all_cells((i) => (view[i].food ? {cell: i} : null), true);
}

function go_anywhere() {
  return try_all_cells((i) => ({cell: i}), true);
}

function colours_excluding(cols) {
  var r = [];
  for(var i = COL_MIN; i < COL_LIM; ++ i) {
    if(cols.indexOf(i) === -1) {
      r.push(i);
    }
  }
  return r;
}

function generate_band(start, width) {
  var r = [];
  for(var i = 0; i < width; ++ i) {
    r.push(start + i);
  }
  return r;
}

function colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function(c) {
      return colours[(colours.indexOf(c) + 1) % colours.length];
    }
  };
}

function random_colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function() {
      return colours[RAND_SEED % colours.length];
    }
  };
}

function fast_diagonal(colourBand) {
  var m = try_all_angles([
    // Avoid nearby checked areas
    (rot) => {
      if(
        !colourBand.contains(view[rot[0]].color) &&
        colourBand.contains(view[rot[5]].color) &&
        colourBand.contains(view[rot[7]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // Go in a straight diagonal line if possible
    (rot) => {
      if(
        !colourBand.contains(view[rot[0]].color) &&
        colourBand.contains(view[rot[8]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // When in doubt, pick randomly but avoid doubling-back
    (rot) => (colourBand.contains(view[rot[0]].color) ? null : {cell: rot[0]}),

    // Double-back when absolutely necessary
    (rot) => ({cell: rot[0]})
  ]);

  // Lay a colour track so that we can avoid doubling-back
  // (and mess up our foes as much as possible)
  if(!colourBand.contains(view[CENTRE].color)) {
    var prevCol = m ? view[8-m.cell].color : WHITE;
    return {cell: CENTRE, color: colourBand.next(prevCol)};
  }

  return m;
}

function follow_edge(obstacleFn, side) {
  // Since we don't know which direction we came from, this can cause us to get
  // stuck on islands, but the random orientation helps to ensure we don't get
  // stuck forever.

  var order = ((side === SIDE_LEFT)
    ? [0, 3, 6, 7, 8, 5, 2, 1, 0]
    : [0, 1, 2, 5, 8, 7, 6, 3, 0]
  );
  return try_all(
    [obstacleFn],
    order.length - 1,
    (fn, i) => (fn(order[i+1]) && !fn(order[i])) ? {cell: order[i]} : null,
    sanity_check
  );
}

function start_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => ((
      !protectedCols.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 2 : 0]].color) &&
      !colourBand.contains(view[rot[1]].color)
    )
      ? {cell: rot[right ? 5 : 3], color: colourBand.next(WHITE)}
      : null)
  ]);
}

function lay_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => {
      var ahead = rot[right ? 2 : 0];
      var behind = rot[right ? 8 : 6];
      if(
        colourBand.contains(view[behind].color) &&
        !protectedCols.contains(view[ahead].color) &&
        !colourBand.contains(view[ahead].color) &&
        !colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        return {cell: ahead, color: colourBand.next(view[behind].color)};
      }
    }
  ]);
}

function follow_dotted_path(colourBand, side, direction) {
  var forwards = (direction === DIR_REVERSE) ? 7 : 1;
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    // Cell on our side? advance
    (rot) => {
      if(
        colourBand.contains(view[rot[right ? 5 : 3]].color) &&
        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[0]].color) &&
        !colourBand.contains(view[rot[2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    },

    // Cell ahead and behind? advance
    (rot) => {
      var passedCol = view[rot[right ? 8 : 6]].color;
      var nextCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(passedCol) &&
        nextCol === colourBand.next(passedCol) &&

        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[right ? 0 : 2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    }
  ]);
}

function escape_dotted_path(colourBand, side, newColourBand) {
  var right = (side === SIDE_RIGHT);
  if(!newColourBand) {
    newColourBand = colourBand;
  }

  return try_all_angles([
    // Escape from beside the line
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        !colourBand.contains(view[rot[right ? 8 : 6]].color) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[rot[7]].color) ||
        colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        // not oriented, or in a corner
        return null;
      }
      return best_of([
        {cell: rot[right ? 0 : 2], color: newColourBand.next(approachingCol)},
        {cell: rot[right ? 3 : 5]},
        {cell: rot[right ? 0 : 2]},
        {cell: rot[right ? 6 : 8]},
        {cell: rot[right ? 2 : 0]},
        {cell: rot[right ? 8 : 6]},
        {cell: rot[right ? 5 : 3]}
      ]);
    },

    // Escape from inside the line
    (rot) => {
      if(
        !colourBand.contains(view[rot[7]].color) ||
        !colourBand.contains(view[rot[1]].color) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      return best_of([
        {cell: rot[3]},
        {cell: rot[5]},
        {cell: rot[0]},
        {cell: rot[2]},
        {cell: rot[6]},
        {cell: rot[8]}
      ]);
    }
  ]);
}

function latch_to_dotted_path(colourBand, side) {
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(approachingCol) &&
        view[rot[right ? 8 : 6]].color === colourBand.next(approachingCol) &&
        !colourBand.contains(view[rot[right ? 5 : 3]].color)
      ) {
        // We're on the wrong side; go inside the line
        return {cell: rot[right ? 5 : 3]};
      }
    },

    // Inside the line? pick a side
    (rot) => {
      var passedCol = view[rot[7]].color;
      var approachingCol = view[rot[1]].color;
      if(
        !colourBand.contains(passedCol) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      if((approachingCol === colourBand.next(passedCol)) === right) {
        return best_of([{cell: rot[3]}, {cell: rot[6]}, {cell: rot[0]}]);
      } else {
        return best_of([{cell: rot[5]}, {cell: rot[2]}, {cell: rot[8]}]);
      }
    }
  ]);
}


// == High-level logic begins here ==


var PARTNER = 1;
var SENTINEL = 2;

var COL_DANCING1 = 8;
var COL_DANCING2 = 7;
var SAFE_COLOURS = random_colour_band(colours_excluding([WHITE, COL_DANCING1]));

function pass_time() {
  // Wait patiently for the blockage to go away by setting
  // random cell colours (unless we're near the sentinel)
  for(var i = 0; i < 9; ++ i) {
    if(i !== 4 && friend_at(i) === SENTINEL) {
      return null;
    }
  }
  return {cell: 0, color: SAFE_COLOURS.next()};
}

function move_sentinel(me, buddies) {
  // Our job is to be a sentinel showing when the queen has wrapped around.
  // We are created first, so will move first.
  // We won't find any food.

  if(!buddies[QUEEN] && !buddies[PARTNER]) {
    // No ongoing dance; make sure our state is good for when they arrive
    return try_all_angles([
      {cell: CENTRE, color: WHITE},
      (rot) => ({cell: rot[1], color: COL_DANCING2}),
      (rot) => ((view[rot[0]].color === COL_DANCING1)
        ? {cell: rot[0], color: SAFE_COLOURS.next()}
        : null)
    ]);
  }

  // Dance when queen passes
  var danceStage = view[CENTRE].color;

  if(danceStage === WHITE) {
    // Dance has not begun yet, but queen & partner are nearby
    return try_all_angles((rot) => {
      if(friend_at(rot[5]) === QUEEN && friend_at(rot[8]) === PARTNER) {
        return {cell: CENTRE, color: COL_DANCING1};
      }
    });
  }

  if(danceStage === COL_DANCING1) {
    if(buddies[PARTNER]) {
      return null; // Wait for partner to see us
    }
    // Partner saw us @8 and moved down, queen followed.
    // We must also move down (will end up on a COL_DANCING2)
    return try_all_angles((rot) =>
      ((friend_at(rot[8]) === QUEEN) ? {cell: rot[7]} : null));
  }

  // Move towards queen counter-clockwise when she's diagonally connected
  return try_all_angles((rot) =>
    ((friend_at(rot[2]) === QUEEN) ? {cell: rot[1]} : null));
}

function move_partner(me, buddies) {
  // Our job is to travel with the queen and keep her oriented.
  // We are created second, so move after the sentinel.
  // Any food we find will immediately go to the queen, since
  // we are adjacent at all times.

  // Queen will be N of us; orient ourselves
  var rot = identify_rotation((rot) => friend_at(rot[1]) === QUEEN);

  if(!rot) {
    // Queen is lagging or lost;
    return null;
  }

  var danceStage = view[rot[0]].color;
  if(
    friend_at(rot[0]) === SENTINEL &&
    (danceStage === COL_DANCING1 || danceStage === COL_DANCING2)
  ) {
    // Dance down (queen will follow)
    return {cell: rot[7]};
  }

  if(view[rot[0]].ant) {
    // Queen is blocked
    return null;
  }

  // Lead queen if both can move
  return {cell: rot[3]};
}

function move_queen(me, buddies) {
  // Our job is to travel over the entire level collecting food.
  // We move last.

  if(buddies[PARTNER]) {
    // Partner will be S or SW of us; follow if they are ahead
    return try_all_angles((rot) =>
      (friend_at(rot[6]) === PARTNER) ? {cell: rot[3]} : null);
  }

  var rot = identify_rotation((rot) => friend_at(rot[3]) === SENTINEL);
  if(rot && view[rot[0]].color >= 7) {
    // Dance down (follow partner)
    return {cell: rot[7]};
  }

  // We're on our own, or the buddy strategy failed. Start again.

  rot = identify_rotation((rot) => friend_at(rot[5]) === SENTINEL);
  if(rot && me.food >= 1) {
    // Already have a sentinel; just need a partner
    return best_of([
      {cell: rot[7], type: PARTNER},
      {cell: rot[6], type: PARTNER},
    ]);
  } else if(me.food >= 2) {
    // Create sentinel first so that we'll know to create the partner next.
    // (ensure the sentinel is created on a white cell so that it won't
    // think it's dancing)
    return try_all_angles(
      (rot) => ((view[rot[5]].color === WHITE)
        ? {cell: rot[5], type: SENTINEL} : null),
      (rot) => ({cell: rot[5], color: WHITE})
    );
  }

  // Not able to start yet; fall back to lone behaviour:
  // Random-walk until we find or make a buddy
  return best_of([
    grab_nearby_food,
    fast_diagonal.bind(null, SAFE_COLOURS),
    go_anywhere
  ]);
}

return play_safe([move_agent([
  PARTNER, move_partner,
  SENTINEL, move_sentinel,
  QUEEN, move_queen,
]), pass_time]);

ফরেনসিক পিঁপড়াগুলি গ্রিডটি সাফ করার জন্য একটি বৈজ্ঞানিক পদ্ধতি গ্রহণ করে। খাবারের জন্য প্রাথমিক ফ্রেঙ্কিক স্ক্যাম্বল হওয়ার পরে, 2 কর্মী পিঁপড়া তৈরি করা হবে। ভূমিকাগুলি হ'ল:

রাণী

রানী আলোর গতিতে একটি সরল লাইনে ভ্রমণ করতে সঙ্গীর সাথে দল বেঁধে দেবে। তাদের কেউই খাবার আনতে ডাইভারেজ করবে না; তারা কেবল হোঁচট খাচ্ছে যা তারা পড়েছে।

অংশীদার

অংশীদার রানিকে নিয়ে একই দিকে চালিত হয় keeping যেহেতু উভয় পিঁপড়ী প্রতিটি মোড়কে 1 স্কোয়ার সরাতে পারে, তারা মাটিতে রঙ করার সময় নষ্ট না করে সরাসরি সরলরেখায় থাকতে সক্ষম।

যদি অংশীদারটি কোনও খাবার খুঁজে পায় তবে তা সঙ্গে সঙ্গে রানীর কাছে চলে যাবে, যেহেতু তারা সর্বদা সংলগ্ন।

প্রহরী

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

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


এগুলি খুব ধারাবাহিকভাবে সম্পাদন করে; তাদের মধ্যে তারা প্রতিটি ফ্রেমে 2 টি সেল ঝাঁপিয়ে দিতে পারে, যার 30000 ফ্রেমের অর্থ 60000 কোষ, এবং 0.1% খাবার সহ, যার অর্থ 60 এর চূড়ান্ত স্কোর, যা তারা বেশ নিরন্তরভাবে অর্জন করে।


(এবং প্রশ্নটি বিটা চলাকালীন আমি প্রস্তুত অন্যটি এখানে! - এটি আমার জন্য এখনই হয়ে গেছে; আমি নিশ্চিত যে এগুলি খুব দ্রুত
ডেভ

স্কোরটি উল্লেখযোগ্যভাবে সামঞ্জস্যপূর্ণ। আরও আকর্ষণীয় প্রতিদ্বন্দ্বীর সাথে
অঙ্গনটি

আমি ভাবছি রানীর ওপারে অন্য সঙ্গী যুক্ত করা কি সাহায্য করবে?
কে জাং

1
@ কেজ্যাং আমার মনে হয় এটি হবে (তাত্ত্বিকভাবে এটি স্কোরটি 90 ডলারে উন্নীত করবে), তবে সেন্ডিনেলের সাথে তাদের দু'টিকে সিঙ্ক করে রাখা যথেষ্ট শক্ত! "সরানো প্রত্যেকে 2 পিক্সেল উপরে উঠান" নাচটি বের করতে আমাকে কিছুটা সময় নিয়েছিল। 3 পিক্সেলে গিয়ে আমার যে কৌশলগুলি নির্ভর করে তার মধ্যে একটি অবরুদ্ধ করে দেবে (সেন্ডিনেল আগে থেকেই নিজের চারপাশের স্পেস প্রস্তুত করে)।
ডেভ

প্রথম লিডারবোর্ডের শীর্ষস্থানীয় ...
ত্রিভোপলাক্স

18

স্লাইডিং মাইনার্স 6.4

const DEBUG = false;
const ADD = (a,b) => a + b;
var toReturn;
var me = view[4].ant;
me.me = true; // for basedOn to know
var food = me.food;
var type = me.type;
var isQueen = type == 5;

// raw directions
const UL = 0; const U  = 1; const UR = 2;
const L  = 3; const C  = 4; const R  = 5;
const DL = 6; const D  = 7; const DR = 8;

// directions from the reference point
const ul = 16; const u  = 17; const ur = 18;
const l  = 19; const c  = 20; const r  = 21;
const dl = 22; const d  = 23; const dr = 24;
const rp = 16;

function allRots (arr) {
  return [arr,
  [arr[2], arr[5], arr[8],
   arr[1], arr[4], arr[7],
   arr[0], arr[3], arr[6]],

  [arr[8], arr[7], arr[6],
   arr[5], arr[4], arr[3],
   arr[2], arr[1], arr[0]],

  [arr[6], arr[3], arr[0],
   arr[7], arr[4], arr[1],
   arr[8], arr[5], arr[2]]];
}
var allVRots = allRots(view);

function rotateCW3([[a,b,c],[d,e,f],[g,h,i]]) {
  return [[g,d,a],[h,e,b],[i,f,c]]
}

function on (where, what) {
  if (Array.isArray(where)) return where.some(c=>on(c, what));
  if (Array.isArray(what)) return what.some(c=>on(where, c));
  return basedOn(get(where), what);
}
function find (what) {
  return view.findIndex(c=>basedOn(c, what));
}
function findAll (what) {
  return view.map((c,i)=>[c,i]).filter(c=>basedOn(c[0], what)).map(c=>c[1]);
}
function count (what) {
  return findAll(what).length;
}
function findRel (what) {
  return ref(find(what));
}
function findAllRel (what) {
  return findAll(what).map(c=>ref(c));
}
function found (what) {
  return find(what) != -1;
}
function get (dir) {
  if (Array.isArray(dir)) return dir.map(c=>get(c));
  return view[raw(dir)];
}
function deq (a, b) {
  return a==b || raw(a)==raw(b);
}

// returns a random number from 0 to 4, based on the rotation. Will always have a possibility of being 0
function random4 () {
  var scores = allRots(view.map(c=>c.color)).map((c) => {
    let cscore = 0;
    c.forEach((c) => {
      cscore*= 8;
      cscore+= c-1;
    });
    return cscore;
  });
  var bestscore = -1, bestindex = 1;
  scores.forEach((score, index) => {
    if (score > bestscore) {
      bestscore = score;
      bestindex = index;
    }
  })
  return bestindex;
}

function rotate (what, times) {
  for (var i = 0; i < times; i++) what = [2,5,8,1,4,7,0,3,6][what];
  return what;
}

function raw(dir) {
  if (dir&rp) return rotate(dir&~rp, selectedRot);
  return dir;
}

function ref(dir) {
  if (dir == -1) return -1;
  if (dir&rp) return dir;
  return rotate(dir, 4-selectedRot)|rp;
}

function move(dir, force) {
  if (Array.isArray(dir)) return dir.some(c=>move(c, force));
  dir = raw(dir);
  return result({cell:dir}, force);
}

function color(dir, col) {
  if (Array.isArray(dir)) return dir.some(cdir => !color(cdir, col));
  dir = raw(dir);
  if (view[dir].color == col) return true;
  result({cell:dir, color:Math.abs(col)});
  return false;
}

function rcolOf(what) {
  return Number.isInteger(what)? what : what.color;
}

function colOf(what) {
  return Math.abs(Number.isInteger(what)? what : what.color);
}
function sees(c1,c2) {
  c1 = raw(c1);
  c2 = raw(c2);
  return Math.abs(c1%3-c2%3)<2 && Math.abs(Math.floor(c1/3)-Math.floor(c2/3))<2;
}

function spawn(dir, t) {
  if (Array.isArray(t)) return t.some(c=>spawn(dir, c));
  if (Array.isArray(dir)) return dir.some(c=>spawn(c, t));
  dir = raw(dir);
  return result({cell:dir, type:t});
}
// repairs a single cell
function correct(dir) {
  dir = raw(dir);
  let col = colOf(selectedPt[dir]);
  if (col && view[dir].color != col) {
    color(dir, col);
    return false;
  }
  return true;
}
// if pattern is repaired, returns true, otherwise fixes one cell
// firstdirs is lowercase (if you do want it to be from the patterns POV)
function repair(firstdirs, onlyThose) {
  //log("FD",firstdirs);
  var found = [];
  view.forEach((v, i) => {
    let col = colOf(selectedPt[i]);
    if (col && v.color != col) {
      found.push(i);
    }
  });
  if (found.length == 0) return true;
  if (firstdirs && (firstdirs = firstdirs.map(c=>raw(c))).some(c=>found.includes(c))) {
    let dir = firstdirs.find(c=>found.includes(c));
    let col = colOf(selectedPt[dir]);
    color(dir, col);
    return false;
  }
  if (!onlyThose) {
    let dir = found[random4() % found.length];
    let col = colOf(selectedPt[dir]);
    color(dir, col);
    return false;
  } else return true;
}

function flatten (arr) {
  return arr.reduce((a,b)=>a.concat(b));
}

var selectedHp, selectedVp, selectedPt, selectedRot;

class Pattern {
  constructor(pattern, inherit) {
    this.pt = pattern;
    if (inherit) {
      this.vp = inherit.vp;
      this.hp = inherit.hp;
      this.rot = inherit.rot;
    } else {
      this.vp = 0;
      this.hp = 0;
      this.rot = 0;
    }
  }

  rotateClockwise() {
    var arr = [];
    for (var i = 0; i < this.pt[0].length; i++) {
      var sarr = [];
      for (var j = this.pt.length-1; j >= 0; j--) {
        sarr.push(this.pt[j][i]);
      }
      arr.push(sarr);
    }
    //log(arr);
    var res = new Pattern(arr, this);
    res.rot = (this.rot+1) % 4;
    return res;
  }

  select(x, y, w, h) {
    var res = new Pattern(this.pt.slice(y, y+h).map(c=>c.slice(x, x+w)), this);
    res.hp+= x;
    res.vp+= y;
    return res;
  }

  rots(dir) {
    var pts = [];
    var pt = new Pattern(this.pt, this);
    for (let i = 0; i < this.lengthIn(dir); i++) {
      pts.push(pt);
      pt = pt.rotate(dir);
    }
    return pts;
  }

  map(fn) {
    return new Pattern(this.pt.map(ln=>ln.map(fn)), this);
  }

  lengthIn(dir) {
    if (dir == U || dir == D) return this.pt.length;
    else if (this.pt.length > 0) return this.pt[0].length;
    else return 0;
  }
  rotate(dir) { // moves the center to that direction, shifting the side
    if (dir == R) {
      var res = new Pattern(this.pt.map(c=>((h,...t)=>t.concat(h))(...c)), this);
      res.hp++;
      return res;
    }
    if (dir == L) {
      var res = new Pattern(this.pt.map(a=>a.slice(-1).concat(a.slice(0,-1))), this);
      res.hp++;
      return res;
    }
    if (dir == D) {
      var res = new Pattern(((h,...t)=>t.concat([h]))(...this.pt), this);
      res.vp++;
      return res;
    }
    throw "rotate unimplemented dir!";
  }

  center(dir) { // moves the center to that direction
    if (dir == R) {
      var res = new Pattern(this.pt.map(c=>((h,...t)=>t.concat(0))(...c)), this);
      res.hp++;
      return res;
    }
    if (dir == L) {
      var res = new Pattern(this.pt.map(a=>[0].concat(a.slice(0,-1))), this);
      res.hp++;
      return res;
    }
    if (dir == D) {
      var res = new Pattern(((h,...t)=>t.concat([new Array(h.length)]))(...this.pt), this);
      res.vp++;
      return res;
    }
    throw "center unimplemented dir!";
  }

  setSize(xs, ys) {
    var arr = [];
    for (let y = 0; y < ys; y++) {
      var ca = [];
      for (let x = 0; x < xs; x++) {
        ca.push(this.pt[y % this.pt.length][x % this.pt[0].length]);
      }
      arr.push(ca);
    }
    return new Pattern(arr, this);
  }

  static add(pattern, action, scorer, presetRot) {
    if (Array.isArray(pattern)) pattern = new Pattern(pattern);
    pattern = pattern.setSize(3,3);
    var cpt = pattern.setSize(3,3);
    var orig = cpt.pt;
    for (let i = 0; i < 4; i++) {
      cpt = cpt.rotateClockwise();
      if (!presetRot || presetRot == cpt.rot) {
        cpt.action = action;
        cpt.scorer = scorer;
        cpt.raw = orig;
        cpt.view = allVRots[cpt.rot];
        allPatterns.push(cpt);
      }
    }
  }


  static choose() {
    var maxScore = -1e307;
    var nextScore = -1e308;
    var maxPt;
    allPatterns.forEach((c) => {
      // null  = easy
      // 0     = bad queen
      // false = no match
      // >0    = score
      var falseN = 0;
      var corrects = c.raw.reduce((a,b)=>a.concat(b)).map((guess, index) => {
        var bo = basedOn(c.view[index], guess, true);
        var ant = guess.ant;
        if (ant && basedOn(c.view[index], {ant})) bo+= 1;
        if (bo === 0) return 0;
        if (bo === false) return false;
        if (bo && rcolOf(guess) > 0) return bo;
        var easy = rcolOf(guess)<=0;
        if (easy) {
          falseN++;
          return null;
        }
        return bo;
      });
      var corrstring = corrects.map((chr,i)=>chr>0? (colOf(c.raw[Math.floor(i/3)][i%3])==1? "W" : "#") : chr===null? "-" : " ").join("");
      function match(pt) {
        return new RegExp(pt.replace(/@/g, "[#-W]").replace(/C/g, "[#-]")).test(corrstring);
      }
      var score = corrects.reduce(ADD)*9/(9-falseN);
      if (match(".?(...)?##.##.*")) {
        if (match("(...)?@@@@@@.*|.?@@.@@.@@.?")) score+= foundEnemy? 5 : 3;
        else score+= foundEnemy? 3 : 1;
      } else if (!foundEnemy) score = Math.min(score/2, 5);
      if (c.scorer instanceof Function) score = c.scorer(score, c, corrects, falseN, match);
      if (DEBUG && score > -1) log(
        "scored", score,
        "corr", /*corrects.map(c =>
          (c===false?"F":c===null?"N":c===true?"T":c)
        )*/corrstring,
        "pt", c.raw.map(c=>c.ant? "A"+c.ant.type : c), c.hp, c.vp);
      if (score >= maxScore) {
        nextScore = maxScore;
        maxScore = score;
        c.corrstr = corrstring;
        maxPt = c;
      }
    });
    var flattened = maxPt.pt.reduce((a,b)=>a.concat(b));
    Pattern.hardcorr = flattened.map((guess, index) => rcolOf(guess)<2? 0 : basedOn(view[index], guess)).reduce(ADD);
    Pattern.corrstr = maxPt.corrstr;
    Pattern.corr = flattened.map((guess, index) => basedOn(view[index], guess)).reduce(ADD);
    Pattern.incorr = 9-Pattern.corr;
    Pattern.confidence = maxScore-nextScore;
    selectedRot = maxPt.rot;
    Pattern.action = maxPt.action;
    selectedPt = flattened;
    selectedHp = maxPt.hp;
    Pattern.raw = maxPt.raw;
    Pattern.view = maxPt.view;
    selectedVp = maxPt.vp;
    Pattern.score = maxScore;
    if (DEBUG) log("score", maxScore, "confidence", Pattern.confidence, "corr", Pattern.corr, "hardc", Pattern.hardcorr, "pt", maxPt.pt);//, "fn", maxPt.action+""
  }
}
var allPatterns = [];
function clear() {
  allPatterns = [];
}
function adds(raw, action, scorer, presetRot) { // must get a 3x3 arr
  var pt = raw;
  var hp = raw.hp;
  var vp = raw.vp;
  for (let rot = 0; rot < 4; rot++) {
    let view = allVRots[rot];
    allPatterns.push({pt, action, scorer, rot, hp, vp, view, raw});
    if (rot!=4) pt = rotateCW3(pt);
  }
}
function refPt(...args) {
  clear();
  if (Array.isArray(args[0])) {
    if (args[0].length != 3) args[0] = args[0].slice(0,3);
    if (args[0][0].length != 3) args[0] = args[0].map(c=>c.slice(0,3));
    adds(...args);
  }
  else Pattern.add(...args);
  Pattern.choose();
}

/*
is the 2nd param a subset of the 1st param.
guess can be a number (color), or an object ({color:..,ant:..,..})
guess.ant can be "worker", "queen", "enemy", "enemyworker", "enemyqueen" with obvious meanings. Note that "friend" ≠ me
guess.ant.type can be an array, ORing

true - correct!
false - not correct
0 - notqueen doesn't match (aka very bad)

negativesEqual makes this always return true for negative colors, otherwise it treats negatives as regular colors
*/
function basedOn(real, guess, negativesEqual) {
  if (Array.isArray(real)) return real.some(c=>basedOn(c, guess, negativesEqual));
  if (Number.isInteger(guess)) guess = {color:guess};
  if (guess.notqueen && real.ant && real.ant.friend && real.ant.type==5) return 0;
  if (guess.not) {
    var bo = basedOn(real, guess.not, negativesEqual);
    if (bo) return 0;
  } 
  if (guess.color && Math.abs(guess.color) != real.color && !(negativesEqual && guess.color<0)) return false; // 0 handles itself
  if (guess.obstacle !== undefined) {
    if (guess.obstacle && !real.ant && !(food && real.food && !isQueen)) return false;
    if (!guess.obstacle && (real.ant || (food && real.food && !isQueen))) return false;
  }
  if (guess.badobstacle !== undefined) {
    if (guess.badobstacle && !(real.ant && !real.ant.friend) && !(food && real.food && !isQueen)) return false;
    if (!guess.badobstacle && ((real.ant && !real.ant.friend) || (food && real.food && !isQueen))) return false;
  }
  if (guess.ant) {
    if (!real.ant) return false;
    if (guess.ant == "worker"      &&!( real.ant.friend && real.ant.type!=5)) return false;
    if (guess.ant == "queen"       &&!( real.ant.friend && real.ant.type==5)) return false;
    if (guess.ant == "enemyqueen"  &&!(!real.ant.friend && real.ant.type==5)) return false;
    if (guess.ant == "enemyworker" &&!(!real.ant.friend && real.ant.type!=5)) return false;
    if (guess.ant == "friend" && (!real.ant.friend || real.ant.me)) return false;
    if (guess.ant == "enemy"  &&  real.ant.friend) return false;
    if (Number.isInteger(guess.ant) && real.ant.type != guess.ant) return false;
    if (guess.ant.friend !== undefined && guess.ant.friend !== real.ant.friend) return false;
    if (guess.ant.type !== undefined && !(Array.isArray(guess.ant.type)? guess.ant.type.some(c=>c == real.ant.type) : guess.ant.type == real.ant.type)) return false;
    if (guess.ant.food !== undefined && guess.ant.food !== real.ant.food) return false;
  }
  if (guess.food !== undefined && guess.food !== real.food) return false;
  // log("matched");
  return true;
}

function result (action, force) {
  if (!force) if (toReturn !== undefined) return 0;
  var color = action.color;
  var type = action.type;
  var cell = action.cell;
  if (type < 1 || type > 4) return false;
  if (!(cell >= 0 && cell <= 8)) return false;
  if (color < 1 || color > 8) return false;
  if (!color && ((view[cell].ant && cell != 4) || (isQueen? (view[cell].food && type) : (food && view[cell].food)))) return false; // can't walk onto ant, can't spawn on food, can't move to food with food
  if (!isQueen && type) return false;
  if (!isQueen && !color && food && view[cell].food) return false;
  if (isQueen && !food && type) return false;
  if (type && cell==C) return false;
  if (color && type) return false;

  toReturn = action;
  return true;
}

const WH = 1; // white   
const C1 = 6; // green   HW
const C2 = 5; // red     
const C3 = 8; // black   
const C4 = 2; // yellow  HW
const C5 = 4; // cyan    HW
const C6 = 7; // blue    HW
const C7 = 3; // purple  HW
// C1=GR,C2=BL,C4=YL,C5=DK
const ENEMY = {ant:"enemy"};
const foundEnemy = found(ENEMY);
  //-----------------------------------------------------------------------------------------------------------------------------------------------------\\
 //----------------------------------------------------------------------- MAIN CODE ---------------------------------------------------------------------\\
//---------------------------------------------------------------------------------------------------------------------------------------------------------\\

function log(...args) {
  if (!DEBUG) return;
  toLogRaw.push(args);
  // for (let i of args) {
  //   if (i === undefined) i = "undefined";
  //   var res = "";
  //   if (typeof i === 'string') res = i;
  //   else res = JSON.stringify(i);
  //   toLog+= res + " ";
  // }
  // toLog+= "\n";
}
if (DEBUG) {
  var toLog = "";
  var logMyLogs = false;
  var toLogRaw = [];
  log(type, view.map(c=>c.ant? "A"+c.ant.type : c.color));
}

const Ut = 1;
const Dt = 2;
const Ht = 4;
const Uo = {ant:{type:Ut,friend:true}};
const Do = {ant:{type:Dt,friend:true}};
const Ho = {ant:{type:Ht,friend:true}};
const Mo = {ant:{type:[Ut,Dt],friend:true}};
const Fo = {food:1};
const Qo = {ant:{type:5,friend:true}};
const EQo = {ant:{type:5,friend:false}};
const FRIEND = {ant:"friend"};
const OBSTACLE = {obstacle:true};
const FREE = {obstacle:false};
const BADOBSTACLE = {badobstacle:true};
const STARTINGFOOD = 6;
const LESSENFOOD = 160;
const ENDINGFOOD = 160;
const isMiner = type==Ut || type==Dt;
var friendCount = count(FRIEND);
if (isMiner) {
  var Mu = type==Ut? u : d;
  var Md = type==Ut? d : u;
  var Mur = Mu+1;
  var Mul = Mu-1;
  var Mdr = Md+1;
  var Mdl = Md-1;
}

const foodExt = [C3, C7, WH];
const rawRail = [
  [WH,-1,C7,-1], // 43 03 13 23
  [C6,WH,WH,-1], // 42 02 12 22

  [C4,C1,C2,C2],
  [C2,C4,C5,C5],
  [C3,C5,C1,C3],


//[C3,C1,C4,C4],
//[C4,C4,C5,C2],
//[C5,C2,C1,C3],

//[C3,C1,C2,C5],
//[C3,C3,C1,C5],
//[C2,C4,C5,C2],


//[C2,C1,C3,C5], // 41 01 11 21
//[C1,C5,C5,C4], // 40 00 10 20
//[C5,C4,C2,C3], // 41 01 11 21
  [C6,WH,WH,-1], // 42 02 12 22
  [WH,-1,C7,-1]  // 43 03 13 23
]
.map((ln,row)=>(row<2||row>4)? ln.map(c=>({not:{ant:{friend:true, type:[Ht, 5]}},color:c})) : ln); // queen can't be in the top & bottom 2 rows

function section(ln, action, scorer) {
  if (ln > 0) section(-ln, action, scorer);
  var sct = rawRail.slice(ln+2, ln+5);
  var parts;
  if (Math.abs(ln) != 2) {
    parts = [];
    for (let i = 0; i < 4; i++) {
      var cpt = sct.map(([a,b,c,d])=>[a,b,c]);
      cpt.hp = i;
      cpt.vp = ln;
      parts.push(cpt);
      if (i!=4) sct = sct.map(([a,b,c,d])=>[b,c,d,a]);
    }
  } else {
    var o = sct.map(c=>c.slice(0,3));
    o.vp = ln;
    o.hp = 0;
    parts = [o];
  }
  parts.map(c=>adds(c, action, scorer));
}

function sabotage(where) {
  if (on(where, 1)) repair([where], true);
  else color(where, 1);
}


section(0, ()=>{
  if (isMiner) {
    if (on([r,ur,dr], Fo)  ||  on([u,d], Fo) && on([l,ul,dl], Mo)) { // FAKE RAIL
      color(on([dr,d],Fo)? [dr,u,ul] : [dr,d,dl], C7);
    }
    else if ([l,ul,dl].every(c=>on(c,{ant:{}})) && !random4()) move([r,u,d,ur,dr]); // peer pressure
    /* AV */ else if (found(EQo)) sabotage(find(EQo));
    else if (repair()) {
      if (on(r,Mo) && (random4() > 1 || random4() && friendCount > 3)) move([l,Mul,Mu,Mdl,Md]);
      if (on([Mu,Mur], ENEMY)) move([R, D, DR]); // move somewhere away from enemy
      else if (on(r, Qo) && on([l,ul,dl], {ant:{type:[Ut,Dt],food:1,friend:true}})) move([Mu, Mul, l, Mdl]); // make place for miners with food; Possibly stuck
      else if (on(r, Qo)) move([Mu, Mul]); // don't do stupid things around queen
      else if (on(l, Qo) && !foundEnemy) move([Mul, Mdl, Mu, Md]); //.. I've done stupid things around queen
      else if (on([Mu,Mur], OBSTACLE)) { // up is blocked :/
        if (random4()) move(on(Mu, FRIEND)? [Mur, r] : r);
        else move([r, Mul, Md, Mul, l, Mdl]);
      }
      else move([Mu, r, Mur, Md, Mdr]); // move along
    }
  } else if (isQueen) {
    var HM = Pattern.view.map(c=>+basedOn(c, Ho));
    var helperRows = [HM.slice(0,3),HM.slice(6,9)].map(c=>c.lastIndexOf(1)).map((c,i) => (c==0 && on(i==0? u : d, OBSTACLE)) ? -1 : c);
    var minH = Math.min(helperRows[0],helperRows[1]);
    var maxH = Math.max(helperRows[0],helperRows[1]);
    if (on(r, FRIEND) && [ur,dr].every(c=>on(c, ENEMY))) move([l,ul,dl]);
    if (found(EQo)) { // vampire?
      move(random4()%2? [ur,dr] : [dr,ur]);
      var eQueenRel = (findRel(EQo)-rp)%3;
      if (eQueenRel == 0) move(r,ur,dr);
      spawn(Mu, [u,d,r,ur,dr]);
    }
    if (foundEnemy) // spawn helpers against enemies
      if (food && minH == -1 && count(Ho) < 2) {
        if (helperRows[0] == -1) spawn([u,ur,ul],Ht);
        else                     spawn([d,dr,dl],Ht);
      }
    if ([r,ur,dr].every(c=>on(c, ENEMY))) move([ul,dl,l,u,d]); // OH GOD NO WHY
    if ((minH == -1 || maxH == 2) && on(r, [ENEMY,Ho]) && Pattern.incorr < 2 && count({ant:{}})-1 != count(Ho))
      move(on(ur, ENEMY)? [d,u,dr,ur,ul,dl,l] : [u,d,ur,dr,ul,dl,l]); // initialize transporting around enemy
    if ((!random4() && on(l, OBSTACLE) && on([ul, dl], OBSTACLE)) && Pattern.corr >= 7) move(r); // move forward sometimes if left is 2/3s full
    else if ([r,ur,dr].every(c=>c.ant && !c.ant.friend)) move([l,ul,dl]);
    else if (food && minH > 0 && (
        count(Mo) == 0 && selectedHp != 1 && Pattern.corr != 9 && food < LESSENFOOD
      ||
        //Pattern.corr === 9 && [u,d].every(c=>on(c,Ho)) && selectedHp === 1 && food >= LESSENFOOD && food < ENDINGFOOD && random4() < 2
        Pattern.corr === 9 && selectedHp == 0 && count(Mo) === 0 && food >= LESSENFOOD && food < ENDINGFOOD && random4() < 2
      )) { // spawn miners
      if (random4()%2) spawn([u,ul], Ut);
      else             spawn([d,dl], Dt);
    } else if (repair()) {
      if (food && minH == -1 && count(Ho) < 2) { // spawn helpers
        if (helperRows[0] == -1) spawn([u,ur,ul],Ht);
        else                     spawn([d,dr,dl],Ht);
      }
      else if (selectedHp != 1  ||  selectedHp==1 && /*(*/(maxH==2 || minH == -1 && helperRows.includes(2)) && (!random4() || food < LESSENFOOD || found(Mo))  ||  foundEnemy) move(r); // move forwards
      else if (on(ul, Do) && on(dl,Uo) && on(l, {ant:{}})) move(r); // miners are in wrong places
    }
  } else { // helper
    var repaired = repair();
    var queenRel = (findRel(Qo)-rp)%3;
    var dir = queenRel==0? 0 : 1;
    if (repair()) {
      if (on(r, EQo) && [u,d,ur,dr].map(c=>on(c, ENEMY)? 1 : 0).reduce(ADD) >= 3) move(c); // protect the queen from the evils ahead
      else if (on(r, Qo)) move([u,d,ur,dr,ul,dl,l]);
      else move((on([d,dr,dl], Ho)? [u+dir,d+dir] : [d+dir,u+dir]).concat([u+(1-dir), d+(1-dir)]), !random4());
    }
  }
})

section(1, ()=>{
  const A = selectedVp > 0? d : u; // away
  const I = selectedVp > 0? u : d; // in
  const AR = A+1;
  const AL = A-1;
  const IR = I+1;
  const IL = I-1;

  if (isMiner) {
    var queenRel = (findRel(Qo)-rp)%3;
    if (on([r,IR], Fo)) color([r,IR, I], C7); // FAKE RAIL
    else if ([l,IL].every(c=>on(c,{ant:{}})) && !random4()) move([r,IR]); // peer pressure
    /* AV */ else if (found(EQo)) sabotage(find(EQo));
    else if ((found(EQo) && random4() && Pattern.dist <= 1 && on(find(EQo), 1)) || repair()) {
      if (on(I, Qo)) move(l); // what am I doing here?
      else if (A == Mu) { // my dir!
        if (!food && selectedHp == 0 && (on(r,Ho) && on(IR, Qo)  ||  count(Mo) >= 6)) move(A); // move out!
        else if (on(IR,Qo) && on([l,IL], {ant:{type:[Mu,Md],friend:true,food:1}})) move(C); // waiting in line :D
        else if (on(IR,Qo)) move(C); // waiting in line :D
        else if (random4()) move([r, I, IR]);
        else move([r, I, IR, l, IL]);
      } else { // not my dir
        // TODO fix \\ if (selectedHp == 0 && count(Mo) >= 6 && food) move(A); // fake rail escape
        if (random4()) {
          move([I, IR, IL, l]);
        } else {
          move([r, I, IR, IL, l]);
        }
      }
    }
  } else if (isQueen) {
    if (found(EQo)) { // vampire?
      var eQueenRel = (findRel(EQo)-rp)%3;
      if (eQueenRel==0) move(r, IR);
      spawn(Mu, [r,IR]);
      spawn(Md, I);
    }
    /* AV */ if (food > 70 && (
      [IR,IL,I,l,r].every(c=>on(c,ENEMY)) // completely encased
      || on(IR, EQo) && [r,I].every(c=>on(c, ENEMY)) // getting leeched
      || on(I, EQo) && [r,l,IL,IR].map(c=>get(c)).map(c=>c.ant? (c.ant.friend? 1 : -1) : 0).reduce(ADD) < 0 // leeched
    )) move([A,AR,AL]); // BAD NEWS COMPLETELY DEAD
    if (!random4() || found(EQo) || repair())
      move(random4()? [IR,r,I,l] : [IR,r,I]);
  } else { // helper
    var queenRel = (findRel(Qo)-rp)%3;
    /* AV */ if (on(r,Qo) && on([I,IR], EQo)) move([IR,I,l,IL]);
    if (on(l, Qo)) { if (!random4() || repair()) move(r) } // queen's transporting
    if (on(I, Qo) && on(IR, {ant:"enemyworker"})) { if (!random4() || repair()) move(r) } // queen needs to transport
    // what was this? if ([l,IL,I].every(c=>on(c,OBSTACLE)) && (count(ENEMY) > 1 || find(EQo)) && !random4()) move([r,ur]);
    if ((selectedVp < 0? /...[#-W]{6}/ : /[#-W]{6}.../).test(Pattern.corrstr) && queenRel == 2 && count(Ho) == 1) move(r); // move forward without repairing
    if (!random4() && queenRel == 1 && selectedHp == 1 && on(AL, {ant:{}})) move(r); // something is out; don't repair
    else if (repair([r,l,A,AR,AL])) {
      if (on(r, ENEMY) && on(I, Qo) && [l,IL].every(c=>on(c,FRIEND))) move(IR); // protect from vampire
      if (on(r, ENEMY) && on(IL, Qo) && [l,IR].every(c=>on(c,FRIEND))) move(I);
      if (on(r, ENEMY) && !get(r).ant.food && on(I, Qo)) move(IR);
      if (queenRel == 1 && selectedHp == 1 && on(AL, {ant:{}})) move(r); // something is out
      else if (on([l,r], Ho)) { // move to the other side
        if (found(Qo)) move([I]); // TODO integrate ,IL,IR
        else move([l,r]);
      }
      else if (queenRel == 2) move(r); // move forward
    }
  }
}, (pscore, pt, corrects, falseN, match) => {
  if (match(".?(...)?@@.@@.*") && !foundEnemy) {
    if (!match(pt.vp>0? ".?@@.@@.*" : ".?...@@.@@.*")) pscore/=2;
  }
  return pscore;
})

if (isMiner) {
  section(2, () => {
    const A = selectedVp > 0? d : u; // away
    const I = selectedVp > 0? u : d; // in
    if (on(A,OBSTACLE)) move(I);
    else if (repair()) move(food? I: Mu);
  }, (pscore, pt, corrects, falseN, match) => match(pt.vp>0? "@@@.@...." : "....@.@@@")? match("@@@@@@@@@")? 100 : ((pt.vp>0) == (type==Dt)? 13 : 10) : 0);
  if (type==Dt) foodExt.reverse();
  if (!found(Ho) && !found(Qo)) {
    var lns = [rawRail[0], rawRail[1]].map(c=>c.slice(0,3));
    [[lns[0],lns[1],lns[0]], [lns[1],lns[0],lns[1]]].map(c=>{
      adds(c, () => {
        var onL;
        if (!food && ((onL = on(l, Fo)) || on(r, Fo))) {
          var foodpt = Pattern.raw.map((ln, i) => [ln[0], foodExt[i], ln[2]]);
          refPt(foodpt,undefined,undefined,selectedRot);
          if (repair()) move(onL? l : r);
        }
        else if (repair([l,r,ul,ur,dl,dr], on([Mul, Mur, Mdl, Mdr, l, r], {ant:{friend:true,type:[Ut,Dt],food:1}}) ||  on([Mu, Md], Mo))) {
          move(food? [Md, Mu] : [Mu, Md]);
        }
      }, (pscore, pt, corrects, falseN, match) => {
        var score = 0;
        var dMatch = match("...@.@@@@");
        var uMatch = match("@.@@.@...");
             if ((type==Ut ^ food) && dMatch) score = 15;
        else if ((type==Dt ^ food) && uMatch) score = 15;
        else if (uMatch || dMatch) score = 6;
        if ([0,2,3,5,6,8].some(c=>basedOn(pt.view[c], FRIEND) && !pt.view[c].ant.food)) score = 0;
        return score;
      });
      if (food) {
        var extp = c.map((ln, i) => [ln[0], foodExt[i], ln[2]]);
        [extp.map(([a,b,c])=>[0,a,b]), extp.map(([a,b,c])=>[b,c,0])].forEach((pt,i) => adds(pt, () => {
          move(i? l : r);
        }, (pscore, pt, corrects, falseN, match) => match("@@@@@@@@@")? 100 : 0));
      }
    });
  }
}

Pattern.choose();
var confident = ((Pattern.confidence >= 1 && (Pattern.score > 4 || Pattern.corr >= 4)) || (Pattern.score >= 9 && Pattern.confidence > 0.05)); // && (selectedHp !=  || !found(Qo));
var failAction = () => {
  if (foundEnemy) {
    log(view);
    log("dead around enemy :/");
    logMyLogs = true;
  }
  if (isQueen) {
    if (found(EQo)) {
      move([8-(find(EQo)-rp) + rp]);
      move(random4()%2? U : UR);
    }
    if (foundEnemy) move(random4()%2? U : UR);
  } else {
    // if (!found(Qo) && found(Fo)) move(find(Fo));
    var enemyPlace = find(ENEMY);
    if (enemyPlace !== -1) color(enemyPlace, get(enemyPlace).color==1? C3 : WH);
  }
}
if (!confident) Pattern.action = failAction;

if (isMiner) {
  if ((Pattern.hardcorr >= 4 || Pattern.score > 5) && confident) Pattern.action();
  else {
    failAction();
  }
} else if (isQueen) {
  if ((Pattern.hardcorr >= 6 || food > STARTINGFOOD+2 || friendCount>1 || found(Mo) || Pattern.score > 6 || (false)) && confident) Pattern.action();
  else if (food >= STARTINGFOOD && friendCount == 1) {
    clear();
    Pattern.add([[1,{ant:Ho.ant,color:1},1],
                 [1,1,1],
                 [1,1,1]], ()=>spawn([ur,ul],Ht));
    Pattern.add([[1,1,{ant:Ho.ant,color:1}],
                 [1,1,1],
                 [1,1,1]], ()=>spawn([ur,u],Ht));
    Pattern.choose();
    if (repair()) Pattern.action();
  } else if (food == 0 && friendCount == 0) { // diagonal search
    if (found(Fo)) {
      move(find(Fo));
    } else {
      clear();
      Pattern.add([[WH,WH,WH],
                   [WH,C1,WH],
                   [C1,WH,WH]], ()=>move(ur));
      Pattern.add([[WH,WH,WH],
                   [WH,WH,WH],
                   [C1,WH,WH]], ()=>color(C, C1));
      Pattern.add([[WH,WH,WH],[WH,WH,WH],[WH,WH,WH]], ()=>color(DL, C1));
      Pattern.choose();
      if (Pattern.corr == 9) Pattern.action();
      else move(random4()? [DL,UL,DR,UL] : [D,L,U,R]);
    }
  } else if (food == 1 && friendCount == 0) spawn([U,L,D,R,UL,DL,UR,DR], Ht);
  else if (friendCount == 1) lightSpeed();
  else if (friendCount > 0) {
    var pt = new Pattern(rawRail).select(0,2,4,3).rotate(L).rotate(L).pt;
    pt[1][2] = {color:pt[1][2], ant:{type:Ht, friend:true}};
    refPt(pt);
    repair([c,u,d,ur,dr]);
  } // TODO wtf to do after this
  else Pattern.action(); // eh fuck it
} else if (type == Ht) {
  if (confident && (Pattern.score >= 4 || Pattern.hardcorr >= 5 || friendCount>1)) Pattern.action();
  else if (found(Qo)) lightSpeed();
  else if (Pattern.hardcorr >= 3 && confident) repair();
}

function lightSpeed() {
  var other = find(isQueen? Ho : Qo);
  var orth = other%2;
  if (isQueen || (view[other].ant.food < STARTINGFOOD && count(Ho) == 1)) { // LS
    if (orth && found(Fo)) { // grab easy food
      var fp = find(Fo);
      if (sees(other, fp)) move(fp);
      else {
        refPt([[0,FRIEND,0],
                     [0,0,0],
                     [0,0,0]]);
        move(l);
      }
    }
    clear();
    // Pattern.when(U,find(FRIEND), ()=>isQueen? move(ul) : move(ur)); when I'm not lazy imma make this a replacement of the below
    Pattern.add([[0,FRIEND,0],
                 [0,0,0],
                 [0,0,0]], ()=>isQueen? move(ul) : move(ur));
    Pattern.add([[0,0,FRIEND],
                 [0,0,0],
                 [0,0,0]], ()=>move(u));
    Pattern.choose();
    Pattern.action();
  }
}

if (DEBUG) log("END", type, view.map(c=>c.ant? "A"+c.ant.type : c.color));
if (DEBUG && logMyLogs) {
  //for (let i = 0; i < toLog.length; i+=800)
  //  console.log(toLog.substring(i,i+800));
  for (let i of toLogRaw) console.log(...i);
}
if (toReturn) return toReturn;
else return {cell:4};

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


প্রথমবারে আবার লিডারবোর্ডে ...
ট্রিকোপল্যাক্স

14

এনজির্নহীন বিমান

ক্রিয়া গ্লাইডারগ্লাইডার বাঁদিকে বাঁকছেগ্লাইডার ডানদিকে ঘুরছে

//console.log(JSON.stringify(view))
var TRAIL = 6;
var SPAWN = 3;
var IDLE = 4;
var FOOD_THRESHOLD = 150;
var SPAWN_MIN = 3;
var HIGHWAY_COLORS = [7,6,4,2,3];
var HIGHWAY_THRESHOLD = 70;
var ret = {cell:4};
if(isOnHighway()) {
    var cont = true;
    //== Make best guess to if in a glider formation ==//
    if(view[4].ant.type == 5) {
        if((findWorker(1) >= 0 && findWorker(4) >= 0) || view[4].ant.food < HIGHWAY_THRESHOLD) {
            cont = false;
        }
    }
    else if(view[4].ant.type == 4) {
        if(findWorker(1) >= 0 && findWorker(5) >= 0) {
            cont = false;
        }
    }
    else if(view[4].ant.type == 3) {
        if(findWorker(2) >= 0 && findWorker(5) >= 0) {
            cont = false;
        }
    }
    else if(view[4].ant.type == 2) {
        if(findWorker(5) < 0) {
            var pos3 = findWorker(3);
            if(pos3 >= 0 && view[pos3].ant.food == 0) {
                cont = false;
            }
        }
        else if(findWorker(3) >= 0 || (findWorker(1) >= 0 && view[findWorker(5)].color == SPAWN))
            cont = false;
    }
    else if(view[4].ant.type == 1) {
        if(findWorker(5) < 0) {
            var pos4 = findWorker(4);
            if(pos4 >= 0 && view[pos4].ant.food == 0) {
                cont = false;
            }
        }
        else if(!isHighwayCenter())
            cont = false;
    }
    if(findWorker(5) >= 0) {
        for(var i=0;i<9;i++) {
            if(view[i].ant != null && !view[i].ant.friend && view[i].ant.type == 5) {
                if(view[i].ant.food > 10 || view[i].ant.food == 0)
                    cont = true;
                else
                    cont = false;
            }
        }
    }
    //== End guesswork ==//
    if(cont) {
        ret = highwayRobbery();
        if(view[4].ant.type == 1) {
            //try to repair
            var curIndex = HIGHWAY_COLORS.indexOf(view[4].color);
            var prvCol = HIGHWAY_COLORS[(curIndex+1)%HIGHWAY_COLORS.length];
            var nxtCol1 = HIGHWAY_COLORS[(curIndex+HIGHWAY_COLORS.length-1)%HIGHWAY_COLORS.length];
            var nxtCol2 = HIGHWAY_COLORS[(curIndex+HIGHWAY_COLORS.length-2)%HIGHWAY_COLORS.length];
            var nxtCol3 = HIGHWAY_COLORS[(curIndex+HIGHWAY_COLORS.length-3)%HIGHWAY_COLORS.length];
            var prevAt = -1;
            for(var i=0;i<9;i++) {
                if(i%2 == 1 && view[i].color == prvCol && view[deRotate(i,1)].color == nxtCol1 && view[deRotate(i,-1)].color == nxtCol1) prevAt = i;
            }
            if(prevAt >= 0) {
                // yep, brute force it. Because I'm lazy.
                var goNxt = 8-prevAt;
                if(view[deRotate(goNxt,1)].color == nxtCol3 && view[deRotate(goNxt,-1)].color == prvCol) ret = {cell:goNxt};
                else if(view[deRotate(goNxt,1)].color == prvCol && view[deRotate(goNxt,-1)].color == nxtCol3) ret = {cell:goNxt};
                else if(view[goNxt].color != nxtCol1) ret = {cell:goNxt,color:nxtCol1};
                else if(view[deRotate(goNxt,2)].color != nxtCol2) ret = {cell:deRotate(goNxt,2),color:nxtCol2};
                else if(view[deRotate(goNxt,-2)].color != nxtCol2) ret = {cell:deRotate(goNxt,-2),color:nxtCol2};
                else if(view[deRotate(goNxt,1)].color != nxtCol3) ret = {cell:deRotate(goNxt,1),color:nxtCol3};
                else if(view[deRotate(goNxt,-1)].color != nxtCol3) ret = {cell:deRotate(goNxt,-1),color:nxtCol3};
                else ret = {cell:goNxt};
                ret = sanityCheck(ret);
                return ret;
            }
        }
        if(view[4].ant.type == 5 && isHighwayCenter()) {
            if(ret.cell >= 0) {
                ret = {cell:8-ret.cell};
                if(view[4].color == SPAWN && (view[4].ant.food > 90 || view[4].ant.food % 7 == 0) && getHighestWorker() == 0 && (view[4].ant.food < 140 || view[4].ant.food % 9 == 0) && view[0].color == 2 && view[4].ant.food > 50 && view[4].ant.food < 200) {
            //fine
                    if(view[4].ant.food % 10 < 5)
                        ret = {cell:deRotate(ret.cell,3),type:3};
                }
                if(view[ret.cell].ant != null && !view[ret.cell].ant.friend && view[ret.cell].ant.food == 0 && view[4].ant.food > 0) {
                    if(view[deRotate(ret.cell,1)].ant == null)
                        ret = {cell:deRotate(ret.cell,1),type:3};
                    if(view[deRotate(ret.cell,-1)].ant == null)
                        ret = {cell:deRotate(ret.cell,1),type:3};
                }
            }
            for(var i=0;i<9;i++) {
                if(view[i].ant != null && !view[i].ant.friend && view[i].ant.type == 5) {
                    ret = {cell:8-i};
                }
            }
        }
        if(ret.cell >= 0) {
            for(var i=0;i<9;i++) {
                if(view[i].ant != null && !view[i].ant.friend && view[i].ant.type == 5) {
                    var rr = basicHighwayMove();
                    if(rr.cell >= 0 && view[4].ant.type != 5)
                        ret = {cell:deRotate(rr.cell,-2)};
                }
            }
            if(view[ret.cell].ant != null) {
                var n = HIGHWAY_COLORS.indexOf(view[4].color) + 1;
                var nextMove = HIGHWAY_COLORS[n % HIGHWAY_COLORS.length];
                for(var i=0;i<9;i++) {
                    if(view[i].color == nextMove) {
                        if(view[i].ant == null) {
                            ret = {cell:i};
                            break;
                        }
                    }
                }
                if(view[4].ant.type == 5) ret = {cell:8-ret.cell};
            }
        }
        if(view[4].ant.type == 5) {
            var foodedEnemy = false;
            for(var i=0;i<9;i++) {
                if(getNumWorkers(3) >= 2) break;
                if(i != 4 && view[i].ant != null && view[i].ant.type == 5 && view[i].ant.food > 25) {
                    if(view[deRotate(i,1)].ant == null) {
                        ret = {cell:deRotate(i,1),type:3};
                    }
                    else if(view[deRotate(i,-1)].ant == null) {
                        ret = {cell:deRotate(i,-1),type:3};
                    }
                    else if(i%2 == 1 && view[deRotate(i,2)].ant == null) {
                        ret = {cell:deRotate(i,2),type:3};
                    }
                    else if(i%2 == 1 && view[deRotate(i,-2)].ant == null) {
                        ret = {cell:deRotate(i,-2),type:3};
                    }
                }
                if(view[i].ant != null && !view[i].ant.friend && view[i].ant.type == 3 && view[8-i].ant == null) {
                    if(i == ret.cell) {
                        ret = {cell:deRotate(i,1)}
                    }
                    else {
                        return {cell:8-i};
                    }
                }
                if(view[i].ant != null && !view[i].ant.friend && view[i].ant.food == 0) {
                    foodedEnemy = true;
                }
            }
        }
        var numAnts = 0;
        for(var i=0;i<9;i++) {
            if(view[i].ant != null)
                numAnts++;
        }
        if(numAnts > 2 && sanityCheck(ret).cell == 4) {
            ret = {cell:findOpenSpace(0,1)};
        }
        if(view[4].ant.type == 3) {
            if(getNumWorkers(5) > 0) {
                for(var i=0;i<9;i++) {
                    if(view[i].ant != null && !view[i].ant.friend && view[i].ant.type == 5) {
                        ret = {cell:4};
                    }
                }
            }
        }
        if(view[4].ant.type == 4 && getNumWorkers(1) && isHighwayCenter()) {
            var workerPos = findWorker(1);
            for(var i=0;i<9;i++) {
                if(!areAdjacent(i,workerPos)) ret = {cell:i};
            }
        }
        if(ret.cell == -1) {
            if(isHighwayCenter()) {
                for(var i=0;i<9;i++) {
                    var p1 = deRotate(i,3);
                    var p2 = deRotate(i,-3);
                    if(view[i].color == view[p1].color && view[i].color == view[p2].color) {
                        ret = {cell:8-i};
                    }
                }
                if(view[4].ant.type == 1 || view[4].ant.type == 5) {
                    ret = {cell:8-ret.cell};
                }
            }
        }
        if(ret.cell >= 0)
            return sanityCheck(ret);
    }
}

switch(view[4].ant.type) {
    case 5:
        ret = doQueen();
        break;
    case 1:
    case 2:
        ret = doSweep();
        break;
    case 3:
    case 4:
        ret = doGuide();
        break;
    default:
        break;
}
//basic sanity check
ret = sanityCheck(ret);
return ret;

function sanityCheck(ret) {
    if(!ret || ret.cell < 0 || ret.cell > 8) {
        return {cell:4};
    }
    if(ret.color) {
        return ret;
    }
    if((ret.cell != 4 && view[ret.cell].ant != null) || (view[ret.cell].food > 0 && (view[4].ant.food > 0 && view[4].ant.type < 5))) {
        return {cell:4};
    }
    if(ret.type && (view[ret.cell].ant != null || view[ret.cell].food > 0 || view[4].ant.food == 0 || view[4].ant.type < 5)) {
        return {cell:4};
    }
    return ret;
}

function doQueen() {
    if((view[4].ant.food == SPAWN_MIN || (view[4].ant.food >= SPAWN_MIN && view[4].ant.food < FOOD_THRESHOLD && (view[4].ant.food % 3 == 1 || isOnHighway()))) && getHighestWorker() <= 1 ) {
        //prep for first ant
        var s0 = view[0].ant;
        var s1 = view[1].ant;
        var s2 = view[2].ant;
        var s3 = view[3].ant;
        var s5 = view[5].ant;
        var s6 = view[6].ant;
        var s7 = view[7].ant;
        var s8 = view[8].ant;
        var nullCount = 0 + (s0 == null?1:0) + (s1 == null?1:0) + (s2 == null?1:0) + (s3 == null?1:0) + (s5 == null?1:0) + (s6 == null?1:0) + (s7 == null?1:0) + (s8 == null?1:0);
        var nullCount2 = 0 + (s0 == null || s0.friend?1:0) + (s1 == null || s1.friend?1:0) + (s2 == null || s2.friend?1:0) + (s3 == null || s3.friend?1:0) + (s5 == null || s5.friend?1:0) + (s6 == null || s6.friend?1:0) + (s7 == null || s7.friend?1:0) + (s8 == null || s8.friend?1:0);
        if(nullCount >= 7 && nullCount2 >= 8 && view[1].food == 0 && view[3].food == 0 && view[5].food == 0 && view[7].food == 0) {
            var high = getHighestWorker();
            if (high <= 1 && view[4].color != SPAWN && !isOnHighway()) {
                // 50% chance of delaying the respawn by 1 additional move away from where we exploded
                // reduces the chance of a second, immediate explosion
                var pos1 = findWorker(1);
                if(findFirstTrail() < 2 && view[4].ant.food > SPAWN_MIN+1 && pos1 < 0) return foreverAlone();
                if(pos1 >= 0) {
                    var space = deRotate(pos1,2);
                    if(view[space].ant != null) return {cell:findOpenSpace(0,1)};
                }
                return {cell:4,color:SPAWN};
            }
            //spawn first ant
            else if(view[4].color == SPAWN) {
                var pos1 = findWorker(1);
                if(pos1 < 0)  {
                    pos1 = findFirstTrail();
                    if(pos1 % 2 == 0) pos1 = deRotate(pos1,1);
                    else pos1 = deRotate(pos1,4);
                }
                var space = findOpenSpace(pos1,2);
                var high = getHighestWorker();
                if(space < 0) return {cell:4,color:TRAIL}
                if(high == 0) { //no workers
                    return {cell:space,type:1};
                }
                else if(high < 4) { //1 worker of type:high
                    return {cell:space,type:high+1};
                }
                else { //1 worker of type 4
                    //we have all workers, skip!
                }
            }
        }
        else {
            return foreverAlone();
        }
    }
    else if(view[4].ant.food == 1 && getHighestWorker() == 0 ) {
        var space = findOpenSpace(1,2);
        return {cell:space,type:1};
    }
    else if(view[4].ant.food >= 1 && getHighestWorker() < 4 && findWorker(1) >= 0) {
        //spawn remaining ants
        if(view[4].color == SPAWN && !isHighwayCenter()) {
            var pos1 = findWorker(getHighestWorker());
            var space = deRotate(pos1,2);
            var high = getHighestWorker();
            if(space < 0 || view[space].ant != null) return {cell:findOpenSpace(0,1)};
            if(high == 0) { //no workers
                return {cell:space,type:1};
            }
            else if(high < 4) { //1 worker of type:high
                return {cell:space,type:high+1};
            }
            else { //1 worker of type 4
                //we have all workers, skip!
            }
        }
    }
    if(view[4].color == SPAWN && getNumWorkers(3) == 1 && getNumWorkers(4) == 1) {
        var one = getNumWorkers(1);
        var two = getNumWorkers(2);
        if((one ^ two) == 1 && (findWorker(1) % 2 == 0 || findWorker(2) % 2 == 0))
            return {cell:4,color:1};
    }
    if(getNumWorkers(1) == 0 && getNumWorkers(2) == 0) {
        if(getNumWorkers(4) == 1 && getNumWorkers(3) == 0) {
            var pos4 = findWorker(4);
            if(view[deRotate(pos4,1)].ant == null && view[deRotate(pos4,2)].ant == null && findWorker(4) % 2 == 1) {
                //finish rotate with only one glider arm
                return {cell:4};
            }
        }
        return foreverAlone();
    }
    else if(getNumWorkers(1) >= 1 && getNumWorkers(2) >= 1 && getNumWorkers(3) >= 1 && getNumWorkers(4) >= 1) {
        if(view[4].color != 2 && findWorker(1)%2 == 1 && findWorker(2)%2 == 1) {
            return {cell:4,color:TRAIL};
        }
        //move diagonally
        var pos = findWorker(4);
        pos = deRotate(pos,1);
        var checkpos = view[deRotate(pos,4)];
        if(checkpos.ant != null && checkpos.ant.friend) {
            if(checkpos.ant.type == 2)
                return {cell:4};
            if(checkpos.ant.type == 1)
                return {cell:4};
        }
        if(view[pos].ant) return {cell:4,color:1};
        return {cell:pos};
    }
    else {
        var pos = findWorker(4);
        if(pos < 0) {
            //if gliding along with only a buddy
            pos = findWorker(1);
            if(pos >= 0 && view[deRotate(pos,2)].food > 0 && view[deRotate(pos,1)].food == 0) {
                return {cell:4};
            }
        }
        if(pos < 0) {
            var s1 = view[1].ant;
            var s3 = view[3].ant;
            var s5 = view[5].ant;
            var s7 = view[7].ant;
            //return {cell:999}
            if(s1 == null) {
                if(s3 == null) {
                    return {cell:0};
                }
                if(s5 == null) {
                    return {cell:2};
                }
            }
            if(s7 == null) {
                if(s3 == null) {
                    return {cell:6};
                }
                if(s5 == null) {
                    return {cell:8};
                }
            }
            return {cell:4};
        }
        pos = deRotate(pos,1);
        var checkpos1 = view[pos];
        for(var i=0;i<9;i++) {
            if(i != 4 && view[i].ant != null && view[i].ant.type == 5 && view[i].ant.food > 2) {
                if(i%2==0) {
                    if(view[deRotate(i,1)].ant == null) return {cell:deRotate(i,1),type:3};
                    if(view[deRotate(i,-1)].ant == null) return {cell:deRotate(i,-1),type:3};
                }
                else {
                    if(view[deRotate(i,1)].ant == null) return {cell:deRotate(i,1),type:3};
                    if(view[deRotate(i,-1)].ant == null) return {cell:deRotate(i,-1),type:3};
                    if(view[deRotate(i,2)].ant == null) return {cell:deRotate(i,2),type:3};
                    if(view[deRotate(i,-2)].ant == null) return {cell:deRotate(i,-2),type:3};
                }
                return {cell:4};
            }
        }
        if(checkpos1.ant != null && view[deRotate(pos,1)].ant != null && !view[deRotate(pos,1)].ant.friend) {
            return foreverAlone();
        }

        var checkpos2 = view[deRotate(pos,4)];
        var checkpos3 = view[deRotate(checkpos,1)];
        if(checkpos1.ant != null && checkpos1.ant.friend && checkpos1.ant.type == 1 && checkpos2.ant != null && checkpos2.ant.friend && checkpos2.ant.type == 2 && checkpos3.ant != null && checkpos3.ant.friend && checkpos3.ant.type == 3) {
            //move out of spawn orientation
            return {cell:4};
        }
        if(view[pos].ant != null) {
            if(checkpos2.ant == null && checkpos1.ant == null) {
                return {cell:8-pos};
            }
            if(!view[pos].ant.friend) {
                return foreverAlone();
            }
            if(view[4].color == TRAIL) return foreverAlone();
            return {cell:4,color:TRAIL};
        }
        if(8 - findWorker(3) == findWorker(4)) {
            //finish rotate to the right
            return {cell:4};
        }
        if((view[deRotate(pos,1)].food > 0 || view[deRotate(pos,2)].food > 0) && view[deRotate(pos,1)].ant == null && view[4].color != TRAIL) {
            if(findWorker(1) < 0 || view[deRotate(findWorker(1),1)].food == 0) {
                return {cell:4};
            }
        }
        return {cell:pos};
    }
    return {cell:100+view[4].ant.type}; //oh god
}

//guides sit next to the queen
function doGuide() {
    var queenPos = findWorker(5);
    var ty = view[4].ant.type==3?2:1;
    var dir = view[4].ant.type==3?1:-1;
    if(queenPos >= 0 && queenPos%2 == 1 && view[queenPos].color == SPAWN) {
        if(view[deRotate(queenPos,dir*2)].ant == null) {
            return {cell:4};
        }
    }
    if(queenPos < 0 || findWorker(ty) < 0) {
        if(findWorker(ty) >= 0 && view[0].color != IDLE) return {cell:0,color:IDLE}
        return firebreak();
    }
    var checkpos = view[deRotate(queenPos,-2*dir)];
    if(view[4].ant.type==4 && checkpos.ant != null && checkpos.ant.friend && checkpos.ant.type == 1) {
        //attempt rotate
        return {cell:deRotate(queenPos,-dir)};
    }
    checkpos = view[deRotate(queenPos,4)];
    if(checkpos.ant != null && checkpos.ant.friend && checkpos.ant.type == ty) {
        //attempt rotate
        if(getNumWorkers(ty) == 1) {
            return {cell:4};
        }
    }
    var pos = deRotate(queenPos,dir);
    if(pos >= 0 && view[4].ant.type==3 && findWorker(4) < 0) {
        //wait for rotate
        if(view[4].color == TRAIL) {
            return {cell:4};
        }
    }
    if(pos >= 0 && findWorker(2) >= 0 && view[deRotate(findWorker(2),1)].ant != null) {
        //rotate
        return {cell:4,color:TRAIL};
    }
    if(pos < 0) pos = 4;
    else if(view[pos].ant != null) return {cell:deRotate(queenPos,4)};
    if(pos == 4 && view[queenPos].color == TRAIL) return {cell:queenPos,color:1};
    return {cell:pos};
}

//sweepers sit next to guides
function doSweep() {
    var queenPos = findWorker(5);
    var followType = view[4].ant.type==1?4:3;
    var pos = findWorker(followType);
    if(pos % 2 == 0 && getNumWorkers(followType) > 1) {
        //if there's more than one worker #4, we want to use the best one
        for(var i=pos+1;i<9;i++) {
            if(i != 4 && view[i].ant != null) {
                if(view[i].ant.friend && view[i].ant.type == followType) {
                    pos = i;
                    break;
                }
            }
        }
    }
    if(queenPos >= 0 && queenPos%2 == 1 && view[queenPos].color == SPAWN) {
        var p = findWorker(view[4].ant.type);
        if(p >= 0 && (deRotate(p,1) == queenPos || deRotate(p,-1) == queenPos)) {
            return {cell:8-queenPos};
        }
        return {cell:4};
    }
    if(queenPos >= 0 && pos < 0) {
        //if Worker #1 is the only ant besides the queen:
        //TODO
    //good
        if(view[queenPos].ant.food <= SPAWN_MIN || !(view[queenPos].ant.food < FOOD_THRESHOLD && view[queenPos].ant.food % 3 == 1 && !isOnHighway())) {
            var go = deRotate(queenPos,-1);
            if((view[deRotate(queenPos,-2)].food > 0 || view[deRotate(queenPos,-3)].food > 0 || (queenPos %2 == 1 && view[deRotate(queenPos,-3)].food > 0)) && view[go].food == 0) {
                go = deRotate(queenPos,2);
                //return {cell:4};
            }
            return {cell:go};
        }
        else if(view[queenPos].ant.food < FOOD_THRESHOLD && view[queenPos].ant.food % 3 == 1) {
            return {cell:4};
        }
    }
    if(queenPos >= 0) {
        var dir = view[4].ant.type==1?1:-1;
        //var checkpos = view[deRotate(pos,-dir)];
        var moveTo = deRotate(pos,dir);
        if(moveTo >= 0 && view[moveTo].ant != null && view[moveTo].ant.friend && view[moveTo].ant.type == 5) {
            moveTo = deRotate(pos,-dir);
        }
        if(view[4].ant.type == 2 && findWorker(1) < 0 && view[queenPos].color != TRAIL) {
            moveTo = 4;
        }
        return {cell:moveTo};
    }
    else {
        if(pos < 0) return {cell:4}; //firebreak();
        var dir = view[4].ant.type==1?-1:1;
        var moveTo = deRotate(pos,dir);
        if(view[4].ant.food > 0 && view[moveTo].food > 0) {
            //have food, attempt to give to queen
            moveTo = deRotate(pos,-dir);
        }
        if(view[4].ant.type==1 && pos >= 0 && (view[deRotate(pos,dir*2)].food > 0 || view[deRotate(pos,dir*3)].food > 0)) {
            //attempt rotate
            moveTo = deRotate(pos,-dir);
        }
        if(view[4].ant.type==2 && pos >= 0 && (view[deRotate(pos,dir*2)].food > 0 || view[deRotate(pos,dir*3)].food > 0)) {
            //attempt rotate
            moveTo = deRotate(pos,-dir);
        }
        if(moveTo >= 0 && view[moveTo].ant != null && view[moveTo].ant.type == 5) {
            if(view[moveTo].ant.friend)
                moveTo = deRotate(moveTo,dir*2);
            else
                moveTo = deRotate(pos,-dir);
        }
        return {cell:moveTo};
    }
    return {cell:100+view[4].ant.type};//oh god
}

function foreverAlone() {
    var s0 = view[0].ant;
    var s1 = view[1].ant;
    var s2 = view[2].ant;
    var s3 = view[3].ant;
    var s5 = view[5].ant;
    var s6 = view[6].ant;
    var s7 = view[7].ant;
    var s8 = view[8].ant;
    //good
    if(!(s0 == null && s1 == null && s2 == null && s3 == null && s5 == null && s6 == null && s7 == null && s8 == null) && view[4].color == TRAIL) {
        if (view[0].color == TRAIL && !view[8].ant && view[8].color != TRAIL) return {cell: 8};
        else if (view[2].color == TRAIL && !view[6].ant && view[6].color != TRAIL) return {cell: 6};
        else if (view[6].color == TRAIL && !view[2].ant && view[2].color != TRAIL) return {cell: 2};
        else if (view[8].color == TRAIL && !view[0].ant && view[0].color != TRAIL) return {cell: 0};
        //Can't find color, or path is blocked? try diagonals regardless of color
        else if (!view[0].ant) return {cell: 0};
        else if (!view[2].ant) return {cell: 2};
        else if (!view[6].ant) return {cell: 6};
        else if (!view[8].ant) return {cell: 8};
        //Everything else failed? Stay put.
        else return {cell: 4};
    }
    //good
    if (view[4].color == TRAIL) { //If on colored square, try to move
        var totGreen = 0;
        for (var i = 0; i < 9; i++) { //Look for food
            if (view[i].food) {
                return {cell: i};
            }
            if(view[i].color == TRAIL) totGreen++;
        }
        var ret = getTrailMove();
        if(view[deRotate(ret.cell,1)].color == TRAIL && totGreen <= 4) ret.cell = deRotate(ret.cell,-1);
        else if(view[deRotate(ret.cell,-1)].color == TRAIL && totGreen <= 4) ret.cell = deRotate(ret.cell,1);
        return ret;
    } else { //If not on colored square, look for food, or set current color to 2.
        for (var i = 0; i < 9; i++) { //Look for enemies
            if (i != 4 && view[i].ant != null && !view[i].ant.friend) {
                var r = findOpenSpace(8-i,1);
                if(view[r].color == TRAIL) r = deRotate(r,1);
                return {cell: r};
            }
        }
        return {cell: 4, color:TRAIL};
    }
}

function getTrailMove() {
    if (view[0].color == TRAIL && !view[8].ant && view[8].color != TRAIL) return {cell: 8};
    else if (view[2].color == TRAIL && !view[6].ant && view[6].color != TRAIL) return {cell: 6};
    else if (view[6].color == TRAIL && !view[2].ant && view[2].color != TRAIL) return {cell: 2};
    else if (view[8].color == TRAIL && !view[0].ant && view[0].color != TRAIL) return {cell: 0};
    //Can't find color, or path is blocked? try diagonals regardless of color
    else if (!view[0].ant) return {cell: 0};
    else if (!view[2].ant) return {cell: 2};
    else if (!view[6].ant) return {cell: 6};
    else if (!view[8].ant) return {cell: 8};
    //Everything else failed? Stay put.
    else return {cell: 4};
}

function firebreak() {
    var ret = -1;
    if(findWorker(5) >= 0) {
        return {cell:8-findWorker(5)};
    }
    if(view[4].color != 5) {
        var myView = [0,0,0,0,0,0,0,0,0]
        for(var i=0; i < 9; i++) {
            myView[i] = view[i].color
            if(view[4].ant.food > 0 && view[i].food > 0) {
                myView[i] = 8;
            }
            if(view[i].ant != null && !view[i].ant.friend) return {cell:findOpenSpace(deRotate(i,2),1)};
        }
        var ret = clearAhead(myView);
        if(ret == null)
            return {cell:4,color:5};
        else {
            if(!(view[ret.cell].ant != null && view[ret.cell].ant.friend == false) && (view[4].ant.food == 0 || view[ret.cell].food == 0))
                return ret;
            return {cell:4,color:5};
        }
    }
    if(view[1].color == 5 && view[3].color == 5 && view[5].color == 5 && view[7].color == 5) {
        if(view[0].color != 8) return {cell:0,color:8};
        if(view[1].color != 8) return {cell:1,color:8};
    }
    if(view[1].color == 5 && view[7].color != 5) ret = {cell:7};
    if(view[3].color == 5 && view[5].color != 5) ret = {cell:5};
    if(view[5].color == 5 && view[3].color != 5) ret = {cell:3};
    if(view[7].color == 5 && view[1].color != 5) ret = {cell:1};
    if(view[1].color != 5 && view[3].color != 5 && view[5].color != 5 && view[7].color != 5) ret = {cell:1};
    if((view[1].color == 5 && view[7].color == 5) || (view[3].color == 5 && view[5].color == 5)) ret = {cell:0};
    var loop = 0;
    while(ret.cell >= 0 && ((view[ret.cell].food > 0 && view[4].ant.food > 0) || view[ret.cell].ant != null) && loop < 9) {
        loop++;
        ret.cell = (ret.cell + 2) % 9;
    }
    if(loop < 9 && ret.cell >= 0) return ret;
    return {cell:4};
}

//7,6,4,2,3
//O7,D2

function highwayRobbery() {
    var move = basicHighwayMove();
    if(move.cell >= 0 && view[move.cell].ant != null) {
        var n = HIGHWAY_COLORS.indexOf(view[4].color) + (view[4].color%2==0?1:HIGHWAY_COLORS.length);
        var nextMove = HIGHWAY_COLORS[n % HIGHWAY_COLORS.length];
        for(var i=0;i<9;i++) {
            if(view[i].color == nextMove) {
                return {cell:i};
            }
        }
    }
    return move;
}

function basicHighwayMove() {
    var isQueen = view[4].ant.type == 5;
    if(isHighwayCenter()) {
        var n = HIGHWAY_COLORS.indexOf(view[4].color) + 1;
        var nextMove = HIGHWAY_COLORS[n % HIGHWAY_COLORS.length];
        for(var i=0;i<9;i++) {
            if(view[i].color == nextMove) {
                if(view[i].ant == null)
                    return {cell:i};
                else {
                    return {cell:deRotate(i,1)};
                }
            }
        }
    }
    else {
        if(view[4].color == 7) {
            //move diagonal to yellow (2)
            for(var i=0;i<9;i++) {
                if(i != 4 && i % 2 == 0 && view[i].color == 2) {
                    return {cell:i};
                }
            }
        }
        else {
            //move orthogonal to blue (7)
            for(var i=0;i<9;i++) {
                if(i % 2 == 1 && view[i].color == 7) {
                    //try ortho yellow first
                    for(var j=0;j<9;j++) {
                        if(j % 2 == 1 && view[j].color == 2 && areAdjacent(i,j))
                            return {cell:j};
                    }
                    return {cell:i};
                }
            }
            //if orthogonal blue doens't exist...
            //...try diagonal to magenta
            for(var i=0;i<9;i++) {
                if(i != 4 && i % 2 == 0 && view[i].color == 3) {
                    return {cell:i};
                }
            }
            if(view[4].color != 2) {
                //...try diagonal blue
                for(var i=0;i<9;i++) {
                    if(i % 2 == 0 && view[i].color == 7)
                        return {cell:i};
                }
            }
            //...and orthogonal yellow
            for(var i=0;i<9;i++) {
                if(i % 2 == 1 && view[i].color == 2)
                    return {cell:i};
            }
        }
        var n = HIGHWAY_COLORS.indexOf(view[4].color) + 1;
        var nextMove = HIGHWAY_COLORS[n % HIGHWAY_COLORS.length];
        for(var i=0;i<9;i++) {
            if(view[i].color == nextMove) {
                return {cell:i};
            }
        }
    }
    return {cell:-1};
}

function isOnHighway() {
    var match = 0;
    var nxt = HIGHWAY_COLORS[(HIGHWAY_COLORS.indexOf(view[4].color)+1) % HIGHWAY_COLORS.length];//4
    var prv = HIGHWAY_COLORS[(HIGHWAY_COLORS.indexOf(view[4].color)+HIGHWAY_COLORS.length-2) % HIGHWAY_COLORS.length];//6
    for(var i=0;i<9;i++) {
        if(HIGHWAY_COLORS.indexOf(view[i].color) >=0 && (i == 4 || view[i].color != view[4].color))
            match++;
    }
    if(match >= 5) {
        //7,6,4,2,3


        if((view[1].color == nxt && view[7].color == prv)||(view[1].color == prv && view[7].color == nxt) || 
            (view[3].color == nxt && view[5].color == prv)||(view[3].color == prv && view[5].color == nxt)) {
            return true;
        }
        if((view[1].color == view[8].color && (view[1].color == nxt || view[1].color == prv))||(view[1].color == view[6].color && (view[1].color == nxt || view[1].color == prv)) || 
            (view[3].color == view[2].color && (view[3].color == nxt || view[3].color == prv))||(view[3].color == view[8].color && (view[3].color == nxt || view[3].color == prv))) {
            return true;
        }
        if((view[0].color == view[7].color && (view[0].color == nxt || view[0].color == prv))||(view[2].color == view[7].color && (view[2].color == nxt || view[2].color == prv)) || 
            (view[0].color == view[5].color && (view[0].color == nxt || view[0].color == prv))||(view[6].color == view[5].color && (view[6].color == nxt || view[6].color == prv))) {
            return true;
        }
        if(isHighwayCenter()) {
            return true;
        }
    }
    return false;
}

function isHighwayCenter() {
    if(HIGHWAY_COLORS.indexOf(view[4].color) >=0 && (((view[0].color != view[8].color || view[2].color != view[6].color) && view[4].ant.type == 1) || (view[0].color != view[8].color && view[2].color != view[6].color))){
        var m1 = view[1].color == view[7].color;
        var m2 = view[2].color == view[8].color;
        var m3 = view[0].color == view[6].color;
        var m4 = view[0].color != 1 && view[2].color != 1;
        if((m1?1:0)+(m2?1:0)+(m3?1:0) >= 2 && m4) {
            if(view[3].color != view[5].color && ((view[2].color != view[5].color && view[8].color != view[5].color) || view[4].ant.type == 1) && ((view[3].color != view[0].color && view[3].color != view[6].color) || view[4].ant.type == 1)) {
                return true;
            }
        }
        m1 = view[3].color == view[5].color;
        m2 = view[0].color == view[2].color;
        m3 = view[6].color == view[8].color;
        m4 = view[0].color != 1 && view[6].color != 1;
    //good
        if((m1?1:0)+(m2?1:0)+(m3?1:0) >= 2 && m4) {
            m1 = view[1].color != view[7].color;
            m2 = (view[0].color != view[1].color && view[1].color != view[2].color);
            m3 = (view[6].color != view[7].color && view[7].color != view[8].color);
            if(m1 && m2 && m3) {
                return true;
            }
            if(view[4].ant.type == 1 && ((m1?1:0)+(m2?1:0)+(m3?1:0)) >= 2) {
                return true;
            }
        }
    }
    return false;
}

function deRotateSide(m, amt) {
    return deRotate(m,amt*2);
}

/**Positive amount is clockwise**/
function deRotate(m, amt) {
    var rotationsCW = [1,2,5,8,7,6,3,0];
    var rotationsCCW = [3,6,7,8,5,2,1,0];
    if(m == 4 || m < 0 || m > 8 || amt == 0) return m;
    if(amt > 0)
        return rotationsCW[(rotationsCW.indexOf(m)+amt)%8];
    amt = -amt;
    return rotationsCCW[(rotationsCCW.indexOf(m)+amt)%8];
}

function areAdjacent(A, B) {
    if(A == 4 || B == 4 || A == B) return true;
    if(A % 2 == 0 && B % 2 == 0) return false;
    if(A % 2 == 1 && B % 2 == 0) return areAdjacent(B,A);
    if(A % 2 == 1 && B % 2 == 1) return !(8-A == B || 8-B == A);
    if(A == 0 && (B == 1 || B == 3)) return true;
    if(A == 2 && (B == 1 || B == 5)) return true;
    if(A == 6 && (B == 3 || B == 7)) return true;
    if(A == 8 && (B == 5 || B == 7)) return true;
    return false;
}

function findFirstTrail() {
    var pos = 0;
    var b = 0;
    while(view[pos].color != TRAIL && b < 8) {
        pos=deRotate(pos,1);
        b++;
    }
    return pos;
}

function clearAhead(sides) {
    var c=0;
    for(var i=0;i<9;i++) {
        if(view[i].color == 5) c++;
        if(view[i].color == 5 && i%2 == 0) c+=10;
    }
    if(c == 2) {
        if(view[0].color == 5 || view[2].color == 5 || view[6].color == 5 || view[8].color == 5) {
            return {cell:4,color:5};
        }
        if(view[0].ant == null)
            return {cell:0};
        if(view[2].ant == null)
            return {cell:2};
        if(view[6].ant == null)
            return {cell:6};
        if(view[8].ant == null)
            return {cell:8};
    }
    c = 0;
    sides[4] = 0;
    var toMatch =[{state:[1,1,1,
                          2,0,2,
                          0,1,0]},
                 {state:[0,2,1,
                         1,0,1,
                         0,2,1]},
                 {state:[0,1,0,
                         2,0,2,
                         1,1,1]},
                 {state:[1,2,0,
                         1,0,1,
                         1,2,0]}];
    for(var m=0;m<4;m++) {
        var score=0;
        for(var j=0;j<9;j++) {
            if(j!=4) {
                if(sides[j] == 5 && toMatch[m].state[j] == 1) {
                    score++;
                }
                if(sides[j] != 5 && (toMatch[m].state[j] == 0 || toMatch[m].state[j] == 2)) {
                    score++;
                }
                if(sides[j] == 5 && toMatch[m].state[j] == 2) {
                    score--;
                }
            }
        }
        if(score >= 6) {
            var clearOrder=[1,0,2];
            for(var r=0;r<clearOrder.length;r++) {
                var s = deRotateSide(clearOrder[r],m);
                if(view[s].color == 5) {
                    if(view[s].ant == null)
                        return {cell:s,color:8};
                    else
                        return {cell:4};
                }
            }
        }
    }
    return null;
}

function findOpenSpace(pos, dir) {
    if(pos > 8 || pos < 0) return pos;
    var b = 0;
    while(view[pos].ant != null && b < 8) {
        pos=deRotate(pos,dir);
        b++;
    }
    return pos;
}

function getHighestWorker() {
    var r=0;
    for(var i=0;i<9;i++) {
        if(i != 4 && view[i].ant != null) {
            if(view[i].ant.friend && view[i].ant.type > r) r = view[i].ant.type;
        }
    }
    return r;
}

function getNumWorkers(type) {
    var r=0;
    for(var i=0;i<9;i++) {
        if(i != 4 && view[i].ant != null) {
            if(view[i].ant.friend && view[i].ant.type == type) r++;
        }
    }
    return r;
}

function findWorker(type) {
    for(var i=0;i<9;i++) {
        if(i != 4 && view[i].ant != null) {
            if(view[i].ant.friend && view[i].ant.type == type) return i;
        }
    }
    return -1;
}

422% সম্পূর্ণ 422% সম্পূর্ণ হয়েছে
কারণ আপডেট 4/22-এ ছিল এই রসিকতাটি খুব দীর্ঘ হয়েছে

অবৈধ পদক্ষেপ শনাক্তকরণ: চেক
টার্নিং:
ট্রিমিং হওয়ার সাথে সাথে রেসপন্সিং কর্মীদের চেক করুন: বেশিরভাগ চেক
করুন অন্যান্য পিঁপড়ে খাওয়া খাবার আটকে থাকা এড়িয়ে চলা: ...

আপডেট 8/1

প্রায়শই দ্বিগুণ হয়ে যায়, ফলস্বরূপ ~ 15% আরও খাদ্য সংগ্রহ করা হয়

আপডেট 8/2

আটকে যাওয়া শক্তিশালী বনাম যোগ করা।

আপডেট 9/9

রেসন শ্রমিকদের 2 এবং 3 কোড যুক্ত করা হয়েছে যখন সেই বাহুটি অনুপস্থিত থাকে।

আপডেট 9/12

পূর্ববর্তী আপডেটটি ফিরিয়ে দিন। গ্লাইডারটি সদ্য প্রসারিত বাহুটি নিয়ে এগিয়ে যেতে পারত, কিন্তু কর্মীরা ঘুরিয়ে দেওয়ার চেষ্টা করার সময় শৃঙ্খলাবদ্ধ হয়ে কাজ করত এবং এটি ফুরিয়ে যায়।

এটি সংশোধন করা ছাড়াও, রেসপ্যান-অল-ওয়ার্কার কোডকে আরও বৈষম্যমূলক রূপে পুনর্গঠিত করে: এটি নিকটস্থ "হারানো" কর্মীদের সাথে সংঘর্ষ হ্রাস করার পাশাপাশি the০ টি খাবারের উপরে রেসপনকে সম্পূর্ণরূপে রোধ করে: 60 টি খাদ্য শীর্ষ 3 স্পটে স্কোর করার জন্য যথেষ্ট বেশিরভাগ সময়, যা কর্মীদের 4 টি খাবার ব্যয় করার চেয়ে ভাল যা সংক্ষিপ্ত ক্রমে আবার ছিটকে যাওয়ার সম্ভাবনা রয়েছে: খুব কম পিঁপড়িরাই 60 এরও বেশি স্কোর করে যখন তারা যাইহোক গ্লাইডারের ক্ষমতা ছাড়িয়ে যায়- হারিয়ে যাওয়া শ্রমিকদের অন্যান্য পিঁপড়ার ট্রেসগুলি গণ্ডগোলের বিষয়ে চালানোর জন্য কিছু কোড যুক্ত করেছে।

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

একটি সংজ্ঞায়িত ভেরিয়েবল ব্যবহারের জন্য রঙটি পুনরায় কনফিগার করা হয়েছে এবং রেলের রেল সিস্টেমে মাইনারগুলিতে "আটকা পড়া" এড়াতে ট্রেল রঙটি হলুদ থেকে সবুজ থেকে পরিবর্তিত হয়েছে (একক রানী ক্রমাগত পুনঃনির্দেশিত হবে)।

নতুন কোডটির কিছুটা আমার অন্যান্য এন্ট্রি, ব্ল্যাক হোল থেকে অন্তর্ভুক্ত করা হয়েছে ।

আপডেট 9/13

স্প্যান-ওরিয়েন্টেশন কোডে মুভ-আউট-অফ-স্প্যান-ওরিয়েন্টেশন কোডটিতে একটি বাগ ফিক্স করা হয়েছে। বেশ কয়েকটি 2এস হ্যান্ডেল পেয়েছে এস এ রূপান্তরিত TRAIL

আপডেট 1/21

  • গ্লাইডার এখন বাম দিকে ঘুরতে পারে (অ্যানিমেশন মুলতুবি)।
  • খাবার পাওয়া মাত্রই এক শ্রমিককে ছড়িয়ে দিয়ে প্রাথমিক গেমটি ত্বরান্বিত করে।
  • ওয়ান-আর্ম গ্লাইডিং উভয় দিককেও ঘুরিয়ে দিতে পারে।
  • "রেসপন শ্রমিকদের না" দোরগোড়ায় উত্থাপন
  • "রেসপান করার চেষ্টা করে এবং ব্যর্থ হওয়াতে খাবারটি অপচয় করবেন না" থেকে কমিয়ে আনা %5হয়েছে%3

আপডেট 1/25

  • কিছু ম্যাচে কয়েক পয়েন্ট দক্ষতা বাড়িয়ে কিছু অচলাবস্থার পরিস্থিতি স্থির করে।

আপডেট 2/20

  • 5-এবং 3-পিঁপড়া কনফিগারেশন উভয়ই আরও স্থিতিশীল করে একাধিক এজ-কেস বিস্ফোরণ / অচলাবস্থার পরিস্থিতি সম্বোধন করেছেন। খাবারের বেশ কয়েকটি ব্যবস্থার ফলস্বরূপ গ্লাইডার বিভ্রান্ত হয়ে পড়ে এবং তা ডেডলকিং হয়ে যায় (বারবার পিছনে পিছনে ঘোরানো) বা বিস্ফোরিত হতে পারে।
    • একটি বিস্ফোরণ ছিল একটি ঘূর্ণনের শেষ ধাপের সময় সুইপার পিঁপড়ে খাবারের দিকে চলে যাওয়ার পরে, ধরে নেওয়া "ছি ছি, আমার কাছে খাবার আছে, রানীর কাছে পৌঁছে দেওয়ার জন্য নিজেকে ত্যাগ করি" যখন এটির প্রয়োজন হয়নি (মানক পদক্ষেপটি বৈধ ছিল )।
    • একটি বিস্ফোরণ ছিল রানির অধীনে থাকা কোষটির ফলাফল ইতিমধ্যে TRAIL(সবুজ), যার ফলে রানীর একটি "স্থির থাকুন" চালিত হয়েছিল (ফ্যালব্যাক দ্বারা foreverAlone()রানীকে দল থেকে দূরে সরিয়ে নিয়ে যাওয়ার ব্যবস্থা করা হয়েছিল a একটি স্টেশনারি গার্ডকে সংশোধন করে এটিকে সংশোধন করা হয়েছে রানী তার পদক্ষেপ নেওয়ার ঠিক আগে রানির ঘরের রঙ।
    • রানীর কোড ঠিক করার চেয়ে আরও কাঙ্ক্ষিত, কারণ এটি আমাদের ডেইলকগুলি থেকে বাঁচতে দেয় যা অন্যথায় ফ্যালব্যাক ধরে রেখে foreverAlone(), রানিকে আউট করে, এমনকি যদি আমরা তার ডানা বাঁচাতে না পারি তবেই ঘটতে পারে ।
  • foreverAlone()রানির অধীনে ঘর TRAIL(সবুজ) থাকলে কেবলমাত্র খাবারের দিকে সরানোর জন্য ফাংশন আপডেট করা হয় । খুব সামান্য দক্ষতা ক্ষতি।
  • গ্লাইডার পুনর্নির্মাণ মোরবেটার একটি সংলগ্ন সবুজ কক্ষের সন্ধান করে, এর পরিবর্তন findFirstYellow()এবং এর ব্যবহার। এটি পূর্বের বুলেট ফলাফলের সাথে একত্রে পূর্বে দেখা কোষগুলি এবং / অথবা সাম্প্রতিক বিস্ফোরণের ঘটনাকে আরও ভালভাবে এড়াতে পারে: একটি নবগঠিত গ্লাইডার - বেশিরভাগ ক্ষেত্রেই - রানীর আগমনকে ধরে না রেখে একটি দিকে সরে যাবে will গ্রহনক্ষত্রের নির্দিষ্ট আবক্র পথ।
    • ফাংশনটির নাম বদলে দেওয়া হয়েছে: হলুদ দীর্ঘ, দীর্ঘ সময়ে রানীর ট্রেইলের রঙ নয়।
    • ফাংশন ছিল ভুল একটি উল্টানো যুক্তিবিজ্ঞান চেক কারণে "লেজ প্রথম সেল" লোকেটিং: while ==পরিবর্তেwhile !=

আপডেট 2/25

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

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

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

2, 3 এবং 4 জন শ্রমিক হাইওয়ে রানির উপর ড্রাইভ বাই চুরি করার চেষ্টা করে, তারপরে ফিরে আসে তাদের নিজস্ব রানীতে, যারা শ্রমিকদের উত্সাহিত করার সময় ...

  • তার নিজের কর্মীদের কেউ দেখতে পাচ্ছেন না
  • ম্যাজেন্টায় বসে আছে
  • প্রান্তিকের মধ্যে খাবার রয়েছে (উভয় পক্ষের নরম সীমানা সহ)
  • একটি সাধারণ এলোমেলো দ্বারা পরিবর্তিত

এটি প্রচুর শ্রমিক তৈরি করা এড়াতে (১০০ ডলারে কাজ করে) এবং যখন বোঝা শ্রমিকরা একটি স্ট্রিং ফিরে আসে, সেখানে খাদ্যতালিকাগুলি আয় হয় (নিজের শ্রমিকদের দেখানোর সময় অচেতনার কারণে) অবশেষে শীর্ষদিকের উপরে গ্লাইডারকে ঠেলে দেয় এবং প্রচুর পরিমাণে বিস্তৃত হয় (ব্যাপকভাবে হ্রাস) নতুন কর্মী।

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

আপডেট 3/16

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

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

নাবালিক টুইটগুলি

  • রানী যখন হাইওয়েতে রয়েছে তা সনাক্ত করে তখন আর স্প্যানিং শুরু করার চেষ্টা করে না
  • কুইলির আর কোনও গ্লাইডার ফর্মেশন সম্পূর্ণরূপে সম্পন্ন করার চেষ্টা করছে যা কখনই সম্পূর্ণ হবে না (কোনও শ্রমিক 4 তৈরি করে, শ্রমিক 4 কর্মী 1 দেখবে না, কর্মী 4 সরানো দূরে থাকবে, পুনরাবৃত্তি করবে)
  • হাইওয়ের রঙ চক্রের সাথে কপিরাইট হওয়ার জন্য খাদ্য মডুলোর মানগুলিকে সামঞ্জস্য করে।
  • একটি "আর্ম দিয়ে ফিনিশ রোটেট" স্থির করে যা অচলাবস্থার কারণ হয়ে দাঁড়িয়েছিল
  • মাইনর ফিক্স isOnHighway()চেক
  • তৈরি পিঁপড়েরা হাইওয়েতে যখন অर्थোগোনাল নীল কক্ষে চলে যাওয়ার আগে একটি অর্থোগোনাল হলুদে সরানো হয় (বিচ্ছিন্ন হয়ে যাওয়ার পরে কেন্দ্রটির সন্ধানে 1 টি বার বাঁচায়)।

আপডেট 3/26

আরও ছোট ছোট টুইট।

আপডেট 4/21

মাইনর ফিক্সস।


আলগাভাবে স্টিম্রোলারের উপর ভিত্তি করে ।

একটি হলুদ ট্রেইল রেখে 4 টি খাবার সংগ্রহ করে। একবার এর চারটি খাবার হয়ে গেলে এটি প্রতিটি কর্মীর মধ্যে একটির চারপাশে তৈরি করে produces এরপরে এটি সর্বাধিক খোঁচায় গ্লাইডিং শুরু করে। শীর্ষে অ্যানিমেশনটি স্থানান্তর করতে 1 গেমের মোড় নিতে সময় লাগে: কর্মী 1 প্রথমে উত্পাদিত হওয়ার পরে, রানির সাথে পালা শেষ করার আগে এটি প্রথমে 2, 3 এবং 4 ব্যবহার করে exec টার্নিং অ্যানিমেশনটিতে 2 টি টার্ন লাগবে, সংক্ষিপ্ত বিরতিগুলি যখন রানী সঞ্চালন করে {cell:4}এবং খাবার যখন নড়ে যায় তখন কর্মীরা 3, 4 এবং রানী {cell:4}ক্রমাগত গ্লাইডিংয়ের জন্য প্রস্তুত করার জন্য সঞ্চালন করে।


আমি এই বট ধারণাটি পছন্দ করি
ধ্বংসাত্মক লেবু

1
নিবন্ধন করুন আমি Steamroller / বিদীর্ণকারী ভাবছিলাম এবং নিজেকে বলে মনে করা ", উপর রাখা রাণী গত যায়, নিশ্চয় আমি পেতে পারেন পাঁচটি পিঁপড়ার চমৎকার খেলতে ..." এক টুকরা কাগজ ধরলাম, কিছু চৌকো বন্ধ অর্ধবৃত্তাকার পার্শ্বচিত্রের মূর্তি, এবং তাদের চলন্ত কাছাকাছি শুরু করে। এটি কাজ করে তাই আমি কিছু কোড লিখেছিলাম। প্রান্তের কেসগুলির জন্য অনেকগুলি ত্রুটি পরিচালনা ও বাগ ফিক্সিং করতে হয়েছিল (প্রারম্ভিক বট আটকে যাবে বা এটি করা সম্ভব সমস্ত খাবার গ্রহণ করবে এবং টার্ন অপারেশনটি অনেকগুলি প্রান্তের পরিস্থিতি প্রবর্তন করবে যেখানে এটি গঠন এবং ক্রাশটি ভেঙে দেবে adding )।
ড্র্যাকো 18

@ ট্রাইকোপলাক্স যতক্ষণ না এটি একটি অন্য পিঁপড়ে পড়ে?
ধ্বংসাত্মক লেবু

পুনঃটুইট করুন এটি কমপক্ষে অযোগ্য ঘোষিত হবে না ...
ড্র্যাকো 18

3
@ কেজাং ওহ আমি করেছি। "//
চেষ্টাটি

13

বাতচক্র

এখানে একটি উইন্ডমিল ... লা মনচা (বা লা মঞ্চ থেকে ভ্যাম্পায়ার?) এর লোকটির জন্য অপেক্ষা করছে যারা এটিকে নামিয়ে আনতে চড়ে যাবে।

উইন্ডমিল, খেলার প্রথম দিকের স্তর

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

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

var AJM=1;var ASM=2;var AE=3;var ASF=4;var AQ=5;var RW=true;var EFCO=false;var THC=1;var TH0=0;var TH1=15;var TH2=17;var TH3=67;var TH4=120;var TH5=390;var THX=15;var THFCO1=9;var THFCO2=26;var THFCO3=75;var RM1=7;var RD1=4;var RM2=19;var RD2=THX;var PW=1;var PY=2;var PP=3;var PC=4;var PR=5;var PG=6;var PB=7;var PK=8;var LN=0;var LCLR=PW;var LT=PB;var LLSF=PP;var LA=PP;var LRL0=PC;var LRL1=PG;var LRL2=LRL0;var LRM0=PR;var LRM1=PB;var LRM1_WRP=PK;var LRM2=PG;var LRR0=PG;var LRR1=PW;var LRR1U=PR;var LRR1V=PY;var LRR1X=PK;var LRR2=PY;var LMX_M0=LCLR;var LMX_M1IN=PC;var LMX_M1OUT=PY;var LMX_M2IN=PP;var LMX_M2OUT=PR;var LMX_M3IN=PB;var LMX_M3OUT=PK;var LMS_WRP=PK;var LMR0=PK;var LML1=PY;var LMR2=PR;var LML3=PC;var LMMF=PG;var LMMH=PP;var LG3=PK;var LG4=PR;var LG5=PK;var LG6=PB;var LP0=LCLR;var LPB=PC;var LPG=PY;var LPG1=PR;var LPX=PP;var FALSE_X9=[false,false,false,false,false,false,false,false,false];
var UNDEF_X9=[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined];
var QCPERD=6;var LCL_QC_RESET=LCLR;var LCRQC=[PY,PP,PC,PR,PG,PK];var LCRQCVAL=Array.from(FALSE_X9);var LCRQC_VALUE=Array.from(UNDEF_X9);for (var i=0; i<QCPERD; i++){LCRQCVAL[LCRQC[i]]=true;LCRQC_VALUE[LCRQC[i]]=i;}var SCPERD=7;var LCL_SC_RESET=LCLR;var LCRSC=[PY,PP,PC,PR,PG,PB,PK];var LCRSCVAL=Array.from(FALSE_X9);var LCRSC_VALUE=Array.from(UNDEF_X9);for (i=0; i<SCPERD; i++){LCRSCVAL[LCRSC[i]]=true;LCRSC_VALUE[LCRSC[i]]=i;}var LCRPHR=Array.from(FALSE_X9);LCRPHR[LPG]=true;LCRPHR[LPG1]=true;var LCRPHASES=Array.from(LCRPHR);LCRPHASES[LPX]=true;var LCRGRM1=Array.from(FALSE_X9);LCRGRM1[LRM1]=true;LCRGRM1[LRM1_WRP]=true;var LCRGRM_ALL=Array.from(FALSE_X9);LCRGRM_ALL[LRM0]=true;LCRGRM_ALL[LRM1]=true;LCRGRM_ALL[LRM1_WRP]=true;LCRGRM_ALL[LRM2]=true;var LCRGRR1_OUT=Array.from(FALSE_X9);LCRGRR1_OUT[LRR1V]=true;LCRGRR1_OUT[LRR1X]=true;var LCRGRR1B=Array.from(LCRGRR1_OUT);LCRGRR1B[LRR1U]=true;var LCRGRR1=Array.from(LCRGRR1B);LCRGRR1[LRR1]=true;var LCRMX_IO=Array.from(FALSE_X9);LCRMX_IO[LMX_M1IN]=true;LCRMX_IO[LMX_M1OUT]=true;LCRMX_IO[LMX_M2IN]=true;LCRMX_IO[LMX_M2OUT]=true;LCRMX_IO[LMX_M3IN ]=true;LCRMX_IO[LMX_M3OUT]=true;var LCRMX=Array.from(LCRMX_IO);LCRMX[LMX_M0]=true;var LCRMX_IN=Array.from(FALSE_X9);LCRMX_IN[LMX_M1IN]=true;LCRMX_IN[LMX_M2IN]=true;LCRMX_IN[LMX_M3IN ]=true;var LCRMX_OUT=Array.from(FALSE_X9);LCRMX_OUT[LMX_M1OUT]=true;LCRMX_OUT[LMX_M2OUT]=true;var LCRMM_FOOD=Array.from(FALSE_X9);LCRMM_FOOD[LCLR]=true;LCRMM_FOOD[LMMF]=true;var LCRMM_HOME=Array.from(FALSE_X9);LCRMM_HOME[LCLR]=true;LCRMM_HOME[LMMH]=true;var LCRMS=Array.from(FALSE_X9);LCRMS[LCLR]=true;LCRMS[LMS_WRP]=true;var LCRFRLL0=Array.from(FALSE_X9);LCRFRLL0[LCLR]=true;LCRFRLL0[LMR0]=true;LCRFRLL0[LMR2]=true;LCRFRLL0[LRM0]=true;LCRFRLL0[LRM2]=true;var LCRFRLL1=Array.from(FALSE_X9);LCRFRLL1[LCLR]=true;LCRFRLL1[LMR0]=true;LCRFRLL1[LMR2]=true;LCRFRLL1[LRR0]=true;LCRFRLL1[LRM1]=true;LCRFRLL1[LRR2]=true;var LCRFRLL2=Array.from(FALSE_X9);LCRFRLL2[LCLR]=true;LCRFRLL2[LMR0]=true;LCRFRLL2[LMR2]=true;LCRFRLL2[LRM0]=true;LCRFRLL2[LRR1V]=true;var TN=8;var POSC=4;var NOP={cell:POSC};var AIMU=1;var AIML=3;var AIMR=5;var AIMD=7;var FWD_CELLS=[[ true,true,false,true,true,false,false,false,false ],[ true,true,true,true,true,true,false,false,false ],[ false,true,true,false,true,true,false,false,false ],[ true,true,false,true,true,false,true,true,false ],[ true,true,true,true,true,true,true,true,true ],[ false,true,true,false,true,true,false,true,true ],[ false,false,false,true,true,false,true,true,false ],[ false,false,false,true,true,true,true,true,true ],[ false,false,false,false,true,true,false,true,true ]];var PTNOM=-9;var PTHOME=[LRM0,LRL0,LRM0,LRL0,LN,LRL0,LN,LN,LRM0];var PTGARDEN=[LG6,LG5,LG4,LN,LN,LG3,LN,LRL0,LRL1];var PTFRM0=[LRL1,LRM1,LCRGRR1,LRL0,LRM0,LRR0,LRL2,LRM2,LRR2];var PTFRM1=[LRL2,LRM2,LRR2,LRL1,LCRGRM1,LCRGRR1,LRL0,LRM0,LRR0];var PTFRM2=[LRL0,LRM0,LRR0,LRL2,LRM2,LRR2,LRL1,LCRGRM1,LCRGRR1];var PTGRM0=[LRL1,LCRGRM1,LCRGRR1,LRL0,LRM0,LRR0,LRL2,LRM2,LRR2];var PTGRM1=PTFRM1;var PTGRM2=PTFRM2;var PTGRM2B=[LRL0,LRM0,LRR0,LRL2,LRM2,LRR2,LRL1,LCRGRM1,LCRGRR1B];var PTGRM1_WRP=[LRL2,LRM2,LRR2,LRL1,LRM1_WRP,LRR1X,LRL0,LRM0,LRR0];var PTFRL0=[LCRFRLL1,LRL1,LRM1,LCRFRLL0,LRL0,LRM0,LCRFRLL2,LRL2,LRM2];var PTFRL1=[LCRFRLL2,LRL2,LRM2,LCRFRLL1,LRL1,LCRGRM1,LCRFRLL0,LRL0,LRM0];var PTFRL0H=[LN,LRL1,LRM1,LN,LRL0,LRM0,LN,LN,LN];var PTFRL1G=[LCRFRLL2,LRL2,LRM2,LG3,LRL1,LCRGRM1,LCRPHASES,LRL0,LRM0];var PTFRL2=[LCRFRLL0,LRL0,LRM0,LCRFRLL2,LRL2,LRM2,LCRFRLL1,LRL1,LCRGRM1];var PTGRL0=[LCRFRLL1,LRL1,LCRGRM1,LCRFRLL0,LRL0,LRM0,LCRFRLL2,LRL2,LRM2];var PTGRL1=PTFRL1;var PTGRL2=PTFRL2;var PTGRR0=[LCRGRM1,LCRGRR1,LCLR,LRM0,LRR0,LMR0,LRM2,LRR2,LCRMX];var PTGRR2=[LRM0,LRR0,LMR0,LRM2,LRR2,LCRMX,LCRGRM1,LCRGRR1,LCLR];var PTGRR1=[LRM0,LCRGRM1,LRM2,LRR0,LCRGRR1,LRR2,LMR0,LCLR,LCRMX];var PTMS0R_IN=[LRR0,LRR1U,LRR2,LMR0,LCLR,LCRMX_IN,LCLR,LCLR,LML1];var PTMS0R_OUT=[LRR0,LRR1U,LRR2,LMR0,LCLR,LCRMX_IO,LCLR,LCLR,LML1];var PTMS0R_OUT1=[LRR0,LCRGRR1_OUT,LRR2,LMR0,LCLR,LCRMX,LCLR,LCLR,LML1];var PTMS0=[LCLR,LCRMM_HOME,LML3,LMR0,LCRMM_FOOD,LCLR,LCLR,LCLR,LML1];var PTMS1=[LMR0,LCRMM_HOME,LCLR,LCLR,LCRMM_FOOD,LML1,LMR2,LCLR,LCLR];var PTMS2=[LCLR,LCRMM_HOME,LML1,LMR2,LCRMM_FOOD,LCLR,LCLR,LCLR,LML3];var PTMS3=[LMR2,LCRMM_HOME,LCLR,LCLR,LCRMM_FOOD,LML3,LMR0,LCLR,LCLR];var PTMS1_IN=[LMR0,LCRMM_HOME,LCRMX_IN,LCLR,LCRMM_FOOD,LML1,LMR2,LCLR,LCLR];var PTMS1_IO=[LMR0,LCRMM_HOME,LCRMX_IO,LCLR,LCRMM_FOOD,LML1,LMR2,LCLR,LCLR];var PTMS0_OUT=[LCLR,LCLR,LML3,LMR0,LCLR,LCRMX_IO,LCLR,LCLR,LML1];var PTMS0_WRAPPING=[LCLR,LCRMM_HOME,LML3,LMR0,LCRMM_FOOD,LCRMS,LRL0,LRL1,LRL2];var PTGRL1_WRP=[LMR0,LCLR,LMS_WRP,LRL0,LRL1,LRL2,LRM0,LRM1_WRP,LRM2];var PTMS0FL=[LMMH,LML3,LN,LMMF,LCLR,LN,LCLR,LML1,LN];var PTMS1FL=[LMMH,LCLR,LN,LMMF,LML1,LN,LCLR,LCLR,LN];var PTMS2FL=[LMMH,LML1,LN,LMMF,LCLR,LN,LCLR,LML3,LN];var PTMS3FL=[LMMH,LCLR,LN,LMMF,LML3,LN,LCLR,LCLR,LN];var PTMS0FR=[LN,LCLR,LMMH,LN,LMR0,LMMF,LN,LCLR,LCLR];var PTMS1FR=[LN,LMR0,LMMH,LN,LCLR,LMMF,LN,LMR2,LCLR];var PTMS2FR=[LN,LCLR,LMMH,LN,LMR2,LMMF,LN,LCLR,LCLR];var PTMS3FR=[LN,LMR2,LMMH,LN,LCLR,LMMF,LN,LMR0,LCLR];var CCW=[6,7,8,5,2,1,0,3,6,7,8,5,2,1,0,3,6,7,8,5,2,1];
var xn=-1;var fwdWrong=[];var rearWrong=[];var here=view[POSC];var mC=here.color;var myself=here.ant;var mT=myself.type;var mF=myself.food;var mS=(mT==AE||(mT!=AQ&&mF>0));if (EFCO&&(mT==AQ)){if (mF<=THFCO1){QCPERD=5;} else if (mF<=THFCO2){QCPERD=4;} else if (mF<=THFCO3){QCPERD=5;}}var dOK=[true,true,true,true,true,true,true,true,true];
var uo=true;var sL=[0,0,0,0,0,0,0,0,0];var sD=[0,0,0,0,0,0,0,0,0];var sN=[0,0,0,0,0,0,0,0,0];var sT=[0,0,0,0,0,0,0,0,0];var fdL=0;var fdD=0;var fdT=0;sT[mC]++;for (i=0; i<TN; i+=2){var cell=view[CCW[i]];sD[cell.color]++;sN[cell.color]++;sT[cell.color]++;if (cell.food>0){fdD++;fdT++;if (mS){dOK[CCW[i]]=false;uo=false;}}}for (i=1; i<TN; i+=2){var cell=view[CCW[i]];sL[cell.color]++;sN[cell.color]++;sT[cell.color]++;if (cell.food>0){fdL++;fdT++;if (mS){dOK[CCW[i]]=false;uo=false;}}}var aF=[0,0,0,0,0,0];var aLF=[0,0,0,0,0,0];var aUF=[0,0,0,0,0,0];var fT=0;var mQ=0;var aE=[0,0,0,0,0,0];var aLE=[0,0,0,0,0,0];var aUE=[0,0,0,0,0,0];var eT=0;for (i=0; i<TN; i++){var cell=view[CCW[i]];if (cell.ant){if (cell.ant.friend){aF[cell.ant.type]++;fT++;if (cell.ant.type==AQ){xn=i&6;mQ=i&1;}if (cell.ant.food>0){aLF[cell.ant.type]++;} else {aUF[cell.ant.type]++;}} else {aE[cell.ant.type]++;eT++;if (cell.ant.food>0){aLE[cell.ant.type]++;} else {aUE[cell.ant.type]++;}}dOK[CCW[i]]=false;uo=false;}}switch (mT){case AQ:return (rQSs());case ASF:if (mQ==1){return (rSSs());} else if (aF[AQ]>0){return (rGSs());} else {return (rLSSy());}case AE:return (rESs());case AJM:case ASM:if (aE[AQ]>0){return (rDSs());} else if (mF>0){return (rLSs());} else {return (rUSs());}default:return NOP;}function rQSs (){switch (aF[ASF]){case 0:return (rQScrSy());case 1:for (var i=0; i<TN; i++){var cell=view[CCW[i]];if (cell.ant&&cell.ant.type==ASF){xn=i&6;if (i&1){if (mF<=THX){return (rQLsSy());} else {return (rQLvSy());}} else {return (rQSgSy());}}}break;case 2:for (i=0; i<TN; i+=2){var cell0=view[CCW[i]];var cell1=view[CCW[i+1]];if ((cell0.ant&&(cell0.ant.type==ASF))&&(cell1.ant&&(cell1.ant.type==ASF))){xn=i;return (rQOSy());}}return (rQCSy());default:return (rQCSy());}return NOP;}function rSSs (){if (view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend&&(view[CCW[xn+3]].ant.type==ASF)){return (rSOSy());} else if (view[CCW[xn+1]].ant.food<=THX){return (rSLSy());} else {return (rSESy());}}function rGSs (){var secCell=view[CCW[xn+7]];if (secCell.ant&&(secCell.ant.friend==1)&&(secCell.ant.type==ASF)){return (rGOSy());} else {return (rGSSy());}return NOP;}function rESs (){if (aF[AQ]>0){return (rEHyS());} else if (aF[AJM] +aF[ASM]>0){return (rEBRSy());} else {return (rEASy());}return NOP;}function rDSs(){if (aF[AQ]>0){return (rDHSy());} else {for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&(view[CCW[i]].ant.type==AQ)){if (i&1){if ((view[CCW[i+1]].ant&&view[CCW[i+1]].ant.friend&&view[CCW[i+2]].ant&&view[CCW[i+2]].ant.friend)||(view[CCW[i-1]].ant&&view[CCW[i-1]].ant.friend&&view[CCW[i+6]].ant&&view[CCW[i+6]].ant.friend)||(view[CCW[i+2]].ant&&view[CCW[i+2]].ant.friend&&view[CCW[i+6]].ant&&view[CCW[i+6]].ant.friend)){if (dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else if (dOK[CCW[i+3]]){return {cell:CCW[i+3]};} else if (dOK[CCW[i+5]]){return {cell:CCW[i+5]};}}} else {if (view[CCW[i+1]].ant&&view[CCW[i+1]].ant.friend&&
view[CCW[i+7]].ant&&view[CCW[i+7]].ant.friend){if (dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else if (dOK[CCW[i+3]]){return {cell:CCW[i+3]};} else if (dOK[CCW[i+5]]){return {cell:CCW[i+5]};} else if (dOK[CCW[i+6]]){return {cell:CCW[i+6]};} else if (dOK[CCW[i+2]]){return {cell:CCW[i+2]};}}if ((i<=2)&&dOK[CCW[i+7]]){return {cell:CCW[i+7]};}if ((i>=4)&&dOK[CCW[i+1]]){return {cell:CCW[i+1]};}}if (fT==0){if (view[CCW[i]].color!=PP){return {cell:CCW[i],color:PP};} else if (mC!=LCLR){return {cell:POSC,color:LCLR};}}}}}return NOP;}function rUSs (){if ((aF[AQ]>0)&&!LCRQCVAL[view[CCW[xn+mQ]].color]){return (rUHSy());} else if ((fT+eT>=4)&&(aF[AJM]+aF[ASM] +aF[AE]>=3)){return (rUCRSy());} else if (aF[AQ]>0){return (rUHSy());} else if (aF[ASF]>0){if (aF[ASF]>1){return (rM2R1Sy());} else {return (rURHSy());}} else if (aF[AE]>0){return (rUBRSy());} else if (spcRL1()){return (rULRL1Sy());} else if (spcRR0()){return (rULRR0Sy());} else if (spcRR2()){return (rULRR2Sy());} else if (spcMS()){return (rUDSSy());} else if (spcRL02()){return (rULRL02Sy());} else if (spcRM()){return (rUTRRSy());} else if (spcRR1()){return (rUPSSy());} else if (spcMS0R()){return (rUESSy());} else if (spcMS0W()){return (rUSWSy());}return (rLostMSy(true));}function rLSs (){if ((fT>=3)&&(fT+eT>=4)){return (rLCRSy());} else if (aF[ASF]>0){if (aF[ASF]>1){return (rM2R1Sy());} else {return (rLRHSy());}} else if (spcMFL()){return (rLLLWSy());} else if (spcMFR()){return (rLLRWSy());} else if (spcRL1()){return (rLLRL1Sy());} else if (spcRR0()){return (rLLRR0Sy());} else if (spcRR2()){return (rLLRR2Sy());} else if (spcMS0R()){return (rLLSSy());} else if (spcMS0ROut()){return (rLLVSSy());} else if (spcMS()&&(aF[AE]==0)){return (rLASSy());} else if (spcRL02()){return (rLLRL02Sy());} else if (spcRM()){return (rLTRRSy());} else if (spcRR1()){return (rLDSSy());} else if (aF[AE]>0){return (rLFRSy());}return (rLostMSy(true));}function rQScrSy(){if (uo){if (fdT>0){return (rQSETc());} else if (mF>=THC){for (var i=0; i<TN; i+=2){if ((view[CCW[i]].color==LT)||(view[CCW[i+1]].color==LT)){return {cell:CCW[i+1],type:ASF};}}return {cell:1,type:ASF};} else if (mC!=LT){if ((mC==LCLR)||(sN[LCLR]>=TN-1)){return {cell:POSC,color:LT};} else {return (rQSTCTc());}} else if ((sN[LCLR]>=4)&&(sN[LT]==1)){for (var i=0; i<TN; i+=2){if ((view[CCW[i]].color==LT)||(view[CCW[i+1]].color==LT)){return {cell:CCW[i+4]};}}} else if (sN[LCLR]==TN){return {cell:0};} else {return (rQSATc());}} else {if ((fdT>0)&&(eT>0)&&(eT==aE[AQ])){return (rQSSTc());} else {return (rQSEvTc());}}return NOP;}function rQSgSy(){if (fdT>0){if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else {for (var i=2; i<TN-1; i++){if (dOK[CCW[xn+i]]&&(view[CCW[xn+i]].food>0)){return {cell:CCW[xn+i]};}}for (var i=2; i<TN-1; i++){if (dOK[CCW[xn+i]]){     return {cell:CCW[xn+i]};}}return NOP;}} else if ((mF>TH0)&&(mC==LCL_QC_RESET)){if (dOK[CCW[xn+7]]){return { cell:CCW[xn+7],type:AE};} else if (view[CCW[xn]].color==LPB){if (dOK[CCW[xn+3]]){return { cell:CCW[xn+3],type:AE};} else if (dOK[CCW[xn+5]]){return { cell:CCW[xn+5],type:AE};} else if (dOK[CCW[xn+6]]){return { cell:CCW[xn+6],type:AJM};} else if (dOK[CCW[xn+2]]){return { cell:CCW[xn+2],type:AJM};} else if (dOK[CCW[xn+4]]){return { cell:CCW[xn+4],type:AJM};} else if (dOK[CCW[xn+1]]){return { cell:CCW[xn+1],type:ASF};}}}return NOP;}function rQOSy(){if ((aE[AQ]>0)&&(mF>0)){for (var i=2; i<TN; i++){if (view[CCW[xn+i]].ant&&(view[CCW[xn+i]].ant.type==AQ)&&!view[CCW[xn+i]].ant.friend){var j=(xn&4) ? 1 : -1;if (dOK[CCW[xn+i-j]]){return {cell:CCW[xn+i-j],type:AJM};} else if (dOK[CCW[xn+i+j]]){return {cell:CCW[xn+i+j],type:AJM};} else if (i==5){var i1=5-2*j;var i2=5+2*j;if (dOK[CCW[xn+i1]]&&!(view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend&&
view[CCW[xn+6]].ant&&view[CCW[xn+6]].ant.friend&&
view[CCW[xn+i2]].ant&&view[CCW[xn+i2]].ant.friend)){return {cell:CCW[xn+i1],type:AJM};} else if (dOK[CCW[xn+i2]]&&!(view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend&&
view[CCW[xn+6]].ant&&view[CCW[xn+6]].ant.friend&&
view[CCW[xn+i1]].ant&&view[CCW[xn+i1]].ant.friend)){return {cell:CCW[xn+i2],type:AJM};}} else if ((i==3)&&dOK[CCW[xn+5]]&&!(view[CCW[xn+2]].ant&&view[CCW[xn+2]].ant.friend&&
view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend)){return {cell:CCW[xn+5],type:AJM};} else if ((i==7)&&dOK[CCW[xn+5]]&&!(view[CCW[xn+6]].ant&&view[CCW[xn+6]].ant.friend)){return {cell:CCW[xn+5],type:AJM};}}}} else if ((mF>0)&&(view[CCW[xn+7]].color==LA)&&dOK[CCW[xn+7]]){return {cell:CCW[xn+7],type:AJM};} else if (view[CCW[xn+1]].ant.food>0){if ((mF>0)&&dOK[CCW[xn+2]]){return {cell:CCW[xn+2],type:AJM};}} else if ((aLF[AJM]+aLF[ASM]>0)&&(mF>0)&&(sN[LA]>0)){for (var i=2; i<TN; i++){var c=CCW[xn+i];if (dOK[c]&&(view[c].color==LA)){return {cell:c,type:AJM};}}} else if (eT>0){var bandits=aUE[1]+aUE[2]+aUE[3]+aUE[4];if ((mF>THX)&&((bandits>=2)||((bandits>=1)&&view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend&&(view[CCW[xn+5]].color==LA)&&(view[CCW[xn+7]].ant&&view[CCW[xn+7]].ant.friend&&
(view[CCW[xn+7]].color==LA))||(view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend&&
(view[CCW[xn+3]].color==LA))))){if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};}}if (mF<RD1){if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};}} else if ((bandits>=1)&&(mF>0)){if ((mF>THX)&&(mF % RM2==RD2+xn/2)){if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};}}for (var i=2; i<TN; i++){var c=CCW[xn+i];var c1,c2;if ((xn==2)||isSc0(view[CCW[xn+1]].color)){c1=CCW[xn+i-1];c2=CCW[xn+i+1];} else if ((xn==6)||isSc1(view[CCW[xn+1]].color)){c1=CCW[xn+i+1];c2=CCW[xn+i-1];} else {break;}if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.food==0)){if (dOK[c1]&&!(view[c2].ant&&view[c2].ant.friend&&view[c2].ant.food>0)){return {cell:c1,type:AJM};} else if (dOK[c2]&&!(view[c1].ant&&view[c1].ant.friend&&view[c1].ant.food>0)){return {cell:c2,type:AJM};}break;}}}}if (!(LCRQCVAL[mC])){return {cell:POSC,color:LCRQC[1]};} else if ((view[CCW[xn]].color==LPX)&&isSc0(view[CCW[xn+1]].color)){if ((mF<=TH0)||(mF % RM1==RD1)){return (rQHTc());} else if (mF<=TH2){if (dOK[CCW[0]]){return {cell:CCW[0],type:AJM};} else {return (rQHTc());}} else {var destCycle=[2,4,6,4,6,2,6,2,4];var destination=destCycle[mF % 9];if (!dOK[CCW[xn+destination]]){destination=destination % 6+2;}if (!dOK[CCW[xn+destination]]){destination=destination % 6+2;}if (!dOK[CCW[xn+destination]]){return (rQHTc());}if (mF<=TH3){if (xn<=2){return {cell:CCW[xn+destination],type:AJM};} else {return (rQHTc());}} else if (mF<=TH4){if (xn<=2){return {cell:CCW[xn+destination],type:((xn>0) ? AJM : ASM)};} else {return (rQHTc());}} else if (mF<=TH5){if (xn==0){return {cell:CCW[xn+destination],type:ASM};} else {return (rQHTc());}} else {return (rQHTc());}}} else {return {cell:POSC,color:incQc(mC)};}return NOP;}function rQLsSy(){if (mF>=TH1){if (mC!=LCLR){return {cell:POSC,color:LCLR};} else {for (var i=0; i<TN; i+=2){if (view[CCW[i]].color!=LCLR){return {cell:CCW[i],color:LCLR};}}}if ((eT==0)&&(fT==1)){return {cell:CCW[xn+3]};}}if ((eT==0)&&(fT==1)){if (view[CCW[xn+2]].food>0){return {cell:CCW[xn+2]};} else if ((view[CCW[xn+3]].food +view[CCW[xn+4]].food>0)&&(view[CCW[xn+1]].color!=LLSF)){return NOP;} else {return {cell:CCW[xn+2]};}} else if (dOK[CCW[xn+2]]&&(dOK[CCW[xn+3]]||(view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend))){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn]]&&dOK[CCW[xn+7]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else {return NOP;}}function rQLvSy(){if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};}return NOP;}function rQCSy(){return NOP;}function rSOSy(){if (!(LCRSCVAL[mC])){return {cell:POSC,color:LCRSC[1]};} else if (isSc0(mC)&&isQc0(view[CCW[xn+1]].color)&&
(view[CCW[xn+3]].color==LPG)){return {cell:CCW[xn+3],color:LPX};} else {return {cell:POSC,color:incSc(mC)};}return NOP;}function rSLSy(){if ((eT==0)&&(fT==1)){if (view[CCW[xn]].food>0){return {cell:CCW[xn]};} else if (view[CCW[xn+7]].food +view[CCW[xn+6]].food>0){return {cell:POSC,color:LLSF};} else {return {cell:CCW[xn]};}} else if ((eT>0)&&view[CCW[xn+2]].ant&&!view[CCW[xn+2]].ant.friend){return {cell:POSC,color:LLSF};} else {if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};}}return NOP;}function rSESy(){if (view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend&&(view[CCW[xn+5]].ant.type==ASF)){if (dOK[CCW[xn]]){return {cell:CCW[xn]};}} else if ((mC==LRR0)&&(view[CCW[xn+5]].color==LG6)){if (dOK[CCW[xn]]){return {cell:CCW[xn]};}} else {if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn]]){return {cell:CCW[xn]};}}return NOP;}function rGSSy(){if (view[CCW[xn]].color!=LCL_QC_RESET){return {cell:CCW[xn],color:LCL_QC_RESET};}if (mC!=LPB){return {cell:POSC,color:LPB};}return (rGGTc());}function rGOSy(){if (aE[AQ]>0){var c=CCW[xn+2];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)&&!view[CCW[xn+1]].ant){return {cell:CCW[xn+1],color:LA};}c=CCW[xn+3];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)&&!view[CCW[xn+1]].ant){return {cell:CCW[xn+1],color:LA};}}if (!LCRPHR[mC]){if ((mC==LPX)&&isSc0(view[CCW[xn+7]].color)){return NOP;} else if (eT==0){return {cell:POSC,color:LPG};}} else if (isSc1(view[CCW[xn+7]].color)&&isQc2(view[CCW[xn]].color)){switch (mC){case LPG:return {cell:POSC,color:LPG1};case LPG1:return {cell:POSC,color:LPG};default:return {cell:POSC,color:LPG};}}if ((eT>0)&&!LCRPHR[mC]&&(xn&4)){return {cell:POSC,color:LPG};} else {return (rGGTc());}}function rLSSy(){if (mC!=LCLR){return {cell:POSC,color:LCLR};}return NOP;}function rEHyS(){if (mQ==1){var ptrn=PTFRL0H;var msm=patC(ptrn,AIMU,0,1);if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (LCRQCVAL[view[CCW[xn+mQ]].color]&&dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};}}return NOP;}function rEBRSy(){if (aF[ASF]>0){return (rELGTc());} else {return (rEBRTc());}}function rEASy(){return NOP;}function rUHSy(){if ((mQ==0)&&(view[CCW[xn]].ant.food<RD1)&&view[CCW[xn+1]].ant&&view[CCW[xn+1]].ant.friend&&(view[CCW[xn+1]].ant.type==ASF)){var cc=[5,6,7,4,2];for (var i=0; i<cc.length; i++){var c=CCW[xn+cc[i]];if (dOK[c]){return {cell:c};}}return NOP;}if ((eT>0)&&(aE[AQ]+aUE[1]+aUE[2] +aUE[3]+aUE[4]>0)){var common;if (mQ==0){common=[1,7];} else {common=[0,2,3,7];}for (var i=0; i<common.length; i++){var c=CCW[xn+common[i]];if (view[c].ant&&!view[c].ant.friend&&((view[c].ant.type==AQ)||(view[c].ant.food==0))){if ((aE[AQ]==0)&&(mC!=LA)){return {cell:POSC,color:LA};} else {return NOP;}}}}if (mQ==0){if (mC!=LRM0){return {cell:POSC,color:LRM0};} else if (view[CCW[xn+3]].color!=LRR0){return {cell:CCW[xn+3],color:LRR0};} else if (view[CCW[xn+7]].color!=LRL0){return {cell:CCW[xn+7],color:LRL0};} else if (view[CCW[xn+5]].color!=LRM1){return {cell:CCW[xn+5],color:LRM1};} else if (view[CCW[xn+6]].color!=LRL1){return {cell:CCW[xn+6],color:LRL1};} else if ((!LCRGRR1[view[CCW[xn+4]].color])&&!(view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend)){return {cell:CCW[xn+4],color:LRR1};}if (LCRQCVAL[view[CCW[xn]].color]||(view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend&&
(view[CCW[xn+5]].ant.food>0))||(view[CCW[xn+6]].ant&&view[CCW[xn+6]].ant.friend&&
(view[CCW[xn+6]].ant.food>0))){if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};}}} else {var ptrn=PTFRL0H;var msm=patC(ptrn,AIMU,0,1);if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (LCRQCVAL[view[CCW[xn+mQ]].color]){if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend&&dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};}}}return NOP;}function rUBRSy(){if (spcRL1()){return (rULRL1Sy());} else if (spcRL02()){return (rULRL02Sy());} else if (spcRM()){return (rUFCRTc());}for (var i=TN-1; i>=0; i--){if (view[CCW[i+1]].ant&&view[CCW[i+1]].ant.friend&&
(view[CCW[i+1]].ant.type==AE)&&dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}function rUTRRSy(){return (rUCRTc());}function rULRL1Sy(){var ptrn=PTGRL1;var msm=patC(ptrn,AIMR,0,1);if (xn>=0){if ((view[CCW[xn+6]].color==LMS_WRP)&&(view[CCW[xn+7]].color==LCLR)&&(view[CCW[xn]].color==LMR0)&&(view[CCW[xn+3]].color!=LRM1_WRP)){return {cell:CCW[xn+3],color:LRM1_WRP};} else if ((view[CCW[xn+3]].color!=LRM1_WRP)&&view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend&&dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else {return NOP;}} else if (spcRM()){return (rUTRRSy());}return (rLostMSy(false));}function rULRL02Sy(){var ptrn;var msm;if (sL[LRM0]>0){ptrn=PTGRL0;msm=patC(ptrn,AIMR,1,1);}if (xn<0){ptrn=PTGRL2;msm=patC(ptrn,AIMR,1,1);}if (xn>=0){if (view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend&&dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else {return NOP;}} else if (spcRM()){return (rUTRRSy());}return (rLostMSy(false));}function rULRR0Sy(){var ptrn=PTGRR0;var msm=patC(ptrn,AIML,2,1);if (xn>=0){return (runUMLeaveRRTactic());} else if (spcRM()){return (rUTRRSy());}return (rLostMSy(false));}function rULRR2Sy(){var ptrn=PTGRR2;var msm=patC(ptrn,AIML,2,1);if (xn>=0){return (runUMLeaveRRTactic());}    return (rLostMSy(false));}function rUPSSy(){var ptrn=PTGRR1;var msm=patC(ptrn,AIMD,3,2);if (xn>=0){var c=CCW[xn+1];if (view[c].ant&&view[c].ant.friend&&(view[c].ant.food>0)){if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else {return NOP;}}if ((view[CCW[xn+2]].color==LMX_M3OUT)&&(view[CCW[xn]].color==LMR0)&&(view[CCW[xn+1]].color==LCLR)&&(mC!=LRR1X)){return {cell:POSC,color:LRR1X};} else if ((mT==AJM)&&(mC==LRR1U)&&(view[CCW[xn]].color==LMR0)&&(view[CCW[xn+1]].color==LCLR)&&LCRMX_OUT[view[CCW[xn+2]].color]){return {cell:POSC,color:LRR1V};} else if ((mC==LRR1X)||((mT==AJM)&&(mC==LRR1V))||((mC==LRR1U)&&(view[CCW[xn]].color==LMR0)&&(view[CCW[xn+1]].color==LCLR)&&LCRMX_IN[view[CCW[xn+2]].color])){if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend&&dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}} else if (mC!=LRR1U){return {cell:POSC,color:LRR1U};} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else {if (dOK[c]){return {cell:c};} else if (view[c].ant&&view[c].ant.friend){if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}} else {return NOP;}}}return (rLostMSy(false));}function rUESSy(){var ptrn=PTMS0R_IN;var msm=patC(ptrn,AIMD,4,2);if (xn>=0){return (rUESTc(ptrn,msm));}return (rLostMSy(false));}function rUDSSy(){var ptrn;var msm;if ((sL[LML3]>=1)&&(sD[LMR2]+sD[LMR0]>=1)){ptrn=PTMS3;msm=patC(ptrn,AIMD,3,2);}if ((xn<0)&&(sL[LMR2]>=1)&&(sD[LML1]+sD[LML3]>=1)){ptrn=PTMS2;msm=patC(ptrn,AIMD,3,2);}if (xn>=0){if ((msm<0)&&(view[CCW[xn]].color==LRM0)&&(view[CCW[xn+1]].color==LRR0)&&(view[CCW[xn+2]].color==LMR0)){if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else {return NOP;}}return (rUDSTc(ptrn,msm));}if ((xn<0)&&(sL[LML1]>=1)&&(sD[LMR0]+sD[LMR2]>=1)){ptrn=PTMS1_IN;msm=patC(ptrn,AIMD,3,4);if (xn<0){ptrn=PTMS1;msm=patC(ptrn,AIMD,3,2);}}if (xn>=0){return (rUDSTc(ptrn,msm));}if ((sD[LML3]+sL[LMR0]>=2)&&(sD[LRL0] >=2)&&(sD[LML1]==0)){ptrn=PTMS0_WRAPPING;msm=patC(ptrn,AIMD,0,1);if (xn>=0){return (rUWRTc(ptrn,msm));}}if ((sL[LMR0]>=1)&&(sD[LML3]+sD[LML1]>=1)){ptrn=PTMS0;msm=patC(ptrn,AIMD,3,2);if (xn>=0){return (rUDSTc(ptrn,msm));}}if (spcRR1()){ptrn=PTGRR1;msm=patC(ptrn,AIMD,3,2);if (xn>=0){if (mC==LRR1){return {cell:POSC,color:LRR1U};}return NOP;}}if (spcMS0R()){ptrn=PTMS0R_IN;msm=patC(ptrn,AIMD,4,2);if (xn>=0){return (rUESTc(ptrn,msm));}}return (rLostMSy(false));}function rUSWSy(){var ptrn=PTMS0_WRAPPING;var msm=patC(ptrn,AIMD,0,1);if (xn>=0){return (rUWRTc(ptrn,msm));}return (rLostMSy(false));}function rURHSy(){return (rMNGTc());}function rUCRSy(){for (var i=TN; i>=1; i--){if (view[CCW[i]].ant&&dOK[CCW[i-1]]){return {cell:CCW[i-1]};}}return NOP;}function rLLLWSy(){var ptrn;var msm;if (mC==LML1){ptrn=PTMS1FL;msm=patC(ptrn,AIML,0,1);if (xn>=0){return (rLLLWTc());}} else if (mC==LML3){ptrn=PTMS3FL;msm=patC(ptrn,AIML,0,1);if (xn>=0){return (rLLLWTc());}} else if (sL[LML1]+sL[LML3]>=2){ptrn=PTMS0FL;msm=patC(ptrn,AIML,0,1);if (xn<0){ptrn=PTMS2FL;msm=patC(ptrn,AIML,0,1);}if (xn>=0){return (rLLLWTc());}} else if (spcMFR()){return (rLLRWSy());} else if (spcMS()){return (rLASSy());}return (rLostMSy(false));}function rLLRWSy(){var ptrn;var msm;if (mC==LMR0){ptrn=PTMS0FR;msm=patC(ptrn,AIMR,0,1);if (xn>=0){return (rLLRWTc());}} else if (mC==LMR2){ptrn=PTMS2FR;msm=patC(ptrn,AIMR,0,1);if (xn>=0){return (rLLRWTc());}} else if (sL[LMR0]+sL[LMR2]>=2){ptrn=PTMS1FR;msm=patC(ptrn,AIMR,0,1);if (xn<0){ptrn=PTMS3FR;msm=patC(ptrn,AIMR,0,1);}if (xn>=0){return (rLLRWTc());}} else if (spcMS()){return (rLASSy());}return (rLostMSy(false));}function rLASSy(){var ptrn;var msm;if ((sL[LML3]>=1)&&(sD[LMR2]+sD[LMR0]>=1)){ptrn=PTMS3;msm=patC(ptrn,AIMU,3,2);}if ((xn<0)&&(sL[LMR2]>=1)&&(sD[LML1]+sD[LML3]>=1)){ptrn=PTMS2;msm=patC(ptrn,AIMU,3,2);}if ((xn<0)&&(sL[LML1]>=1)&&(sD[LMR0]+sD[LMR2]>=1)){ptrn=PTMS1_IO;msm=patC(ptrn,AIMU,0,1);if (xn<0){ptrn=PTMS1;msm=patC(ptrn,AIMU,3,2);}}if (xn>=0){return (rLASTc(ptrn,msm));}if ((sD[LML3]+sL[LMR0]>=2)&&(sD[LRL0] >=2)&&(sD[LML1]==0)){ptrn=PTMS0_OUT;msm=patC(ptrn,AIMU,0,1);if (xn>=0){return {cell:CCW[xn+3],color:LCLR};}ptrn=PTMS0_WRAPPING;msm=patC(ptrn,AIMD,0,1);if (xn>=0){return (rLWRTc(ptrn,msm));}}if ((sL[LMR0]>=1)&&(sD[LML3]+sD[LML1]>=1)){ptrn=PTMS0;msm=patC(ptrn,AIMU,3,2);if (xn>=0){return (rLASTc(ptrn,msm));}}if (spcRM()){return (rLTRRSy());}return (rLostMSy(false));}function rLLSSy(){var ptrn=PTMS0R_OUT;var msm=patC(ptrn,AIMU,0,1);if (xn>=0){} else {ptrn=PTMS0R_IN;msm=patC(ptrn,AIMU,4,2);if (xn>=0){ptrn=PTMS0R_OUT;msm=patC(ptrn,AIMU,0,1);}}if (xn>=0){return (rLLSTc(ptrn,msm));} else if (spcMS()){return (rLASSy());} else {return (rLostMSy(false));}return NOP;}function rLLVSSy(){var ptrn=PTMS0R_OUT1;var msm=patC(ptrn,AIMU,0,1);if (xn>=0){if (view[CCW[xn+3]].color==LCLR){return {cell:CCW[xn+3],color:((mT==ASM) ? LMX_M2OUT : LMX_M1OUT)};
} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend&&
dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}} else if (spcMS()){return (rLASSy());}return (rLostMSy(false));}function rLDSSy(){var ptrn=PTGRR1;var msm=patC(ptrn,AIMU,1,1);if (xn>=0){if ((view[CCW[xn]].color==LMR0)&&(view[CCW[xn+1]].color==LCLR)){if ((mC==LRR1X)&&(view[CCW[xn+2]].color!=LMX_M3OUT)){return {cell:CCW[xn+2],color:LMX_M3OUT};}if ((view[CCW[xn+2]].color==LMX_M3OUT)&&(mC!=LRR1X)){return {cell:POSC,color:LRR1X};} else if ((LCRMX_OUT[view[CCW[xn+2]].color])&&
(mC!=LRR1V)){return {cell:POSC,color:LRR1V};} else if ((LCRMX_IN[view[CCW[xn+2]].color])&&(mC!=LRR1U)){return {cell:POSC,color:LRR1U};} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};}}if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}}return (rLostMSy(false));}function rLTRRSy(){return (rLCRTc());}function rLFRSy(){for (var i=1; i<TN; i+=2){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==AE)&&dOK[CCW[i+2]]){return {cell:CCW[i+2]};}}return NOP;}function rLRHSy(){var ptrn=PTFRL1G;var msm=patC(ptrn,AIMR,0,1);if (xn>=0){return (rLRLTc());}return (rMNGTc());}function rLLRL1Sy(){var ptrn=PTGRL1;var msm=patC(ptrn,AIMR,0,1);if (xn>=0){return (rLRLTc());} else if (spcRM()){return (rLTRRSy());}return (rLostMSy(false));}function rLLRL02Sy(){var ptrn;var msm;if (sL[LRM0]>0){ptrn=PTGRL0;msm=patC(ptrn,AIMR,1,1);}if (xn<0){ptrn=PTGRL2;msm=patC(ptrn,AIMR,1,1);}if (xn>=0){return (rLRLTc());}return (rLostMSy(false));}function rLLRR0Sy(){var ptrn=PTGRR0;var msm=patC(ptrn,AIML,2,1);if (xn>=0){return (rLRRTc());} else if (spcRM()){return (rLTRRSy());}return (rLostMSy(false));}function rLLRR2Sy(){var ptrn=PTGRR2;var msm=patC(ptrn,AIML,2,1);if (xn>=0){return (rLRRTc());} else if (spcRM()){return (rLTRRSy());}return (rLostMSy(false));}function rLCRSy(){for (var i=TN; i>=1; i--){if (!dOK[CCW[i]]&&dOK[CCW[i-1]]){return {cell:CCW[i-1]};}}return NOP;}function rM2R1Sy(){for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==ASF)&&view[CCW[i+1]].ant&&view[CCW[i+1]].ant.friend&&
(view[CCW[i+1]].ant.type==ASF)){if (i&1){} else {}if (dOK[CCW[i+7]]){return {cell:CCW[i+7]};} else {return NOP;}}}return (rLostMSy(true));}function rLostMSy(totally){if ((fdT>0)&&(mF==0)){for (var i=0; i<TN; i++){if ((view[CCW[i]].food>0)&&dOK[CCW[i]]){return {cell:CCW[i]};}}}if (totally&(fT==0)){if (((mC==PY)&&(sN[PY]==0))||((mC==PR)&&(sN[PR]==0))){return {cell:POSC,color:PP};}if (((mC==PG)&&(sN[PG]==0))||((mC==PC)&&(sN[PC]==0))||((mC==PB)&&(sN[PB]==0))||((mC==PP)&&(sN[PP]==0))){return {cell:POSC,color:PW};} else if ((sT[PG]==0)&&(((mC==PK)&&(sN[PK]==0))||((mC==PY)&&(sN[PY]==0))||((mC==PR)&&(sN[PR]==0)))){return {cell:POSC,color:PW};} else if ((mC!=PW)&&(sN[mC]>=4)){return {cell:POSC,color:PW};}}if ((mC==PG)&&(sL[PG]>=2)){return {cell:POSC,color:PW};} else if (((mC==PK)||(mC==PR))&&(sN[PK]+sN[PR]>=3)){return {cell:POSC,color:PW};}if (sN[PW]<=4){var preferredColors =[PG,PB,PC,PP,PY,PR,PK];for (var ci=0; ci<preferredColors.length; ci++){var c=preferredColors[ci];if (mC==c){break;}if (sN[c]>0){for (var i=1; i<TN; i++){if ((view[CCW[i]].color==c)&&dOK[CCW[i]]){return {cell:CCW[i]};}}}}}if (RW){for (var i=1; i<TN; i+=2){if (dOK[CCW[i]]){return {cell:CCW[i]};}}for (i=0; i<TN; i+=2){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;} else {return NOP;}}function rDHSy(){if (mQ==0){var c=CCW[xn+2];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)&&!view[CCW[xn+1]].ant){return {cell:CCW[xn+1],color:LA};}c=CCW[xn+6];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)&&!view[CCW[xn+7]].ant){return {cell:CCW[xn+7],color:LA};}} else {var c=CCW[xn+4];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)&&!view[CCW[xn+3]].ant){return {cell:CCW[xn+3],color:LA};}c=CCW[xn+6];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)&&!view[CCW[xn+7]].ant){return {cell:CCW[xn+7],color:LA};}c=CCW[xn+5];if (view[c].ant&&!view[c].ant.friend&&(view[c].ant.type==AQ)&&(view[c].ant.food>0)){if (!view[CCW[xn+3]].ant){return {cell:CCW[xn+3],color:LA};} else if (!view[CCW[xn+7]].ant){return {cell:CCW[xn+7],color:LA};}}}return NOP;}function rQSETc(){if (mC!=LT){return {cell:POSC,color:LT};}for (var i=0; i<TN; i++){if (view[CCW[i]].food>0){return {cell:CCW[i]};}}return NOP;}function rQSSTc(){for (var i=0; i<TN; i++){if ((view[CCW[i]].food>0)&&(dOK[CCW[i]])){return {cell:CCW[i]};}}return NOP;}function rQSTCTc(){if ((mC!=LCLR)&&(sN[mC]>=4)){if (sN[LT]==0){return {cell:POSC,color:LT};} else if (sN[LT]>=3){return {cell:POSC,color:LT};} else {for (var i=0; i<TN; i++){if ((view[CCW[i]].color==LT)&&(view[CCW[i+2]].color!=LT)){return {cell:CCW[i+2],color:LT};}}return NOP;}} else if (sN[LT]==1){for (var i=0; i<TN; i++){if ((view[CCW[i]].color==LT)&&(view[CCW[i+4]].color!=LCLR)){if (view[CCW[i+1]].color==LCLR){return { cell:CCW[i+1]};} else if (view[CCW[i+7]].color==LCLR){return { cell:CCW[i+7]};} else {return {cell:POSC,color:LT};}}}return {cell:POSC,color:LT};} else {return {cell:POSC,color:LT};}return NOP;}function rQSATc(){for (var i=0; i<TN; i++){if ((view[CCW[i]].color==LCLR)&&(view[CCW[i+1]].color==LCLR)&&(view[CCW[i+2]].color==LCLR)){if ((view[CCW[i+3]].color==LCLR)&&(view[CCW[i+4]].color==LCLR)){return {cell:CCW[i+2]};}return {cell:CCW[i+1]};}}for (i=TN-1; i>=0; i--){if (view[CCW[i]].color!=LT){return {cell:CCW[i]};}}for (i=0; i<TN; i++){if (view[CCW[i]].color!=LT){return {cell:CCW[i],color:LCLR};}}return {cell:0,color:LCLR};}function rQSEvTc(){if (sN[LT]>0){for (var i=0; i<TN; i++){if (view[CCW[i]].color==LT){xn=i&6;}}if ( dOK[CCW[xn+7]]&&dOK[CCW[xn]]&&dOK[CCW[xn+1]]&&dOK[CCW[xn+2]]&&dOK[CCW[xn+3]] ){return {cell:CCW[xn+1]};} else if (dOK[CCW[xn+5]]&&dOK[CCW[xn+6]]&&dOK[CCW[xn+7]]&&dOK[CCW[xn]]&&dOK[CCW[xn+1]]){return {cell:CCW[xn+7]};} else if (dOK[CCW[xn+3]]&&dOK[CCW[xn+4]]&&dOK[CCW[xn+5]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+5]]&&dOK[CCW[xn+6]]&&dOK[CCW[xn+7]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+1]]&&dOK[CCW[xn+2]]&&dOK[CCW[xn+3]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn+7]]&&dOK[CCW[xn]]&&dOK[CCW[xn+1]]){return {cell:CCW[xn]};} else {for (i=0; i<TN; i++){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}} else {for (var i=0; i<TN; i++){if (dOK[CCW[i]]&&dOK[CCW[i+1]]&&dOK[CCW[i+2]]&&dOK[CCW[i+3]]&&dOK[CCW[i+4]]){return {cell:CCW[i+2]};}}for (i=0; i<TN; i++){if (dOK[CCW[i]]&&dOK[CCW[i+1]]&&dOK[CCW[i+2]]){return {cell:CCW[i+1]};}}for (i=0; i<TN; i++){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}return NOP;}function rQHTc(){var ptrn=PTHOME;var msm=patC(ptrn,POSC,0,1);if (msm!=0){var cc=fwdWrong[0];return {cell:cc.v,color:ptrn[cc.p]};} else {return NOP;}}function rGGTc(){var ptrn=PTGARDEN;var msm=patC(ptrn,POSC,0,1);if (msm!=0){var cc=fwdWrong[0];return {cell:cc.v,color:ptrn[cc.p]};} else {return NOP;}}function rUFCRTc(){var ptrn;var msm;if (mC==LRM0){ptrn=PTFRM0;msm=patC(ptrn,AIMU,4,1);if ((xn<0)&&(eT>0)){ptrn=PTFRM1;msm=patC(ptrn,AIMU,4,1);}if ((xn<0)&&(eT>0)){ptrn=PTFRM2;msm=patC(ptrn,AIMU,4,1);}} else if (mC==LRM2){ptrn=PTFRM2;msm=patC(ptrn,AIMU,4,1);if ((xn<0)&&(eT>0)){ptrn=PTFRM0;msm=patC(ptrn,AIMU,4,1);}if ((xn<0)&&(eT>0)){ptrn=PTFRM1;msm=patC(ptrn,AIMU,4,1);}} else if (mC==LRM1){ptrn=PTFRM1;msm=patC(ptrn,AIMU,4,1);if ((xn<0)&&(eT>0)){ptrn=PTFRM2;msm=patC(ptrn,AIMU,4,1);}if ((xn<0)&&(eT>0)){ptrn=PTFRM0;msm=patC(ptrn,AIMU,4,1);}} else if (mC==LRM1_WRP){ptrn=PTGRM1_WRP;msm=patC(ptrn,AIMR,1,1);}if ((xn<0)&&spcRR1()){return (rUPSSy());}if (xn<0){return (rLostMSy(false));}if (msm==0){if (fdL>0){if ((view[CCW[xn+7]].food>0)&&dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else if ((view[CCW[xn+3]].food>0)&&dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};}}if ((mC==LRM1)&&(view[CCW[xn+3]].color!=LRR1X)&&(view[CCW[xn+3]].color!=LRR1U)&&!((mT==AJM)&&(view[CCW[xn+3]].color==LRR1V))&&dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};}if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};}return NOP;}for (var i=0; i<TN; i++){var ce=CCW[xn+i];if (view[ce].ant&&view[ce].ant.friend&&(view[ce].ant.type==AE)){if ((2<=i)&&(i<=4)){var msmSaved=msm;var fwdWrongSaved=Array.from(fwdWrong);var rearWrongSaved=Array.from(rearWrong);xn=xn % 4+4;msm=patC(ptrn,POSC,0,1);if (msm<msmSaved){xn=xn % 4+4;msm=msmSaved;fwdWrong=fwdWrongSaved;rearWrong=rearWrongSaved;} else {}break;}}}if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else {var cc=rearWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};}return NOP;}function rUCRTc(){var ptrn;var msm;if (mC==LRM0){ptrn=PTGRM0;msm=patC(ptrn,AIMU,4,2);if ((xn<0)&&spcRR1()){return (rUPSSy());}if ((xn<0)&&(eT>0)){ptrn=PTGRM1;msm=patC(ptrn,AIMU,4,2);}if ((xn<0)&&(eT>0)){ptrn=PTGRM2;msm=patC(ptrn,AIMU,4,2);}} else if (mC==LRM2){ptrn=PTGRM2;msm=patC(ptrn,AIMU,4,2);if ((xn<0)&&(eT>0)){ptrn=PTGRM0;msm=patC(ptrn,AIMU,4,2);}if ((xn<0)&&(eT>0)){ptrn=PTGRM1;msm=patC(ptrn,AIMU,4,2);}} else if (mC==LRM1){ptrn=PTGRM1;msm=patC(ptrn,AIMU,4,2);if ((xn<0)&&(eT>0)){ptrn=PTGRM2;msm=patC(ptrn,AIMU,4,2);}if ((xn<0)&&(eT>0)){ptrn=PTGRM0;msm=patC(ptrn,AIMU,4,2);}} else if (mC==LRM1_WRP){ptrn=PTGRM1_WRP;msm=patC(ptrn,AIMR,1,1);}if ((xn<0)&&spcRR1()){return (rUPSSy());}if (xn<0){return (rLostMSy(true));}if (msm==0){if (fdL>0){if ((view[CCW[xn+7]].food>0)&&dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else if ((view[CCW[xn+3]].food>0)&&dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};}}if ((mC==LRM1)&&(view[CCW[xn+3]].color!=LRR1X)&&(view[CCW[xn+3]].color!=LRR1U)){if ((((mT==AJM)&&(view[CCW[xn+3]].color==LRR1))||((mT==ASM)&&(view[CCW[xn+3]].color==LRR1V)))&&dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};}}if (mC==LRM0&&(view[CCW[xn+5]].color==LRM1_WRP)&&!(view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend)){return {cell:CCW[xn+5],color:LRM1};}var c=CCW[xn+5];if (dOK[c]){return {cell:c};} else if (view[c].ant&&view[c].ant.friend){var evade=false;if (view[c].ant.food>0){evade=true;} else if (view[CCW[xn+1]].ant&&view[CCW[xn+1]].ant.friend&&(view[CCW[xn+1]].ant.food==0)){evade=true;}if (evade){if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else {return NOP;}} else {return NOP;}}} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else {var cc=rearWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};}return NOP;}function rUESTc(ptrn,msm){switch (view[CCW[xn+3]].color){case LMX_M0:return {cell:CCW[xn+3],color:LMX_M1IN};case LMX_M1OUT:if (mT==ASM){return {cell:CCW[xn+3],color:LMX_M2IN};}break;case LMX_M2OUT:if (mT==ASM){return {cell:CCW[xn+3],color:LMX_M3IN};}break;case LMX_M3OUT:break;case LMX_M1IN:case LMX_M2IN:case LMX_M3IN:if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if ((msm==0)&&dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else {break;}default:break;}if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};}return NOP;}function runUMLeaveRRTactic(){if (view[CCW[xn+7]].ant&&view[CCW[xn+7]].ant.friend&&dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else {return NOP;}}function rUDSTc(ptrn,msm){var c=CCW[xn+1];if ((msm==0)&&(fdL>0)&&(view[CCW[xn+3]].food+view[CCW[xn+7]].food>0)){if (mC!=LMMF){return {cell:POSC,color:LMMF};} else if (view[CCW[xn+5]].color!=LMMH){return {cell:CCW[xn+5],color:LMMH};} else if ((view[CCW[xn+3]].food>0)&&dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if ((view[CCW[xn+7]].food>0)&&dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};}} else if ((msm<0)&&!(view[c].ant&&view[c].ant.friend)){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (msm>=0){if (dOK[c]){return {cell:c};} else {if (view[c].ant&&view[c].ant.friend){if (view[c].ant.food>0){if ((view[CCW[xn]].color==LCLR)&&dOK[CCW[xn]]){return {cell:CCW[xn]};} else if ((view[CCW[xn+2]].color==LCLR)&&dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else {return NOP;}} else {var c=CCW[xn+5];if (view[c].ant&&view[c].ant.friend&&(view[c].ant.food==0)){if (view[c].color==LMMH){if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else {return NOP;}} else if (mC!=LMMH){return {cell:POSC,color:LMMH};} else {return NOP;}} else {return NOP;}}} else {return NOP;}}}return NOP;}function rUWRTc(ptrn,msm){if (view[CCW[xn+3]].color!=LMS_WRP){return {cell:CCW[xn+3],color:LMS_WRP};} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};}return NOP;}function rLLLWTc(){if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else {return NOP;}}function rLLRWTc(){if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else {return NOP;}}function rLWRTc(ptrn,msm){if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else {return NOP;}}function rLASTc(ptrn,msm){var c=CCW[xn+5];if ((msm<0)&&!(view[c].ant&&view[c].ant.friend)){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (mC==LMMF){return {cell:POSC,color:LCLR};} else if (view[CCW[xn+5]].color==LMMH){return {cell:CCW[xn+5],color:LCLR};} else if (msm>=0){if (dOK[c]){return {cell:c};} else if ((view[c].food>0)&&(eT==0)){if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};}}}return NOP;}function rLLSTc(ptrn,msm){if (msm<0){if (view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend){return NOP;}var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};}switch (view[CCW[xn+3]].color){case LMX_M1IN:return {cell:CCW[xn+3],color:LMX_M1OUT};case LMX_M2IN:return {cell:CCW[xn+3],color:LMX_M2OUT};case LMX_M3IN:default:return {cell:CCW[xn+3],color:LMX_M3OUT};case LMX_M1OUT:case LMX_M2OUT:case LMX_M3OUT:if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};}break;}return NOP;}function rLCRTc(){var ptrn;var msm;var trust=(aF[AE]>0 ? 1 : 0);if (mC==LRM0){ptrn=PTGRM0;msm=patC(ptrn,AIMD,3,2-trust);if ((xn<0)&&(eT>0)){ptrn=PTGRM1;msm=patC(ptrn,AIMD,3,2);}if ((xn<0)&&(eT>0)){ptrn=PTGRM2B;msm=patC(ptrn,AIMD,3,2);}} else if (mC==LRM2){ptrn=PTGRM2B;msm=patC(ptrn,AIMD,3,2-trust);if ((xn<0)&&(eT>0)){ptrn=PTGRM0;msm=patC(ptrn,AIMD,3,2);}if ((xn<0)&&(eT>0)){ptrn=PTGRM1;msm=patC(ptrn,AIMD,3,2);}} else if (mC==LRM1){ptrn=PTGRM1;msm=patC(ptrn,AIMD,3,2-trust);if ((xn<0)&&(eT>0)){ptrn=PTGRM2B;msm=patC(ptrn,AIMD,3,2);}if ((xn<0)&&(eT>0)){ptrn=PTGRM0;msm=patC(ptrn,AIMD,3,2);}} else if (mC==LRM1_WRP){ptrn=PTGRM1;msm=patC(ptrn,AIMD,3,2);if (xn>=0){if (view[CCW[xn+3]].color!=LRR1X){return {cell:CCW[xn+3],color:LRR1X};} else if (!(view[CCW[xn+7]].ant&&view[CCW[xn+7]].ant.friend)){return {cell:POSC,color:LRM1};}}}if (xn<0){if (spcRR1()){return (rLDSSy());}return (rLostMSy(true));}if (msm==0){var c=CCW[xn+1];if (dOK[c]){return {cell:c};} else if (view[c].ant&&view[c].ant.friend){var evade=false;if (view[c].ant.food==0){evade=true;} else if (view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend&&(view[CCW[xn+5]].ant.food>0)){evade=true;}if (evade){if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else {return NOP;}} else {return NOP;}}} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else {var cc=rearWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};}return NOP;}function rLRLTc(){if (view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend&&
dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else {return NOP;}}function rLRRTc(){if (view[CCW[xn+7]].ant&&view[CCW[xn+7]].ant.friend&&dOK[CCW[xn]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else {return NOP;}}function rMNGTc(){for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==ASF)){if (view[CCW[i]].color==LCLR){if (i&1){if ((view[CCW[i+3]].color==LG5)&&dOK[CCW[i+3]]){return {cell:CCW[i+3]};}} else {if ((view[CCW[i+4]].color==LG6)&&dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else if ((view[CCW[i+3]].color==LG5)&&dOK[CCW[i+3]]){return {cell:CCW[i+3]};}}return (rLostMSy(true));} else if (dOK[CCW[i+1]]){return {cell:CCW[i+1]};}}}return NOP;}function rELGTc(){var ptrn=PTFRL1G;var msm;for (var i=0; i<TN; i+=2){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==ASF)){xn=i;break;}}msm=patC(ptrn,AIMU,0,1);if (xn<0){return NOP;} else if ((msm==0)&&dOK[CCW[xn+5]]&&((view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend)||
(view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend))){return {cell:CCW[xn+5]};} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (msm>0){var cc=rearWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else {return NOP;}return NOP;}function rEBRTc(){var ptrn;var msm;if (mC==LRL0){for (var i=0; i<TN; i+=2){var c=CCW[i];if ((view[c].color==LRM0)&&view[c].ant&&view[c].ant.friend&&((view[CCW[i]].ant.type==AJM)||(view[CCW[i]].ant.type==ASM))){ptrn=PTFRL2;msm=patC(ptrn,AIMU,1,1);if (xn>=0){break;}}}if (xn<0){ptrn=PTFRL0;msm=patC(ptrn,AIMU,1,1);}if (xn<0){ptrn=PTFRL2;msm=patC(ptrn,AIMU,1,1);}if ((xn<0)&&(eT>0)){ptrn=PTFRL1;msm=patC(ptrn,AIMU,1,1);}if (xn<0){return rECLRETc();}} else if (mC==LRL1){ptrn=PTFRL1;msm=patC(ptrn,AIMU,1,1);if ((xn<0)&&(eT>0)){ptrn=PTFRL2;msm=patC(ptrn,AIMU,1,1);}if ((xn<0)&&(eT>0)){ptrn=PTFRL0;msm=patC(ptrn,AIMU,1,1);}if (xn<0){return rECLRETc();}} else if ((mC==LRR2)&&(sL[LRL1]>=1)&&(sL[LRL0]==0)){return {cell:POSC,color:LRL0};}if ((msm==0)&&dOK[CCW[xn+5]]&&((view[CCW[xn+3]].ant&&view[CCW[xn+3]].ant.friend)||
(view[CCW[xn+4]].ant&&view[CCW[xn+4]].ant.friend))){return {cell:CCW[xn+5]};} else if (msm<0){var cc=fwdWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else if (msm>0){var cc=rearWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};} else {return NOP;}return NOP;}function rECLRETc(){var ptrn;var msm;for (var i=3; i<TN+2; i+=2){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
((view[CCW[i]].ant.type==AJM)||(view[CCW[i]].ant.type==ASM))){xn=i-3;if (mC==LRL0){ptrn=PTFRL0;msm=patC(ptrn,AIMR,1,0.3);if (msm==PTNOM){ptrn=PTFRL2;msm=patC(ptrn,AIMR,1,0.3);}} else if (mC==LRL1){ptrn=PTFRL1;msm=patC(ptrn,AIMR,1,0.3);}if (msm>0){var cc=rearWrong[0];return {cell:cc.v,color:fixup(ptrn[cc.p])};}return NOP;}}return NOP;}function patC(ptrn,targetCell,qG,wt){if (xn>=0){return (patCO(ptrn,targetCell,qG,wt,xn));} else {var msm;for (var o=0; o<TN; o+=2){msm=patCO(ptrn,targetCell,qG,wt,o);if (xn>=0){return msm;}}return PTNOM;}}function patCO(ptrn,targetCell,qG,wt,ortn){var fwdFCs=FWD_CELLS[targetCell];var totDscs=0;fwdWrong=[];rearWrong=[];if ((Array.isArray(ptrn[POSC])&&!ptrn[POSC][mC])||
((ptrn[POSC]>0)&&(mC!=ptrn[POSC]))){if (fwdFCs[POSC]){fwdWrong.push({p:POSC,v:POSC});totDscs+=1;} else {rearWrong.push({p:POSC,v:POSC});totDscs+=wt;}}if ((xn<0)&&(totDscs>qG)){return PTNOM;}var jFrom=0;switch (targetCell){case AIMU:jFrom=4;break;case AIML:jFrom=6;break;case AIMR:jFrom=2;break;case AIMD:case POSC:default:break;}for (var j=jFrom; j<TN+jFrom; j++){var posP=CCW[j];var posV=CCW[ortn+j];var c=view[posV].color;if ((Array.isArray(ptrn[posP])&&!ptrn[posP][c])||
((ptrn[posP]>0)&&(c!=ptrn[posP]))){if (fwdFCs[posP]){fwdWrong.push({p:posP,v:posV});totDscs+=1;} else {rearWrong.push({p:posP,v:posV});totDscs+=wt;}}if ((xn<0)&&(totDscs>qG)){return PTNOM;}}if ((xn<0)){xn=ortn;}if (fwdWrong.length==0){return (totDscs);} else {return (-totDscs);}}function isQc0(color){return (LCRQCVAL[color]&&(LCRQC_VALUE[color]==0));
}function isQc2(color){return (LCRQCVAL[color]&&(LCRQC_VALUE[color]==2));
}function incQc(color){if (LCRQCVAL[color]){if (LCRQC_VALUE[color]>=QCPERD){return LCRQC[0];} else {return (LCRQC[(LCRQC_VALUE[color]+1) % QCPERD]);
}} else {return undefined;}}function isSc0(color){return (LCRSCVAL[color]&&(LCRSC_VALUE[color]==0));
}function isSc1(color){return (LCRSCVAL[color]&&(LCRSC_VALUE[color]==1));
}function incSc(color){if (LCRSCVAL[color]){return (LCRSC[(LCRSC_VALUE[color]+1) % SCPERD]);
} else {return undefined;}}function spcMS(){return (((mC==LCLR)||((mF+fdL>0)&&(mC==LMMF))||((mF>0)&&(mC==LMMH)))&&(sN[LMR0]+sN[LML1] +sN[LMR2]+sN[LML3]>=2)&&(sN[LCLR]>=3)&&(sN[LMMF] +sN[LMMH] +sN[PB]<=3)); }function spcRM(){return (LCRGRM_ALL[mC]&&(sT[LRL0]+sT[LRL1]>=3)&&(sN[LRL0]>=1)&&(sN[LRR0]+sN[LRR2]>=2)&&(sT[LRM0]+sT[LRM1_WRP] +sT[LRM1]+sT[LRM2]>=2)&&(sT[LCLR]<=4));}function spcRL1(){return ((mC==LRL1)&&(sL[LRL0]>=2)&&(sD[LRM0]>=1)&&(sL[LRM1_WRP]+sL[LRM1]>=1)&&(sD[LRM2]>=1));}function spcRL02(){return ((mC==LRL0)&&(sL[LRL1]+sL[LRL2]>=2)&&(sN[LRM0]>=1)&&(sD[LRM1_WRP]+sD[LRM1]>=1));}function spcRR0(){return ((mC==LRR0)&&(sL[LRM1]==0)&&(sD[LRM1]+sD[LRM1_WRP]>=1)&&(sL[LMR0]>=1)&&(sL[LRR2]>=1));}function spcRR1(){return (LCRGRR1[mC]&&(sN[LRR0]>=2)&&(sL[LRR2]>=1)&&(sD[LRM0]>=1)&&(sN[LCLR]<=3)&&(sL[LRM1] +sL[LRM1_WRP]>=1));}function spcRR2(){return ((mC==LRR2)&&(sD[LCLR]>=1)&&(sD[LRM0]>=1)&&(sD[LRM1]+sD[LMR0]>=2)&&(sL[LRR0]>=2));}function spcMS0R(){return((mC==LCLR)&&(sL[LMR0]>=1)&&(sL[LRR1U]>=1)&&(sD[LRR2]>=1)&&(sD[LRR0]>=1));}function spcMS0ROut(){return ((mC==LCLR)&&(sL[LMR0]+sL[LRR1V]>=2)&&(sD[LRR2]>=2)&&(sD[LRR0]>=1));}function spcMS0W(){return ((mC==LCLR)&&(sD[LRL0]>=3)&&(sL[LRL1]>=1)&&(sL[LMS_WRP]>=2)&&(sN[LCLR]>=2));}function spcMFL(){return ((sL[LMMF]>=1)&&(sD[LMMH]>=1)&&(sT[LCLR]>=2)&&(sT[LML1]+sT[LML3]>=1));}function spcMFR(){return ((sL[LMMF]>=1)&&(sD[LMMH]>=1)&&(sT[LCLR]>=2)&&(sT[LMR0]+sT[LMR2]>=1));}function fixup(ptrnCell){if (Array.isArray(ptrnCell)){for (var i=1; i<=9; i++){if (ptrnCell[i]){return i;}}return LCLR;} else {return ptrnCell;}}

(ট্রাইকোপ্লেক্স এবং ডিজাইমার পরামর্শে - যার জন্য অনেক ধন্যবাদ! - এটি পাঠযোগ্যতার ব্যয়ে, পিপিসি আকারের সীমাতে ফিট করার জন্য uglified করা হয়েছে Edit সম্পাদনা: আনবিড্রিজড অরিজিনাল, যথেষ্ট মন্তব্য করা এবং অর্থপূর্ণ পরিবর্তনশীল এবং ফাংশন নাম সহ, এখন উপলব্ধ গিটহাবে ।)

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

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

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

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

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

এমনকি কোনও বড় ক্ষতি ছাড়াই, প্রতিটি গেমটি প্রকাশের সাথে সাথে খনির দক্ষতা অনেক হ্রাস পাবে। প্রাথমিকভাবে, আমরা আশা করি যে অর্ধ আলোর গতিতে একটি খনিজ ড্রিলিং এবং হালকা গতিতে প্রত্যাবর্তন করতে হবে প্রতি 1000 পদক্ষেপে 1 টি খাবার সরবরাহ করা। শেষের দিকে, এটি 1000 চাল হিসাবে প্রতি খনিতে প্রতি 0.12-0.14 খাবারের মতো। দীর্ঘতর রেলগুলি ভ্রমণ, বেশিরভাগ সাদা শ্যাফ্ট প্যাটার্নটি আর বেশিরভাগই সাদা ক্যানভাসে আঁকা এবং শ্যাফ্ট এবং রেলগুলি মেরামত করতে সময় লাগে; খনি শ্রমিকরা আটকা পড়ে, বা হারিয়ে যায় বা প্রতিপক্ষের সাথে পেইন্টবল সংঘর্ষে জড়িয়ে পড়ে।

আমাদের খনিজরা কোনও বড় ট্র্যাফিক জ্যাম থেকে নিজেকে সরিয়ে নেওয়ার চেষ্টা করে।

এবং বন্ধুত্বপূর্ণ অনুপ্রবেশকারীদের মোকাবেলা করার জন্য একটি প্রাথমিক প্রতিরোধ ব্যবস্থা রয়েছে।

আমাদের বাড়ির উঠোনের স্টিমরল করার চেষ্টা করা বাঞ্ছনীয় নয়। আমাদের কর্মীরা আনন্দিত হবে না।

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

CCWএই সংখ্যাটি নিয়ামকের viewসাবস্ক্রিপ্টগুলিতে অনুবাদ করার জন্য একটি অ্যারে ( ) দিয়ে একটি কোণে শুরু হয়ে প্রতিবেশী কক্ষগুলি গণনা করা ঘড়ির কাঁটা হিসাবে বিবেচনা করে implementation যখন আমাদের উত্তরটি অনুভূত করতে আমাদের প্রয়োজন (এবং সক্ষম হয়ে) থাকে, তখন আমরা আমাদের কম্পাস সেট করি, এটি একটি বেস সাবস্ক্রিপ্টCCW। পিঁপড়া ফাংশনটি সর্বদা তার চারপাশের পরিসংখ্যান করে শুরু হয়, বিশেষত বর্ণালী রেকর্ডিংয়ের মাধ্যমে (প্রতিটি বর্ণের প্রায়শই কত ঘন ঘন ঘটে) এবং তারপরে কৌশল এবং কৌশলগুলির বহু-স্তরের সিদ্ধান্তের গাছের সাথে পিঁপড়ার ধরণ এবং পরিস্থিতি দ্বারা শাখা করা হয়। এটি খুব সাধারণ পরিস্থিতি খুব দ্রুত মোকাবেলা করার সময় অদ্ভুত বিশেষ কিছু ক্ষেত্রে পরিচালনা করতে সক্ষম হয়। গাছটির প্রায় 200 টি পাতা রয়েছে যা একটি ঘর আঁকেন বা একটি পদক্ষেপ নিয়ে বা একটি পিঁপড়া তৈরি করে এবং 70 এরও বেশি যা কিছুই করেন না - 2 ^ 27 সম্ভাব্য ভিউ রঙের নিদর্শনগুলি থেকে সম্ভাব্য পিঁপড়ার দ্বারা গুণিত, দর্শনীয় খাবার এবং খাবার বাহিত।

এখানে হাবের জ্যামিতির ASCII রেন্ডারিং রয়েছে:

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   | ^ |MR2|   | v |MR2|   | ^ |   |   |   |   |   |   |   |   |
|   |   |   |   | i |   |   | a | r |  rail 2   |   |   |   |   |   |   |   |
+---+---+---+---+-n-+---+---+-c-+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |ML1|   |   |ML1| a |   |RL0|RM0|RR0|   |   |   |   |   |   |   |
|   |   |   | y | u |   | y | t |   | c | r | g |   |   |   |   |   |   |   |
+---+---+---+---+-s-+---+---+-e-+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |MX | e |MR0|MX | d |MR0|RL2|RM2|RR2|MX |ML1|   |ML3|   |ML1|   |
|   |   |   | c |   | k | y |   | k | c | g | y | c | y |   | c |   | y |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |RR1|RR0|RR2|RR1|RR0|RR2|RR1|RR0|RL1|RM1|RR1|   | shaft in use  |  >|   |
|  r|   | g | y | r | g | y | y | g | g | b | r |   |   |   |   |   |   |   |
+--a+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| <i|RM1|RM0|RM2|RM1|RM0|RM2|RM1|RM0|RL0|RM0|RR0|MR0|   |MR2|   |MR0|   |   |
|  l| b | r | g | b | r | g | b | r | c | r | g | k |   | r |   | k |   |   |
+-- +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|  3|RL1|RL0|RL2|RL1|RL0|RL2|RL1|RL0|*Q*|RL0|RL1|RL2|RL0|RL1|RL2|RL0|RL1|   |
|   | g | c | c | g | c | c | g | c |clk| c | g | c | c | g | c | c | g |r  |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+a--+
|   |   |   |   |   |   |   |G3 |Grd|Sec|RM0|RM1|RM2|RM0|RM1|RM2|RM0|RM1|i >|
|   |   |   |   |   |   |   | k |r/y|clk| r | b | g | r | b | g | r | b |l  |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ --+
|   |   |   |   |   |   |   |G4 |G5 |G6 |RR0|RR1|RR2|RR0|RR1|RR2|RR0|RR1|1  |
|   |   |   |   |   |   |   | r | k | b | g | y | y | g | r | y | g |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |MR0|   |MX |MR0|   |MX |   |   |   |
|   |   |   |   |   |   |   |   |   |   | k |   | y | k |   | c |   |   |   |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

(জুনিয়র খনিজক দ্বারা প্রথম বংশদ্ভুত সময়কালে এবং তার পরে এমএক্স এবং আরআর 1 রঙ দেখানো)।

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

v1.1 অযোগ্যতার জন্য একটি কারণ স্থির করে এবং কয়েকটি ছোটখাট বর্ধন যোগ করে।

v1.2 আরও কয়েকটি সংশোধন এবং বর্ধন যোগ করে।

ভি 1.3 ডেভেরvar মতো কঠোর-মোড কন্ট্রোলারগুলিতে এই কাজটি করার জন্য পূর্বে মিশ্র ঘোষণাগুলি যুক্ত করে ; কোন কার্যকরী পরিবর্তন।

v1.4 রসুনের ব্যবহার সম্পর্কে রানী এবং উদ্যানের মধ্যে একটি ভুল বোঝাবুঝির সমাধান করে (যেমন ভ্যাম্পায়ারগুলি রেল 3 বরাবর আগত তা আবিষ্কার করতে চলেছে), একটি বোকা নিদর্শন-সংজ্ঞা বাগ নিরাময় করে এবং কয়েকটি প্রান্তের ক্ষেত্রে উন্নতি করে।

v1.5 উইন্ডমিলকে একটি নতুন কৌশল শিখিয়েছে - পিঁপড়ে-ফাঁপা দেখতে চান?

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

v1.7 অপ্রাপ্তবয়স্ক স্থিতিস্থাপকতা সমাধানগুলি বাদ দিয়ে একটি লাইটস্পিড- স্টাইল স্টার্টআপ পর্ব ব্যবহার করে, আগে নিষ্পত্তি করার জন্য নয়, তবে খাবারের বৃহত স্টকের সাথে মীমাংসা করতে। (লাইটস্পিডের টেন্ডেমের প্রত্যাশিত খাদ্য ফেরতের হারকে ছাড়িয়ে যাওয়ার জন্য আমাদের min জন খনিকার প্রয়োজন, সুতরাং তাদের সাধ্যের আগে খনির দিকে স্যুইচ করার কোনও অর্থ নেই))

v1.8 লাইটস্পিড-ফেজ লজিকের একটি অচলাবস্থা স্থির করে এবং আরও গুরুত্বপূর্ণ, v1.6 এ প্রবর্তিত একটি স্প্যাগিং বাগটি নিরাময় করে যার ফলে অযোগ্যতার ফলস্বরূপ ঘটেছিল।

ভি 1.9 অন্য একটি বিদেশী অযোগ্যতাযুক্ত বাগটি সংশোধন করে, সাময়িকভাবে শ্যাফটে কিছু যানজটের কেসকে সম্বোধন করে এবং সর্বশেষতম ভ্যাম্পেরিক আবিষ্কারগুলি মোকাবেলা করার চেষ্টা করে।

ভি 2.0 গুরুতর প্রয়োজনে রানিকে একটি বিদ্যমান হাবটি পুরোপুরি ত্যাগ করতে সক্ষম করে, লাইটস্পিড-স্টাইলের স্ক্র্যাম্বলিংয়ের অবলম্বন করে এবং ভাগ্যটি পরে আবার স্থায়ী হয়ে মূল সাইট থেকে দূরে একটি নতুন মিল খুঁজে পায়। অন্যদিকে ভেরিয়েবল-স্পিড ফুড কন্ট্রোলড অসিলিটারের পরীক্ষা-নিরীক্ষার ফলে দৃinc় বিশ্বাসের উন্নতি হয়নি। আরও বেশি খনি শ্রমিককে আগে পাঠানো কিছু প্রতিযোগীদের দুর্ঘটনার হারকে বাড়িয়ে তুলত, তবে আমাদের নিজস্বও। এফসিও কোডটি এখনও রয়েছে তবে আপাতত অক্ষম করা হয়েছে।

v2.1 তিনটি প্রান্তের মামলাগুলিকে সম্বোধন করে যেখানে শ্রমিকরা স্থগিতাদেশের চেয়ে ভাল পদক্ষেপ নিয়েছিল।


মাইনারদের শ্যাফ্টগুলি ট্রেল-ইরেজারের কারণে এটির কারণ: আমার নকশার সাথে এটি খুব কমই সম্ভব নয় যে কোনও ট্রেইল-ইরেজার একটি শ্যাফ্ট আবিষ্কার করলে এর ফলে এটি রেলপথে ফিরে আসে, তবে আপনার কমপক্ষে একটি 50% সুযোগ রয়েছে রেল পথে একটি ট্রেইল-ইরেজারকে নেতৃত্ব দেওয়ার। আমি একটি না পেয়ে কমপক্ষে আধা ঘন্টা আরও ভাল খাদের প্যাটার্নটি অনুসন্ধান
করছিলাম

হ্যাঁ, এটি একটি বিষয়। অন্যদিকে, ট্রেইল-ইরেজারগুলি রেলের সাথে বিরক্ত হতে পারে এবং জিগজ্যাগের পিছনে পিছন থেকে ফিরে প্রাচীরের পাশ দিয়ে চলে যেতে পারে ... কঠিন অঞ্চলে ড্রিলিং করার সময় বিকল্প প্যাটার্নটি আরও দৃust় হয় (যদিও অবর্ণনীয় নয়)।
GNiklasch

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

1
আমি ব্যাখ্যা পছন্দ। স্থানীয় প্রসঙ্গে নির্ভর করে দুটি ভিন্ন আচরণ তৈরি করতে বিশেষত একটি শ্রমিক প্রকার ব্যবহার করা।
ট্রাইকোপলাক্স

1
@ থ্রিচোপল্যাক্স ওফস - মাথা উঁচু করার জন্য ধন্যবাদ! কারণ জানা (দুটি দ্বারা সাবস্ক্রিপ্ট বন্ধ), সিএফ সংখ্যা # 6 । আমি এই উপলক্ষটি কয়েক অন্যান্য সামান্য সংশোধনগুলি পরীক্ষা করার জন্য ব্যবহার করব। কিছু প্রতিক্রিয়া পরীক্ষার পরে কোডটি পুনরায় মিনাইফ করার পরে আমার উত্তর আপডেট করবে।
জিনিক্ল্যাশ

12

কৃষ্ণ গহ্বর

var COLOR=8
var COLOR2=7
var COLOR3=2
var LOCKDOWN=8
var orthogonals = [1, 3, 7, 5]
var isQueen = view[4].ant.type==5
var rotationsCW = [1,2,5,8,7,6,3,0]
var rotationsCCW = [3,6,7,8,5,2,1,0]
var matchStates = [
    {state:[0,0,0,
            0,1,0,
            0,0,0],move:0,back:0,fill:true},
    {state:[1,0,0,
            0,1,0,
            0,0,0],move:1,back:3,fill:true},
    {state:[0,1,0,
            1,0,0,
            0,0,0],move:0,back:0,fill:false},
    {state:[0,1,0,
            0,0,1,
            0,0,0],move:2,back:2,fill:false},
    {state:[0,0,1,
            0,0,1,
            0,1,0],move:8,back:2,fill:false},
    //5:
    {state:[1,0,0,
            1,0,0,
            0,1,0],move:2,back:6,fill:false},
    {state:[0,1,0,
            0,1,0,
            0,0,0],move:2,back:0,fill:false},
    {state:[1,0,0,
            1,1,0,
            0,0,0],move:1,back:6,fill:false},
    {state:[0,1,1,
            0,1,0,
            0,0,0],move:5,back:0,fill:false},
    {state:[0,1,0,
            1,1,0,
            0,0,0],move:2,back:6,fill:false},
    //10:
    {state:[1,1,0,
            0,1,0,
            0,0,0],move:2,back:3,fill:false},
    {state:[1,1,0,
            1,1,0,
            0,0,0],move:2,back:6,fill:false},
    {state:[0,1,1,
            0,1,1,
            0,0,0],move:8,back:0,fill:false},
    {state:[1,1,1,
            0,1,0,
            0,0,0],move:5,back:3,fill:false},
    {state:[1,0,0,
            1,1,0,
            1,0,0],move:1,back:7,fill:false},
    //15:
    {state:[0,1,0,
            1,1,1,
            0,0,0],move:8,back:6,fill:false},
    {state:[1,1,1,
            1,1,0,
            0,0,0],move:5,back:6,fill:false},
    {state:[1,0,0,
            1,1,0,
            1,1,0],move:1,back:8,fill:false},
    {state:[1,1,0,
            1,1,0,
            1,0,0],move:2,back:7,fill:false},
    {state:[1,1,1,
            0,1,1,
            0,0,0],move:8,back:3,fill:false},
    //20:
    {state:[1,1,1,
            0,0,1,
            0,0,1],move:7,back:3,fill:true},
    {state:[1,1,1,
            1,0,0,
            1,0,0],move:5,back:7,fill:true},
    {state:[1,0,0,
            1,0,0,
            1,1,1],move:1,back:5,fill:true},
    {state:[0,0,1,
            0,0,1,
            1,1,1],move:3,back:1,fill:true},
    {state:[1,1,1,
            0,1,1,
            0,0,1],move:7,back:3,fill:true},
    //25:
    {state:[1,1,1,
            1,1,0,
            1,0,0],move:5,back:7,fill:true},
    {state:[1,0,0,
            1,1,0,
            1,1,1],move:1,back:5,fill:true},
    {state:[1,1,1,
            1,1,1,
            0,0,0],move:8,back:6,fill:true},
    {state:[1,1,1,
            1,1,1,
            1,0,0],move:8,back:7,fill:true},
    {state:[1,1,1,
            1,1,0,
            1,1,0],move:5,back:8,fill:true},
    {state:[1,1,1,
            1,1,1,
            1,1,0],move:8,back:8,fill:true},
    //30:
    {state:[1,1,1,
            1,1,1,
            1,0,1],move:7,back:7,fill:true},
    {state:[1,1,1,
            1,1,0,
            1,1,1],move:5,back:5,fill:true},
    {state:[1,0,1,
            1,1,1,
            1,1,1],move:1,back:1,fill:true},
    {state:[1,1,1,
            0,1,1,
            1,1,1],move:3,back:3,fill:true},
    {state:[1,1,1,
            1,1,1,
            1,1,1],move:9,back:9,fill:false},
    //35:
]
function matchesColor(c) {
    return c==COLOR || c==COLOR2 || c==COLOR3 || (view[4] == COLOR3 && c == LOCKDOWN)
}
function matchesNonLineColor(c) {
    return c==COLOR || c==COLOR2
}
function isAnyColor(c) {
    var r=0
    for(var i=0;i<9;i++) {
        if(view[i].color == c) r++
    }
    return r
}
function howManyAnts() {
    var r=0;
    for(var i=0;i<9;i++) {
        if(view[i].ant != null) r++
    }
    return r
}
function deRotate(m, amt) {
    if(m == 4 || m < 0 || m > 8 || amt == 0) return m
    if(amt > 0)
        return rotationsCW[(rotationsCW.indexOf(m)+amt)%8]
    amt = -amt
    return rotationsCCW[(rotationsCCW.indexOf(m)+amt)%8]
}
function deRotateSide(m, amt) {
    return deRotate(m,amt*2)
}
function matchWhileLost(sides) {
    var c=0;
    for(var i=0;i<9;i++) {
        if(view[i].color == COLOR3) c++
        if(view[i].color == COLOR3 && i%2 == 0) c+=10
    }
    if(c == 2) {
        if(view[0].color == COLOR3 || view[2].color == COLOR3 || view[6].color == COLOR3 || view[8].color == COLOR3) {
            return {cell:4,color:COLOR3}
        }
        if(view[0].ant == null)
            return {cell:0}
        if(view[2].ant == null)
            return {cell:2}
        if(view[6].ant == null)
            return {cell:6}
        if(view[8].ant == null)
            return {cell:8}
    }
    c = 0
    sides[4] = 0
    var toMatch =[{state:[1,1,1,
                         2,0,2,
                         0,1,0]},
                 {state:[0,2,1,
                         1,0,1,
                         0,2,1]},
                 {state:[0,1,0,
                         2,0,2,
                         1,1,1]},
                 {state:[1,2,0,
                         1,0,1,
                         1,2,0]}]
    for(var m=0;m<4;m++) {
        var score=0
        for(var j=0;j<9;j++) {
            if(j!=4) {
                if(sides[j] == COLOR3 && toMatch[m].state[j] == 1) {
                    score++
                }
                if(sides[j] != COLOR3 && (toMatch[m].state[j] == 0 || toMatch[m].state[j] == 2)) {
                    score++
                }
                if(sides[j] == COLOR3 && toMatch[m].state[j] == 2) {
                    score--
                }
            }
        }
        if(score >= 6) {
            var clearOrder=[1,0,2]
            for(var r=0;r<clearOrder.length;r++) {
                var s = deRotateSide(clearOrder[r],m)
                if(view[s].color == COLOR3) {
                    if(view[s].ant == null)
                        return {cell:s,color:COLOR}
                    else
                        return {cell:4}
                }
            }
        }
    }
    return null
}
function matchBlueStyle(sides) {
    return null
}
function bestMatch(sides) {
    var c=0;
    for(var i=0;i<9;i++) {
        if(sides[i] > 1) c++
    }
    if(!isQueen && view[4].ant.food > 0) {
        c++
        sides[4] = 8
    }
    if(c <= 1) {
        return {state:matchStates[0],rot:0,fill:matchStates[0].fill}
    }
    c = 0
    while(!matchesColor(sides[0]) && !matchesColor(sides[1]) && c < 4) {
        var s2 = [0,0,0,0,0,0,0,0,0]
        s2[0] = sides[2]
        s2[1] = sides[5]
        s2[2] = sides[8]
        s2[3] = sides[1]
        s2[5] = sides[7]
        s2[6] = sides[0]
        s2[7] = sides[3]
        s2[8] = sides[6]
        sides = s2
        c++
    }
    while(c < 8 && (matchesColor(sides[0]) || matchesColor(sides[1])) && matchesColor(sides[8])) {
        var s2 = [0,0,0,0,0,0,0,0,0]
        s2[0] = sides[2]
        s2[1] = sides[5]
        s2[2] = sides[8]
        s2[3] = sides[1]
        s2[5] = sides[7]
        s2[6] = sides[0]
        s2[7] = sides[3]
        s2[8] = sides[6]
        sides = s2
        c++
    }
    var bestState = null
    var bestMatchScore = -1
    for(var i = 0; i < matchStates.length; i++) {
        var score=0
        for(var j=0;j<9;j++) {
            if(j!=4) {
                if(matchesColor(sides[j]) && matchStates[i].state[j] == 1) {
                    score++
                }
                if(!matchesColor(sides[j]) && matchStates[i].state[j] == 0) {
                    score++
                }
            }
        }
        if(score >= bestMatchScore) {
            //console.log("state " + i + ": " + score);
            bestMatchScore = score
            bestState = matchStates[i]
        }
    }
    return {state:bestState,rot:c,fill:bestState.fill,score:bestMatchScore}
}
function getHighestWorker() {
    var r=0;
    for(var i=0;i<9;i++) {
        if(i != 4 && view[i].ant != null) {
            if(view[i].ant.friend && view[i].ant.type > r) r = view[i].ant.type
        }
    }
    return r
}
function pathLost() {
    var i, j
    var safe = []
    for(var q=0;q<9;q++) {
        if(q != 4 && view[q].ant != null && view[q].ant.friend && (view[q].ant.type > view[4].ant.type && view[4].ant.food == 0 && view[q].ant.type < 5)) {
            if(!matchesColor(view[4].color)) return {cell:4,color:COLOR}
            return {cell:4}
        }
    }
    if (matchesNonLineColor(view[4].color)) {
        var myView = [0,0,0,0,0,0,0,0,0]
        for(var i=0; i < 9; i++) {
            myView[i] = view[i].color
            if(!isQueen && view[4].ant.food > 0 && view[i].food > 0) {
                myView[i] = COLOR;
            }
        }
        var ret = matchWhileLost(myView)
        if(ret == null)
            return {cell:4, color:COLOR3}
        else {
            if(!(view[ret.cell].ant != null && view[ret.cell].ant.friend == false) && (view[4].ant.food == 0 || view[ret.cell].food == 0 || isQueen))
                return ret
        }
    }
    for (i=0; i<view.length; i++) {
        if (view[i].ant === null && (view[4].ant.food == 0 || view[i].food == 0 || isQueen)) {
            safe.push(i);
        }
    }
    for (i=0; i<4; i++) {
        j = (i+2) % 4
        if (matchesNonLineColor(view[orthogonals[i]].color) && view[orthogonals[j]].color == COLOR3) {
            if (view[orthogonals[i]].ant == null) {
                return {cell:orthogonals[i]}
            } else if (safe.length > 0) {
                return {cell:safe[0]}
            } else if (view[0].ant === null && (view[4].ant.food == 0 || view[0].food == 0 || isQueen)) {
                return {cell:0}
            }
        }
    }
    if (view[1].ant === null && (view[4].ant.food == 0 || view[1].food == 0 || isQueen)) {
        return {cell:1}
    } else {
        if(!matchesColor(view[4].color)) return {cell:4,color:COLOR}
        return {cell:4}
    }
}
function isAllyAdjacentTo(view, place) {
    var i = deRotate(place, 1)
    var j = deRotate(place, -1)
    if(view[i].ant != null && view[i].ant.friend && view[i].ant.type < 5) return 1
    if(view[j].ant != null && view[j].ant.friend && view[j].ant.type < 5) return 1
    if(orthogonals.indexOf(place) >= 0) {
        i = deRotate(place, 2)
        j = deRotate(place, -2)
        if(view[i].ant != null && view[i].ant.friend && view[i].ant.type < 5) return 2
        if(view[j].ant != null && view[j].ant.friend && view[j].ant.type < 5) return 2
    }
    return 0
}
function findOpenSpace(pos, dir) {
    if(pos > 8 || pos < 0) return pos
    if(view[pos].ant != null && view[pos].ant.friend && view[4].ant.food == 0) {
        pos=deRotate(pos,4)
    }
    //var inc = dir>0?1:-1
    var b = 0
    while(view[pos].ant != null && b < 8) {
        pos=deRotate(pos,dir)
        b++
    }
    return pos
}
//end functions
function getReturn() {
    var colToPlace=COLOR
    var blueAmt = isAnyColor(COLOR2)
    var myView = [0,0,0,0,0,0,0,0,0]
    for(var i=0; i < 9; i++) {
        myView[i] = view[i].color
        if(!isQueen && view[4].ant.food > 0 && view[i].food > 0) {
            myView[i] = COLOR;
        }
        if(!isQueen && view[4].ant.food == 0 && view[i].ant != null && view[i].ant.food > 0) {
            if(!matchesColor(view[4].color)) return {cell:4,color:COLOR}
            return {cell:4};
            //myView[i] = COLOR;
        }
        if(view[i].ant != null && !view[i].ant.friend) {
            myView[i] = COLOR;
        }
    }
    if(isQueen) {
        for(var i=0; i < 9; i++) {
            if(i != 4 && !matchesColor(view[i].color) && view[i].ant != null) {
                myView[i] = COLOR
            }
        }
    }
    //console.log("view:")
    //console.log(myView)
    //console.log("1")
    var match = bestMatch(myView)
    if(match.state.move != 9) {
        var ctY = 0
        var lastY = -1
        var ctW = 0
        var lastW = -1
        for(var i=0; i < 9; i++) {
            if(view[i].color == COLOR3) {
                myView[i] = 8
                ctY++
                lastY = i
            }
            else if(!matchesColor(view[i].color)) {
                ctW++
                lastW = i
            }
        }
        if(ctY > 0 && isQueen && view[4].ant.food > 0 && ctW >= 1) {
            if(view[4].color != COLOR3 && matchesColor(view[4].color))
                return {cell:4,color:COLOR3}
            var tt = deRotate(lastW,-1)
            if(view[tt].color != COLOR2)
                return {cell:tt,color:COLOR2}
            lastW = findOpenSpace(lastW,1)
            return {cell:lastW}
        }
        else if(ctY >= 2 && ctW >= 3)
            match = bestMatch(myView)
        else if(ctY > 0 && view[lastY].ant == null && ctW >= 3) {
            return {cell:lastY,color:1}
        }
    }
    //console.log("2")
    if(!isQueen) {
        for(var i=0; i < 9; i++) {
            if(view[i].ant != null && view[i].ant.type == 5 && view[i].ant.food > 0 && view[i].ant.food <= 2) {
                if(view[4].ant.type == 4)
                    return {cell:4,color:COLOR2}
                return {cell:4}
            }
        }
    }
    //console.log("3")
    if(blueAmt > 0 && view[4].color != COLOR3 && match.state.move != 9) {
        //console.log("Some blue")
        var mb = match.state.back
        mb = deRotateSide(mb,match.rot)
        if(!isQueen || view[4].ant.food <= 2) {
            var a = deRotate(mb,1)
            var b = deRotate(mb,-1)//TODO should be -1
            //console.log("mb: " + mb + "," + a + "," + b)
            if(mb != 9 && (view[mb].color == COLOR2 || view[4].color == COLOR2 || view[a].color == COLOR2 || view[b].color == COLOR2)) {
                //blue behind
                //console.log("Blue behind")
                colToPlace = COLOR2
            }
            else {
                //console.log("No blue behind")
                //console.log(match)
                var myView2 = [0,0,0,0,0,0,0,0,0]
                //construct a view without blue in it
                for(var i=0; i < 9; i++) {
                    myView2[i] = view[i].color == COLOR2?1:view[i].color
                }
                var match2 = bestMatch(myView2)
                if(match2.state.move == 9 || match2.state == matchStates[0]) {
                    //zero or one black
                    //console.log("<= 1 Black")
                    //console.log(myView2)
                    //console.log(match2.state)
                    colToPlace = COLOR2
                }
                else if(view[4].ant.type != 4) {
                    var mf = match2.state.move
                    mf = deRotateSide(mf,match2.rot)
                    //console.log("mf: " + mf)
                    if(mf != 9 && view[mf].color == COLOR2 && view[mf].ant == null) {
                        //about to move onto blue
                        //console.log("Moving onto blue")
                        //console.log(view)
                        //console.log(myView2)
                        return {cell:mf,color:1}
                    }
                    var clearOrder=[1,3,5,7,0,2,6,8]
                    for(var r=0;r<clearOrder.length;r++) {
                        var s = deRotateSide(clearOrder[r],0)
                        if(view[s].color == COLOR2 && (view[s].ant == null || !view[s].ant.friend || (isQueen && view[4].ant.food == 0))) {
                            //console.log("DIE BLUE SCUM")
                            //console.log(view)
                            //console.log(myView2)
                            return {cell:s,color:1}
                        }
                        else if(isQueen && view[s].ant != null && view[s].ant.friend) {
                            //console.log("Blue Queen")
                            //console.log(view)
                            //console.log(myView2)
                            return {cell:4,color:COLOR2}
                        }
                    }
                }
            }
        }
        //console.log("Nothing happened")
    }
    //console.log("4")
    if(view[4].ant.type <= 2) {
      for(var i=0; i < 9; i++) {
        if(view[i].ant != null && !view[i].ant.friend) {
          var canSeeAlly = isAllyAdjacentTo(view,i)
          if(canSeeAlly == 0) {
            if(view[i].color == LOCKDOWN) {
              var a = deRotate(i, 1)
              var b = deRotate(i, -1)
              if(view[a].color != LOCKDOWN) return {cell:a,color:LOCKDOWN}
              if(view[b].color != LOCKDOWN) return {cell:b,color:LOCKDOWN}
              if(orthogonals.indexOf(i) >= 0) {
                a = deRotate(i, 2)
                b = deRotate(i, -2)
                if(view[a].color != LOCKDOWN) return {cell:a,color:LOCKDOWN}
                if(view[b].color != LOCKDOWN) return {cell:b,color:LOCKDOWN}
              }
            }
            else {
              return {cell:i,color:LOCKDOWN}
            }
            if(view[4].color == LOCKDOWN || view[4].color == COLOR) {
              var ii = deRotate(i,4)
              ii = findOpenSpace(ii,1)
              return {cell:ii}
            }
            return {cell:4,color:COLOR}
          }
          else if(canSeeAlly == 2) {
            var m = deRotate(i, 2)
            var j = deRotate(i, -2)
            if(view[m].ant != null && view[m].ant.friend && view[m].ant.type < 5) return {cell:m,color:LOCKDOWN}
            if(view[j].ant != null && view[j].ant.friend && view[j].ant.type < 5) return {cell:j,color:LOCKDOWN}
          }
          else if(view[4].color == LOCKDOWN || view[4].color == 2) {

          }
          else {
            return {cell:4,color:2}
          }
        }
      }
      for(var i=0; i < 9; i++) {
        if(view[i].ant != null && view[i].ant.friend && (view[i].ant.type > view[4].ant.type && view[4].ant.food == 0)) {
          if(match.state.move == 9)
            return {cell:4}
          if(view[i].ant.type == 5)
            return {cell:4}
          var m = findOpenSpace(i,1)
          if(view[m].ant == null)
            return {cell:m}
          return {cell:4,color:2}
        }
      }
    }
    else if(view[4].ant.type <= 4) {
      for(var i=0; i < 9; i++) {
        if(view[i].ant != null && !view[i].ant.friend) {
          var canSeeAlly = isAllyAdjacentTo(view,i)
          if(canSeeAlly == 0) {
            if(view[i].color == LOCKDOWN) {
              var a = deRotate(i, 1)
              var b = deRotate(i, -1)
              if(view[a].color != LOCKDOWN) return {cell:a,color:LOCKDOWN}
              if(view[b].color != LOCKDOWN) return {cell:b,color:LOCKDOWN}
              if(orthogonals.indexOf(i) >= 0) {
                a = deRotate(i, 2)
                b = deRotate(i, -2)
                if(view[a].color != LOCKDOWN) return {cell:a,color:LOCKDOWN}
                if(view[b].color != LOCKDOWN) return {cell:b,color:LOCKDOWN}
              }
            }
            else {
              return {cell:i,color:LOCKDOWN}
            }
            if(view[4].color == LOCKDOWN || view[4].color == COLOR) {
              var ii = deRotate(i,4)
              ii = findOpenSpace(ii,1)
              return {cell:ii}
            }
            return {cell:4,color:COLOR}
          }
          else if(canSeeAlly == 2) {
                var m = deRotate(i, 2)
                j = deRotate(i, -2)
                if(view[m].ant != null && view[i].ant.friend && view[m].ant.type < 5) return {cell:m,color:LOCKDOWN}
                if(view[j].ant != null && view[j].ant.friend && view[j].ant.type < 5) return {cell:j,color:LOCKDOWN}
          }
          else if(view[4].color == LOCKDOWN || view[4].color == 2) {

          }
          else {
            return {cell:4,color:2}
          }
        }
      }
    }
    else if(view[4].ant.food > 4) {
        for(var i=0; i < 9; i++) {
            if(view[i].ant != null && !view[i].ant.friend) {
                var canSeeAlly = isAllyAdjacentTo(view,i)
                if(canSeeAlly == 0) {
                    var m = findOpenSpace(i,1)
                    if(view[m].ant == null)
                        return {cell:m,type:1}
                    return {cell:4,color:3}
                }
            }
        }
        var high = getHighestWorker()
        if(high >= 3 && view[4].ant.food % 2 == 1 && view[4].ant.food < 40) {
            var typeToSpawn = 1
            if(view[4].ant.food < 10 && high == 4 && view[4].ant.food % 4 == 1) {
                typeToSpawn = 3
            }
            var m = findOpenSpace(0,1)
            var canSeeAlly = isAllyAdjacentTo(view,m)
            if(canSeeAlly == 0 && view[m].ant == null)
                return {cell:m,type:typeToSpawn}
        }
    }
    //console.log("5")
    var m = match.state.move
    if(isQueen && view[4].ant.food > 0 && view[4].ant.food <= 2 && isAnyColor(COLOR2) == 0 && isAnyColor(COLOR3) == 0 && m < 9) {
        var high = getHighestWorker()+1
        var num = howManyAnts();
        //high += Math.max(num-2,0)
        if(high < 5) {
            m = deRotate(m,match.rot+4) //get space behind
            m = findOpenSpace(m,1) //make sure its open
            if(view[m].ant == null && view[m].food == 0)
                return {cell:m,type:high}
            return {cell:4}
        }
        else {
            //return {cell:9}
            colToPlace = COLOR2
        }
    }
    if(!isQueen && view[4].ant.food > 0 /*&& view[4].ant.type >= 3*/) {
        //console.log("type 3")
        m = match.state.back
        //console.log(m)
        colToPlace = COLOR
    }
    if(view[4].ant.type == 3) {
        colToPlace = COLOR
    }
    //console.log("6")
    if(!matchesColor(view[4].color) && !(!isQueen && view[4].ant.food)) {
        //console.log("6a")
        /*for(var j=0; j < 9; j++) {
            if(j != 4 && view[j].ant != null && view[j].ant.friend && view[j].ant.food > 0 && j != match.back) {
                m = match.state.move
                if(m < 9) {
                    m = findOpenSpace(m,1)
                    if(view[m].ant == null)
                        return {cell:m}
                    return {cell:4}
                }
                return {cell:4,color:colToPlace}
            }
        }*/
        if(isQueen && view[4].color == LOCKDOWN) {
          m = deRotateSide(m,match.rot)
          m = findOpenSpace(m,1)
          return {cell:m}
        }
        return {cell:4,color:colToPlace}
    }
    if(match.fill && !matchesColor(view[4].color)) {
        return {cell:4,color:colToPlace}
    }
    if(m >= 9) {
        if(!matchesColor(view[4].color)) {
            return {cell:4,color:COLOR}
        }
        //console.log("lost! " + view[4].ant.food);
        //console.log(pathLost());
        return pathLost()
    }
    //console.log("7")
    //console.log("m0: " + m + "+" + match.rot)
    m = deRotateSide(m,match.rot)
    //console.log("m1: " + m)
    m = findOpenSpace(m,1)
    //console.log("m2: " + m)
    if(view[4].ant.food > 0 && !matchesColor(view[4].color) /*&& (view[4].ant.type >= 3)*/) {
        var anyFood = false
        for(var x=0;x<9;x++) {
            if(view[x].food > 0) anyFood = true;
        }
        if(!anyFood)
            return {cell:4,color:colToPlace}
    }
    //console.log("m3: " + m)
    m = findOpenSpace(m,1)
    //console.log("m4: " + m)
    if((!isQueen && view[4].ant.food > 0 && view[m].food > 0) && view[m].ant == null) return {cell:4}
    return {cell:m}
}
var ret = getReturn()
ret = sanityCheck(ret)
return ret
function sanityCheck(ret) {
    if(!ret || ret.cell < 0 || ret.cell > 8 || (ret.cell != 4 && (ret.color == null || ret.color == 0) && view[ret.cell].ant != null) || (view[ret.cell].food > 0 && (view[4].ant.food > 0 && view[4].ant.type < 5))) {
        return {cell:4}
    }
    if(ret.type && (view[ret.cell].ant != null || view[ret.cell].food > 0)) {
        return {cell:4}
    }
    return ret;
}

এটি একটি বিশাল, বিশাল পিঁপড়া ফাংশন। এটি এটি করে:

ব্ল্যাকহোল

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

bestMatch()পিপড়া দ্বারা পরিদর্শন করা (পরিবর্তনযোগ্য) নেয় এবং সেরা ম্যাচটি খুঁজে পায় এবং সেরা ম্যাচটি matchStatesফিরিয়ে দেয়।

ক্যানি চারদিকে ঘোরাতে গিয়ে একটা কাজ করে, কালো করে ফেলে:

  • শ্রমিক তৈরি করুন যতক্ষণ না সে একজন রানী হয়ে এমন কোনও কর্মী তৈরি করতে যান, তারপরে নীল রঙ পরিবর্তন করা যায়। পরিবর্তে নীল কাছাকাছি জায়গাগুলি নীল দেখায় এমন কোনও রঙ রাখার কোনও পিঁপড়।
  • রানী, যদি সে নীল দেখায়, খাবার খায়।

টাইপ 1 এবং 2 কর্মীরা রান্নার মতো খাবার খুঁজে না পাওয়া পর্যন্ত কাজ করে, তারপর তারা বৃত্তের চারপাশে হাঁটা এবং রানিকে খাবার না দেওয়া পর্যন্ত তারা রঙ ছেড়ে দেওয়া ছেড়ে দেয়।

টাইপ 3 এবং 4 কর্মীরা খাবার খুঁজে না পাওয়া পর্যন্ত রানির মতো কাজ করে, তারপর তারা বৃত্তের চারপাশে পিছনে কাজ করে (এখনও রঙ রাখছে) যতক্ষণ না তারা রানীর হাতে খাবার না দেয় off

যে কোনও পিঁপড়ে নিজেকে আবিষ্কার করে সেগুলি হারিয়ে যায় pathLost()যা একটি স্মার্ট স্ট্রেইট লাইনের অ্যালগরিদম (এটি লিটারালিভাবে কিছুটা টুইটের সাহায্যে মেটা থেকে স্মার্ট সোজা পথের কাজ )।

সেই টুইটগুলি হ'ল:

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

ক্রসওভার উদাহরণ

এর বাইরে, বাকী বেশিরভাগটি হ'ল ত্রুটিটি নিশ্চিত করার জন্য যে কোনও পিঁপড়েরা অবৈধ ক্রিয়াকলাপ না করে (অন্যান্য পিঁপড়ির দিকে চলেছে, খাবারের দিকে চলেছে, খাবারে পিঁপড়াগুলি ছড়িয়ে দিচ্ছে ...) যদিও কোডের বিভাজনকে পরিচালনা করার ক্ষেত্রে সবচেয়ে বড় ত্রুটি নীচে রয়েছে although :

if(view[4].ant.food > 0 && !matchesColor(view[4].color) && (view[4].ant.type >= 3) || surroundingColor > 6) {
  var anyFood = false
  for(var x=0;x<9;x++) {
    if(view[x].food > 0) anyFood = true;
  }
  if(!anyFood)
    return {cell:4,color:colToPlace}
}

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

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

আপডেট 7/23

নির্দিষ্ট প্রান্ত-ক্ষেত্রে কিছু সমস্যা লক্ষ্য করা গেল, যেমন:

রানী কোনও শত্রুর দিকে যেতে চায়

এবং এটি অ্যাকাউন্টে খুব ছোটখাট টুইট করেছেন। মূলত, শত্রু পিঁপড়া এবং বোঝা শ্রমিকদের রঙিন টাইল হিসাবে গণ্য করুন।

আপডেট 7/26

ফক্স, আমি আরও কিছু জানি না।

  • আরও শক্তিশালী হওয়ার জন্য টুইকেড-হারিয়ে যাওয়া-হলুদ-ট্রেইল-ত্রুটি হ্যান্ডলিং
  • টুইকড বন্ধু-পাথ-সংঘর্ষ হ্যান্ডলিং আরও শক্তিশালী হতে
  • ট্রেল ইরেজার নিউট্রালাইজার কোড যুক্ত করা হয়েছে
  • যোগ করা হয়েছে "নীল পথচিহ্নগুলি" সনাক্তকরণ এবং পরিচালনা করার কোড [বিটা]
  • মেড রানী হোর্ড মোডে যাওয়ার পরে শ্রমিকদের উত্পাদন চালিয়ে যান (মাঝে মাঝে, কমপক্ষে)
  • অবৈধ পদক্ষেপ স্যানিটেশন
  • বিবিধ স্প্যাগেটি কোড
  • কনসোল.লগ সরানো হয়েছে
  • অপসারণ হিরোব্রিন
  • সংযোজন ডিস্ক যোগ করা হয়েছে

নতুন স্বীকৃতি ডিস্ক

হলুদ লেজ ছাড়াই:

মাইনাস হলুদ

আপডেট 7/26 পার্ট 2

  • সম্পূর্ণরূপে "নীল দিয়ে আমি কী করব?" কোড
    • অপসারণ ডিস্ক সরানো হয়েছে
  • লবণ এবং মরিচ যোগ করা
  • "আমি কোন পথে মুখোমুখি আছি?" সহ স্থির সমস্যাগুলি সনাক্তকরণ
    • বিজ্ঞপ্তি আকার সরানো
    • বর্গক্ষেত্র আকার যুক্ত করা হয়েছে
      • দেখতে এখন একঘেয়ে লাগছে
  • ট্রেইল-ইরেজারের প্রতিরোধ ক্ষমতা অপসারণ করা হয়েছে
  • "আমি হারিয়ে গেলাম" কোডে স্মার্ট যুক্ত হয়েছে, আটকে যাওয়া পিঁপড়াগুলি হ্রাস করে

আপডেট 7/31

  • অ্যান্টি-ট্রেইল-ইরেজার কোডটি পুনরায় যুক্ত করা হয়েছে (এটি "নীল সরান" আপডেটে হারিয়ে গেছে)
  • স্যানিটি চেক ফাংশনটি অন্যান্য পিঁপড়ার নীচে রঙিন কোষগুলিকে আটকাচ্ছিল
  • আরও ভাল অ্যান্টি-ইরেজার ফিক্স: একক ইরেজারকে মোকাবেলা করার জন্য এখন আর 3 কর্মীর প্রয়োজন নেই

আপডেট 8/4

নাবালিক টুইটগুলি।

  • লকডাউন রঙ এখন কালো
  • সমস্ত পিঁপড়ে খাবার সরবরাহ করতে "পিছনে" হাঁটা হয়। এই যান্ত্রিকরা কম পিঁপড়াকে ট্রেইল-ইরেজারের "বুদবুদ" এর ফাঁদে ফেলে দেবে
  • একে অপরের আটকে না যাওয়া হারানো পিঁপড়াদের ভাল পরিচালনা ling
  • "কেবল উদ্যান" প্রান্তিক হ্রাস 40 এ

দুর্বলতা

  • ইরেজিওর।
  • রঙিন টেম্পারিং।

মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
মার্টিন এন্ডার

12

ভ্যাম্পায়ার এমকে ৮.৮ (পুনরায় ভ্যাম্পড)

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


আমার সমস্ত উত্তরগুলি একই স্তরের নিম্ন-স্তরের সহায়ক ফাংশনগুলি ভাগ করে নিচ্ছে। এই উত্তরের নির্দিষ্ট কোডটি দেখতে "উচ্চ-স্তরের যুক্তি এখানে সন্ধান করুন" অনুসন্ধান করুন।

// == Shared low-level helpers for all solutions ==
var QUEEN = 5

var WHITE = 1
var COL_MIN = WHITE
var COL_LIM = 9

var CENTRE = 4

var NOP = {cell: CENTRE}

var DIR_FORWARDS = false
var DIR_REVERSE = true
var SIDE_RIGHT = true
var SIDE_LEFT = false

function sanity_check(movement) {
    var me = view[CENTRE].ant
    if(!movement || (movement.cell|0) !== movement.cell || movement.cell < 0 || movement.cell > 8) {
        return false
    }
    if(movement.type) {
        if(movement.color) {
            return false
        }
        if((movement.type|0) !== movement.type || movement.type < 1 || movement.type > 4) {
            return false
        }
        if(view[movement.cell].ant || view[movement.cell].food) {
            return false
        }
        if(me.type !== QUEEN || me.food < 1) {
            return false
        }
        return true
    }
    if(movement.color) {
        if((movement.color|0) !== movement.color || movement.color < COL_MIN || movement.color >= COL_LIM) {
            return false
        }
        if(view[movement.cell].color === movement.color) {
            return false
        }
        return true
    }
    if(view[movement.cell].ant && movement.cell != 4) {
        return false
    }
    if(view[movement.cell].food + me.food > 1 && me.type !== QUEEN) {
        return false
    }
    return true
}

function as_array(o) {
    if(Array.isArray(o)) {
        return o
    }
    return [o]
}

function best_of(movements) {
    var m
    for(var i = 0; i < movements.length; ++ i) {
        if(typeof(movements[i]) === 'function') {
            m = movements[i]()
        } else {
            m = movements[i]
        }
        if(sanity_check(m)) {
            return m
        }
    }
    return null
}

function play_safe(movement) {
    // Avoid disqualification: no-op if moves are invalid
    return best_of(as_array(movement)) || NOP
}

var RAND_SEED = (() => {
    var s = 0
    for(var i = 0; i < 9; ++ i) {
        s += view[i].color * (i + 1)
        s += view[i].ant ? i * i : 0
        s += view[i].food ? i * i * i : 0
    }
    return s % 29
})()

var ROTATIONS = [
    [0, 1, 2, 3, 4, 5, 6, 7, 8],
    [6, 3, 0, 7, 4, 1, 8, 5, 2],
    [8, 7, 6, 5, 4, 3, 2, 1, 0],
    [2, 5, 8, 1, 4, 7, 0, 3, 6],
]

function areAdjacent(A, B) {
    if(A == 4 || B == 4 || A == B) return true
    if(A % 2 == 0 && B % 2 == 0) return false
    if(A % 2 == 1 && B % 2 == 0) return areAdjacent(B,A)
    if(A % 2 == 1 && B % 2 == 1) return !(8-A == B || 8-B == A)
    if(A == 0 && (B == 1 || B == 3)) return true
    if(A == 2 && (B == 1 || B == 5)) return true
    if(A == 6 && (B == 3 || B == 7)) return true
    if(A == 8 && (B == 5 || B == 7)) return true
    return false
}

function try_all(fns, limit, wrapperFn, checkFn) {
    var m
    fns = as_array(fns)
    for(var i = 0; i < fns.length; ++ i) {
        if(typeof(fns[i]) !== 'function') {
            if(checkFn(m = fns[i])) {
                return m
            }
            continue
        }
        for(var j = 0; j < limit; ++ j) {
            if(checkFn(m = wrapperFn(fns[i], j))) {
                return m
            }
        }
    }
    return null
}

function identify_rotation(testFns) {
    // testFns MUST be functions, not constants
    return try_all(
        testFns,
        4,
        (fn, r) => fn(ROTATIONS[r]) ? ROTATIONS[r] : null,
        (r) => r
    )
}

function near(a, b) {
    return (
        Math.abs(a % 3 - b % 3) < 2 &&
        Math.abs(Math.floor(a / 3) - Math.floor(b / 3)) < 2
    )
}

function try_all_angles(solverFns) {
    return try_all(
        solverFns,
        4,
        (fn, r) => fn(ROTATIONS[r]),
        sanity_check
    )
}

function try_all_cells(solverFns, skipCentre) {
    return try_all(
        solverFns,
        9,
        (fn, i) => ((i === CENTRE && skipCentre) ? null : fn(i)),
        sanity_check
    )
}

function try_all_cells_near(p, solverFns) {
    return try_all(
        solverFns,
        9,
        (fn, i) => ((i !== p && near(p, i)) ? fn(i) : null),
        sanity_check
    )
}

function ant_type_at(i, friend) {
    return (view[i].ant && view[i].ant.friend === friend) ? view[i].ant.type : 0
}

function friend_at(i) {
    return ant_type_at(i, true)
}

function foe_at(i) {
    return ant_type_at(i, false)
}

function foe_near() {
    for(var i = 0; i < 9; ++ i) {
        if(i !== 4 && view[i].ant && !view[i].ant.friend) {
            return true
        }
    }
    return false
}

function ant_type_near(p, friend) {
    for(var i = 0; i < 9; ++ i) {
        if(i !== 4 && ant_type_at(i, friend) && near(i, p)) {
            return true
        }
    }
    return false
}

function move_agent(agents) {
    var me = view[CENTRE].ant
    var buddies = [0, 0, 0, 0, 0, 0]
    for(var i = 0; i < 9; ++ i) {
        ++ buddies[friend_at(i)]
    }

    for(var i = 0; i < agents.length; i += 2) {
        if(agents[i] === me.type) {
            return agents[i+1](me, buddies)
        }
    }
    return null
}

function grab_nearby_food() {
    return try_all_cells((i) => (view[i].food ? {cell: i} : null), true)
}

function go_anywhere() {
    return try_all_cells((i) => ({cell: i}), true)
}

function colours_excluding(cols) {
    var r = []
    for(var i = COL_MIN; i < COL_LIM; ++ i) {
        if(cols.indexOf(i) === -1) {
            r.push(i)
        }
    }
    return r
}

function generate_band(start, width) {
    var r = []
    for(var i = 0; i < width; ++ i) {
        r.push(start + i)
    }
    return r
}

function colour_band(colours) {
    return {
        contains: function(c) {
            return colours.indexOf(c) !== -1
        },
        next: function(c) {
            return colours[(colours.indexOf(c) + 1) % colours.length]
        },
        prev: function(c) {
            return colours[(colours.indexOf(c) + colours.length - 1) % colours.length]
        }
    }
}

function random_colour_band(colours) {
    return {
        contains: function(c) {
            return colours.indexOf(c) !== -1
        },
        next: function() {
            return colours[RAND_SEED % colours.length]
        }
    }
}

function fast_diagonal(colourBand) {
    var m = try_all_angles([
        // Avoid nearby checked areas
        (rot) => {
            if(
                !colourBand.contains(view[rot[0]].color) &&
                colourBand.contains(view[rot[5]].color) &&
                colourBand.contains(view[rot[7]].color)
            ) {
                return {cell: rot[0]}
            }
        },

        // Go in a straight diagonal line if possible
        (rot) => {
            if(
                !colourBand.contains(view[rot[0]].color) &&
                colourBand.contains(view[rot[8]].color)
            ) {
                return {cell: rot[0]}
            }
        },

        // When in doubt, pick randomly but avoid doubling-back
        (rot) => (colourBand.contains(view[rot[0]].color) ? null : {cell: rot[0]}),

        // Double-back when absolutely necessary
        (rot) => ({cell: rot[0]})
    ])

    // Lay a colour track so that we can avoid doubling-back
    // (and mess up our foes as much as possible)
    if(!colourBand.contains(view[CENTRE].color)) {
        var prevCol = m ? view[8-m.cell].color : WHITE

        var colours = [0, 0, 0, 0, 0, 0, 0, 0, 0]
        for(var i = 0; i < 9; ++ i) {
            ++ colours[view[i].color]
        }

        return {cell: CENTRE, color: colourBand.next(prevCol)}
    }

    return m
}

function checkAllNearEnvirons(colours, buddies) {
        var nearMoves = [victims.length]
        for(var e = 0; e < victims.length; e++) {
                var env = victims[e]
                nearMoves[e] = null
                if(env.near_nest(colours)) {
                        nearMoves[e] = env.near_nest_move(colours, buddies)
                }
        }
        return best_of(nearMoves)
}

function follow_edge(obstacleFn, side) {
    // Since we don't know which direction we came from, this can cause us to get
    // stuck on islands, but the random orientation helps to ensure we don't get
    // stuck forever.

    var order = ((side === SIDE_LEFT)
        ? [0, 3, 6, 7, 8, 5, 2, 1, 0]
        : [0, 1, 2, 5, 8, 7, 6, 3, 0]
    )
    return try_all(
        [obstacleFn],
        order.length - 1,
        (fn, i) => (fn(order[i+1]) && !fn(order[i])) ? {cell: order[i]} : null,
        sanity_check
    )
}

function start_dotted_path(colourBand, side, protectedCols) {
    var right = (side === SIDE_RIGHT)
    return try_all_angles([
        (rot) => ((
            !protectedCols.contains(view[rot[right ? 5 : 3]].color) &&
            !colourBand.contains(view[rot[right ? 5 : 3]].color) &&
            !colourBand.contains(view[rot[right ? 2 : 0]].color) &&
            !colourBand.contains(view[rot[1]].color)
        )
            ? {cell: rot[right ? 5 : 3], color: colourBand.next(WHITE)}
            : null)
    ])
}

function lay_dotted_path(colourBand, side, protectedCols) {
    var right = (side === SIDE_RIGHT)
    return try_all_angles([
        (rot) => {
            var ahead = rot[right ? 2 : 0]
            var behind = rot[right ? 8 : 6]
            if(
                colourBand.contains(view[behind].color) &&
                !protectedCols.contains(view[ahead].color) &&
                !colourBand.contains(view[ahead].color) &&
                !colourBand.contains(view[rot[right ? 6 : 8]].color)
            ) {
                return {cell: ahead, color: colourBand.next(view[behind].color)}
            }
        }
    ])
}

function follow_dotted_path(colourBand, side, direction) {
    var forwards = (direction === DIR_REVERSE) ? 7 : 1
    var right = (side === SIDE_RIGHT)

    return try_all_angles([
        // Cell on our side? advance
        (rot) => {
            if(
                colourBand.contains(view[rot[right ? 5 : 3]].color) &&
                // Prevent sticking / trickery
                !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
                !colourBand.contains(view[rot[0]].color) &&
                !colourBand.contains(view[rot[2]].color)
            ) {
                return {cell: rot[forwards]}
            }
        },

        // Cell ahead and behind? advance
        (rot) => {
            var passedCol = view[rot[right ? 8 : 6]].color
            var nextCol = view[rot[right ? 2 : 0]].color
            if(
                colourBand.contains(passedCol) &&
                nextCol === colourBand.next(passedCol) &&

                // Prevent sticking / trickery
                !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
                !colourBand.contains(view[rot[right ? 0 : 2]].color)
            ) {
                return {cell: rot[forwards]}
            }
        }
    ])
}

function escape_dotted_path(colourBand, side, newColourBand) {
    var right = (side === SIDE_RIGHT)
    if(!newColourBand) {
        newColourBand = colourBand
    }

    return try_all_angles([
        // Escape from beside the line
        (rot) => {
            var approachingCol = view[rot[right ? 2 : 0]].color
            if(
                !colourBand.contains(view[rot[right ? 8 : 6]].color) ||
                !colourBand.contains(approachingCol) ||
                colourBand.contains(view[rot[7]].color) ||
                colourBand.contains(view[rot[right ? 6 : 8]].color)
            ) {
                // not oriented, or in a corner
                return null
            }
            return best_of([
                {cell: rot[right ? 0 : 2], color: newColourBand.next(approachingCol)},
                {cell: rot[right ? 3 : 5]},
                {cell: rot[right ? 0 : 2]},
                {cell: rot[right ? 6 : 8]},
                {cell: rot[right ? 2 : 0]},
                {cell: rot[right ? 8 : 6]},
                {cell: rot[right ? 5 : 3]}
            ])
        },

        // Escape from inside the line
        (rot) => {
            if(
                !colourBand.contains(view[rot[7]].color) ||
                !colourBand.contains(view[rot[1]].color) ||
                colourBand.contains(view[CENTRE].color)
            ) {
                return null
            }
            return best_of([
                {cell: rot[3]},
                {cell: rot[5]},
                {cell: rot[0]},
                {cell: rot[2]},
                {cell: rot[6]},
                {cell: rot[8]}
            ])
        }
    ])
}

function latch_to_dotted_path(colourBand, side) {
    var right = (side === SIDE_RIGHT)

    return try_all_angles([
        (rot) => {
            var approachingCol = view[rot[right ? 2 : 0]].color
            if(
                colourBand.contains(approachingCol) &&
                view[rot[right ? 8 : 6]].color === colourBand.next(approachingCol) &&
                !colourBand.contains(view[rot[right ? 5 : 3]].color)
            ) {
                // We're on the wrong side; go inside the line
                return {cell: rot[right ? 5 : 3]}
            }
        },

        // Inside the line? pick a side
        (rot) => {
            var passedCol = view[rot[7]].color
            var approachingCol = view[rot[1]].color
            if(
                !colourBand.contains(passedCol) ||
                !colourBand.contains(approachingCol) ||
                colourBand.contains(view[CENTRE].color)
            ) {
                return null
            }
            if((approachingCol === colourBand.next(passedCol)) === right) {
                return best_of([{cell: rot[3]}, {cell: rot[6]}, {cell: rot[0]}])
            } else {
                return best_of([{cell: rot[5]}, {cell: rot[2]}, {cell: rot[8]}])
            }
        }
    ])
}


// == High-level logic begins here ==


var TARGET_COLOURS_ZIG = colour_band([4, 5, 7, 8])
var TARGET_COLOURS_FIREFLY = colour_band([2, 5, 8])
var GROUND_COLOURS_BH = colour_band([2, 7, 8])
var SAFE_COLOURS = random_colour_band([8])

var THIEF = 1
var BOUNCER = 2
var LANCE = 4
var LANCE_TIP = 3

var INITIAL_GATHER = 12

function colour_band_prev(band, base) {
    if(!band.contains(base)) {
        return band.next(WHITE)
    }
    var cur = band.next(base)
    var c
    while((c = band.next(cur)) !== base) {
        cur = c
    }
    return cur
}

function white_near(p) {
    for(var i = 0; i < 9; ++ i) {
        if(near(i, p) && view[i].color === WHITE) {
            return true
        }
    }
    return false
}

function white_near(p, min) {
    var c = 0
    for(var i = 0; i < 9; ++ i) {
        if(near(i, p) && view[i].color === WHITE) {
            if(++c >= min) return true
        }
    }
    return false
}

var TARGET_ARRANGEMENT_RAIL = [
    [8,4,5,8,5,2,4,2,6],
    [8,5,2,4,2,6,6,4,5],
    [4,2,6,6,4,5,8,4,5],
    [6,4,5,8,4,5,8,5,2]
]
var TARGET_NEAR_RAIL = [
    [2,4,0,5,8,0,4,8,0,1], //Not Valid for Worker #1
    [2,6,0,4,5,0,4,5,0,0],
    [4,6,0,2,4,0,5,8,0,0],
    [4,8,0,4,6,0,2,4,0,0],
    [4,5,0,5,2,0,2,6,0,1], //NV 1
    [4,5,0,4,5,0,5,2,0,5], //NV Q
    [5,2,0,2,6,0,4,5,0,0],
    [5,8,0,4,8,0,4,6,0,5]  //NV Q
]
var TARGET_COLOURS_RAIL = colour_band([4,5,2,4])
var rail_miners = {
    name:function() { return "rail_miners"; },
    near_nest: function(colours) {
        var bestScore = 0
        var enemyQueen = false
        // check every rotation for each 3x3 rail possibility
        TARGET_NEAR_RAIL.forEach(function (arrangement) {
            ROTATIONS.forEach(function (rot){
                var sevenVal = 1
                var score = 0
                for(var i = 0; i < 9; i++) {
                    score += arrangement[i] == view[rot[i]].color?1:0
                    score += (arrangement[i] == 0 && view[rot[i]].color == 7)?sevenVal:0
                    score += (arrangement[i] == 0 && !(view[rot[i]].color == 7 || view[rot[i]].color == 1))?-1:0
                    if(arrangement[i] == 0 && view[rot[i]].color == view[rot[i-2]].color) score -= 2
                    if(view[rot[i]].color) sevenVal = 0
                    enemyQueen |= view[i].ant && view[i].ant.type == QUEEN && !view[i].ant.friend
                    if(view[i].ant != null && view[i].ant.friend && view[i].ant.type == THIEF && view[i].color == WHITE) score++
                }
                if(score > bestScore && arrangement[9] != view[4].ant.type) {
                    bestScore = score
                }
            })
        })
        if(bestScore >= (5 - (enemyQueen && view[4].ant.type == 1?1:0))) {
            if(highway.likely_nest(colours)) return false
            return true
        }
        return false
    },
    worth_leeching: function(myFood, buddies) {
        var numFours = 0
        var foodNeed = 11
        for(var i = 0; i < 9; i++) {
            if(foe_at(i) == 4) numFours++
        }
        if(!buddies[THIEF]) return false
        if(view[4].ant.type != 5 && buddies[QUEEN] && myFood < 500 && myFood+buddies[THIEF] > (foodNeed-numFours*3)) return true
        return myFood < 500 && myFood >= (foodNeed-numFours*3)
    },
    near_nest_move: function(colours, buddies) {
        var victim_pos = -1
        var avoid_pos = -1
        var friend_pos = -1
        for(var i = 0; i < 9; i++) {
            if(foe_at(i) == QUEEN) victim_pos = i
            if(foe_at(i) > 0 && foe_at(i) < 4) avoid_pos = i
            if(friend_at(i) == THIEF) friend_pos = i
        }
        if(victim_pos >= 0) return rail_miners.follow_victim(view[4].ant, buddies, colours, victim_pos)
        if(view[4].ant.type == THIEF && buddies[QUEEN]) return NOP
        if(view[4].ant.type == QUEEN && rail_miners.worth_leeching(view[4].ant.food, buddies)) {
            if(avoid_pos >= 0 && view[4].color != WHITE) {
                return best_of([
                    try_all_angles.bind(null, [
                        (rot) => (friend_at(rot[1]) === THIEF ? {cell: rot[0]} : null),
                        (rot) => (friend_at(rot[0]) === THIEF ? {cell: rot[3]} : null)
                    ]),
                    try_all_angles.bind(null, [
                        (rot) => (friend_at(rot[1]) === THIEF ? {cell: rot[2]} : null),
                        (rot) => (friend_at(rot[0]) === THIEF ? {cell: rot[1]} : null)
                    ]),
                    NOP
                ])
            }
            var allowed = [[8,4,8],[4,6,8],[6,8,4],[5,5,6],[6,5,2],[2,6,5]]
            var curr = [view[4].color,view[friend_pos].color,view[8-friend_pos].color]
            var found = false
            allowed.forEach(function (al) {
                if(al[0] == curr[0] && al[1] == curr[1] && al[2] == curr[2]) {
                    found = true
                }
            })
            if(!found) {
                return best_of([
                    try_all_angles.bind(null, [
                        (rot) => (friend_at(rot[1]) === THIEF && [2,4,5].indexOf(view[rot[2]].color) >= 0 ? {cell: rot[2]} : null),
                        (rot) => (friend_at(rot[1]) === THIEF && [2,4,5].indexOf(view[rot[0]].color) >= 0 ? {cell: rot[0]} : null)
                    ]),
                    NOP
                ])
            }
            return NOP
        }
        return null
    },
    likely_nest: function(colours) {
        var bestScore = 0
        // check every rotation for each 3x3 rail possibility
        var q = 0
        TARGET_ARRANGEMENT_RAIL.forEach(function (arrangement) {
            var j = 0
            ROTATIONS.forEach(function (rot){
                var score = 0
                for(var i = 0; i < 9; i++) {
                    score += arrangement[i] == view[rot[i]].color?1:0
                    if(view[i].ant != null && view[i].ant.friend && view[i].ant.type == THIEF && view[i].color == WHITE) score++
                }
                if(score > bestScore) {
                    bestScore = score
                }
                j++
            })
            q++
        })
        if(view[4].ant.type == THIEF && rail_miners.near_nest(colours)) return true
        if(bestScore >= 7) {
            if(highway.likely_nest(colours)) return false
            return true
        }
        return false
    },

    likely_victim: function(victim_pos) {
        return true
    },

    follow_victim: function(me, buddies, colours, victim_pos) {
        if(me.type == QUEEN) {
            if(victim_pos % 2 == 0) {
                return best_of([
                    try_all_angles.bind(null, [
                        (rot) => (foe_at(rot[0]) === QUEEN && friend_at(rot[5]) == THIEF ? {cell: rot[2]} : null),
                        (rot) => (foe_at(rot[0]) === QUEEN /*&& friend_at(rot[7]) == THIEF*/ ? {cell: rot[6]} : null)
                    ]),
                    NOP
                ])
            }
            else {
                return best_of([
                    try_all_angles.bind(null, [
                        (rot) => (foe_at(rot[1]) === QUEEN && friend_at(rot[2]) == THIEF ? {cell: rot[5], type: THIEF} : null),
                        (rot) => (foe_at(rot[1]) === QUEEN ? {cell: rot[3], type: THIEF} : null),
                        (rot) => (foe_at(rot[1]) === QUEEN ? {cell: rot[5], type: THIEF} : null),
                        (rot) => (buddies[THIEF] < 4 && foe_at(rot[1]) === QUEEN ? {cell: rot[2], type: THIEF} : null),
                        (rot) => (buddies[THIEF] < 4 && foe_at(rot[1]) === QUEEN ? {cell: rot[0], type: THIEF} : null)
                    ]),
                    NOP
                ])
            }
        }
        return NOP
    },
    find_victim: function(me, buddies, colours) {
        var forwardCell = -1
        var current = view[CENTRE].color
        var target = TARGET_COLOURS_RAIL.next(current)
        var antitarget = TARGET_COLOURS_RAIL.prev(current)
        var queenPos = -1
        for(var i = 0; i < 9; i++) {
            if(i % 2 == 1 && view[i].color == target && view[8-i].color == antitarget && current != WHITE){
                forwardCell = i
            }
            if(friend_at(i) == QUEEN) queenPos = i
        }
        if(forwardCell < 0 && current == 4) {
            target = 4
            antitarget = 2
            for(var i = 0; i < 9; i++) {
                if(i % 2 == 1 && view[i].color == target && view[8-i].color == antitarget){
                    forwardCell = i
                }
            }
        }
        if(me.type == QUEEN) {
            var numEn = 0
            for(var i = 0; i < 9; i++) {
                if(i % 2 == 1 && friend_at(i) == THIEF && friend_at(8-i) == THIEF){
                    if(foe_at(deRotate(i,1)) > 0)
                        return {cell:forwardCell}
                    if(foe_at(deRotate(i,-1)) > 0)
                        return {cell:forwardCell}
                    return NOP
                }
                if(i % 2 == 0 && friend_at(i) == THIEF && friend_at(deRotate(i,2)) == THIEF){
                    return {cell:deRotate(i,3), type:THIEF}
                }
            }
            return wilderness.find_victim(me, buddies, colours)
        }
        else if(forwardCell >= 0) {
            if(friend_at(forwardCell) == QUEEN) {
                return best_of([
                    try_all_angles.bind(null, [
                        (rot) => (friend_at(rot[1]) === QUEEN ? {cell: rot[0]} : null),
                        (rot) => (friend_at(rot[0]) === QUEEN ? {cell: rot[3]} : null)
                    ]),
                    go_anywhere
                ])
            }
        }
        else if(queenPos>=0 && view[queenPos].color == WHITE && (foe_at(deRotate(queenPos,2)) && foe_at(deRotate(queenPos,-2)))) {
            return wilderness.find_victim(me, buddies, colours)
        }
        if(me.type == THIEF && forwardCell >= 0 && buddies[THIEF] == 1) {
            return wilderness.find_victim(me, buddies, colours)
        }
        return NOP
    }
}

var TARGET_ARRANGEMENT_WIND = [
        [5,4,0,7,6,0,6,4,0],
        [7,6,0,6,4,0,5,4,0],
        [6,4,0,5,4,0,7,6,0]
]
var TARGET_ARRANGEMENT_WINDCENTER = [
        [2,7,6,2,6,4,6,5,4],
        [2,6,4,6,5,4,2,7,6],
        [6,5,4,2,7,6,2,6,4]
]
var WIND_BAND = colour_band([5,6,7])
var windmill = {
    name:function() { return "windmill"; },
    near_nest: function(colours) { return false; },
    near_nest_move: function(colours, buddies) { return null; },
    likely_nest: function(colours) { // Main nest detection
        var bestScore = 0
        // check every rotation for each 3x3 rail possibility
        TARGET_ARRANGEMENT_WIND.forEach(function (arrangement) {
            ROTATIONS.forEach(function (rot){
                var score = 0
                for(var i = 0; i < 9; i++) {
                    score += arrangement[i] == view[rot[i]].color?1:0
                }
                if(score > bestScore) {
                    bestScore = score
                }
            })
        })
        if(bestScore >= 5 && view[4].ant.type != THIEF) {
            return true
        }

        var bestScore = 0
        // check every rotation for each 3x3 rail possibility
        TARGET_ARRANGEMENT_WINDCENTER.forEach(function (arrangement) {
            ROTATIONS.forEach(function (rot){
                var score = 0
                for(var i = 0; i < 9; i++) {
                    score += arrangement[i] == view[rot[i]].color?1:0
                }
                if(score > bestScore) {
                    bestScore = score
                }
            })
        })
        if(bestScore >= 8) {
            return true
        }
        var buddies = [0, 0, 0, 0, 0, 0]
        for(var i = 0; i < 9; ++ i) {
            ++ buddies[friend_at(i)]
        }
        return buddies[LANCE] || buddies[LANCE_TIP]
    },
    worth_leeching: function(myFood, buddies) {
        if(view[4].ant.type == THIEF && (buddies[LANCE] > 0 || buddies[LANCE_TIP] > 0)) return true
        return myFood > 5 || (myFood > 1 && buddies[LANCE])
    },
    likely_victim: function(victim_pos) {
        return false
    },

    follow_victim: function(me, buddies, colours, victim_pos) {
        // nest is chaotic and varies by direction of approach
        // We'll let the Find Victim logic handle this
        return NOP
    },

    find_victim: function(me, buddies, colours) {
        if(me.type == THIEF) {
            var queenPos = -1
            var lancePos = -1
            var tipPos = -1
            for(var i=0;i<9;i++) {
                if(friend_at(i) == QUEEN) queenPos = i
                if(friend_at(i) == LANCE) lancePos = i
                if(friend_at(i) == LANCE_TIP) tipPos = i
            }
            if(queenPos < 0 || (foe_at(deRotate(queenPos,1)) > 0 && foe_at(deRotate(queenPos,2)) > 0)) {
                if(queenPos < 0)
                    return go_anywhere
                return {cell:8-queenPos}
            }
            if(queenPos % 2 == 1 && tipPos % 2 == 0) {
                return go_anywhere
            }
            if(queenPos % 2 == 0 && lancePos % 2 == 1) {
                return go_anywhere
            }
            if(queenPos % 2 == 1 && foe_at(deRotate(queenPos,-2)) > 0) {
                return go_anywhere
            }
            return NOP
        }
        if(buddies[LANCE_TIP]) {
            var lancePos = -1
            for(var i=0;i<9;i++) {
                if(friend_at(i) == LANCE_TIP) {
                    lancePos = i
                }
            }
            if(buddies[LANCE]) {
                if(friend_at(8-lancePos) == LANCE) {
                    if(foe_at(deRotate(8-lancePos,1)) == 1 || foe_at(deRotate(8-lancePos,2)) == 1) {
                        var ret = NOP
                        if(lancePos % 2 == 1)
                            ret = {cell:deRotate(8-lancePos,-2)}
                        if(lancePos % 2 == 0)
                            ret = {cell:deRotate(8-lancePos,-3)}
                        if(!sanity_check(ret)) {
                            ret = best_of([
                                try_all_cells_near(lancePos, (i) => (ant_type_at(i) == 0 && view[i].color == 6 ? {cell: i} : null), true),
                                NOP
                            ])
                        }
                        return ret
                    }
                    if(foe_at(deRotate(lancePos,-2)) > 0) {
                        return {cell:deRotate(lancePos,2)}
                    }
                    return NOP
                }
                if(friend_at(deRotate(lancePos,3)) == LANCE) {
                    if((view[lancePos].color == 2 && view[4].color == 7) || foe_at(8-lancePos)) {
                        return {cell:deRotate(lancePos,1)}
                    }
                    return NOP
                }
                if(view[4].color == 6 && view[lancePos].color == 6 && friend_at(deRotate(lancePos,1)) == LANCE) {
                    if(foe_at(deRotate(lancePos,2)) > 0) {

                        return {cell:8-deRotate(lancePos,2)}
                    }
                    return NOP
                }
                if(view[lancePos].color == 2 && view[deRotate(lancePos,-3)].color == 5 && friend_at(deRotate(lancePos,-3)) == LANCE) {
                    return NOP
                }
                if(lancePos % 2 == 0) {
                    if(foe_at(deRotate(lancePos,-1)) > 0 && lancePos % 2 == 1) return {cell:deRotate(lancePos,2)}
                    if(view[deRotate(lancePos,-1)].color != 5) return {cell:deRotate(lancePos,-1),color:5}
                    if(view[deRotate(lancePos,-1)].color == 3 && view[4].color == 1) return {cell:4,color:3}
                    if(view[deRotate(lancePos,-1)].color == 5 && view[4].color == 3) return {cell:4,color:2}
                    if(view[deRotate(lancePos,-1)].color == 5 && view[4].color == 2) return {cell:4,color:1}
                    if(view[deRotate(lancePos,-1)].color == 5 && view[4].color == 7 && view[deRotate(lancePos,-1)].ant == null) return {cell:deRotate(lancePos,-1),type:THIEF}
                    if(view[deRotate(lancePos,-1)].color == 5 && view[4].color == 7) return {cell:4,color:3}
                }
                return {cell:deRotate(lancePos,-1)}
            }
            if(view[4].color == WHITE && view[lancePos].color == WHITE) {
                return {cell:deRotate(lancePos,-2),type:BOUNCER}
            }
            if(view[deRotate(lancePos,-1)].ant != null && view[deRotate(lancePos,-1)].ant.type == 5) {
                return {cell:deRotate(lancePos,2)}
            }
            if(view[4].color == 6 && view[deRotate(lancePos,1)].color == 7) {
                return {cell:deRotate(lancePos,1)}
            }
            if(foe_at(deRotate(lancePos,-2)) > 0 || foe_at(deRotate(lancePos,-3)) > 0) {
                if(foe_at(deRotate(lancePos,-2)) > 0 && foe_at(deRotate(lancePos,3)) > 0 && (foe_at(deRotate(lancePos,-1)) > 0 || foe_at(deRotate(lancePos,4)) > 0)) {
                    return {cell:deRotate(lancePos,1)}
                }
                if(foe_at(deRotate(lancePos,3)) > 0) {
                    return NOP
                }
                return {cell:deRotate(lancePos,1)}
            }
            if(foe_at(deRotate(lancePos,2)) > 0 && view[deRotate(lancePos,-1)].color != 2) {
                return {cell:deRotate(lancePos,-1),color:2}
            }
            if(foe_at(deRotate(lancePos,-1)) > 0) {
                return {cell:deRotate(lancePos,1)}
            }
            if(lancePos % 2 == 1 && friend_at(deRotate(lancePos,-1)) == THIEF) {
                return {cell:deRotate(lancePos,-2)}
            }
            return {cell:deRotate(lancePos,-1)}
        }
        else if(buddies[LANCE]) {
            var lancePos = -1
            for(var i=0;i<9;i++) {
                if(view[i].ant && view[i].ant.friend && view[i].ant.type == LANCE) {
                    lancePos = i
                }
            }
            if(view[4].color == 3 && lancePos % 2 == 1) return NOP
            var moveNext = lancePos % 2 == 1 ? {cell:deRotate(lancePos,2)} : {cell:deRotate(lancePos,1)}
            if(view[moveNext.cell].ant != null && !view[moveNext.cell].ant.friend) {
                moveNext = {cell:deRotate(lancePos,1),type:LANCE_TIP}
            }
            if(view[lancePos].ant.food > 0) {
                if(lancePos % 2 == 1)
                    return {cell:deRotate(lancePos,4),type:LANCE_TIP}
                else
                    return {cell:deRotate(lancePos,3),type:LANCE_TIP}
            }
            if(view[lancePos].color == 6 && view[moveNext.cell].color == 8 && view[deRotate(lancePos,2)].color == 5) {
                return {cell:moveNext.cell,type:LANCE_TIP}
            }

            return moveNext
        }
        else {
            var current = view[CENTRE].color
            var standOn = WIND_BAND.next(WIND_BAND.next(WIND_BAND.next(current)))
            var target = WIND_BAND.next(current)
            var antitarget = WIND_BAND.next(target)
            if(current != standOn) return wilderness.find_victim(me, buddies, colours)

            var ret = best_of([
                try_all_cells((i) => ((i % 2 == 1 && view[i].color == target && view[8-i].color == antitarget && ([2,5,6].indexOf(view[deRotate(i,-1)].color) >= 0) && (view[i].color != 5 || view[deRotate(i,1)].color == 4)) ? {cell: i, type: LANCE} : null), true),
                NOP
            ])
            if(ret.cell == 4) {
                return wilderness.find_victim(me, buddies, colours)
            }
            return ret
        }
        return NOP
    }
}

var TARGET_ARRANGEMENT_HIGHWAY = [
    [2,3,7,6,8,2,3,7,6],
    [2,3,7,7,6,4,4,2,3],
    [2,4,6,7,3,2,4,6,7],
    [3,2,4,4,6,7,7,3,2],
    [3,4,7,7,2,6,6,3,4],
    [3,4,7,2,6,3,4,7,2],
    [3,6,2,2,7,4,4,3,6],
    [4,7,2,2,5,6,3,4,7],
    [4,6,7,2,6,3,3,4,7],
    [4,6,7,7,3,2,2,4,6],
    [6,4,2,3,7,6,4,2,3],
    [7,3,2,2,4,6,6,7,3],
    [7,4,3,6,2,7,4,3,5]
]
var HIGHWAY_BAND = colour_band([2,7,4,3,6])
var HIGHWAY_BAND2 = colour_band([2,3,7,6,4])

var highway = {
    name:function() { return "highway"; },                                     // For debugging
    near_nest: function(colours) { return false; },                // For dodging enemy workers without getting lost
    near_nest_move: function(colours, buddies) { return null; }, // How to move when near_nest is true
    likely_nest: function(colours) { // Main nest detection
        var bestScore = 0
        // check every rotation for each 3x3 rail possibility
        TARGET_ARRANGEMENT_HIGHWAY.forEach(function (arrangement) {
            ROTATIONS.forEach(function (rot){
                var score = 0
                for(var i = 0; i < 9; i++) {
                    score += arrangement[i] == view[rot[i]].color?1:0
                }
                if(score > bestScore) {
                    bestScore = score
                }
            })
        })
        if(bestScore >= 7) {
            return true
        }
        if(this.isCenter(colours)) return true

        return false
    },         // Main nest detection
    isCenter: function(colours) {
        var bestScore = 0
        ROTATIONS.forEach(function (rot){
            var score = 0
            for(var i = 0; i < 9; i++) {
                if(i >= 3 && i <= 5 && [2,7,4,3,6].indexOf(view[rot[i]].color) >= 0 && (i == 4 || view[rot[i]].color != view[rot[8-i]].color)) {
                    if(i != 4) {
                        score++
                    }
                    else {
                        if(view[rot[3]].color != view[rot[5]].color && view[rot[1]].color == view[rot[7]].color && (view[rot[4]].color != view[rot[1]].color && view[rot[4]].color != view[rot[3]].color && view[rot[4]].color != view[rot[5]].color && view[rot[4]].color != view[rot[7]].color)) {
                            score++
                        }
                    }
                }
                else if(i >= 6) {
                    if(view[rot[i]].color == view[rot[i-6]].color && [2,7,4,3,6].indexOf(view[rot[i]].color) >= 0 && (i == 7 || view[rot[i]].color != view[rot[8-i]].color) && view[rot[i]].color != view[4].color) {
                        score += 2
                    }
                }
            }
            if(score > bestScore) {
                bestScore = score
            }
        })
        if(bestScore >= 7) {
            return true
        }
        return false
    },
    worth_leeching:function(myFood, buddies){ return myFood > 80 && myFood < 500; }, // Is this nest worth leeching?
    likely_victim: function(victim_pos) {
        return true
    },   // Identifying the target queen
    follow_victim: function(me, buddies, colours, victim_pos) {
        if(me.type == QUEEN && buddies[THIEF] < 3) {
            return best_of([
                try_all_cells((i) => (near(i, victim_pos) ? {cell: i, type: THIEF} : null), true),
                try_all_cells((i) => ({cell: i, type: THIEF}), true)
            ])
        }
        if(me.type == THIEF && buddies[QUEEN])
            return NOP
        return go_anywhere
    },   // How to handle what happens when the enemy queen is found
    find_victim: function(me, buddies, colours) {
        if(me.type == THIEF && !buddies[QUEEN]) {
            for(var i=0;i<9;i++) {
                if(foe_at(i)) return NOP
            }
            var target = HIGHWAY_BAND.prev(view[4].color)
            var followRail = best_of([
                try_all_cells((i) => (i % 2 == 1 && view[i].color == target) ? {cell:i} : null),
                NOP
            ])
        }
        else {
            var target = HIGHWAY_BAND.next(view[4].color)
            var followRail = best_of([
                try_all_cells((i) => (i % 2 == 1 && view[i].color == target) ? {cell:i} : null),
                NOP
            ])
        }
        return followRail
    }                // How to follow the nest
}

var wilderness = {
    name:function() { return "wilderness"; },
    near_nest: function(colours) { return false; },
    near_nest_move: function(colours, buddies) { return null; },
    likely_nest: function(colours) {
        return true
    },
    worth_leeching: function(myFood, buddies) {
        return true
    },
    likely_victim: function(victim_pos) {
        return true
    },

    follow_victim: function(me, buddies, colours, victim_pos) {
        // We stumbled across a random queen; make the most of it
        // TODO
        if(rail_miners.near_nest(colours)) {
            return rail_miners.follow_victim(me, buddies, colours, victim_pos)
        }

        // avoids blocking off the rail miner queen from her workers
        // (we'd like to leech her again)
        if(me.type === QUEEN && !buddies[THIEF] && me.food > 0) {

            // Make a buddy to help us steal
            return best_of([
                try_all_cells((i) => (near(i, victim_pos) ? {cell: i, type: THIEF} : null), true),
                try_all_cells((i) => ({cell: i, type: THIEF}), true)
            ])
        }
        else if(me.type === QUEEN){
            var enemyCount = 0
            var allyPos = -1
            for(var a=0; a<9; a++) {
                if(a != 4 && view[a].ant != null) {
                    if(view[a].ant.friend) {
                        if(near(a,victim_pos)){
                            allyPos = a
                        }
                    }
                    else if(view[a].ant.type != 5) {
                        enemyCount++
                    }
                }
            }
            if(enemyCount >= buddies[THIEF] && allyPos >= 0) {
                //if next to the queen and we're outnumbered, move back to the center of the rail.
                var target = TARGET_COLOURS_RAIL.prev(view[allyPos].color)
                var best = best_of([
                    try_all_cells((i) => (near(i, victim_pos) && i % 2 == 0 ? {cell: i, type: THIEF} : null), true),
                    try_all_cells((i) => (near(i, victim_pos) ? {cell: i, type: THIEF} : null), true)
                ])
                if(best != null) return best

                best_of([
                    try_all_cells((i) => ((view[i].color == target && i != 4 && areAdjacent(i,a)) ? {cell: i} : null))
                ])
                if(best != null) return best

                return best_of([
                    {cell:deRotate(allyPos,1)},
                    {cell:deRotate(allyPos,-1)}
                ])
            }
        }

        return NOP
    },
    find_victim: function(me, buddies, colours) {
        if(me.type === QUEEN) {
            var in_void = true
            for(var i = 0; i < 9; ++ i) {
                if(view[i].color !== WHITE && !SAFE_COLOURS.contains(view[i].color)) {
                    in_void = false
                    break
                }
            }
            if(!in_void) {
                // because of avoiding returning Miner on a Rail workers
                // we dodge sideways and this takes us back onto track
                var nearMove = checkAllNearEnvirons(colours, buddies)
                if(nearMove) return nearMove
            }
            return best_of([
                // Make a buddy once we have a reasonable stash of food so we can
                // search the board faster
                // (but avoid making buddies when there's a potential nest nearby
                // better to wait until we find their queen)
                (!buddies[THIEF] && me.food >= INITIAL_GATHER && in_void) &&
                    try_all_cells((i) => ({cell: i, type: THIEF}), true),

                // Follow buddy in search of victims
                buddies[THIEF] && try_all_angles.bind(null, [
                    (rot) => (friend_at(rot[1]) === THIEF ? {cell: rot[2]} : null),
                    (rot) => (friend_at(rot[0]) === THIEF ? {cell: rot[1]} : null)
                ]),
                buddies[THIEF] && try_all_angles.bind(null, [
                    (rot) => (friend_at(rot[1]) === THIEF ? {cell: rot[0]} : null),
                    (rot) => (friend_at(rot[0]) === THIEF ? {cell: rot[3]} : null)
                ]),
                buddies[THIEF] && NOP, // Don't lose our buddy!

                // Random walk until we can make a buddy or find the victim
                grab_nearby_food,
                foe_near() ? go_anywhere : fast_diagonal.bind(null, SAFE_COLOURS),
                go_anywhere
            ])
        } else if(me.type === THIEF) {
            return best_of([
                // Lost the queen! Random walk because we have nothing better to do.
                // (don't leave lines; they could disrupt the pattern)
                !buddies[QUEEN] && go_anywhere,
                buddies[BOUNCER] && go_anywhere,
                buddies[THIEF] > 1 && go_anywhere, //untested
                // Follow queen in search of victims
                try_all_angles.bind(null, [
                    (rot) => (friend_at(rot[1]) === QUEEN ? {cell: rot[0]} : null),
                    (rot) => (friend_at(rot[0]) === QUEEN ? {cell: rot[3]} : null)
                ]),
                NOP // Don't lose our buddy!
            ])
        }
    }
}

var victims = [highway, rail_miners, windmill]

function guess_environment(colours, buddies) {
    var food = view[4].ant.food
    if(view[4].ant.type !== QUEEN) {
        for(var i = 0; i < 9; i++) {
            if(i != 4 && view[i].ant && view[i].ant.friend && view[i].ant.type === QUEEN) {
                food = view[i].ant.food
            }
        }
    }
    for(var i = 0; i < victims.length; ++ i) {
        if(victims[i].likely_nest(colours) && victims[i].worth_leeching(food, buddies)) {
            return victims[i]
        }
    }

    return wilderness
}

function is_safe(i) {
    var nearThief = false
    var nearOfficer = false
    for(var j = 0; j < 9; ++ j) {
        if(friend_at(j) === THIEF) {
            nearThief = true
        }
        if(foe_at(j) && foe_at(j) !== QUEEN) {
            nearOfficer = true
        }
    }
    return nearThief && !nearOfficer
}

function move(me, buddies) {
    var colours = [0, 0, 0, 0, 0, 0, 0, 0, 0]
    for(var i = 0; i < 9; ++ i) {
        ++ colours[view[i].color]
    }
    var env = guess_environment(colours,buddies)
    var victim_pos = -1
    var queen_pos = -1
    for(var i = 0; i < 9; ++ i) {
        if(foe_at(i) === QUEEN && env.likely_victim(i) && view[i].ant.food > 0) {
            victim_pos = i
            if(view[i].ant.food > 0) {
                break
            }
        }
        if(friend_at(i) === QUEEN) {
            queen_pos = i
        }
    }

    var in_void = true
    for(var i = 0; i < 9; ++ i) {
        if(view[i].color !== WHITE || (i != 4 && me.type === BOUNCER && friend_at(i) === BOUNCER)) {
            in_void = false
            break
        }
    }
    if(me.type === BOUNCER) {
        if(env === wilderness && in_void) {
            // Our work is done; leave queen and wander at random
            if(buddies[QUEEN]) {
                return best_of([
                    try_all_cells((i) => (ant_type_near(i, true) ? null : {cell: i}), true),
                    go_anywhere
                ])
            }
            return NOP
        }
        else if(env === rail_miners) {
            // Our work is done; leave queen and wander at random
            if(buddies[QUEEN]) {
                var allAngles = try_all_angles.bind(null, [
                    (rot) => (friend_at(rot[1]) === QUEEN ? {cell: rot[0]} : null),
                    (rot) => (friend_at(rot[0]) === QUEEN ? {cell: rot[3]} : null),
                    NOP
                ])
                return best_of([
                    //if next to an enemy queen, move out of the way
                    try_all_cells((i) => (foe_at(i) == QUEEN ? {cell:9-i} : null), true),
                    try_all_cells((i) => (foe_at(i) == QUEEN ? {cell:7-i} : null), true),
                    allAngles
                ])
            }
            return NOP
        } else if(buddies[QUEEN]) {
            // Escort queen out of nest
            var allAngles = try_all_angles.bind(null, [
                (rot) => (friend_at(rot[1]) === QUEEN ? {cell: rot[0]} : null),
                (rot) => (friend_at(rot[0]) === QUEEN ? {cell: rot[3]} : null),
                NOP
            ])

            return best_of([
                //if next to an enemy queen, move out of the way
                try_all_cells((i) => (foe_at(i) == QUEEN ? {cell:9-i} : null), true),
                try_all_cells((i) => (foe_at(i) == QUEEN ? {cell:7-i} : null), true),
                allAngles
            ])
        }
        else {
            return go_anywhere
        }
    } else if(buddies[BOUNCER]) {
        if(me.type === QUEEN) {
            // Be escorted out of nest
            return try_all_angles.bind(null, [
                (rot) => (friend_at(rot[1]) === BOUNCER ? {cell: rot[2]} : null),
                (rot) => (friend_at(rot[0]) === BOUNCER ? {cell: rot[1]} : null),
                go_anywhere,
                NOP
            ])
        } else {
            // Get out of the way
            return try_all_angles.bind(null, [
                (rot) => (friend_at(rot[1]) === QUEEN ? {cell: rot[7]} : null),
                (rot) => (friend_at(rot[0]) === QUEEN ? {cell: rot[8]} : null),
                (rot) => (friend_at(rot[1]) === BOUNCER ? {cell: rot[7]} : null),
                (rot) => (friend_at(rot[0]) === BOUNCER ? {cell: rot[8]} : null),
                go_anywhere
            ])
        }
    }
    if(victim_pos !== -1) {
        // abandon the queen if she's dry.
        // abandon rail miner's queen so she has at least 10 food (otherwise she produces workers 3:4 food she aquires)
        // value is higher than 10 because there's two to three rounds of theft (at 4 ants each) before the queen gets out of range
        // this can still leave the rail miner's queen lower than 10, but unlikely
        // other queens are abandoned if they have less than 5 food, due to the "max 4 ants stealing" and at 0 food, she's not a target.
        if(view[victim_pos].ant.food < 5 || (env == rail_miners && view[victim_pos].ant.food < 28)) {
            if(me.type == THIEF) {
                if(rail_miners.near_nest(colours)) {
                    // we'd rather reuse the workers
                    return NOP
                }
            }
            // Victim is out of food; bounce out of nest
            if(env == rail_miners) {
                if(me.type == QUEEN && me.food < 300 && !buddies[BOUNCER]) {
                    if(friend_at(deRotate(victim_pos,2)) == THIEF && foe_at(deRotate(victim_pos,3)) == 0) return {cell:deRotate(victim_pos,3),type:BOUNCER}
                    if(friend_at(deRotate(victim_pos,-2)) == THIEF && foe_at(deRotate(victim_pos,-3)) == 0) return {cell:deRotate(victim_pos,-3),type:BOUNCER}
                }
                // murder SlM
                return NOP
            }
            var m = try_all_cells((i) => ({cell: i, type: BOUNCER}), true)
            if(m) {
                return m
            }
        }
        if(me.type === QUEEN && buddies[THIEF] && !is_safe(CENTRE)) {
            // Try to avoid getting food stolen back from us
            var m = try_all_cells((i) => (is_safe(i) ? {cell: i} : null), true)
            if(m) {
                return m
            }
        }
        return env.follow_victim(me, buddies, colours, victim_pos)
    } else {
        return env.find_victim(me, buddies, colours)
    }
}

// LANCE is only used by windmill targetting, easier to break this out as its own method
function moveLance(me, buddies) {
    var queenPos = -1
    var tipPos = -1
    var enQueenPos = -1
    if(buddies[BOUNCER]) {
        for(var i=0;i<9;i++) {
            if(friend_at(i) == BOUNCER) {
                return {cell:8-i}
            }
        }
    }
    for(var i=0;i<9;i++) {
        if(friend_at(i) == QUEEN) {
            queenPos = i
        }
        if(friend_at(i) == LANCE_TIP) {
            tipPos = i
        }
        if(foe_at(i) == QUEEN) enQueenPos = i
    }
    if(!buddies[QUEEN]) {
        for(var i=0;i<9;i++) {
            if(i % 2 == 0 && friend_at(i) == QUEEN) {
                if(view[deRotate(i,3)].ant != null && view[deRotate(i,3)].ant.friend && view[deRotate(i,3)].ant.type == LANCE_TIP) return NOP
                return {cell:deRotate(i,1)}
            }
        }
        if(!buddies[LANCE_TIP] && !buddies[THIEF] && view[4].color == 2) {
            for(var i = 0; i < 9; ++ i) {
                if(view[i].color == 1) return {cell:i}
            }
        }
        if(enQueenPos >= 0 && enQueenPos % 2 == 0 && foe_at(deRotate(enQueenPos,1)) == 1) {
            return {cell:deRotate(enQueenPos,-3)}
        }
        if(enQueenPos >= 0 && enQueenPos % 2 == 1 && foe_at(deRotate(enQueenPos,2)) == 1) {
            return {cell:8-enQueenPos}
        }
        if(enQueenPos >= 0 && (me.food > 0 || foe_at(deRotate(enQueenPos,-1)) || foe_at(deRotate(enQueenPos,3)))) {
            if(enQueenPos % 2 == 0 && (foe_at(deRotate(enQueenPos,4)) || friend_at(deRotate(enQueenPos,4)) == THIEF)) {
                return {cell:deRotate(enQueenPos,-3)}
            }
        }
        return NOP
    }
    if(buddies[LANCE_TIP]) {
        if(deRotate(queenPos,-1) == tipPos && view[tipPos].color == 8) return {cell:8-tipPos}
        if(deRotate(queenPos,-1) == tipPos) return try_all_cells((i) => (areAdjacent(i,tipPos) && view[i].color == 5 ? {cell:i} : null))
        if(foe_at(8-tipPos) == QUEEN) return {cell:8-tipPos,color:6}
        if(foe_at(8-queenPos) > 0 || foe_at(deRotate(8-queenPos,1)) > 0) return NOP
        return try_all_cells((i) => (!areAdjacent(i,queenPos) && !areAdjacent(i,tipPos) ? {cell:i} : null))
    }
    if(view[4].color != 4 && view[4].color != 6) {
        if(foe_at(8-queenPos) == QUEEN) {
            var formation = try_all_angles.bind(null, [
                (rot) => (foe_at(rot[1]) === 1 && foe_at(rot[2]) === QUEEN ? {cell: rot[3]} : null),
                (rot) => (foe_at(rot[1]) === 1 && foe_at(rot[0]) === QUEEN ? {cell: rot[7]} : null),
                (rot) => (foe_at(rot[1]) === 1 && view[rot[1]].ant.food > 0 && foe_at(rot[6]) === QUEEN && friend_at(rot[2]) === QUEEN ? {cell: rot[5]} : null),
            ])()
            if(formation != null) {
                return formation
            }
            return NOP
        }
        if(foe_at(deRotate(queenPos,1)) > 0 && foe_at(deRotate(queenPos,-1)) > 0) {
            return {cell:deRotate(queenPos,-3)}
        }
        return best_of([
            try_all_cells((i) => (enQueenPos ==-1 && i % 2 == 1 && (view[i].color == 4 || view[i].color == 6) && view[deRotate(i,1)].color != 2 && view[deRotate(i,-1)].color != 2 && areAdjacent(i,queenPos) ? {cell: i} : null), true),
            ((view[4].color != 6 || view[4].color != 4) && queenPos % 2 == 0 && view[deRotate(queenPos,-3)].color == 5) ? {cell:4,color:6} : null,
            NOP
        ])
    }
    else {
        var queenOn = view[8-queenPos].color
        var target = WIND_BAND.next(queenOn)
        var prior = WIND_BAND.next(target)
        var followRail = best_of([
            try_all_cells((i) => (view[deRotate(i,-3)].color == prior && view[deRotate(i,-1)].color == target && areAdjacent(i,queenPos) && (view[i].color == 4 || view[i].color == 6) ? {cell: i} : null), true),
            queenPos % 2 == 1 ? (view[queenPos].color == 4 || view[4].color == 4 ? NOP : {cell:deRotate(queenPos,-2)}) : (view[queenPos].color == 4 || view[queenPos].color == 6 ? {cell:deRotate(queenPos,-1)} : NOP)
        ])

        if(view[deRotate(queenPos,-1)].ant != null) {
            if(!view[deRotate(queenPos,-1)].ant.friend && view[deRotate(queenPos,-2)].ant != null && !view[deRotate(queenPos,-2)].ant.friend) {
                return NOP
            }
            if(queenPos % 2 == 0 && !view[deRotate(queenPos,-1)].ant.friend && view[deRotate(queenPos,-2)].ant == null && (view[queenPos].color == 3 || view[queenPos].color == WHITE)) {
                return {cell:deRotate(queenPos,-3)}
            }
            if(queenPos % 2 == 0 && friend_at(deRotate(queenPos,-1)) == THIEF && view[deRotate(queenPos,-2)].ant == null && (view[queenPos].color == 3 || view[queenPos].color == WHITE)) {
                return {cell:deRotate(queenPos,-3)}
            }
            return NOP
        }
        if(me.food > 0 && queenPos % 2 == 0) {
            return {cell:deRotate(queenPos,-1)}
        }
        if(foe_at(deRotate(queenPos,-3)) > 0 && (view[queenPos].color == 1 || view[deRotate(queenPos,1)].color == 1 || view[deRotate(queenPos,-1)].color == 1)) {
            if(view[queenPos].color == 3) {
                return followRail
            }
            if(view[queenPos].color == 7) return NOP
            return {cell:queenPos,color:3}
        }
        if((foe_at(deRotate(queenPos,-2)) > 0 || foe_at(deRotate(queenPos,-3)) > 0) && queenPos % 2 == 0 && view[deRotate(queenPos,-1)].color == 5) {
            if(view[queenPos].color == 7) return NOP
            return {cell:queenPos,color:3}
        }
        if(view[deRotate(queenPos,-4)].ant != null && !view[deRotate(queenPos,-4)].ant.friend && (view[queenPos].color == 1 || view[deRotate(queenPos,1)].color == 1 || view[deRotate(queenPos,-1)].color == 1)) {
            if(view[queenPos].color == 7) return NOP
            return {cell:queenPos,color:3}
        }
        if((followRail == null || followRail.cell == 4) && foe_at(deRotate(queenPos,-2)) == 1) {
            if(view[queenPos].color == 7) return NOP
            return {cell:queenPos,color:3}
        }
        if(followRail != null && followRail.cell != 4 && view[followRail.cell].color == 6 && view[deRotate(followRail.cell,1)].color == 6) {
            followRail = {cell:deRotate(followRail.cell,1)}
        }
        return followRail
    }
    return NOP
}

// LANCE_TIP never needs to move
// Unfortunately, reusing an existing worker type for this purpose is not easily possible.
// Used against Sliding Miners as a stationary blocker to prevent the queen slipping past.
function moveTip(me, buddies) {
    var queenPos = -1
    var in_void = true
    for(var i=0;i<9;i++) {
        if(friend_at(i) == QUEEN) {
            queenPos = i
        }
        if(view[i].color != WHITE) {
            in_void = false
        }
    }
    var colours = [0, 0, 0, 0, 0, 0, 0, 0, 0]
    var enemies = 0
    for(var i = 0; i < 9; ++ i) {
        ++ colours[view[i].color]
        if(foe_at(i) > 0) enemies++
    }
    var onRails = rail_miners.near_nest(colours)
    if(buddies[QUEEN] && !buddies[LANCE]) {
        if(onRails) return NOP
        if(foe_at(8-queenPos) == 4) {
            return {cell:deRotate(queenPos,2)}
        }
        if(in_void) return {cell:deRotate(queenPos,4)}
        if(enemies == 2 && queenPos % 2 == 0 && view[deRotate(queenPos,1)].ant == null) {
            return {cell:queenPos,color:7}
        }
        if(enemies == 2 && queenPos % 2 == 1) {
            return {cell:deRotate(queenPos,-1),color:7}
        }
    }
    if(buddies[QUEEN] && buddies[LANCE]) {
        if(enemies == 0 && view[queenPos].color == 1) return NOP
        if(view[deRotate(queenPos,1)].color == 5 && friend_at(deRotate(queenPos,1)) == LANCE) return {cell:deRotate(queenPos,4)}
        return {cell:deRotate(queenPos,2)}
    }
    if(!buddies[QUEEN] && view[4].color == 2) {
        for(var i = 0; i < 9; ++ i) {
            if(view[i].color == 8) return {cell:i}
        }
    }
    if(queenPos >=0 && foe_at(deRotate(queenPos,2)) > 0 && view[deRotate(queenPos,2)].ant.food == 0 && foe_at(deRotate(queenPos,4)) > 0 && view[deRotate(queenPos,4)].ant.food > 0) {
        return {cell:queenPos,color:7}
    }
    return NOP
}

function deRotate(m, amt) {
    var rotationsCW = [1,2,5,8,7,6,3,0]
    var rotationsCCW = [3,6,7,8,5,2,1,0]
    if(m == 4 || m < 0 || m > 8 || amt == 0) return m
    if(amt > 0)
        return rotationsCW[(rotationsCW.indexOf(m)+amt)%8]
    amt = -amt
    return rotationsCCW[(rotationsCCW.indexOf(m)+amt)%8]
}

return play_safe(move_agent([
    THIEF, move,
    QUEEN, move,
    BOUNCER, move,
    LANCE, moveLance,
    LANCE_TIP, moveTip
]))

"শত্রু রানী সংলগ্ন একটি উদীয়মান কর্মী যদি উপস্থিত হয় তবে 1 টুকরো খাবার চুরি করবে" এই নিয়মটি কাজে লাগিয়ে কেউ কোনও উত্তর পোস্ট করেনি, তাই আমি ঠিক করেছিলাম!

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

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

লক্ষ্যগুলি বর্ণনার সাথে সাথে কোডগুলিতে প্রদর্শিত হয় সেগুলি অনুসরণ করে:

ব্ল্যাক হোল (টার্গেট অক্ষম)

এটি যখন ব্ল্যাক হোলকে আবিষ্কার করবে, তখন আমরা তাদের রানী খুঁজে বের করব, বা তাদের কর্মীরা আমাদের নিজস্ব খাবার খেয়ে ফেলবে, বা আমরা ঝাঁপিয়ে পড়ে অনুসন্ধান চালিয়ে যাব কিনা তা একেবারেই এলোমেলো। দেখা যাচ্ছে ব্ল্যাক হোল লক্ষ্য করা বেশ শক্ত।

জিগগার্যাট (টার্গেট অক্ষম)

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

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

রেলপথে খনিবিদদের জন্য, রানী খনিকারীর মূল রেল ব্যবস্থাটির কেন্দ্রে বসে আছে কিনা তা দেখতে এটি একটি নিষ্ঠুর-শক্তি অনুসন্ধান ব্যবহার করে। এরপরে এটি এটিকে তার উত্সটিতে ফিরে আসে (খনিকারদের শ্রমিকদের চারপাশে যেতে দেয়)। একবার রানির কাছে এটি চোরকে স্বাভাবিক হিসাবে উত্সাহ দেয় এবং রানিকে 9 টি খাবারে নামিয়ে দেয়। 10 খাবারের আওতায় মাইনার রানী তার দেওয়া প্রতিটি 4 খাবারের জন্য 3 জন শ্রমিক তৈরি করে, স্বল্প-প্রত্যাবর্তনের সম্ভাবনার আশেপাশে থাকে। বাউন্স আউট এবং পরে ফিরে। (এই পরিবেশের কোড সরবরাহ করার জন্য ধন্যবাদ ড্রাকো 18 তে যান!)

এটি যখন জিগগারেটের সন্ধান করে, এটি বেশ ভাল করে এবং আকর্ষণীয় বিস্ফোরণ ঘটায়, যেমন এই প্রথম প্রোটোটাইপে দেখা গেছে (বাউন্সিংয়ের আগে যোগ করার আগে):

বিস্ফোরিত জিগগারেট

ফায়ারফ্লাই (টার্গেট অক্ষম)

ফায়ারফ্লাই লক্ষ্যবস্তু করা ব্লকটি জিগগারেট কোডটি বেসলাইন হিসাবে ব্যবহার করে তবে ব্যবহৃত রঙগুলিকে ওভাররাইড করে। এটি কোনও লেখকের পক্ষে বাইট-কাউন্ট কম রেখে সহজেই নতুন ভ্যাম্পায়ার টার্গেট তৈরি করা সহজ করে তোলে। ফায়ারফ্লাই কোডটি অক্ষম করা হয়েছিল যখন ফায়ারফ্লাই খাদ্য সংগ্রহ না করে, তবে এমকে-তে পুনরায় সক্ষম করা হয়েছিল। 5।

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

একটি রেল (মোআরআর) / স্লাইডিং মাইন্ডারস (এসএলএম) এর খনি

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

তবে সর্বাধিক সাধারণ ফলাফলটি হ'ল আমরা কখনই কিছুই পাই না। এটি এখনও সেই ক্ষেত্রে ঠিক আছে; স্কোরবোর্ডের মাঝামাঝি

বাতচক্র

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

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

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

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

রিনিউয়েবল এনার্জি (এমকে)) উইন্ডমিলকে লক্ষ্য করে যুক্তি সংশোধন করে, মূলত এমকে the এর পরিবর্তনগুলি পূর্বাবস্থায় ফিরিয়ে দেয়, কারণ উইন্ডমিলের এমন পরিবর্তন ছিল যা কোডটি সময়ের সাথে 100% জাল করতে ব্যর্থ করেছিল। সংশোধিত সাফল্যের হার প্রায় 70%, বাকি 30% বোবা ভাগ্যের কারণে এটি অনিবার্য। পদ্ধতির ভেক্টর আস্তে আস্তে পরিবর্তিত হয়েছে।

হাইওয়ে

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

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

ভ্যাম্পায়ারের যদি 1000 টি খাবার বা তার বেশি থাকে তবে সে হাইওয়ে উপেক্ষা করে, কারণ এই মুহুর্তে, এটি কোনও বিষয় নয়।


1
@ ট্রাইকপ্লেক্স কোনও সমস্যা নেই; আমি যখন এটির দ্বিতীয়বার দেখার জন্য সময় পাই তখন আমি এখন যা উন্নতি করতে পারবো তা দেখতে পাচ্ছি যে শ্রমিকের চারপাশে ঝাঁকুনির দরকার নেই। যতক্ষণ না এটি তৈরি হওয়া পর্যন্ত, আমি মনে করি যে মূল বিষয়টি প্রতিপক্ষের সন্ধান করা সহজ হওয়ার জন্য অপেক্ষা করেছিল!
ডেভ

9
এটি সত্যিই মানে।
ধ্বংসাত্মক লেবু

2
ট্রাইকোপলাক্স স্পষ্টভাবে এই ধরনের দুর্বলতা-শোষণ কৌশলকে
মঞ্জুরি দিয়েছিল

1
আমি "এটি সত্যই বোঝায়" upvated কারণ আমি সম্মত, এবং এটি একটি বিশেষ জিনিস যা আমি বিশেষভাবে এই প্রতিযোগিতায় দেখতে চেয়েছিলাম ...
ট্রাইকোপল্যাক্স

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

11

ল্যাংটনের পিপড়া

আমার সমস্ত উত্তরগুলিতে ফর্মিক ফাংশন ফ্রেমওয়ার্ক আকারে অনুরূপ নিম্ন-স্তরের যুক্তি থাকবে। "হাই-লেভেল লজিক স্টার্টস এখানে" ফ্রেমওয়ার্কের কোডটির সমাপ্তি চিহ্নিত করে।

// FORMIC FUNCTIONS FRAMEWORK //
// Version 1.0                //

var WHITE = 1;
var QUEEN = 5;
var HERE = 4;
var MY_VO = view[HERE];
var ME = MY_VO.ant;
var NOP = move(HERE);

var ORTHOGONALS = [1, 3, 5, 7];
var DIAGONALS = [0, 2, 6, 8];
var DIRECTIONS = [0, 1, 2, 3, 5, 6, 7, 8];
var ALL_CELLS = [0, 1, 2, 3, 4, 5, 6, 7, 8];
var VIEW_ORIENTATIONS = [
  [0,1,2,
   3,4,5,
   6,7,8],

  [6,3,0,
   7,4,1,
   8,5,2],

  [8,7,6,
   5,4,3,
   2,1,0],

  [2,5,8,
   1,4,7,
   0,3,6]
];

function rotateCW(cell, amount) {
  if (cell === HERE) return cell;
  var order = [0, 1, 2, 5, 8, 7, 6, 3];
  return order[(order.indexOf(cell) + amount + 8) % 8];
}

function isDiagonal(cell) {
  return DIAGONALS.includes(cell);
}
function isOrthogonal(cell) {
  return ORTHOGONALS.includes(cell);
}

function move(cell) {
  return {cell: cell};
}
function moveMany(cells) {
  var p = [];
  for (var i = 0; i < cells.length; i++) p.push(move(cells[i]));
  return p;
}

function color(cell, col) {
  return {cell: cell, color: col};
}
function colorMany(cells, col) {
  var p = [];
  for (var i = 0; i < cells.length; i++) p.push(color(cells[i], col));
  return p;
}

function spawn(cell, type) {
  return {cell: cell, type: type};
}
function spawnMany(cells, type) {
  var p = [];
  for (var i = 0; i < cells.length; i++) p.push(spawn(cells[i], type));
  return p;
}

function isSane(action, ant) {
  // TODO: Minimize this
  if (ant === undefined || !ant.isObject) ant = ME;
  if (action === undefined || action.cell < 0 || action.cell >= 9) return false;
  if (action.color !== undefined) {
    if (action.color < 1 || action.color > 8) return false;
    return true;
  }
  else if (action.type !== undefined) {
    if (action.type < 1 || action.type > 4) return false;
    if (ant.type !== QUEEN || ant.food === 0) return false;
    if (isOccupied(action.cell, ant) || view[action.cell].food !== 0) return false;
    return true;
  }
  else {
    if (isOccupied(action.cell, ant) && action.cell !== HERE) return false;
    return true;
  }
}
function isOccupied(cell, ant) {
  if (ant === undefined || !ant.isObject) ant = ME;
  return view[cell].ant !== null || (view[cell].food > 0 && ant.type !== QUEEN && ant.food === 1);
}
function isColoringMeaningful(action) {
  return isSane(action) && action.color !== undefined && view[action.cell].color !== action.color;
}

function test(cell, test) {
  var vo = view[cell];
  return (test.color === undefined || test.color === vo.color) &&
         (test.food === undefined || test.food === vo.food) &&
         (test.ant === undefined || test.ant === vo.ant || (
           (test.ant !== null && vo.ant !== null) &&
           (test.ant.food === undefined || test.ant.food === vo.ant.food) &&
           (test.ant.type === undefined || test.ant.type === vo.ant.type) &&
           (test.ant.friend === undefined || test.ant.friend === vo.ant.friend)
         ));
}

function findOrientation(tests) {
  var best = {orientation: null, matches: []};
  for (var o = 0; o < VIEW_ORIENTATIONS.length; o++) {
    var matches = [];
    for (var i = 0; i < tests.length; i++) {
      if (test(VIEW_ORIENTATIONS[o][tests[i].cell], tests[i])) {
        matches.push(tests[i]);
      }
    }
    if (matches.length > best.matches.length) {
      best.orientation = o;
      best.matches = matches;
    }
  }

  return best;
}

function orientCells(orientation, cells) {
  if (orientation === null || orientation < 0 || orientation >= 4) orientation = 0;
  for (var i = 0; i < cells.length; i++) {
    cells[i] = VIEW_ORIENTATIONS[orientation][cells[i]];
  }
  return cells;
}

function findFirst(func, cells) {
  if (cells === undefined) cells = ALL_CELLS;
  for (var i = 0; i < cells.length; i++) {
    if (func(cells[i])) return cells[i];
  }
  return null;
}
function findAll(func, cells) {
  if (cells === undefined) cells = ALL_CELLS;
  var found = [];
  for (var i = 0; i < cells.length; i++) {
    if (func(cells[i])) found.push(cells[i]);
  }
  return found;
}

// HIGH-LEVEL LOGIC STARTS HERE //
var ROAD_COL = 3;
var SIM_COLS = [ 1, 8, 5, 6, 4, 2, 7, 3]; // SIM_COLS.length must be greater or equal to SIM_ROTS.length
var SIM_ROTS = [-1,-1,+1,-1,-1,+1,-1,-1];
// Here are some additional rulesets to play around with:
// [+1,-1,+1,-1,+1,-1,+1,-1] // Classic Langton's ant, extended to use all 8 colors cyclically
// [+1,+1,-1,+1,-1,+1,+1]    // Produces a very interesting highway
// [-1,-1,+1,-1,-1,+1,-1,-1] // The default one -- chosen because it produces a highway nearly instantly, and the highway itself is pretty efficient
// [-1,+1,-1,-1,-1,+1,+1,-1]
// [-1,-1,+1,-1,-1,+1,-1,-1]
// [-1,+1,-1,-1,-1,+1,+1,-1]
// [+1,-1,+1,+1,+1,-1]

var ANCHOR = 1;
var TAIL = 2;

var DEBUG_MODE = false;

function getSimColIndex(cell) {
  return Math.max(SIM_COLS.lastIndexOf(view[cell].color, SIM_ROTS.length - 1), 0);
}
function getNextSimCol(simColIndex) {
  return SIM_COLS[(simColIndex + 1) % SIM_ROTS.length];
}
function getSimRot(simColIndex) {
  return SIM_ROTS[simColIndex];
}

function run() {
  switch (ME.type) {
    case QUEEN: {
      var anch = findFirst(c => test(c, {ant: {type: ANCHOR, friend: true}}), DIRECTIONS);
      if (anch !== null) {
        if (isOrthogonal(anch)) {
          var tail = findFirst(c => test(c, {ant: {type: TAIL, friend: true}}), DIAGONALS);
          if (tail !== null) {
            return [move(rotateCW(anch, -2 * getSimRot(getSimColIndex(HERE))))].filter(isSane)[0] || NOP;
          } else {
            var nanch = rotateCW(anch, -getSimRot(getSimColIndex(anch)));
            return color(nanch, getNextSimCol(getSimColIndex(nanch)));
          }
        } else {
          return NOP;
        }
      } else {
        var tailO;
        if (ME.food === 2) {
          return spawnMany(ORTHOGONALS, TAIL).filter(isSane)[0] || NOP;
        } else if (ME.food === 1 && (tailO = findOrientation([{cell: 1, ant: {type: TAIL, friend: true}}])).orientation !== null) {
          return spawnMany(orientCells(tailO.orientation, [3, 5]), ANCHOR).filter(isSane)[0] || NOP;
        }

        var f;
        if ((f = findFirst(c => test(c, {food: 1})))) {
          return move(f);
        }

        if (test(HERE, {color: ROAD_COL})) {
          return moveMany(orientCells(findOrientation([{cell: 0, color: ROAD_COL}]).orientation, [8, 6, 2])).filter(a => isSane(a) && !test(a.cell, {color: ROAD_COL}))[0] || moveMany(DIAGONALS).filter(isSane)[0] || NOP;
        } else {
          return color(HERE, ROAD_COL);
        }
      }
      break;
    }
    case ANCHOR: {
      var queen = findFirst(c => test(c, {ant: {type: QUEEN, friend: true}}), DIAGONALS);
      var tail = findFirst(c => test(c, {ant: {type: TAIL, friend: true}}), ORTHOGONALS);
      var qp = [rotateCW(queen, -1), rotateCW(queen, +1)];
      var tp = [rotateCW(tail, -2), rotateCW(tail, +2)];
      for (var i = 0; i < qp.length; i++) {
        for (var j = 0; j < tp.length; j++) {
          if (qp[i] === tp[j]) return [move(qp[i])].filter(isSane)[0] || NOP;
        }
      }
      return NOP;
      break;
    }
    case TAIL: {
      var anch = findFirst(c => test(c, {ant: {type: ANCHOR, friend: true}}), DIAGONALS);
      if (anch !== null) {
        var rot = getSimRot(getSimColIndex(anch));
        var nanch = rotateCW(anch, rot);
        if (test(nanch, {ant: {type: QUEEN, friend: true}})) return [move(rotateCW(anch, -rot))].filter(isSane)[0] || NOP;
        return [move(nanch)].filter(isSane)[0] || NOP;
      } else {
        return NOP;
      }
      break;
    }
  }
}

var output = run();
if (isSane(output)) return output;
else {
  if (DEBUG_MODE) {
    return;
  } else {
    return NOP;
  }
}

ল্যাংটনের পিঁপড়া ("আরএল") ল্যাংটনের পিঁপড়া ("LLRLLRLL")


ভূমিকা

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

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

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


ব্যাখ্যা

রঙগুলি ( SIM_COLS) এর সাথে সম্পর্কিত ঘূর্ণন রয়েছে ( SIM_ROTS) যা রানী তার শিরোনামের দিক পরিবর্তন করতে ব্যবহার করে। +1মানে ঘড়ির কাঁটার ঘোরানো ("আর"), -1মানে ঘড়ির কাঁটার বিপরীতে ঘূর্ণন ("এল")। সর্বোত্তম Langton এর পিপীলিকা হবে SIM_COLS = [ 1, 8], SIM_ROTS = [+1,-1]SIM_COLSঅ্যারে কার্যকরভাবে সব উপাদান যে একটি মানানসই উপাদান না থাকে বর্জন SIM_ROTSঅ্যারে। সমস্ত রঙ যেগুলি ছাঁটা SIM_COLSঅ্যারের মধ্যে নেই তা রঙ 0 হিসাবে গণ্য হয় এবং কখনও পিঁপড়ে নিজেই উত্পাদিত হয় না।

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

প্রাথমিক স্ক্যাম্বল শেষ করার পরে, রানী অ্যাঙ্কর এবং টেইল নামে দুটি পিঁপড়া তৈরি করেন । রানী প্রথমে লেজটি তৈরি করেছিলেন, সংলগ্ন অর্থোগোনালি (কক্ষ 1, 3, 5, 7) রানির কাছে। তারপরে, তিনি অ্যাঙ্কর, রানির সাথে সংলগ্ন অরথোগোনালি এবং লেজটিতে তির্যকভাবে (কোষ 0, 2, 6, 8) সজ্জিত করেন।

আচরণটি দুটি ভিন্ন ধাপের একটি চির-পুনরাবৃত্তি চক্র নিয়ে গঠিত।

ধাপ 1

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

অ্যাঙ্কর: কিছু করে না।

রানী: অ্যাঙ্কর সন্ধান করে এবং পিঁপড়াটি যেদিকে চলেছে তার বিপরীত হিসাবে আচরণ করে। দিকটি তখন রানির অধীনে রঙ অনুসারে আবর্তিত হয়। রানী ঘোরানো দিক নির্দেশিত কক্ষে চলে আসে।

ধাপ ২

লেজ: কিছুই করে না।

অ্যাঙ্কর: একটি কক্ষের সন্ধান করে যা লেজটির সাথে তির্যকভাবে এবং কুইনের সাথে অर्थোগোনালি সংলগ্ন এবং সেখানে চলে যায়। এখানে সর্বাধিক একটি কক্ষ রয়েছে।

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

কী করবেন তা নির্ধারণ করা হচ্ছে

দ্য অরথোগোনালি অনুসন্ধান করে রানী বর্তমান পদক্ষেপটি নির্ধারণ করে। যদি সে এটি খুঁজে পায় তবে তিনি 1 ধাপে রয়েছেন Otherwise নইলে, তিনি 2 ধাপে রয়েছেন rare বিরল ক্ষেত্রে, তিনি অ্যাঙ্করটিকে নিজের সাথে তির্যকভাবে খুঁজে পেতে পারেন। সেক্ষেত্রে সে কিছুই করবে না।

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

লেজটি অ্যাঙ্করটি তির্যকভাবে অনুসন্ধান করে বর্তমান পদক্ষেপটি নির্ধারণ করে। এটি যদি এটি খুঁজে পায় তবে এটি 1 ধাপে রয়েছে on অন্যথায়, এটি দ্বিতীয় ধাপে।

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


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


3
পিপিসিজিতে আপনাকে স্বাগতম!
স্টেডিবক্স

10

জিগুরাট v3.0

var clockwise = [1,2,5,0,4,8,3,6,7];
var opposite = [8,7,6,5,4,3,2,1,0];
var cyclic_cw = [0,1,2,5,8,7,6,3,0];
var worker_colors = [4,5,7,8];
var next_worker_color = [1,1,1,1,5,7,1,8,4];
var prev_worker_color = [1,1,1,1,8,4,1,5,7];
var diags = [0,2,6,8];
var orthos = [1,3,5,7];
var cleaning_color = 6;


// Borrowed from Medusa
function clean(move) {
    if (move["color"] == undefined) {
        if (view[move["cell"]].ant != null) {
            move = {cell: 4};
        }
        if (move["type"] == undefined) {
            if (view[move["cell"]].food == 1 && view[4].ant.type < 5 && view[4].ant.food > 0) {
                move = {cell: 4};
            }
        } else if (view[4].ant.type != 5 || view[4].ant.food == 0 || view[move["cell"]].food == 1) {
            move = {cell: 4};
        }
    }
    return move;
}

function worker_blank(cel) {
    return (worker_colors.indexOf(view[cel].color) < 0);
}

// Own status
var my_color = view[4].color;
var my_food = view[4].ant.food;
var my_type = view[4].ant.type;

// Random free cell
var free_cell = 4;
for (var cel = 0; cel < 9; cel++) {
    if (view[cel].ant == null) {
    free_cell = cel;
    }
}

// Check surroundings
var blanks = 0;
var outer_edge = 0;
var inner_edge = 0;
var next_edge = -1;
var prev_nonblank = -1;
var some_nonblank = -1;
var prev_cell = -1;
var next_cell = -1;
var food_cell = -1;
var nonblank_color = 0;
var cleaning_marker = -1;
var uniform = 1;
var low_type = -1;
var friend_workers = 0;
var guards = 0;
var enemies = 0;
var enemy_queens = 0;
var my_queen = -1;

if (!worker_blank(4)) {
    nonblank_color = view[4].color;
}
for (var ix = 0; ix < 8; ix++) {
    var cel = cyclic_cw[ix];
    var cel2 = cyclic_cw[ix+1];
    if (view[cel].food == 1) {
    food_cell = cel;
    }
    if (worker_blank(cel)) {
    blanks++;
    if (!worker_blank(cel2)) {
        if (worker_blank(4)) {
        outer_edge = 1;
        } else {
        inner_edge = 1;
        }
        next_edge = cel;
            prev_nonblank = cel2;
    }
    if (view[cel].color == cleaning_color) {
        cleaning_marker = cel;
    }
    } else {
    some_nonblank = cel;
    if (nonblank_color == 0) {
        nonblank_color = view[cel].color;
    } else if (view[cel].color != nonblank_color) {
        uniform = 0;
    }
    }
    if ((!worker_blank(4) && view[cel2].color == prev_worker_color[my_color] && view[cel2].ant == null) || (worker_blank(4) && !worker_blank(cel2))) {
    prev_cell = cel2;
    }
    if (!worker_blank(4) && view[cel2].color == next_worker_color[my_color] && view[cel2].ant == null) {
    next_cell = cel2;
    }
    if (view[cel].ant != null) {
    var the_ant = view[cel].ant;
    if (the_ant.friend) {
        if (low_type < 0 || the_ant.type < low_type) {
        low_type = the_ant.type;
        }
        if (the_ant.type == 4) {
        guards++;
        } else if (the_ant.type == 5) {
        my_queen = cel;
        } else {
        friend_workers++;
        }
    } else {
        enemies++;
        if (the_ant.type == 5) {
        enemy_queens++;
        }
    }
    }
}

// Queen before finding food (motile)
if (my_type == 5 && worker_blank(4)) {
    if (my_food > 1) {
    return {cell:4, color:worker_colors[1]};
    }
    if (food_cell >= 0 && my_color != 1) {
    return clean({cell:food_cell});
    }
    if (my_color == 2) {
    for (var ix = 0; ix < 4; ix++) {
        var cel = diags[ix];
        var oppo = opposite[cel];
        if (view[cel].color == 2) {
        if (view[oppo].color == 1 && worker_blank(oppo) && view[oppo].ant == null) {
            return clean({cell:oppo});
        }
                if (view[oppo].color != 2) {
            return {cell:oppo, color:1};
                }
        }
    }
        for (var ix = 0; ix < 4; ix++) {
        var cel = diags[ix];
        if (view[cel].color != 2) {
        return {cell:cel, color:2};
        }
    }
    }
    if (my_color == 1) {
    return {cell:4, color:2};
    }
    return clean({cell:free_cell});
}

// Queen after finding food (sessile)
if (my_type == 5) {
    for (var ix = 0; ix < 8; ix++) {
        cel = cyclic_cw[ix];
    if (worker_blank(cel)) {
            return {cell:cel, color:worker_colors[1]};
    }
    }

    if (my_color != worker_colors[0]) {
        if (my_food > 0) {
        return clean({cell:free_cell, type:1});
        } else {
            return {cell:4, color:worker_colors[0]};
        }
    }
    if (my_food > 0) {
    if (my_food > 3 && guards < 2) {
        return clean({cell:free_cell, type:4});
    }
    if (0 < low_type && low_type < 3) {
        return clean({cell:free_cell, type:(low_type + 1)});
    }
    }
    return {cell:4};
}

// Queen's guard

if (my_type == 4) {
    // Queen is a nbor
    if (my_queen >= 0) {
    if (enemy_queens > 0) {
        return {cell:4};
    }
    if (my_queen == 1) {
        return clean({cell:5});
    }
    return clean({cell:clockwise[my_queen]});
    }
    // Try to get to queen
    if (prev_cell >= 0) {
    return clean({cell:prev_cell});
    }
    // Wander
    return clean({cell:free_cell});
}

// Worker

// Create new ziggurat
if (blanks == 8 && cleaning_marker < 0 && my_color != cleaning_color) {
    if (worker_colors.indexOf(my_color) >= 0) {
    return {cell:free_cell, color:my_color};
    }
    return {cell:free_cell, color:worker_colors[0]};
}

var front = view[1].color;
if (!worker_blank(4) && !worker_blank(1) && my_color != front) {
    if (view[7].color == front || (view[6].color == front && view[8].color == front)) {
        return {cell:4, color:front};
    }
}

if (my_food == 0) {
    // Grab food
    if (food_cell >= 0 && (!worker_blank(4) || !worker_blank(food_cell))) {
        return clean({cell:food_cell});
    }

    // Clear marked uniform region
    if (my_color == cleaning_color && uniform) {
    if (blanks < 7) {
        return {cell:some_nonblank, color:1};
    } else if (blanks == 7) {
        return {cell:some_nonblank, color:cleaning_color};
    }
    }

    // Follow cleaning color
    if (blanks == 8) {
    if (cleaning_marker < 0 || my_color == cleaning_color) {
        return {cell:4, color:1};
    } else if (cleaning_marker >= 0) {
        return clean({cell:cleaning_marker});
    }
    }

    // Dive into uniform region
    if (blanks > 3 && worker_blank(4) && worker_blank(1) && !worker_blank(2) && view[2].color == view[5].color && view[2].color == view[8].color) {
    return clean({cell:2});
    }

    // Mark uniform region for clearing
    if (!worker_blank(4) && uniform && (blanks < 4 || (blanks < 7 && ((worker_blank(1) && worker_blank(7)) || (worker_blank(3) && worker_blank(5)))))) {
    return {cell:4, color:cleaning_color};
    }

    // Extend edge
    if (outer_edge) {
    var new_color = 0;
    var cl = clockwise[next_edge];
    var cl2 = clockwise[cl];
    if (!worker_blank(1) && view[7].color == view[1].color) {
        new_color = view[1].color;
    } else if (!worker_blank(3) && view[5].color == view[3].color) {
        new_color = view[3].color;
        } else if (!worker_blank(cl2) && view[cl].color == next_worker_color[view[cl2].color]) {
        if (cl > 1) {
        new_color = view[cl].color;
        } else {
        new_color = next_worker_color[view[cl].color];
        }
    } else if (!worker_blank(cl)) {
        new_color = next_worker_color[view[cl].color];
        } else if (prev_nonblank >= 0) {
            new_color = next_worker_color[prev_nonblank];
    }
    if (new_color == 0 && blanks < 2) {
        new_color = worker_colors[0];
    }
        if (new_color > 0) {
            return {cell:4, color:new_color};
        } else {
            return clean({cell:next_edge});
        }
    }

    // Escape from hole
    if (worker_blank(4) && blanks == 0) {
        return {cell:4, color:next_worker_color[nonblank_color]};
    }

    // Go outside or fill it
    if (inner_edge && next_edge >= 0) {
    if (friend_workers > 1) {
        return clean({cell:free_cell});
    }
        if (blanks == 4 && prev_nonblank >= 0) {
            return {cell:next_edge, color:next_worker_color[view[prev_nonblank].color]};
        }
    if (view[next_edge].ant == null) {
            return clean({cell:next_edge});
    }
    return {cell:4};
    }

    // Go toward border
    if (!worker_blank(4) && next_cell >= 0 && next_cell != 1) {
    return clean({cell:next_cell});
    }

    // Wander
    return clean({cell:free_cell});
}

if (my_food > 0) {
    // Take food to queen
    if ((prev_cell >= 0 && prev_cell != 1) || (prev_cell >= 0 && worker_blank(4))) {
    return clean({cell:prev_cell});
    }

    // Wander
    if (worker_blank(free_cell) && !worker_blank(4)) {
    return {cell:4};
    }
    return clean({cell:free_cell});
}

return clean({cell:free_cell});

কিভাবে এটা কাজ করে

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

মন্তব্য

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

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

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

আমি জেএসকে সত্যই জানি না, সুতরাং কোডটি হররডের জগাখিচুড়ি।

ডোরাকাটা অঞ্চলের চিত্র এখানে:

প্রাচীন মেসোপটেমিয়ার ধাপওয়ালা পিরামিড আকৃতির মন্দির যার শীর্ষে নির্মিত হত উপাসনাগার


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

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

1
@ ট্রাইকপ্লেক্স আমি সবেমাত্র বট আপডেট করেছি updated এটি এখন কখনও অবৈধ পদক্ষেপ করা উচিত নয় এবং সামগ্রিকভাবে কিছুটা স্মার্ট।
Zgarb

1
এবং, নতুন সংস্করণটি মনে হচ্ছে এটি কিছুটা অসুবিধায় একটি ট্রেইল-ইরেজারের আক্রমণ থেকে বেঁচে থাকতে পারে। সম্পর্কে নিশ্চিত নই, যদি একাধিক আক্রমণ ঘটে যদিও
pppery

1
@ ট্রাইকপ্লেক্স এখনই ঠিক করা উচিত। আমি অন্যান্য উন্নতিও যুক্ত করেছি।
জগারব

9

দাবানল এমকে .৩

আমার সমস্ত উত্তরগুলি একই স্তরের নিম্ন-স্তরের সহায়ক ফাংশনগুলি ভাগ করে নিচ্ছে। এই উত্তরের নির্দিষ্ট কোডটি দেখতে "উচ্চ-স্তরের যুক্তি এখানে সন্ধান করুন" অনুসন্ধান করুন।

// == Shared low-level helpers for all solutions ==

var QUEEN = 5;

var WHITE = 1;
var COL_MIN = WHITE;
var COL_LIM = 9;

var CENTRE = 4;

var NOP = {cell: CENTRE};

var DIR_FORWARDS = false;
var DIR_REVERSE = true;
var SIDE_RIGHT = true;
var SIDE_LEFT = false;

function sanity_check(movement) {
  var me = view[CENTRE].ant;
  if(!movement || (movement.cell|0) !== movement.cell || movement.cell < 0 || movement.cell > 8) {
    return false;
  }
  if(movement.type) {
    if(movement.color) {
      return false;
    }
    if((movement.type|0) !== movement.type || movement.type < 1 || movement.type > 4) {
      return false;
    }
    if(view[movement.cell].ant || view[movement.cell].food) {
      return false;
    }
    if(me.type !== QUEEN || me.food < 1) {
      return false;
    }
    return true;
  }
  if(movement.color) {
    if((movement.color|0) !== movement.color || movement.color < COL_MIN || movement.color >= COL_LIM) {
      return false;
    }
    if(view[movement.cell].color === movement.color) {
      return false;
    }
    return true;
  }
  if(movement.cell !== CENTRE && view[movement.cell].ant) {
    return false;
  }
  if(view[movement.cell].food + me.food > 1 && me.type !== QUEEN) {
    return false;
  }
  return true;
}

function as_array(o) {
  if(Array.isArray(o)) {
    return o;
  }
  return [o];
}

function best_of(movements) {
  var m;
  for(var i = 0; i < movements.length; ++ i) {
    if(typeof(movements[i]) === 'function') {
      m = movements[i]();
    } else {
      m = movements[i];
    }
    if(sanity_check(m)) {
      return m;
    }
  }
  return null;
}

function play_safe(movement) {
  // Avoid disqualification: no-op if moves are invalid
  return best_of(as_array(movement)) || NOP;
}

var RAND_SEED = (() => {
  var s = 0;
  for(var i = 0; i < 9; ++ i) {
    s += view[i].color * (i + 1);
    s += view[i].ant ? i * i : 0;
    s += view[i].food ? i * i * i : 0;
  }
  return s % 29;
})();

var ROTATIONS = [
  [0, 1, 2, 3, 4, 5, 6, 7, 8],
  [6, 3, 0, 7, 4, 1, 8, 5, 2],
  [8, 7, 6, 5, 4, 3, 2, 1, 0],
  [2, 5, 8, 1, 4, 7, 0, 3, 6],
];

function try_all(fns, limit, wrapperFn, checkFn) {
  var m;
  fns = as_array(fns);
  for(var i = 0; i < fns.length; ++ i) {
    if(typeof(fns[i]) !== 'function') {
      if(checkFn(m = fns[i])) {
        return m;
      }
      continue;
    }
    for(var j = 0; j < limit; ++ j) {
      if(checkFn(m = wrapperFn(fns[i], j))) {
        return m;
      }
    }
  }
  return null;
}

function identify_rotation(testFns) {
  // testFns MUST be functions, not constants
  return try_all(
    testFns,
    4,
    (fn, r) => fn(ROTATIONS[r]) ? ROTATIONS[r] : null,
    (r) => r
  );
}

function near(a, b) {
  return (
    Math.abs(a % 3 - b % 3) < 2 &&
    Math.abs(Math.floor(a / 3) - Math.floor(b / 3)) < 2
  );
}

function try_all_angles(solverFns) {
  return try_all(
    solverFns,
    4,
    (fn, r) => fn(ROTATIONS[r]),
    sanity_check
  );
}

function try_all_cells(solverFns, skipCentre) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i === CENTRE && skipCentre) ? null : fn(i)),
    sanity_check
  );
}

function try_all_cells_near(p, solverFns) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i !== p && near(p, i)) ? fn(i) : null),
    sanity_check
  );
}

function ant_type_at(i, friend) {
  return (view[i].ant && view[i].ant.friend === friend) ? view[i].ant.type : 0;
}

function friend_at(i) {
  return ant_type_at(i, true);
}

function foe_at(i) {
  return ant_type_at(i, false);
}

function ant_type_near(p, friend) {
  for(var i = 0; i < 9; ++ i) {
    if(i !== 4 && ant_type_at(i, friend) && near(i, p)) {
      return true;
    }
  }
  return false;
}

function move_agent(agents) {
  var me = view[CENTRE].ant;
  var buddies = [0, 0, 0, 0, 0, 0];
  for(var i = 0; i < 9; ++ i) {
    ++ buddies[friend_at(i)];
  }

  for(var i = 0; i < agents.length; i += 2) {
    if(agents[i] === me.type) {
      return agents[i+1](me, buddies);
    }
  }
  return null;
}

function grab_nearby_food() {
  return try_all_cells((i) => (view[i].food ? {cell: i} : null), true);
}

function go_anywhere() {
  return try_all_cells((i) => ({cell: i}), true);
}

function colours_excluding(cols) {
  var r = [];
  for(var i = COL_MIN; i < COL_LIM; ++ i) {
    if(cols.indexOf(i) === -1) {
      r.push(i);
    }
  }
  return r;
}

function generate_band(start, width) {
  var r = [];
  for(var i = 0; i < width; ++ i) {
    r.push(start + i);
  }
  return r;
}

function colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function(c) {
      return colours[(colours.indexOf(c) + 1) % colours.length];
    }
  };
}

function random_colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function() {
      return colours[RAND_SEED % colours.length];
    }
  };
}

function fast_diagonal(colourBand, avoidedColours) {
  if(!avoidedColours) {
    avoidedColours = colourBand;
  }
  var m = try_all_angles([
    // Avoid nearby checked areas
    (rot) => {
      if(
        !avoidedColours.contains(view[rot[0]].color) &&
        avoidedColours.contains(view[rot[5]].color) &&
        avoidedColours.contains(view[rot[7]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // Go in a straight diagonal line if possible
    (rot) => {
      if(
        !avoidedColours.contains(view[rot[0]].color) &&
        avoidedColours.contains(view[rot[8]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // When in doubt, pick randomly but avoid doubling-back
    (rot) => (avoidedColours.contains(view[rot[0]].color) ? null : {cell: rot[0]}),

    // Double-back when absolutely necessary
    (rot) => ({cell: rot[0]})
  ]);

  // Lay a colour track so that we can avoid doubling-back
  // (and mess up our foes as much as possible)
  if(!avoidedColours.contains(view[CENTRE].color)) {
    var prevCol = m ? view[8-m.cell].color : WHITE;
    return {cell: CENTRE, color: colourBand.next(prevCol)};
  }

  return m;
}

function follow_edge(obstacleFn, side, resultFn) {
  // Since we don't know which direction we came from, this can cause us to get
  // stuck on islands, but the random orientation helps to ensure we don't get
  // stuck forever.

  if(!resultFn) {
    resultFn = (i) => ({cell: i});
  }

  var order = ((side === SIDE_LEFT)
    ? [0, 3, 6, 7, 8, 5, 2, 1, 0]
    : [0, 1, 2, 5, 8, 7, 6, 3, 0]
  );
  return try_all(
    [obstacleFn],
    order.length - 1,
    (fn, i) => ((fn(order[i+1]) && !fn(order[i])) ? resultFn(order[i]) : null),
    sanity_check
  );
}

function start_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => ((
      !protectedCols.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 2 : 0]].color) &&
      !colourBand.contains(view[rot[1]].color)
    )
      ? {cell: rot[right ? 5 : 3], color: colourBand.next(WHITE)}
      : null)
  ]);
}

function lay_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => {
      var ahead = rot[right ? 2 : 0];
      var behind = rot[right ? 8 : 6];
      if(
        colourBand.contains(view[behind].color) &&
        !protectedCols.contains(view[ahead].color) &&
        !colourBand.contains(view[ahead].color) &&
        !colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        return {cell: ahead, color: colourBand.next(view[behind].color)};
      }
    }
  ]);
}

function follow_dotted_path(colourBand, side, direction) {
  var forwards = (direction === DIR_REVERSE) ? 7 : 1;
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    // Cell on our side? advance
    (rot) => {
      if(
        colourBand.contains(view[rot[right ? 5 : 3]].color) &&
        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[0]].color) &&
        !colourBand.contains(view[rot[2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    },

    // Cell ahead and behind? advance
    (rot) => {
      var passedCol = view[rot[right ? 8 : 6]].color;
      var nextCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(passedCol) &&
        nextCol === colourBand.next(passedCol) &&

        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[right ? 0 : 2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    }
  ]);
}

function escape_dotted_path(colourBand, side, newColourBand) {
  var right = (side === SIDE_RIGHT);
  if(!newColourBand) {
    newColourBand = colourBand;
  }

  return try_all_angles([
    // Escape from beside the line
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        !colourBand.contains(view[rot[right ? 8 : 6]].color) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[rot[7]].color) ||
        colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        // not oriented, or in a corner
        return null;
      }
      return best_of([
        {cell: rot[right ? 0 : 2], color: newColourBand.next(approachingCol)},
        {cell: rot[right ? 3 : 5]},
        {cell: rot[right ? 0 : 2]},
        {cell: rot[right ? 6 : 8]},
        {cell: rot[right ? 2 : 0]},
        {cell: rot[right ? 8 : 6]},
        {cell: rot[right ? 5 : 3]}
      ]);
    },

    // Escape from inside the line
    (rot) => {
      if(
        !colourBand.contains(view[rot[7]].color) ||
        !colourBand.contains(view[rot[1]].color) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      return best_of([
        {cell: rot[3]},
        {cell: rot[5]},
        {cell: rot[0]},
        {cell: rot[2]},
        {cell: rot[6]},
        {cell: rot[8]}
      ]);
    }
  ]);
}

function latch_to_dotted_path(colourBand, side) {
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(approachingCol) &&
        view[rot[right ? 8 : 6]].color === colourBand.next(approachingCol) &&
        !colourBand.contains(view[rot[right ? 5 : 3]].color)
      ) {
        // We're on the wrong side; go inside the line
        return {cell: rot[right ? 5 : 3]};
      }
    },

    // Inside the line? pick a side
    (rot) => {
      var passedCol = view[rot[7]].color;
      var approachingCol = view[rot[1]].color;
      if(
        !colourBand.contains(passedCol) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      if((approachingCol === colourBand.next(passedCol)) === right) {
        return best_of([{cell: rot[3]}, {cell: rot[6]}, {cell: rot[0]}]);
      } else {
        return best_of([{cell: rot[5]}, {cell: rot[2]}, {cell: rot[8]}]);
      }
    }
  ]);
}


// == High-level logic begins here ==


var groundCol = 5;
var poisonCol = 8;

var DIRECTOR = 1;
var FORAGER0 = 2;
var FORAGER1 = 3;
var FORAGER2 = 4;
var MAX_FORAGER_TYPES = 3; // Worker creation throttle
var MIN_FOOD = 3; // Don't embarrass ourselves when things go bad
var MAX_FOOD_SPAWN = 80; // If we're doing well, don't spoil it all

var GROUND_COLOURS = colour_band([groundCol, poisonCol]);
var POISON_COLOURS = colour_band([poisonCol]);
var SAFE_COLOURS = random_colour_band(colours_excluding([WHITE, groundCol, poisonCol]));
var INITIAL_OBSTACLES = random_colour_band(colours_excluding([WHITE]));

function ground_at(i) {
  return GROUND_COLOURS.contains(view[i].color);
}

function unlaiden_friend_at(i) {
  return friend_at(i) && (friend_at(i) === QUEEN || !view[i].ant.food);
}

function obstacle_at(i) {
  // foes are unpredictable, so don't consider them obstacles
  return view[i].food || unlaiden_friend_at(i) || GROUND_COLOURS.contains(view[i].color);
}

function wait_if_blocked(i) {
  return friend_at(i) ? {cell:CENTRE} : {cell: i};
}

function move_director(me, buddies) {
  if(!buddies[QUEEN]) {
    // Lost the queen!
    return go_anywhere();
  }

  var rot = identify_rotation((rot) => (
    friend_at(rot[0]) === QUEEN || friend_at(rot[1]) === QUEEN
  ));

  var ready = (friend_at(rot[1]) === QUEEN && view[rot[1]].color === groundCol);
  var shift = (view[rot[2]].color === groundCol && GROUND_COLOURS.contains(view[rot[5]].color));

  return best_of([
    // Ensure we never end up underground unless we mean to, and provide a
    // base poison layer to help workers find the right side if lost
    {cell: CENTRE, color: poisonCol},
//    {cell: rot[5], color: poisonCol},
    {cell: rot[3], color: poisonCol},

    // Move up to avoid own line after wrapping (us being underground is a signal)
    (ready && shift) && {cell: rot[2]},

    // Advance
    (ready && !shift) && {cell: rot[5]},

    // Make the poison layer more solid if we have extra time
    {cell: rot[7], color: poisonCol},
    {cell: rot[6], color: poisonCol},
    {cell: rot[8], color: poisonCol},

    // Don't lose the queen
    NOP
  ]);
}

function move_forager(me, buddies) {
  var underground = GROUND_COLOURS.contains(view[CENTRE].color);
  var buried = 0;
  for(var i = 0; i < 9; ++ i) {
    if(i !== 4 && GROUND_COLOURS.contains(view[i].color)) {
      ++ buried;
    }
  }
  var travelCol = underground ? POISON_COLOURS : SAFE_COLOURS;

  if(buddies[DIRECTOR]) {
    // We've somehow got in the way of the line; get out of the way
    return try_all_angles((rot) =>
      ((friend_at(rot[6]) === DIRECTOR || friend_at(rot[7]) === DIRECTOR) &&
      best_of([{cell: rot[0]}, {cell: rot[1]}, {cell: rot[2]}])));
  }

  if(me.food) {
    // We have food for the queen; run ahead to find her as fast as we can

    return best_of([
      // Identify confusing pinch points and close them (don't get stuck on islands)
      try_all_angles((rot) => (
        obstacle_at(rot[1]) && obstacle_at(rot[7]) &&
        !obstacle_at(rot[5]) && !GROUND_COLOURS.contains(view[CENTRE].color)
      ) && {cell: CENTRE, color: groundCol}),

      // We're enclosed; mark this as a dead-end
      (buried >= 7) && {cell: CENTRE, color: poisonCol},

      // Race to queen, but don't climb over each other and cause a blockage
      follow_edge(obstacle_at, SIDE_RIGHT, wait_if_blocked),

      // Lost? Travel quickly to find the surface again
      fast_diagonal.bind(null, travelCol),

      // Totally lost
      go_anywhere
    ]);
  }

  if(buddies[QUEEN]) {
    // Don't overtake the queen!
    return NOP;
  }

  // Paint the ground
  if(!underground) {
    return {cell: CENTRE, color: groundCol};
  }

  return best_of([
    // Unpaint small islands which would confuse us or our buddies
    (buried >= 3) && try_all_angles((rot) => (
      !view[rot[0]].ant &&
      GROUND_COLOURS.contains(view[rot[0]].color) &&
      !GROUND_COLOURS.contains(view[rot[1]].color) &&
      !GROUND_COLOURS.contains(view[rot[3]].color)
    ) && {cell: rot[0], color: SAFE_COLOURS.next(WHITE)}),

    (buried >= 3) && try_all_angles((rot) => (
      !view[rot[1]].ant &&
      GROUND_COLOURS.contains(view[rot[1]].color) &&
      !GROUND_COLOURS.contains(view[rot[0]].color) &&
      !GROUND_COLOURS.contains(view[rot[2]].color)
    ) && {cell: rot[1], color: SAFE_COLOURS.next(WHITE)}),

    // Follow line
    follow_edge(ground_at, SIDE_RIGHT, wait_if_blocked),

    // Disoriented; find the surface again
    fast_diagonal.bind(null, travelCol),

    // Totally lost; random walk
    {cell: 0}
  ]);
}

function move_queen(me, buddies) {
  if(buddies[DIRECTOR]) {
    var rot = identify_rotation((rot) => (
      (friend_at(rot[7]) === DIRECTOR && view[rot[7]].color !== groundCol) ||
      (friend_at(rot[5]) === DIRECTOR && view[rot[5]].color === groundCol) ||
      friend_at(rot[8]) === DIRECTOR
    ));

    var rand14 = rot === ROTATIONS[0];
    var existing = friend_at(rot[0]);
    var nextType = existing ? (existing + 1) : FORAGER0;
    var workerSpawn = (
      me.food > MIN_FOOD && me.food < MAX_FOOD_SPAWN &&
      view[rot[3]].color === groundCol && // Don't spawn if disrupted
      view[rot[0]].color === WHITE && // Don't spawn while stuck in a nest
      view[rot[1]].color === WHITE &&
      !friend_at(rot[1]) && !friend_at(rot[3]) && !friend_at(rot[6]) &&
      (existing || rand14) // reduce likelihood of spawning new chains
    );

    return best_of([
      // Paint ground
      {cell: CENTRE, color: groundCol},

      // Follow director up slopes
      (friend_at(rot[5]) === DIRECTOR) && {cell: rot[2]},
      (friend_at(rot[5]) === DIRECTOR) && {cell: rot[1]},

      // Recognise likely erasure issues and correct
      view[rot[2]].color === groundCol && GROUND_COLOURS.contains(view[rot[8]].color) &&
        {cell: CENTRE, color: groundCol},

      // Clear cells which could confuse workers
      GROUND_COLOURS.contains(view[rot[2]].color) && {cell: rot[2], color: SAFE_COLOURS.next(WHITE)},

      // Spawn new workers when ready (throttle probabilistically)
      (workerSpawn && nextType < FORAGER0 + MAX_FORAGER_TYPES) && {cell: rot[1], type: nextType},

      // Follow director along flat planes
      (friend_at(rot[8]) === DIRECTOR) && {cell: rot[5]},

      // Don't lose director
      NOP
    ]);
  }

  return best_of([
    // Begin wildfire
    (me.food >= MIN_FOOD + MAX_FORAGER_TYPES + 1) && try_all_angles((rot) =>
      (view[rot[5]].color !== groundCol && sanity_check({cell: rot[5]}) &&
        {cell: rot[8], type: DIRECTOR})),

    // Hungry or too crowded to begin; frantically find food
    grab_nearby_food,
    fast_diagonal.bind(null, SAFE_COLOURS, INITIAL_OBSTACLES),
    go_anywhere,
    {cell: 1, color: SAFE_COLOURS.next(WHITE)}
  ]);
}

return play_safe(move_agent([
  DIRECTOR, move_director,
  FORAGER0, move_forager,
  FORAGER1, move_forager,
  FORAGER2, move_forager,
  QUEEN, move_queen,
]));

ওয়াইল্ডফায়ার পিঁপড়গুলি তাদের পথে সমস্ত কিছু গ্রাস করে বোর্ডটি স্ফীত করে। এটি ব্ল্যাক হোল (ড্রাকো 18 এর দ্বারা) ধারণাগুলি আমার ফরেনসিক এন্টিসের সাথে মিশ্রিত করে অনুপ্রাণিত হয়েছিল ।

রানী দ্রুত একটি স্ট্যাশ খাবার সংগ্রহ করে শুরু করবেন। একবার তার পর্যাপ্ততা পেলে, সে সরলরেখায় চলতে শুরু করবে এবং কিছু সাহায্যকারীকে ছড়িয়ে দেবে। এই সাহায্যকারীরা একটি সুশৃঙ্খল লাইনে তার পিছনে অনুসরণ করবে, তারা খাবার পেলে ধরতে ছুটে যাবে।

এমকে ২. রানিকে তার দিক বজায় রাখতে সহায়তা করার জন্য একটি বিশেষজ্ঞ পিপড়া ব্যবহার করে এবং হারিয়ে যাওয়া কর্মীদের ব্যান্ডের সঠিক দিকটি খুঁজে পেতে সহায়তা করার জন্য এই পিপড়াটি কালো রঙের একটি ট্রেইলও দেয়। উন্নত কর্মী নেভিগেশনের সাথে একত্রিত হয়ে প্রতিযোগী পিঁপড়ার সাথে মিশ্রিত হলে এটি এখন আরও ভাল পারফর্ম করে। এটি এমনকি (শেষ পর্যন্ত) লাল বিন্দুর বাসা মারার পরে পুনরুদ্ধার করে।

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

এমকে ৩.৩ "একক কুইন" প্রবেশের দ্বারা উত্পাদিত তির্যক লাল রেখার বিরুদ্ধে সুরক্ষা যুক্ত করে, যা কিছু অনুরূপ পরিস্থিতিতে সহায়তা করে। শ্রমিকরা এখন এলোমেলো রেল পথ দ্বারা বিভ্রান্ত হওয়ার সম্ভাবনা খুব কম, এবং এটি আরও ভাল পরিবেশিত হচ্ছে বলে মনে হয়।

প্রোটোটাইপের একটির ফলাফল এখানে:

ফায়ার

(হ্যাঁ, এটি 865 কর্মী পিঁপড় ... এবং এর, 5 খাবার)


এখানে প্রতিযোগিতা সহ একটি স্ক্রিনশট:

পরিষ্কারের আগুন


এবং এখানে আমি কীভাবে মনে মনে পিঁপড়াদের কল্পনা করি (সমান্তরাল সংগীত):

পাপ্রিকা প্যারেড


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
মার্টিন এন্ডার

আপনার সংগীত শুনতে পাচ্ছে না ...
এনএইচ।

1
@NH। ব্যাঙ / বিশৃঙ্খলা / সাধারণ উন্মাদনা চলচ্চিত্র পাপ্রিকা থেকে। আপনি যদি সংগীত জানতে চান, তা দেখুন!
ডেভ

9

আলোর গতি

আমার সমস্ত উত্তরগুলিতে ফর্মিক ফাংশন ফ্রেমওয়ার্ক আকারে অনুরূপ নিম্ন-স্তরের যুক্তি থাকবে। "হাই-লেভেল লজিক স্টার্টস এখানে" ফ্রেমওয়ার্কের কোডটির সমাপ্তি চিহ্নিত করে।

 //  FORMIC FRAMEWORK  //
// Version 6.1.10     //
const WHITE = 1;
const QUEEN = 5;
const CENTER = 4;
const HERE = view[CENTER];
const ME = HERE.ant;
const ORTHOGONALS = [1, 3, 5, 7];
const DIAGONALS = [0, 2, 6, 8];
const DIAGONALS_ORTHOGONALS = [0, 2, 6, 8, 1, 3, 5, 7];
const DIRECTIONS = [0, 1, 2, 3, 5, 6, 7, 8];
const CLOCKWISE_DIRECTIONS = [0, 1, 2, 5, 8, 7, 6, 3];
const CELLS = [0, 1, 2, 3, 4, 5, 6, 7, 8];
const ROTATIONS = [
  [0, 1, 2,
   3, 4, 5,
   6, 7, 8],

  [6, 3, 0,
   7, 4, 1,
   8, 5, 2],

  [8, 7, 6,
   5, 4, 3,
   2, 1, 0],

  [2, 5, 8,
   1, 4, 7,
   0, 3, 6]
];
const NEIGHBORS = [
  [1, 4, 3],
  [2, 5, 4, 3, 0],
  [5, 4, 1],
  [0, 1, 4, 7, 6],
  [0, 1, 2, 5, 8, 7, 6, 3],
  [8, 7, 4, 1, 2],
  [3, 4, 7],
  [6, 3, 4, 5, 8],
  [7, 4, 5]
];
const HORIZONTAL_FLIP = [2, 1, 0, 5, 4, 3, 8, 7, 6];
const VERTICAL_FLIP = [6, 7, 8, 3, 4, 5, 0, 1, 2];

const DEBUG_MODE = false;
function dump() {
  if (DEBUG_MODE) {
    throw "dump() not implemented";
  }
}
function log(...args) {
  if (DEBUG_MODE) {
    console.log(...args);
  }
}
function error(...args) {
  log("Transformed view state:", view);
  log(...args);
  throw "A critical error has occurred!";
}

function createArray(func, length) {
  const arr = [];
  for (let i = 0; i < length; i++) {
    arr.push(func(i, arr));
  }
  return arr;
}

class Test {
  run(cell) {
    error("No run method defined for this instance of Test:", this);
  }
  find(cells = CELLS) {
    return cells.find((c) => this.run(c));
  }
  findIndex(cells = CELLS) {
    return cells.findIndex((c) => this.run(c));
  }
  filter(cells = CELLS) {
    return cells.filter((c) => this.run(c));
  }
  every(cells = CELLS) {
    return cells.every((c) => this.run(c));
  }
  some(cells = CELLS) {
    return cells.some((c) => this.run(c));
  }
  count(cells = CELLS) {
    return this.filter(cells).length;
  }
  invert() {
    return new InverseTest(this);
  }
  and(test) {
    return new EveryTest(this, test);
  }
  or(test) {
    return new SomeTest(this, test);
  }
}

class InverseTest extends Test {
  constructor(test) {
    super();
    this.test = test;
  }
  run(cell) {
    return !this.test.run(cell);
  }
  invert() {
    return this.test;
  }
}

class CombinedTest extends Test {
  constructor(...tests) {
    super();
    this.tests = tests;
  }
  append(test) {
    this.tests.push(test);
    return this;
  }
}
class EveryTest extends CombinedTest {
  run(cell) {
    return this.tests.every((test) => test.run(cell));
  }
  and(test) {
    return this.append(test);
  }
}
class SomeTest extends CombinedTest {
  run(cell) {
    return this.tests.some((test) => test.run(cell));
  }
  or(test) {
    return this.append(test);
  }
}

class ColorTest extends Test {
  constructor(color) {
    super();
    this.color = color;
  }
  run(cell) {
    return view[cell].color === this.color;
  }
}
class ColorBandTest extends SomeTest {
  constructor(colorBand) {
    super(...colorBand.map((color) => new ColorTest(color)));
  }
}

class FoodTest extends Test {
  constructor(hasFood = true) {
    super();
    this.food = hasFood ? 1 : 0;
  }
  run(cell) {
    return view[cell].food === this.food;
  }
}

class AntTest extends Test {
  constructor(friend, type, food) {
    super();
    this.friend = friend;
    this.type = type;
    this.food = food;
  }
  run(cell) {
    const ant = view[cell].ant;
    return ant !== null && (this.type === undefined || ant.type === this.type) && (this.friend === undefined || ant.friend === this.friend) && (this.food === undefined || (this.food ? ant.food > 0 : ant.food === 0));
  }
}

class NeighborTest extends Test {
  constructor(test) {
    super();
    this.test = test;
  }
  run(cell) {
    return this.test.some(NEIGHBORS[cell]);
  }
}

class MatchTest extends Test {
  constructor(matches) {
    super();
    this.matches = matches;
  }
  run(cell) {
    return this.matches[cell];
  }
}

class CustomTest extends Test {
  constructor(func, ...args) {
    super();
    this.func = func;
    this.args = args;
  }
  run(cell) {
    return this.func(cell, ...this.args);
  }
}

class Action {
  constructor(cell, test) {
    this.cell = cell;
    this.test = test;
  }

  valid() {
    return this.cell >= 0 && this.cell < 9 && (!this.test || this.test.run(this.cell));
  }
  attempt() {
    return this.valid() ? this : null;
  }
  static tryAll(...actions) {
    return actions.find((action) => action instanceof this && action.valid()) || null;
  }
}
class Move extends Action {
  constructor(cell, test) {
    super(cell, test);
  }

  valid() {
    return super.valid() && view[this.cell].ant === null && (view[this.cell].food === 0 || ME.food === 0 || ME.type === QUEEN);
  }
  static many(cells, test) {
    return cells.map((cell) => new this(cell, test));
  }
}
class Paint extends Action {
  constructor(cell, color, test) {
    super(cell, test);
    this.color = color;
  }

  valid() {
    return super.valid() && view[this.cell].color !== this.color && this.color >= 1 && this.color <= 8;
  }
  static many(cells, colors, test) {
    return cells.map((cell, i) => new this(cell, colors[i % colors.length], test));
  }
}
class Spawn extends Action {
  constructor(cell, type, test) {
    super(cell, test);
    this.type = type;
  }

  valid() {
    return super.valid() && view[this.cell].ant === null && view[this.cell].food === 0 && ME.food > 0 && ME.type === QUEEN && this.type >= 1 && this.type <= 4;
  }
  static many(cells, type, test) {
    return cells.map((cell, i) => new this(cell, type, test));
  }
}
class NOP extends Action {
  constructor() {
    super(CENTER);
  }

  valid() {
    return true;
  }
}

class Context {
  apply(func, ...args) {
    const hiddenView = view;
    if (this.viewTranslator) {
      view = this.viewTranslator(hiddenView);
    }

    let output = func(...args);
    if (output instanceof Action && this.outputTranslator) {
      this.outputTranslator(output);
    }

    view = hiddenView;
    return output;
  }
}

class TranslationContext extends Context {
  constructor(translationArray) {
    super();
    this.translationArray = translationArray;
  }

  viewTranslator(oldView) {
    const newView = [];
    for (let i = 0; i < 9; i++) {
      newView.push(oldView[this.translationArray[i]]);
    }
    return newView;
  }

  outputTranslator(out) {
    out.cell = this.translationArray[out.cell];
  }
}
class RotationContext extends TranslationContext {
  constructor(orientation) {
    super(ROTATIONS[orientation]);
    this.orientation = orientation;
  }
}
class OffsetContext extends TranslationContext {
  constructor(centerCell) {
    throw "OffsetContext not implemented";
  }
}
class HorizontalReflectionContext extends TranslationContext {
  constructor() {
    super(HORIZONTAL_FLIP);
  }
}
class VerticalReflectionContext extends TranslationContext {
  constructor() {
    super(VERTICAL_FLIP);
  }
}

class ColorMapContext extends Context {
  constructor(map, unmap) {
    super();
    this.map = map;
    this.unmap = unmap;
  }

  viewTranslator(oldView) {
    return oldView.map((cell) => ({color: this.map[cell.color - 1], food: cell.food, ant: cell.ant}));
  }

  outputTranslator(out) {
    out.color = this.unmap[out.color - 1];
  }
}

class XY {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }

  static fromTuples(...xyTuples) {
    return xyTuples.map((xy) => new this(xy[0], xy[1]));
  }
}

class WrapProperties {
  constructor(horizontal, vertical, size, wrapOffsets) {
    this.horizontal = !!horizontal;
    this.vertical = !!vertical;
    this.size = size;
    this.wrapOffsets = wrapOffsets || {};
  }
}

class ScoredTest {
  constructor(test, score = 1) {
    this.test = test;
    this.score = score;
  }

  run(cell) {
    return this.test.run(cell) ? this.score : 0;
  }
}

class Environment {
  constructor(tests, wrapping) {
    this.tests = tests.map((test) => test instanceof Test ? new ScoredTest(test) : test);
    this.wrapping = wrapping;
  }

  at(x, y) {
    const w = this.wrapping;
    while ((w.horizontal && (x < 0 || x >= w.size.x)) || (w.vertical && (y < 0 || y >= w.size.y))) {
      if (w.horizontal) {
        if (x < 0) {
          x += w.size.x;
          y += w.wrapOffsets.left || 0;
        } else if (x >= w.size.x) {
          x -= w.size.x;
          y += w.wrapOffsets.right || 0;
        }
      }

      if (w.vertical) {
        if (y < 0) {
          y += w.size.y;
          x += w.wrapOffsets.up || 0;
        } else if (y >= w.size.y) {
          y -= w.size.y;
          x += w.wrapOffsets.down || 0;
        }
      }
    }

    if ((!w.horizontal || (x >= 0 && x < w.size.x)) && (!w.vertical || (y >= 0 || y < w.size.y))) {
      return this.tests[x + y * w.size.x];
    } else {
      return null;
    }
  }
  around(x, y) {
    const arr = [];
    for (let oy = -1; oy <= 1; oy++) {
      for (let ox = -1; ox <= 1; ox++) {
        arr.push(this.at(x + ox, y + oy));
      }
    }
    return arr;
  }

  detect(...positions) {
    return createArray((i) => new RotationContext(i), 4).reduce((best, context) => {
      const next = context.apply(() => {
        return positions.reduce((best, pos, i) => {
          let score = 0;
          const matches = this.around(pos.x, pos.y).map((test, i) => {
            if (test && (test.test instanceof Test)) {
              const result = test.run(i);
              if (result) {
                score += result;
                return true;
              } else {
                return false;
              }
            } else {
              return null;
            }
          });
          if (score > best.score) {
            return {position: pos, positionIndex: i, orientation: context.orientation, environment: this, matches: matches, score: score, confidence: score - best.score};
          } else {
            best.confidence = Math.min(best.score - score, best.confidence);
            return best;
          }
        }, {position: positions[0], positionIndex: 0, orientation: 0, environment: this, matches: [], score: 0, confidence: 0});
      });
      if (next.score > best.score) {
        next.confidence = next.score - best.score;
        return next;
      } else {
        best.confidence = Math.min(best.score - next.score, best.confidence);
        return best;
      }
    }, {position: positions[0], positionIndex: 0, orientation: 0, environment: this, matches: [], score: 0, confidence: 0});
  }

  static chooseBest(...detectionResults) {
    const r = detectionResults.reduce((best, result, i) => {
      if (result.score > best.score) {
        result.index = i;
        result.confidence = result.score - best.score;
        return result;
      } else {
        best.confidence = Math.min(best.score - result.score, best.confidence);
        return best;
      }
    });
    r.index = r.index || 0;
    return r;
  }
}

class ColoredEnvironment extends Environment {
  constructor(colors, wrapping) {
    super(colors.map((color) => new ColorTest(color)), wrapping);
  }

  getPainter(detectionResult) {
    return new (class Painter {
      constructor(loc) {
        this.pos = loc.position;
        this.matches = loc.matches;
        this.colors = loc.environment.around(this.pos.x, this.pos.y).map((test) => test && test.test instanceof ColorTest ? test.test.color : null);
        this.test = new MatchTest(loc.matches).invert();
        this.orient = loc.orientation;
      }

      paint(...cells) {
        return cells.map((cell) => new Paint(cell, this.colors[cell], this.test));
      }
      cleanup(eraseColor, eraseTargets, ...cells) {
        const eraseQual = this.test.and(new ColorBandTest(eraseTargets));
        return cells.map((cell) => new Paint(cell, eraseColor, eraseQual));
      }
    })(detectionResult);
  }
}

// HIGH-LEVEL LOGIC STARTS HERE //
const PARTNER = 1;

// TODO: Do a 180 when 3 workers are in front of us
function logicOrthogonal(frontC, sideC, backC, backCells, moveCells) {
  const a = [frontC, sideC, backC, backCells, moveCells];
  const f = new FoodTest;
  return Action.tryAll(
    ...Move.many([frontC, sideC], f),
    f.some(backCells) ? new Move(backC) : null,
    ...Move.many(moveCells),
    new NOP
  );
}
function logicDiagonal(adjacentC) {
  return Action.tryAll(...Move.many(adjacentC), new NOP);
}
function logic(partnerTest, partnerOrthC, partnerDiagC, frontC, sideC, backC, backCells, moveCells, adjacentC) {
  function detectEnv(c) {
    return new Environment(createArray((i) => i === c ? partnerTest : undefined, 9), new WrapProperties(false, false, new XY(3, 3), null)).detect(new XY(1, 1));
  }
  const orth = detectEnv(partnerOrthC);
  const diag = detectEnv(partnerDiagC);
  return orth.score === 1 ? new RotationContext(orth.orientation).apply(() => logicOrthogonal(frontC, sideC, backC, backCells, moveCells)) : 
    diag.score === 1 ? new RotationContext(diag.orientation).apply(() => logicDiagonal(adjacentC)) : 
    error("How did we get here?");
}

if (ME.type === QUEEN) {
  const partner = new AntTest(true, PARTNER);
  if (partner.some(DIRECTIONS)) {
    return logic(partner, 5, 8, 2, 1, 7, [0, 3, 6, 7], [2, 7, 1, 8], [5, 7]);
  } else {
    const COLOR = 5;
    const bgTest = new ColorTest(WHITE);
    if (bgTest.run(CENTER)) {
      return new Paint(CENTER, COLOR).attempt() || error("Something went terribly wrong while painting own cell");
    }

    const food = new FoodTest().find(DIRECTIONS);
    if (food !== undefined) {
      return new Move(food);
    }

    const det = new ColoredEnvironment([
      WHITE, WHITE, WHITE, 
      WHITE, undefined, undefined,
      WHITE, undefined, COLOR
    ], new WrapProperties(false, false, new XY(3, 3))).detect(new XY(1, 1));
    return (ME.food > 0 ? Action.tryAll(...Spawn.many(ORTHOGONALS, PARTNER)) : null) ||
      (det.score === 6 ? new RotationContext(det.orientation).apply(() => Action.tryAll(...Move.many([0, 2, 6, 1, 3, 5, 7, 8]))) : null) ||
      Action.tryAll(...Move.many(DIAGONALS_ORTHOGONALS), new NOP);
  }
} else {
  return logic(new AntTest(true, QUEEN), 1, 0, 2, 5, 3, [8, 7, 6, 3], [2, 3, 5, 0], [1, 3]);
}

ব্যাখ্যা

এটি এমন একটি সরল পিঁপড় যা আমি হতবাক হয়ে যায় কেউ এর আগে কখনও ভাবেনি ...

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

সংস্করণ 2.0+ বাইরে! কোডটিতে মন্তব্যগুলি বৈশিষ্ট্যযুক্ত যা এই এন্ট্রিটির বিশদগুলি ব্যাখ্যা করে।


পরিবর্তণের

সংস্করণ 1.0

  • প্রাথমিক প্রকাশ

সংস্করণ 2.0

  • সম্পূর্ণরূপে চালিত কৌশলগুলি
    • আরও চলন বিকল্পের জন্য এখন তির্যক সংলগ্নতা ব্যবহার করে
    • খাবার দখল করার আচরণ পরিবর্তন করে changed
      • গড় সংগ্রহের হার অপরিবর্তিত রয়েছে, তবে সিস্টেমটি আরও শক্তিশালী
      • একাধিক খাবার উপস্থিত হলে অচলাবস্থা রোধ করে অবিচ্ছিন্নতা বাড়িয়ে তোলে significantly
      • পরিবর্তনের দিকের হারকে হ্রাস করেছে
      • নিজের পেছনে খাবার দখল করতে পারে
    • বাধা এড়ানোর জন্য পরিবর্তিত আচরণ
      • অচলাবস্থার সম্ভাবনা হ্রাস করে, আরও ধারাবাহিকতা বাড়িয়ে তোলে
      • একেবারে প্রয়োজনীয় না হলে ইউ-টার্ন হয় না, মোট মোট ক্ষেত্রফল coveredাকা থাকে
  • কোড ক্লিন আপ
  • মন্তব্য যুক্ত

সংস্করণ 2.1

  • একটি বিদেশী অচলাবস্থার সমাধান

সংস্করণ 2.2

  • অন্য একটি বিদেশী অচলাবস্থার সমাধান

সংস্করণ 2.3

  • শত্রুদের এড়ানো এখন উল্লেখযোগ্যভাবে কার্যকর

সংস্করণ 2.3.1

  • শত্রুদের এড়ানো এখনও আরও কার্যকর

সংস্করণ 2.4

  • ফরমিক ফ্রেমওয়ার্ক 5.0.4 সংস্করণে আপডেট হয়েছে (1.0 থেকে)
  • রিফ্যাক্টর কোড (সংস্করণ ২.৩.১ এর সাথে প্রায় একইরকম আচরণ)

সংস্করণ 2.5

  • ফরমিক ফ্রেমওয়ার্ক 6.1.10 সংস্করণে আপডেট হয়েছে (5.0.4 থেকে)
  • নতুন কোডিং স্ট্যান্ডার্ডের সাথে মিলানোর জন্য রিফ্যাক্টর কোড (সংস্করণ 2.4 এর সাথে প্রায় একই রকম আচরণ)
  • সরানো কোড মন্তব্য :(

সংস্করণ 2.5.0.1

  • মাইনর ফিক্স

সংস্করণ 2.5.0.2

  • সাহায্যে নির্দিষ্ট অযোগ্যতা বাগ dzaima মধ্যে চ্যাট

সংস্করণ 2.5.0.3

  • ডিবাগ করা অক্ষম

8

পথচিহ্ন-রবার

var i, j
var orthogonals = [1, 3, 7, 5]  // These are the non-diagonal cells
if(view[4].ant.type == 5) {
//Queen moves straight to get food
// Color own cell if white
if (view[4].color != 6) { 
    return {cell:4, color:6}
}
var specified = null;
// Otherwise move to a white cell opposite a colored cell
for (i=0; i<4; i++) {
    j = (i+2) % 4
    if (view[orthogonals[i]].color !== 6 &&
        view[orthogonals[j]].color == 6 && !view[orthogonals[i]].ant) {
        specified = {cell:orthogonals[i]}
    } else if (view[4].ant.food < 8 && view[4].ant.food && view[orthogonals[i]].color !== 6 && !view[orthogonals[i]].ant && !view[orthogonals[i]].food && view[orthogonals[i]].color !== 1) {
        //create workers once I encounter a trail
        return {cell:orthogonals[i], type:(view[orthogonals[i]].color%4)+1};
    } else if (view[orthogonals[i]].food) {
        return {cell:orthogonals[i]}
    }
}
if(specified) { return specified; }
// Otherwise move to one of the vertical or horizontal cells if not occupied
for (i=1; i<9; i+=2) {
    if (!view[i].ant) {
        return {cell:i}
    }
}

// Otherwise move to one of the diagonal cells if not occupied
for (i=0; i<9; i+=2) {
    if (!view[i].ant) {
        return {cell:i};
    }
}

// Otherwise don't move at all
return {cell:4};
}
//workers erase their trails
//Follow the trail to erase
var move, color, enemyAnt = false;
var nearbyColoredCells = 0;
if(view[4].color != 1){
   color =  {cell:4, color:1}
}
for(i=0;i<9;i++) {
    if(i != 4 && view[i].color != 1 && !view[i].ant && (!view[4].ant.food || !view[i].food) && (!move || (view[i].color % 4 + 1) == view[4].type || (view[move.cell].color == 6 && view[i].color != 6))) {
        move = {cell:i}
    }
    if(view[i].ant && view[i].ant.friend && view[i].ant.type == 5){
       return {cell:4}
    }
    if(i != 4 && view[i].color != 1 && view[i].color != 6){
        nearbyColoredCells += 1;
    }
    if(view[i].ant && !view[i].ant.friend) {
         enemyAnt = i;
    }
}
if(nearbyColoredCells <= 1 || enemyAnt > 1) {
    // Either I'm following a standard trail or there are enemy workers; possibly decolor own cell and move
    if(color && (!move || !enemyAnt)) { return color; }
    if(move) { return move; }
} else if (nearbyColoredCells > 1){
   for (i = 0; i < 9; i++){
       if(view[i].color != 1){ return {cell:i, color:1} }
   }
}
// uh-oh, our trail ended or we got lost -- random walk
// find a safe place to move
for (i=0;i<9;i+=1) {
    if (!view[i].ant && (!view[4].ant.food || !view[i].food)) {
       return {cell:i}
    }
}
return {cell:4}

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


1
নাশকতার! The রোমানরা তোমার সাথে কি করেছিল?
ডেভ

এই এন্ট্রিটি ব্ল্যাক হোলগুলির সাথে জগাখিচুড়ি করতে অনেক মজা পাচ্ছে ...
ফ্রেঞ্জি লি

2
@ ডেভ তারা এই চ্যালেঞ্জের প্রতিযোগিতামূলক এন্ট্রি জমা দিয়েছে ...
পিপ্পারি

2
ইয়াহ, এই খেলোয়াড় কখনও কখনও তার সমস্ত খাবার নষ্ট করে দেয়, কারণ এটি রোমান পিঁপড়েদের দ্বারা বিভ্রান্ত হয়
পিপ্পারি

2
দ্বিতীয় আপডেট: আর আর শুরুতে খাদ্য সংগ্রহ করে না, পরে
নাশকতার

8

Hyperwave

আমার সমস্ত উত্তরগুলিতে ফর্মিক ফাংশন ফ্রেমওয়ার্ক আকারে অনুরূপ নিম্ন-স্তরের যুক্তি থাকবে। "হাই-লেভেল লজিক স্টার্টস এখানে" ফ্রেমওয়ার্কের কোডটির সমাপ্তি চিহ্নিত করে।

 //  FORMIC FRAMEWORK  //
// Version 6.1.10     //
const WHITE = 1;
const QUEEN = 5;
const CENTER = 4;
const HERE = view[CENTER];
const ME = HERE.ant;
const ORTHOGONALS = [1, 3, 5, 7];
const DIAGONALS = [0, 2, 6, 8];
const DIAGONALS_ORTHOGONALS = [0, 2, 6, 8, 1, 3, 5, 7];
const DIRECTIONS = [0, 1, 2, 3, 5, 6, 7, 8];
const CLOCKWISE_DIRECTIONS = [0, 1, 2, 5, 8, 7, 6, 3];
const CELLS = [0, 1, 2, 3, 4, 5, 6, 7, 8];
const ROTATIONS = [
  [0, 1, 2,
   3, 4, 5,
   6, 7, 8],

  [6, 3, 0,
   7, 4, 1,
   8, 5, 2],

  [8, 7, 6,
   5, 4, 3,
   2, 1, 0],

  [2, 5, 8,
   1, 4, 7,
   0, 3, 6]
];
const NEIGHBORS = [
  [1, 4, 3],
  [2, 5, 4, 3, 0],
  [5, 4, 1],
  [0, 1, 4, 7, 6],
  [0, 1, 2, 5, 8, 7, 6, 3],
  [8, 7, 4, 1, 2],
  [3, 4, 7],
  [6, 3, 4, 5, 8],
  [7, 4, 5]
];
const HORIZONTAL_FLIP = [2, 1, 0, 5, 4, 3, 8, 7, 6];
const VERTICAL_FLIP = [6, 7, 8, 3, 4, 5, 0, 1, 2];

const DEBUG_MODE = true;
function dump() {
  if (DEBUG_MODE) {
    throw "dump() not implemented";
  }
}
function log(...args) {
  if (DEBUG_MODE) {
    console.log(...args);
  }
}
function error(...args) {
  log("Transformed view state:", view);
  log(...args);
  throw "A critical error has occurred!";
}

function createArray(func, length) {
  const arr = [];
  for (let i = 0; i < length; i++) {
    arr.push(func(i, arr));
  }
  return arr;
}

class Test {
  run(cell) {
    error("No run method defined for this instance of Test:", this);
  }
  find(cells = CELLS) {
    return cells.find((c) => this.run(c));
  }
  findIndex(cells = CELLS) {
    return cells.findIndex((c) => this.run(c));
  }
  filter(cells = CELLS) {
    return cells.filter((c) => this.run(c));
  }
  every(cells = CELLS) {
    return cells.every((c) => this.run(c));
  }
  some(cells = CELLS) {
    return cells.some((c) => this.run(c));
  }
  count(cells = CELLS) {
    return this.filter(cells).length;
  }
  invert() {
    return new InverseTest(this);
  }
  and(test) {
    return new EveryTest(this, test);
  }
  or(test) {
    return new SomeTest(this, test);
  }
}

class InverseTest extends Test {
  constructor(test) {
    super();
    this.test = test;
  }
  run(cell) {
    return !this.test.run(cell);
  }
  invert() {
    return this.test;
  }
}

class CombinedTest extends Test {
  constructor(...tests) {
    super();
    this.tests = tests;
  }
  append(test) {
    this.tests.push(test);
    return this;
  }
}
class EveryTest extends CombinedTest {
  run(cell) {
    return this.tests.every((test) => test.run(cell));
  }
  and(test) {
    return this.append(test);
  }
}
class SomeTest extends CombinedTest {
  run(cell) {
    return this.tests.some((test) => test.run(cell));
  }
  or(test) {
    return this.append(test);
  }
}

class ColorTest extends Test {
  constructor(color) {
    super();
    this.color = color;
  }
  run(cell) {
    return view[cell].color === this.color;
  }
}
class ColorBandTest extends SomeTest {
  constructor(colorBand) {
    super(...colorBand.map((color) => new ColorTest(color)));
  }
}

class FoodTest extends Test {
  constructor(hasFood = true) {
    super();
    this.food = hasFood ? 1 : 0;
  }
  run(cell) {
    return view[cell].food === this.food;
  }
}

class AntTest extends Test {
  constructor(friend, type, food) {
    super();
    this.friend = friend;
    this.type = type;
    this.food = food;
  }
  run(cell) {
    const ant = view[cell].ant;
    return ant !== null && (this.type === undefined || ant.type === this.type) && (this.friend === undefined || ant.friend === this.friend) && (this.food === undefined || (this.food ? ant.food > 0 : ant.food === 0));
  }
}

class NeighborTest extends Test {
  constructor(test) {
    super();
    this.test = test;
  }
  run(cell) {
    return this.test.some(NEIGHBORS[cell]);
  }
}

class MatchTest extends Test {
  constructor(matches) {
    super();
    this.matches = matches;
  }
  run(cell) {
    return this.matches[cell];
  }
}

class CustomTest extends Test {
  constructor(func, ...args) {
    super();
    this.func = func;
    this.args = args;
  }
  run(cell) {
    return this.func(cell, ...this.args);
  }
}

class Action {
  constructor(cell, test) {
    this.cell = cell;
    this.test = test;
  }

  valid() {
    return this.cell >= 0 && this.cell < 9 && (!this.test || this.test.run(this.cell));
  }
  attempt() {
    return this.valid() ? this : null;
  }
  static tryAll(...actions) {
    return actions.find((action) => action instanceof this && action.valid()) || null;
  }
}
class Move extends Action {
  constructor(cell, test) {
    super(cell, test);
  }

  valid() {
    return super.valid() && view[this.cell].ant === null && (view[this.cell].food === 0 || ME.food === 0 || ME.type === QUEEN);
  }
  static many(cells, test) {
    return cells.map((cell) => new this(cell, test));
  }
}
class Paint extends Action {
  constructor(cell, color, test) {
    super(cell, test);
    this.color = color;
  }

  valid() {
    return super.valid() && view[this.cell].color !== this.color && this.color >= 1 && this.color <= 8;
  }
  static many(cells, colors, test) {
    return cells.map((cell, i) => new this(cell, colors[i % colors.length], test));
  }
}
class Spawn extends Action {
  constructor(cell, type, test) {
    super(cell, test);
    this.type = type;
  }

  valid() {
    return super.valid() && view[this.cell].ant === null && view[this.cell].food === 0 && ME.food > 0 && ME.type === QUEEN && this.type >= 1 && this.type <= 4;
  }
  static many(cells, type, test) {
    return cells.map((cell, i) => new this(cell, type, test));
  }
}
class NOP extends Action {
  constructor() {
    super(CENTER);
  }

  valid() {
    return true;
  }
}

class Context {
  apply(func, ...args) {
    const hiddenView = view;
    if (this.viewTranslator) {
      view = this.viewTranslator(hiddenView);
    }

    let output = func(...args);
    if (output instanceof Action && this.outputTranslator) {
      this.outputTranslator(output);
    }

    view = hiddenView;
    return output;
  }
}

class TranslationContext extends Context {
  constructor(translationArray) {
    super();
    this.translationArray = translationArray;
  }

  viewTranslator(oldView) {
    const newView = [];
    for (let i = 0; i < 9; i++) {
      newView.push(oldView[this.translationArray[i]]);
    }
    return newView;
  }

  outputTranslator(out) {
    out.cell = this.translationArray[out.cell];
  }
}
class RotationContext extends TranslationContext {
  constructor(orientation) {
    super(ROTATIONS[orientation]);
    this.orientation = orientation;
  }
}
class OffsetContext extends TranslationContext {
  constructor(centerCell) {
    throw "OffsetContext not implemented";
  }
}
class HorizontalReflectionContext extends TranslationContext {
  constructor() {
    super(HORIZONTAL_FLIP);
  }
}
class VerticalReflectionContext extends TranslationContext {
  constructor() {
    super(VERTICAL_FLIP);
  }
}

class ColorMapContext extends Context {
  constructor(map, unmap) {
    super();
    this.map = map;
    this.unmap = unmap;
  }

  viewTranslator(oldView) {
    return oldView.map((cell) => ({color: this.map[cell.color - 1], food: cell.food, ant: cell.ant}));
  }

  outputTranslator(out) {
    out.color = this.unmap[out.color - 1];
  }
}

class XY {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }

  static fromTuples(...xyTuples) {
    return xyTuples.map((xy) => new this(xy[0], xy[1]));
  }
}

class WrapProperties {
  constructor(horizontal, vertical, size, wrapOffsets) {
    this.horizontal = !!horizontal;
    this.vertical = !!vertical;
    this.size = size;
    this.wrapOffsets = wrapOffsets || {};
  }
}

class ScoredTest {
  constructor(test, score = 1) {
    this.test = test;
    this.score = score;
  }

  run(cell) {
    return this.test.run(cell) ? this.score : 0;
  }
}

class Environment {
  constructor(tests, wrapping) {
    this.tests = tests.map((test) => test instanceof Test ? new ScoredTest(test) : test);
    this.wrapping = wrapping;
  }

  at(x, y) {
    const w = this.wrapping;
    while ((w.horizontal && (x < 0 || x >= w.size.x)) || (w.vertical && (y < 0 || y >= w.size.y))) {
      if (w.horizontal) {
        if (x < 0) {
          x += w.size.x;
          y += w.wrapOffsets.left || 0;
        } else if (x >= w.size.x) {
          x -= w.size.x;
          y += w.wrapOffsets.right || 0;
        }
      }

      if (w.vertical) {
        if (y < 0) {
          y += w.size.y;
          x += w.wrapOffsets.up || 0;
        } else if (y >= w.size.y) {
          y -= w.size.y;
          x += w.wrapOffsets.down || 0;
        }
      }
    }

    if ((!w.horizontal || (x >= 0 && x < w.size.x)) && (!w.vertical || (y >= 0 || y < w.size.y))) {
      return this.tests[x + y * w.size.x];
    } else {
      return null;
    }
  }
  around(x, y) {
    const arr = [];
    for (let oy = -1; oy <= 1; oy++) {
      for (let ox = -1; ox <= 1; ox++) {
        arr.push(this.at(x + ox, y + oy));
      }
    }
    return arr;
  }

  detect(...positions) {
    return createArray((i) => new RotationContext(i), 4).reduce((best, context) => {
      const next = context.apply(() => {
        return positions.reduce((best, pos, i) => {
          let score = 0;
          const matches = this.around(pos.x, pos.y).map((test, i) => {
            if (test && (test.test instanceof Test)) {
              const result = test.run(i);
              if (result) {
                score += result;
                return true;
              } else {
                return false;
              }
            } else {
              return null;
            }
          });
          if (score > best.score) {
            return {position: pos, positionIndex: i, orientation: context.orientation, environment: this, matches: matches, score: score, confidence: score - best.score};
          } else {
            best.confidence = Math.min(best.score - score, best.confidence);
            return best;
          }
        }, {position: positions[0], positionIndex: 0, orientation: 0, environment: this, matches: [], score: 0, confidence: 0});
      });
      if (next.score > best.score) {
        next.confidence = next.score - best.score;
        return next;
      } else {
        best.confidence = Math.min(best.score - next.score, best.confidence);
        return best;
      }
    }, {position: positions[0], positionIndex: 0, orientation: 0, environment: this, matches: [], score: 0, confidence: 0});
  }

  static chooseBest(...detectionResults) {
    const r = detectionResults.reduce((best, result, i) => {
      if (result.score > best.score) {
        result.index = i;
        result.confidence = result.score - best.score;
        return result;
      } else {
        best.confidence = Math.min(best.score - result.score, best.confidence);
        return best;
      }
    });
    r.index = r.index || 0;
    return r;
  }
}

class ColoredEnvironment extends Environment {
  constructor(colors, wrapping) {
    super(colors.map((color) => new ColorTest(color)), wrapping);
  }

  getPainter(detectionResult) {
    return new (class Painter {
      constructor(loc) {
        this.pos = loc.position;
        this.matches = loc.matches;
        this.colors = loc.environment.around(this.pos.x, this.pos.y).map((test) => test && test.test instanceof ColorTest ? test.test.color : null);
        this.test = new MatchTest(loc.matches).invert();
        this.orient = loc.orientation;
      }

      paint(...cells) {
        return cells.map((cell) => new Paint(cell, this.colors[cell], this.test));
      }
      cleanup(eraseColor, eraseTargets, ...cells) {
        const eraseQual = this.test.and(new ColorBandTest(eraseTargets));
        return cells.map((cell) => new Paint(cell, eraseColor, eraseQual));
      }
    })(detectionResult);
  }
}

// HIGH-LEVEL LOGIC STARTS HERE //
// TODO:
// - more food checkpoints (no disadvantages because it's illogical for WFW to "premanently lose" workers)
// - randomly shifting 1 up (5% chance? watch out for hoarding stealing your randomness!)
// - randomly skip painting a tiny bit of local cells (prevent deadlock against ants outside of view)
// - escape routine when situation is dire (many workers near the queen/partner)

const COLOR_BAND = [4, 7, 3, 2, 8];

const PARTNER = 2;
const WORKER = 1;

const START_FOOD = 6;
const MIN_CONFIDENCE = 2;

const PATTERN = new ColoredEnvironment(COLOR_BAND, new WrapProperties(true, true, new XY(COLOR_BAND.length, 1), {up: 2, down: -2})).detect(...createArray((i) => new XY(i, 0), COLOR_BAND.length));

function checkpoint(val, tolerance) {
  return ME.food >= val - tolerance && ME.food <= val;
}
function shouldSpawn() {
  return PATTERN.orientation === 0 && PATTERN.positionIndex % 3 === 0 &&
    ME.food < 400 &&
    (ME.food < 75 || PATTERN.positionIndex === 0) && 
    !checkpoint(300, 4) &&
    !checkpoint(200, 5) &&
    !checkpoint(160, 3) &&
    !checkpoint(130, 2) &&
    !checkpoint(100, 2) &&
    !checkpoint(75, 2) &&
    !checkpoint(50, 2) &&
    !checkpoint(35, 1) &&
    !checkpoint(20, 1) &&
    !checkpoint(10, 0);
}

function lightspeed() {
  // TODO: Do a 180 when 3 workers are in front of us
  function logicOrthogonal(frontC, sideC, backC, backCells, moveCells) {
    const a = [frontC, sideC, backC, backCells, moveCells];
    const f = new FoodTest;
    return Action.tryAll(
      ...Move.many([frontC, sideC], f),
      f.some(backCells) ? new Move(backC) : null,
      ...Move.many(moveCells),
      new NOP
    );
  }
  function logicDiagonal(adjacentC) {
    return Action.tryAll(...Move.many(adjacentC), new NOP);
  }
  function logic(partnerTest, partnerOrthC, partnerDiagC, frontC, sideC, backC, backCells, moveCells, adjacentC) {
    function detectEnv(c) {
      return new Environment(createArray((i) => i === c ? partnerTest : undefined, 9), new WrapProperties(false, false, new XY(3, 3), null)).detect(new XY(1, 1));
    }
    const orth = detectEnv(partnerOrthC);
    const diag = detectEnv(partnerDiagC);
    return orth.score === 1 ? new RotationContext(orth.orientation).apply(() => logicOrthogonal(frontC, sideC, backC, backCells, moveCells)) : 
      diag.score === 1 ? new RotationContext(diag.orientation).apply(() => logicDiagonal(adjacentC)) : 
      error("How did we get here?");
  }

  if (ME.type === QUEEN) {
    const partner = new AntTest(true, PARTNER);
    if (partner.some(DIRECTIONS)) {
      return logic(partner, 5, 8, 2, 1, 7, [0, 3, 6, 7], [2, 7, 1, 8], [5, 7]);
    } else {
      const COLOR = 5;
      const bgTest = new ColorTest(WHITE);
      if (bgTest.run(CENTER)) {
        return new Paint(CENTER, COLOR).attempt() || error("Something went terribly wrong while painting own cell");
      }

      const food = new FoodTest().find(DIRECTIONS);
      if (food !== undefined) {
        return new Move(food);
      }

      const det = new ColoredEnvironment([
        WHITE, WHITE, WHITE, 
        WHITE, undefined, undefined,
        WHITE, undefined, COLOR
      ], new WrapProperties(false, false, new XY(3, 3))).detect(new XY(1, 1));
      return (ME.food > 0 ? Action.tryAll(...Spawn.many(ORTHOGONALS, PARTNER)) : null) ||
        (det.score === 6 ? new RotationContext(det.orientation).apply(() => Action.tryAll(...Move.many([0, 2, 6, 1, 3, 5, 7, 8]))) : null) ||
        Action.tryAll(...Move.many(DIAGONALS_ORTHOGONALS), new NOP);
    }
  } else {
    return logic(new AntTest(true, QUEEN), 1, 0, 2, 5, 3, [8, 7, 6, 3], [2, 3, 5, 0], [1, 3]);
  }
}

function queen() {
  const partnerTest = new AntTest(true, PARTNER);
  if (PATTERN.confidence < MIN_CONFIDENCE && (ME.food < START_FOOD || partnerTest.some(DIAGONALS))) return lightspeed();
  return new RotationContext(PATTERN.orientation).apply(() => {
    const partnerCell = new AntTest(true, PARTNER).find(DIRECTIONS);
    const p = PATTERN.environment.getPainter(PATTERN);
    const e = new AntTest(false);
    const enemy = e.some(DIRECTIONS);
    return Action.tryAll(
      ...!PATTERN.matches[8] ? [
        ...!enemy ? [...p.paint(7, 4, 5, 1, 2), ...shouldSpawn() && PATTERN.score === 8 ? Spawn.many([0, 2], WORKER) : []] : [],
        ...partnerCell === 1 ? Move.many(e.run(5) ? [0, 2] : PATTERN.orientation === 1 && PATTERN.positionIndex % 3 === 1 ? [2, 0, 5] : [5, 2, 0]) : 
          partnerCell === 0 ? Move.many(e.run(1) ? [3] : enemy ? [1, 3] : []) :
          partnerCell === 2 ? Move.many(e.run(1) ? [5] : []) :
          []
      ] : [
        ...!enemy ? p.paint(8, 7, 6, 5, 4, 3, 2, 1, 0) : [],
        ...Move.many(partnerCell === 1 ? [2, 0] : partnerCell === 0 ? [1, 3] : partnerCell === 2 && e.run(1) ? [5] : [])
      ],
      new NOP
    )
  });
}
function partner() {
  const queenTest = new AntTest(true, QUEEN)
  const queenCell = queenTest.find(DIRECTIONS);
  if (queenCell === undefined) {
    return new NOP; // TODO: What do we do if we've lost our queen?
  }
  if (PATTERN.confidence < MIN_CONFIDENCE && (view[queenCell].ant.food < START_FOOD || DIAGONALS.includes(queenCell))) return lightspeed();
  return PATTERN.confidence >= MIN_CONFIDENCE ? new RotationContext(PATTERN.orientation).apply(() => {
    const queenCell = queenTest.find(DIRECTIONS);
    const e = new AntTest(false);
    const enemy = e.some(DIRECTIONS);
    return Action.tryAll(
      ...!enemy ? PATTERN.environment.getPainter(PATTERN).paint(...CELLS) : [],
      ...Move.many([
        [1],
        [0, 2],
        [1],
        [0, 1],
        [], // Queen can't be on cell 4 - I'm here, after all!
        [2, 1],
        [3],
        [],
        [5]
      ][queenCell]),
      new NOP
    )
  }) : new NOP;
}
function worker() {
  const m = new MatchTest(PATTERN.matches);
  const n = m.invert();
  const u = new AntTest(true, WORKER, false);
  const l = new AntTest(true, WORKER, true);
  const q = new AntTest(true, QUEEN);
  const pt = new AntTest(true, PARTNER);
  const p = PATTERN.environment.getPainter(PATTERN);
  return new RotationContext(PATTERN.orientation).apply(() => { // TODO: Unique (random?) behavior when confidence low
    if (ME.food === 0) {
      const f = new FoodTest();
      const count = n.count([6, 7, 8]);
      return Action.tryAll(
        ...PATTERN.confidence >= 2 ? p.paint(4, 0, 1, 2) : [],
        //...p.cleanup(WHITE, COLOR_BAND, ...CELLS),
        ...((food) => food !== undefined ? [...p.paint(...NEIGHBORS[food], food), new Move(food)] : [])(f.find(DIRECTIONS)),
        ...q.or(pt).some(DIRECTIONS) || u.some([6, 7, 8, 5, 2]) ? Move.many([0, 1, 3], m) : [],
        ...count > 1 ? p.paint(...[6, 7, 8]) : [],
        ...count === 1 ? [...p.paint(...[3, 5]), ...Move.many([7, 8, 6, 3], m)] : [],
        /*n.run(6) ? new Move(3, m) : null,
        ...n.run(7) ? Move.many([6, 3], m) : [],
        n.run(8) ? new Move(7, m) : null,*/
        n.run(5) ? new Move(5) : null,
        ...Move.many([2, 1, 0, 3], m),
        new NOP
        /*
        ...(PATTERN.confidence >= 2 ? [...(PATTERN.score < 8 || new AntTest(false).some(DIRECTIONS) ? p.paint(4, 3, 0, 1, 2, 5) : []), ...p.cleanup(WHITE, COLOR_BAND, ...CELLS)] : []),
        ...((food) => food !== undefined ? [...p.paint(...NEIGHBORS[food]), new Move(food)] : [])(f.find(DIRECTIONS)), ...(
          w ? Move.many([1, 0, 2]) :
          m.some([4, 3]) ? p.paint(4, 3) :
          m.some([0, 1, 2]) ? Move.many([1, 5]) :
          m.run(6) ? [new Move(3)] :
          m.run(7) ? Move.many([6, 3]) :
          m.run(8) ? [new Move(7)] :
          m.run(5) ? Move.many([5, 7]) :
          Move.many([2, 1, 5])
        )
        new NOP*/
      );
    } else {
      return Action.tryAll(
        //...Move.many(new AntTest(true, WORKER).some([2, 5, 8, 7]) || PATTERN.score < 9 ? [8, 7, 6, 3] : [5, 8, 2], m.invert()),
        ...((test) => createArray((i) => new Move(CLOCKWISE_DIRECTIONS[(6 - i) % 8], test), 5))(new CustomTest((cell, moveTest, blockTest) => {
          const i = CLOCKWISE_DIRECTIONS.findIndex((c) => c === cell);
          return moveTest.run(CLOCKWISE_DIRECTIONS[i]) && blockTest.run(CLOCKWISE_DIRECTIONS[((i - 1) + 8) % 8]);
        }, m, n.or(new AntTest().and(l.invert())))),
        ...Move.many([2, 5, 1, 8], m),
        //...Move.many([...(PATTERN.score === 9 && !new AntTest(true, WORKER).some(DIRECTIONS) ? [2] : []), 5, 8, 7, 6, 3], m),
        new NOP
      );
    }
  });
}

switch (ME.type) {
  case QUEEN: {
    return queen();
  }
  case PARTNER: {
    return partner();
  }
  case WORKER: {
    return worker();
  }
}

সময়ের চাপের কারণে আমি এই প্রবেশের সমস্ত বিবরণ অস্থায়ীভাবে সরিয়েছি। আমি পরবর্তী তারিখে এই বড় আপডেটের একটি বিশদ বিবরণ যুক্ত করব।


পরিবর্তণের

সংস্করণ 1.0

  • প্রাথমিক প্রকাশ

সংস্করণ 2.0

  • হাইপারওয়েভ দিয়ে হাইওয়ে প্রতিস্থাপন করা হয়েছে

সংস্করণ 2.0.1

  • হটফিক্সড হোর্ডিং মেকানিজম

এটি দেখার জন্য সুন্দর শুরু হয়, তারপরে ভয়াবহ
আকারে

1
রাস্তার বিরুদ্ধে ভ্যাম্পিরিক আদেশ কার্যকর করার সময়।
ড্রাকো 18s

@ ড্রাকো 18 তে সময় বাড়ার সাথে সাথে আমি কেবল ভ্যাম্পায়ারকে আরও বেশি খাওয়ানোর জন্য যাচ্ছি - আমার অনেকগুলি উন্নতি করার ইচ্ছা আছে।
অ্যালিয়ন

3
প্রথম এন্ট্রি আমি দেখেছি যা স্ট্যান্ডার্ড গেমের সময়ের মধ্যে পুরোপুরি বোর্ডটি গ্রহন করতে পারে। খুব চিত্তাকর্ষক.
ডেভ

7

রোমান অ্যান্টস এমকে ২

আমার সমস্ত উত্তরগুলি একই স্তরের নিম্ন-স্তরের সহায়ক ফাংশনগুলি ভাগ করে নিচ্ছে। এই উত্তরের নির্দিষ্ট কোডটি দেখতে "উচ্চ-স্তরের যুক্তি এখানে সন্ধান করুন" অনুসন্ধান করুন।

// == Shared low-level helpers for all solutions ==

var QUEEN = 5;

var WHITE = 1;
var COL_MIN = WHITE;
var COL_LIM = 9;

var CENTRE = 4;

var NOP = {cell: CENTRE};

var DIR_FORWARDS = false;
var DIR_REVERSE = true;
var SIDE_RIGHT = true;
var SIDE_LEFT = false;

function sanity_check(movement) {
  var me = view[CENTRE].ant;
  if(!movement || movement.cell < 0 || movement.cell > 8) {
    return false;
  }
  if(movement.type) {
    if(movement.color) {
      return false;
    }
    if(movement.type < 1 || movement.type > 4) {
      return false;
    }
    if(view[movement.cell].ant || view[movement.cell].food) {
      return false;
    }
    if(me.type !== QUEEN || me.food < 1) {
      return false;
    }
    return true;
  }
  if(movement.color) {
    if(movement.color < COL_MIN || movement.color >= COL_LIM) {
      return false;
    }
    if(view[movement.cell].color === movement.color) {
      return false;
    }
    return true;
  }
  if(view[movement.cell].ant) {
    return false;
  }
  if(view[movement.cell].food + me.food > 1 && me.type !== QUEEN) {
    return false;
  }
  return true;
}

function as_array(o) {
  if(Array.isArray(o)) {
    return o;
  }
  return [o];
}

function best_of(movements) {
  var m;
  for(var i = 0; i < movements.length; ++ i) {
    if(typeof(movements[i]) === 'function') {
      m = movements[i]();
    } else {
      m = movements[i];
    }
    if(sanity_check(m)) {
      return m;
    }
  }
  return null;
}

function play_safe(movement) {
  // Avoid disqualification: no-op if moves are invalid
  return best_of(as_array(movement)) || NOP;
}

var RAND_SEED = (() => {
  var s = 0;
  for(var i = 0; i < 9; ++ i) {
    s += view[i].color * (i + 1);
    s += view[i].ant ? i * i : 0;
    s += view[i].food ? i * i * i : 0;
  }
  return s % 29;
})();

var ROTATIONS = [
  [0, 1, 2, 3, 4, 5, 6, 7, 8],
  [6, 3, 0, 7, 4, 1, 8, 5, 2],
  [8, 7, 6, 5, 4, 3, 2, 1, 0],
  [2, 5, 8, 1, 4, 7, 0, 3, 6],
];

function try_all(fns, limit, wrapperFn, checkFn) {
  var m;
  fns = as_array(fns);
  for(var i = 0; i < fns.length; ++ i) {
    if(typeof(fns[i]) !== 'function') {
      if(checkFn(m = fns[i])) {
        return m;
      }
      continue;
    }
    for(var j = 0; j < limit; ++ j) {
      if(checkFn(m = wrapperFn(fns[i], j))) {
        return m;
      }
    }
  }
  return null;
}

function identify_rotation(testFns) {
  // testFns MUST be functions, not constants
  return try_all(
    testFns,
    4,
    (fn, r) => fn(ROTATIONS[r]) ? ROTATIONS[r] : null,
    (r) => r
  );
}

function near(a, b) {
  return (
    Math.abs(a % 3 - b % 3) < 2 &&
    Math.abs(Math.floor(a / 3) - Math.floor(b / 3)) < 2
  );
}

function try_all_angles(solverFns) {
  return try_all(
    solverFns,
    4,
    (fn, r) => fn(ROTATIONS[r]),
    sanity_check
  );
}

function try_all_cells(solverFns, skipCentre) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i === CENTRE && skipCentre) ? null : fn(i)),
    sanity_check
  );
}

function try_all_cells_near(p, solverFns) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i !== p && near(p, i)) ? fn(i) : null),
    sanity_check
  );
}

function ant_type_at(i, friend) {
  return (view[i].ant && view[i].ant.friend === friend) ? view[i].ant.type : 0;
}

function friend_at(i) {
  return ant_type_at(i, true);
}

function foe_at(i) {
  return ant_type_at(i, false);
}

function foe_near(p) {
  for(var i = 0; i < 9; ++ i) {
    if(foe_at(i) && near(i, p)) {
      return true;
    }
  }
  return false;
}

function move_agent(agents) {
  var me = view[CENTRE].ant;
  var buddies = [0, 0, 0, 0, 0, 0];
  for(var i = 0; i < 9; ++ i) {
    ++ buddies[friend_at(i)];
  }

  for(var i = 0; i < agents.length; i += 2) {
    if(agents[i] === me.type) {
      return agents[i+1](me, buddies);
    }
  }
  return null;
}

function grab_nearby_food() {
  return try_all_cells((i) => (view[i].food ? {cell: i} : null), true);
}

function go_anywhere() {
  return try_all_cells((i) => ({cell: i}), true);
}

function colours_excluding(cols) {
  var r = [];
  for(var i = COL_MIN; i < COL_LIM; ++ i) {
    if(cols.indexOf(i) === -1) {
      r.push(i);
    }
  }
  return r;
}

function generate_band(start, width) {
  var r = [];
  for(var i = 0; i < width; ++ i) {
    r.push(start + i);
  }
  return r;
}

function colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function(c) {
      return colours[(colours.indexOf(c) + 1) % colours.length];
    }
  };
}

function random_colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function() {
      return colours[RAND_SEED % colours.length];
    }
  };
}

function fast_diagonal(colourBand) {
  var m = try_all_angles([
    // Avoid nearby checked areas
    (rot) => {
      if(
        !colourBand.contains(view[rot[0]].color) &&
        colourBand.contains(view[rot[5]].color) &&
        colourBand.contains(view[rot[7]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // Go in a straight diagonal line if possible
    (rot) => {
      if(
        !colourBand.contains(view[rot[0]].color) &&
        colourBand.contains(view[rot[8]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // When in doubt, pick randomly but avoid doubling-back
    (rot) => (colourBand.contains(view[rot[0]].color) ? null : {cell: rot[0]}),

    // Double-back when absolutely necessary
    (rot) => ({cell: rot[0]})
  ]);

  // Lay a colour track so that we can avoid doubling-back
  // (and mess up our foes as much as possible)
  if(!colourBand.contains(view[CENTRE].color)) {
    var prevCol = m ? view[8-m.cell].color : WHITE;
    return {cell: CENTRE, color: colourBand.next(prevCol)};
  }

  return m;
}

function follow_edge(obstacleFn, side) {
  // Since we don't know which direction we came from, this can cause us to get
  // stuck on islands, but the random orientation helps to ensure we don't get
  // stuck forever.

  var order = ((side === SIDE_LEFT)
    ? [0, 3, 6, 7, 8, 5, 2, 1, 0]
    : [0, 1, 2, 5, 8, 7, 6, 3, 0]
  );
  return try_all(
    [obstacleFn],
    order.length - 1,
    (fn, i) => (fn(order[i+1]) && !fn(order[i])) ? {cell: order[i]} : null,
    sanity_check
  );
}

function start_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => ((
      !protectedCols.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 2 : 0]].color) &&
      !colourBand.contains(view[rot[1]].color)
    )
      ? {cell: rot[right ? 5 : 3], color: colourBand.next(WHITE)}
      : null)
  ]);
}

function lay_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => {
      var ahead = rot[right ? 2 : 0];
      var behind = rot[right ? 8 : 6];
      if(
        colourBand.contains(view[behind].color) &&
        !protectedCols.contains(view[ahead].color) &&
        !colourBand.contains(view[ahead].color) &&
        !colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        return {cell: ahead, color: colourBand.next(view[behind].color)};
      }
    }
  ]);
}

function follow_dotted_path(colourBand, side, direction) {
  var forwards = (direction === DIR_REVERSE) ? 7 : 1;
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    // Cell on our side? advance
    (rot) => {
      if(
        colourBand.contains(view[rot[right ? 5 : 3]].color) &&
        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[0]].color) &&
        !colourBand.contains(view[rot[2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    },

    // Cell ahead and behind? advance
    (rot) => {
      var passedCol = view[rot[right ? 8 : 6]].color;
      var nextCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(passedCol) &&
        nextCol === colourBand.next(passedCol) &&

        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[right ? 0 : 2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    }
  ]);
}

function escape_dotted_path(colourBand, side, newColourBand) {
  var right = (side === SIDE_RIGHT);
  if(!newColourBand) {
    newColourBand = colourBand;
  }

  return try_all_angles([
    // Escape from beside the line
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        !colourBand.contains(view[rot[right ? 8 : 6]].color) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[rot[7]].color) ||
        colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        // not oriented, or in a corner
        return null;
      }
      return best_of([
        {cell: rot[right ? 0 : 2], color: newColourBand.next(approachingCol)},
        {cell: rot[right ? 3 : 5]},
        {cell: rot[right ? 0 : 2]},
        {cell: rot[right ? 6 : 8]},
        {cell: rot[right ? 2 : 0]},
        {cell: rot[right ? 8 : 6]},
        {cell: rot[right ? 5 : 3]}
      ]);
    },

    // Escape from inside the line
    (rot) => {
      if(
        !colourBand.contains(view[rot[7]].color) ||
        !colourBand.contains(view[rot[1]].color) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      return best_of([
        {cell: rot[3]},
        {cell: rot[5]},
        {cell: rot[0]},
        {cell: rot[2]},
        {cell: rot[6]},
        {cell: rot[8]}
      ]);
    }
  ]);
}

function latch_to_dotted_path(colourBand, side) {
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(approachingCol) &&
        view[rot[right ? 8 : 6]].color === colourBand.next(approachingCol) &&
        !colourBand.contains(view[rot[right ? 5 : 3]].color)
      ) {
        // We're on the wrong side; go inside the line
        return {cell: rot[right ? 5 : 3]};
      }
    },

    // Inside the line? pick a side
    (rot) => {
      var passedCol = view[rot[7]].color;
      var approachingCol = view[rot[1]].color;
      if(
        !colourBand.contains(passedCol) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      if((approachingCol === colourBand.next(passedCol)) === right) {
        return best_of([{cell: rot[3]}, {cell: rot[6]}, {cell: rot[0]}]);
      } else {
        return best_of([{cell: rot[5]}, {cell: rot[2]}, {cell: rot[8]}]);
      }
    }
  ]);
}


// == High-level logic begins here ==


var QUEEN_COL = colour_band(generate_band(3, 3));
var WORKER_COL = colour_band(generate_band(6, 3));
var AVOID_COL = colour_band([2]);
var INVERT_COL = colour_band([WHITE, 2]);

var MIN_FOOD = 5;
var MAX_WORKER_FOOD = 10;

function decide() {
  var me = view[CENTRE].ant;
  var queen = me.type === QUEEN;

  if(queen && me.food > MIN_FOOD && me.food < MAX_WORKER_FOOD) {
    var m = try_all_cells((i) => {
      if(view[i].food && !foe_near(i)) {
        // Try to spawn a worker next to the food;
        // the worker will pick up the food on the next turn
        return try_all_cells_near(i, (j) => ({cell: j, type: 1}));
      }
    }, true);
    if(sanity_check(m)) {
      return m;
    }
  }

  if(!queen && me.food) {
    return best_of([
      // Look for queen
      follow_dotted_path.bind(null, QUEEN_COL, SIDE_RIGHT, DIR_FORWARDS),
      latch_to_dotted_path.bind(null, QUEEN_COL, SIDE_RIGHT),

      // Failed to find queen's trail; try following worker trails backwards
      follow_dotted_path.bind(null, WORKER_COL, SIDE_RIGHT, DIR_REVERSE),
      latch_to_dotted_path.bind(null, WORKER_COL, SIDE_RIGHT),

      // Failed to find any trail; cover ground as quickly as possible
      fast_diagonal.bind(null, AVOID_COL)
    ]);
  }

  var myCol = queen ? QUEEN_COL : WORKER_COL;
  return best_of([
    grab_nearby_food,

    // Disperse workers away from queen
    !queen && escape_dotted_path.bind(null, QUEEN_COL, SIDE_RIGHT, WORKER_COL),

    // Follow our own path
    follow_dotted_path.bind(null, myCol, SIDE_RIGHT, DIR_FORWARDS),

    // If our path looks suspicious, it could have wrapped; try to escape it
    escape_dotted_path.bind(null, myCol, SIDE_RIGHT),

    // Explore
    // Laying a path causes us to move at 2/3 c, so workers can catch up.
    lay_dotted_path.bind(null, myCol, SIDE_RIGHT, QUEEN_COL),
    start_dotted_path.bind(null, myCol, SIDE_RIGHT, QUEEN_COL),

    // Fall-back to white dots if we're inside a colour block
    lay_dotted_path.bind(null, myCol, SIDE_RIGHT, INVERT_COL),
    start_dotted_path.bind(null, myCol, SIDE_RIGHT, INVERT_COL),

    // Stuck for some reason; try to escape
    fast_diagonal.bind(null, AVOID_COL)
  ]);
}

return play_safe([
  decide,

  // No valid moves; try to find *anywhere* we can go.
  go_anywhere,

  // Try changing a nearby cell's colour for the heck of it.
  {cell: 1, color: view[1].color % 8 + 1}
]);

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

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

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

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

শেষ অবধি, কোনও আউটপুটে একটি স্যানিটি চেকিং পদ্ধতি প্রয়োগ করা হয়েছে যা নিশ্চিত করে যে এটি অযোগ্য হতে পারে না (আশা করি!)


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


(এটি বিটা থাকাকালীন আমি প্রস্তুত একটি এখানে )
ডেভ

মোটামুটি অর্ডার অফ-প্রস্থের জন্য: আমি কেবল এটি চালিয়েছি এবং 30 টি খাদ্য + 6 কর্মী পিঁপড়ে পেয়েছি। এটি বিকাশের সময় আমি যে সংখ্যাগুলি দেখেছি তার সাথে সামঞ্জস্যপূর্ণ।
ডেভ

এটি 50% গতি বৃদ্ধির জন্য রাস্তায় ফাঁক ফেলে দেওয়ার একটি ঝরঝরে কৌশল। এছাড়াও এর অর্থ রাস্তাগুলি প্রথমে সুনির্দিষ্টভাবে দেখা যায় - আপনার পিঁপড়াকে খুঁজে পেতে আমাকে কিছুটা সময় নিয়েছিল ... তবে এটি উদাহরণের খেলোয়াড়দের সহজেই ছাপিয়ে যায়, বিশেষত শ্রমিকরা ফিরে আসা শুরু করার পরে। কিছু শ্রমিক হলুদ এবং সাদা চেকবোর্ড প্যাটার্নের বিল্ডিংয়ের কাজ শেষ করে - নিশ্চিত না যে সে পরিকল্পনার অংশ কিনা?
ট্রাইকোপলাক্স

1
টুইটারে আমি ব্যাখ্যায় তা রাখতে ভুলে গেছি (তারা ভুলে গিয়েছিল!)। আমি ব্যাখ্যা আপডেট করেছি। সংক্ষেপে: এটি পরিকল্পনার অংশ, তবে এটি দুর্দান্ত পরিকল্পনা নয়।
ডেভ

দুর্দান্ত ব্যাখ্যা!
ট্রাইকোপলাক্স

7

মনোরেল

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

var c0=5 //red
var c1=4 //cyan
var c2=6 //green
var c3=3 //magenta
var c4=7 //blue
var c5=8 //black
var c6=2 //yellow
var cN=1 //white

var ws=4 //support
var wb=3 //bodyguard
var wg=1 //gather
var wq=5 //queen

var v=[[0, 1, 2, 3, 4, 5, 6, 7, 8],
       [8, 7, 6, 5, 4, 3, 2, 1, 0],
       [6, 3, 0, 7, 4, 1, 8, 5, 2],
       [2, 5, 8, 1, 4, 7, 0, 3, 6]]

var x1=[0,2,6,8]
var x2=[8,6,2,0]

var r1=[1,7,3,5]
var r2=[5,3,7,1]

switch(view[4].ant.type)
{
 case 5: return queen()
 case 4: return support()
 case 3: return bodyguard()
 case 1: return gather()
 default: return {cell:4}
}

function queen()
{
 if(fAlly(ws)<0)
 {
  if(view[4].color==c1&&view[4].ant.food>0)
  {
   var o=findOrient(c1,c2,c3)
   if(sOpen(v[o][7])) return {cell:v[o][7],type:ws}
   return doThing()
  }
  else if(view[4].color==c0&&view[4].ant.food>=6)
  {
   var o=findOrient(c1,c2,c3)
   if(view[v[o][1]].color!=c1) return {cell:v[o][1],color:c1}
   if(view[v[o][0]].color!=c2) return {cell:v[o][0],color:c2}
   if(view[v[o][2]].color!=c3) return {cell:v[o][2],color:c3}
   if(sOpen(v[o][7])) return {cell:v[o][7],type:ws}
  }
  return wander(c0)
 }
 else
 {
  if(view[4].color==c0&&view[4].ant.food<7)
  {
   if(view[4].ant.food >=5)
   {
    var o=findOrient(c1,c2,c3)
    if(sOpen(v[o][1])) return {cell:v[o][1],type:wb}
    if(sOpen(v[o][0])) return {cell:v[o][0],type:wb}
    if(sOpen(v[o][2])) return {cell:v[o][2],type:wb}
   }
   if(view[4].ant.food>0)
   {
    var op=fOpen()
    if(op>=0) return {cell:op,type:wg}
   }
  }
  return doThing()
 }
}

function doThing()
{
 if(view[4].color!=c1) return {cell:4,color:c1}
 var o=findOrient(c1,c2,c3)
 if(view[4].ant.food>0&&fAlly(wg)>=0&&o==0)
 {
  var op=fOpen()
  if(op>=0) return {cell:op,type:wg}
 }
 if(view[v[o][1]].color!=c1&&pootis(v[o][1])) return {cell:v[o][1],color:c1}
 if(view[v[o][0]].color!=c2&&pootis(v[o][0])) return {cell:v[o][0],color:c2}
 if(view[v[o][2]].color!=c3&&pootis(v[o][2])) return {cell:v[o][2],color:c3}
 if(mOpen(v[o][1])) return {cell:v[o][1]}
 if(view[v[o][3]].color!=c2&&pootis(v[o][3])) return {cell:v[o][3],color:c2}
 if(view[v[o][5]].color!=c3&&pootis(v[o][5])) return {cell:v[o][5],color:c3}
 if(view[v[o][6]].color!=c2&&pootis(v[o][6])) return {cell:v[o][6],color:c2}
 if(view[v[o][8]].color!=c3&&pootis(v[o][8])) return {cell:v[o][8],color:c3}
 if(view[v[o][7]].color!=c1&&pootis(v[o][7])) return {cell:v[o][7],color:c1}
 return {cell:4}
}

function support()
{
 var o = findOrient(c1,c2,c3)
 var p = fAlly(wq)

 switch(p)
 {
  case v[o][0]:
   //if(mOpen(v[o][3])) return {cell:v[o][3]}
   //if(mOpen(v[o][1])) return {cell:v[o][1]}
   break
  case v[o][1]:
   //if(view[v[o][0]].food&&mOpen([v[o][0]])) return {cell:v[o][0]}
   //if(view[v[o][2]].food&&mOpen([v[o][2]])) return {cell:v[o][2]}
   break
  case v[o][2]:
   //if(mOpen(v[o][5])) return {cell:v[o][5]}
   //if(mOpen(v[o][1])) return {cell:v[o][1]}
   break
  case v[o][3]:
   //if(mOpen(v[o][6])) return {cell:v[o][6]}
   break
  case v[o][5]:
   //if(mOpen(v[o][8])) return {cell:v[o][8]}
   break
  case v[o][6]: break
  case v[o][7]: break
  case v[o][8]: break
  default:
   if(sOpen(v[o][1])) return {cell:v[o][1]}
   break
 }
 return {cell:4}
}

function bodyguard()
{
 var o=0
 switch(view[4].color)
 {
  case c1: o=findOrient(c1,c2,c3);break
  case c2: o=findOrient(c2,c6,c1);break
  case c3: o=findOrient(c3,c1,c6);break
  default: return {cell:4}
 }
 var p = fAlly(wq)
 if(view[4].ant.food>0)
 {
  switch(p)
  {
   case v[o][0]:
    if(sOpen(v[o][1])) return {cell:v[o][1]}
    if(sOpen(v[o][3])) return {cell:v[o][3]}
    break
   case v[o][1]:
    if(sOpen([v[o][0]])) return {cell:v[o][0]}
    if(sOpen([v[o][2]])) return {cell:v[o][2]}
    break
   case v[o][2]:
    if(sOpen(v[o][1])) return {cell:v[o][1]}
    if(sOpen(v[o][5])) return {cell:v[o][5]}
    break
   case v[o][3]:
    if(sOpen([v[o][0]])) return {cell:v[o][0]}
    if(sOpen([v[o][1]])) return {cell:v[o][1]}
    break
   case v[o][5]:
    if(sOpen([v[o][2]])) return {cell:v[o][2]}
    if(sOpen([v[o][1]])) return {cell:v[o][1]}
    break
   case v[o][6]:
    if(sOpen([v[o][0]])) return {cell:v[o][0]}
    if(sOpen([v[o][1]])) return {cell:v[o][1]}
    if(sOpen([v[o][3]])) return {cell:v[o][3]}
    break
   case v[o][7]:
    if(sOpen([v[o][1]])) return {cell:v[o][1]}
    if(sOpen([v[o][0]])) return {cell:v[o][0]}
    if(sOpen([v[o][2]])) return {cell:v[o][2]}
    break
   case v[o][8]:
    if(sOpen([v[o][2]])) return {cell:v[o][2]}
    if(sOpen([v[o][1]])) return {cell:v[o][1]}
    if(sOpen([v[o][5]])) return {cell:v[o][5]}
    break
   default:
  }
 }
 else
 {
  switch(p)
  {
   case v[o][0]:
    if(mOpen(v[o][1])) return {cell:v[o][1]}
    if(mOpen(v[o][3])) return {cell:v[o][3]}
    break
   case v[o][1]:
    if(view[v[o][2]].food&&mOpen([v[o][2]])) return {cell:v[o][2]}
    if(mOpen([v[o][0]])) return {cell:v[o][0]}
    if(mOpen([v[o][2]])) return {cell:v[o][2]}
    break
   case v[o][2]:
    if(mOpen(v[o][1])) return {cell:v[o][1]}
    if(mOpen(v[o][5])) return {cell:v[o][5]}
    break
   case v[o][3]:
    if(view[v[o][1]].food&&mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][0]])) return {cell:v[o][0]}
    if(mOpen([v[o][1]])) return {cell:v[o][1]}
    break
   case v[o][5]:
    if(view[v[o][1]].food&&mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][2]])) return {cell:v[o][2]}
    if(mOpen([v[o][1]])) return {cell:v[o][1]}
    break
   case v[o][6]:
    if(view[v[o][1]].food&&mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][0]])) return {cell:v[o][0]}
    if(mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][3]])) return {cell:v[o][3]}
    break
   case v[o][7]:
    if(view[v[o][0]].food&&mOpen([v[o][0]])) return {cell:v[o][0]}
    if(view[v[o][2]].food&&mOpen([v[o][2]])) return {cell:v[o][2]}
    if(mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][0]])) return {cell:v[o][0]}
    if(mOpen([v[o][2]])) return {cell:v[o][2]}
    break
   case v[o][8]:
    if(view[v[o][1]].food&&mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][2]])) return {cell:v[o][2]}
    if(mOpen([v[o][1]])) return {cell:v[o][1]}
    if(mOpen([v[o][5]])) return {cell:v[o][5]}
    break
   default:
  }
 }
 if(view[4].color==c1)
 {
  if(view[v[o][1]].color!=c1&&pootis(v[o][1])) return {cell:v[o][1],color:c1}
  if(view[v[o][0]].color!=c2&&pootis(v[o][0])) return {cell:v[o][0],color:c2}
  if(view[v[o][2]].color!=c3&&pootis(v[o][2])) return {cell:v[o][2],color:c3}
  if(view[v[o][3]].color!=c2) return {cell:v[o][3],color:c2}
  if(view[v[o][5]].color!=c3) return {cell:v[o][5],color:c3}
  if(view[v[o][6]].color!=c2) return {cell:v[o][6],color:c2}
  if(view[v[o][8]].color!=c3) return {cell:v[o][8],color:c3}
  if(view[v[o][7]].color!=c1) return {cell:v[o][7],color:c1}
 }
 return {cell:4}
}

function gather()
{
 if(view[4].ant.food>0)
 {
  if(view[4].color==c1&&(testSQ(c1,c2)||testSQ(c1,c3))) return gDoThing(c1,c3,c2)
  if(view[4].color==c2&&testSQ(c2,c1)) return gDoThing(c2,c1,c6)
  if(view[4].color==c3&&testSQ(c3,c1)) return gDoThing(c3,c6,c1)
  return wander(c5)
 }
 var n=fAlly(wq)
 if(n<0) return wander(c4)
 switch(n)
 {
  case 0:
   if(mOpen(8)) return {cell:8}
   if(mOpen(7)) return {cell:7}
   if(mOpen(5)) return {cell:5}
   break
  case 1:
   if(mOpen(6)) return {cell:6}
   if(mOpen(8)) return {cell:8}
   if(mOpen(7)) return {cell:7}
   break
  case 2:
   if(mOpen(6)) return {cell:6}
   if(mOpen(3)) return {cell:3}
   if(mOpen(7)) return {cell:7}
   break
  case 3:
   if(mOpen(8)) return {cell:8}
   if(mOpen(2)) return {cell:2}
   if(mOpen(5)) return {cell:5}
   break
  case 5:
   if(mOpen(0)) return {cell:0}
   if(mOpen(6)) return {cell:6}
   if(mOpen(3)) return {cell:3}
   break
  case 6:
   if(mOpen(2)) return {cell:2}
   if(mOpen(5)) return {cell:5}
   if(mOpen(1)) return {cell:1}
   break
  case 7:
   if(mOpen(2)) return {cell:2}
   if(mOpen(0)) return {cell:0}
   if(mOpen(1)) return {cell:1}
   break
  case 8:
   if(mOpen(0)) return {cell:0}
   if(mOpen(1)) return {cell:1}
   if(mOpen(3)) return {cell:3}
   break
  default:
   break
 }
 return {cell:4}
}

function testSQ(ac1,ac2)
{
 for(var i=0;i<4;i++)
 {
  if(view[r1[i]].color==ac1)
  {
   if(view[v[i][0]].color==ac2&&view[v[i][3]].color==ac2) return 1
   if(view[v[i][2]].color==ac2&&view[v[i][5]].color==ac2) return 1
  }
 }
 return 0
}

function gDoThing(ac1,ac2,ac3)
{
 var o=findOrient(ac1,ac2,ac3)
 if(view[v[o][1]].color!=ac1&&pootis(v[o][1])) return {cell:v[o][1],color:ac1}
 if(view[v[o][0]].color!=ac2&&pootis(v[o][0])) return {cell:v[o][0],color:ac2}
 if(view[v[o][2]].color!=ac3&&pootis(v[o][2])) return {cell:v[o][2],color:ac3}
 if(sOpen(v[o][1])) return {cell:v[o][1]}
 if(ac1==c2)
 {
  if(sOpen(v[o][0])) return {cell:v[o][0]}
  if(sOpen(v[o][3])) return {cell:v[o][3]}
  if(sOpen(v[o][6])) return {cell:v[o][6]}
 }
 else if(ac1==c3)
 {
  if(sOpen(v[o][2])) return {cell:v[o][2]}
  if(sOpen(v[o][5])) return {cell:v[o][5]}
  if(sOpen(v[o][8])) return {cell:v[o][8]}
 }
 else
 {
  if(sOpen(v[o][0])) return {cell:v[o][0]}
  if(sOpen(v[o][2])) return {cell:v[o][2]}
  if(sOpen(v[o][3])) return {cell:v[o][3]}
  if(sOpen(v[o][5])) return {cell:v[o][5]}
 }
 return {cell:4}
}

function pootis(p)
{
 var a=view[p].ant
 if(a!=null&&a.friend&&a.type==wg&&(view[p].color==c4||view[p].color==c5)) return 0
 return 1
}

function fAlly(t)
{
 var a=view[4].ant
 for(var i=0;i<9;i++)
 {
  if(i==4) i++
  a=view[i].ant
  if(a!=null&&a.friend&&a.type==t) return i
 }
 return -1
}

function fOpen()
{
 for(var i=0;i<9;i++)
 {
  if(i==4) i++
  if(sOpen(i)) return i
 }
 return -1
}

function sOpen(p)
{
 return (view[p].ant==null&&!view[p].food)
}

function mOpen(p)
{
 return (view[p].ant==null)
}

function wander(ac)
{
 if(view[4].ant.type==5||view[4].ant.food==0)
 {
  var vf = vFood()
  if(vf>=0) return {cell:vf}
  if(view[4].color!=ac) return {cell:4,color:ac}
  for(var i=0;i<4;i++)
  {
   if(view[x1[i]].color==ac&&view[x2[i]].color!=ac&&view[x2[i]].color!=c1&&mOpen(x2[i])) return {cell:x2[i]}
  }
  for(var i=0;i<4;i++)
  {
   if(mOpen(x1[i])&&view[x1[i]].color!=c1) return {cell:x1[i]}
  }
 }
 else
 {
  if(view[4].color!=ac) return {cell:4,color:ac}
  for(var i=0;i<4;i++)
  {
   if(view[x1[i]].color==ac&&view[x2[i]].color!=ac&&sOpen(x2[i])) return {cell:x2[i]}
  }
  for(var i=0;i<4;i++)
  {
   if(sOpen(x1[i])) return {cell:x1[i]}
  }
 }
 return {cell:4}
}

function findOrient(ac1,ac2,ac3)
{
 var w=[0,0,0,0]
 w[0]=DI(view[0].color,view[1].color,view[2].color,0,ac1,ac2,ac3)
 w[1]=DI(view[8].color,view[7].color,view[6].color,1,ac1,ac2,ac3)
 w[2]=DI(view[6].color,view[3].color,view[0].color,2,ac1,ac2,ac3)
 w[3]=DI(view[2].color,view[5].color,view[8].color,3,ac1,ac2,ac3)
 var t=[0,0,0,0]
 for(var i=0;i<4;i++)
 {
  switch(w[i])
  {
   case 4: t[0]++;break
   case 5: t[1]++;break
   case 6: t[2]++;break
   case 7: t[3]++;break
   case 8: t[0]+=2;break
   case 9: t[1]+=2;break
   case 10: t[2]+=2;break
   case 11: t[3]+=2;break
   case 12: t[0]+=3;break
   case 13: t[1]+=3;break
   case 14: t[2]+=3;break
   case 15: t[3]+=3;break
   default: break
  }
 }
 var m=Math.max(...t)
 for(var i=0;i<4;i++)
 {
  if(t[i]==m) return i
 }
 return 0
}

function DI(v1,v2,v3,d,ac1,ac2,ac3)
{
 var t=[0,0,0,0]
 switch(v1)
 {
  case ac2: t[0]++;t[3]++;break
  case ac3: t[1]++;t[2]++;break
  default: break
 }
 switch(v2)
 {
  case ac1: t[0]++;t[1]++;break
  case ac2: t[3]++;break
  case ac3: t[2]++;break
  default: break
 }
 switch(v3)
 {
  case ac2: t[1]++;t[3]++;break
  case ac3: t[0]++;t[2]++;break
  default: break
 }
 var m=Math.max(...t)
 if(m==0) return 0
 var n=0
 for(var i=0;i<4;i++)
 {
  if(t[i]==m){n=i;break}
 }
 if((d==2&&n==2)||(d==3&&n==3)) n=1
 else if((d==2&&n==3)||(d==3&&n==2)) n=0
 else n^=d
 return m*4+n
}

function vFood()
{
 for(var i=0;i<9;i++)
 {
  if(view[i].food) return i
 }
 return -1
}

function nColor(c)
{
 var t=0
 for(var i=0;i<9;i++)
 {
  if(view[i].color==c) t++
 }
 return t
}

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

ঠিক আছে, এখানে 2 সংস্করণ। এখন সংগ্রহকারীরা আসলে কিছু করে।

সংস্করণ এখন 2.1। ব্ল্যাক হোল যে কোনও সময় একই গেমটিতে একসাথে উপস্থিত হওয়ার সময় পুরো লেজটি খেতে বাধা দিতে হলুদ / সায়ান চিহ্নগুলি ঘুরিয়ে দেওয়া হয়েছে।

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

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

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


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

@ কোটবেটা আমি আপনার প্যারানিয়া বুঝতে পেরেছি ... আমি এই চ্যালেঞ্জটি সবেমাত্র দেখেছি তাই চ্যালেঞ্জটির গতি থামার আগে আমি একটি এন্ট্রি তৈরির প্রক্রিয়ায় আছি।
মোগি

ঠিক আছে তাহলে. আমি শীঘ্রই নিশ্চিত হতে পারি না এটি খুব শীঘ্রই শেষ হবে কিনা, আপডেটগুলি কীভাবে কিছুটা কমছে down
উদ্ধৃতিবেটা

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

দেখে মনে হচ্ছে আপনার পিঁপড়াগুলি আমার কিছু ট্রেইল-ক্লিয়ারিং কোড চাইবে (ব্ল্যাক হোল দেখুন কীভাবে পিঁপড়াগুলি পুরানো ট্রেইলগুলি পরিষ্কার করে দেয়)। i.stack.imgur.com/DTmA6.png
ড্রাকো 18

6

ক্লাস্ট্রোফোবিক কুইন

রঙিন-অঞ্চলগুলি এড়ানোর চেষ্টা করার সময় একটি রানী-কেবল পন্থা যা এলোমেলো হাঁটাচলা করে। শীর্ষ প্রতিযোগী নন, তবে পরিমিতরূপে সফল এবং টেম্পার-প্রমাণ। পরামিতি টুইটগুলি চলছে progress

var i, j
var orthogonals = [1, 3, 7, 5]  // These are the non-diagonal cells
var move;
var scores = [];   // An array of how desirable each potential move is
var score, neighbor, claustrophobia, newColor;
var crowdedNeighbors = null;   // How many diagonal neighbors are colored CROWDED?
var runningFrom = null;    // When in running phase, which direction did we come from?
var runningTo = null;      // When in running phase, which direction should we head?

// Assign color magic numbers to variables
var EMPTY = 1;
var VISITED = 4;
var CROWDED = 7;
var RUNNING = 8;

function neighbors(cell) {
    switch (cell) {
        case 0: return [1, 3];
        case 1: return [0, 2];
        case 2: return [1, 5];
        case 3: return [0, 6];
        case 4: return orthogonals;
        case 5: return [2, 8];
        case 6: return [3, 7];
        case 7: return [6, 8];
        case 8: return [7, 5];
        default: return null;
    }
}

function isHungry(ant) {
    if (ant.type === 5 || ant.food === 0) {
        return true;
    } else {
        return false;
    }
}

// Color own cell based on the number of neighbors that are colored
claustrophobia = 0;
for (i=0; i<9; i++) {
    if (view[i].color !== EMPTY || i === 4) {
        claustrophobia++;
    }
    if (i % 2 === 0 && i !== 4) {
        if (view[i].color === CROWDED) {
            crowdedNeighbors++;
        } else if (view[i].color === RUNNING) {
            crowdedNeighbors++;
            runningFrom = i;
        }
    }
}

if (claustrophobia > 4) {
    if (crowdedNeighbors > 1 || runningFrom !== null) {
        // We're entering or currently in a straight-line running state
        // in which we keep going until we find sufficient whitespace
        newColor = RUNNING;
    } else {
        newColor = CROWDED;
    }
} else {
    newColor = VISITED;
}
if (view[4].color !== newColor) {
    return {cell:4, color:newColor}
}

// If we've already colored the current cell properly, and we're in running mode,
// then move diametrically away from the runningFrom cell
switch (runningFrom) {
    case 0:
        runningTo = 8;
        break;
    case 2:
        runningTo = 6;
        break;
    case 6:
        runningTo = 2;
        break;
    case 8:
        runningTo = 0;
        break;
    default:
        break;
}

// Calculate a score for each potential move
// Lower numbers are better; null means illegal move
// Unexplored areas are better; food is the best (as long as ant can eat); don't move onto other ants
for (i=0; i<9; i++) {
    // Base score of tile is 2 times color of tile
    score = 2 * (view[i].color);
    // Add colors of neighboring tiles
    for (neighbor of neighbors(i)) {
        score += view[neighbor].color;
    }
    // Give very good score to runningTo tile, unless it's also RUNNING color
    if (i === runningTo && view[i].color !== RUNNING) {
        score -= 4;   // Magic number, possibly to be tweaked
    }
    if (i!==4 && view[i].ant) {
        // Tile contains another ant; give very bad score
        score = null;
    } else if (view[i].food) {
        // If a tile contains food, it's either highly desirable if the ant can eat, or illegal if it can't
        if (isHungry(view[4].ant)) {
            // Ant can eat; give food tile very good score
            score = -1;
        } else {
            // Ant cannot eat; give food tile very bad score
            score = null;
        }
    }
    scores.push(score);
}

// Select best move based on the scores array
move = 4;   // By default, stay put (this probably won't be the best move)
for (i=0; i<9; i++) {
    if (scores[i] !== null && scores[i] < scores[move]) {
        move = i;
    }
}

return {cell:move};

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

এখানে চিত্র বর্ণনা লিখুন


কোনও ছলনা-প্রমাণ নয়; ট্রেইল-
ইরেজারটি

1
এর, স্কোয়ারে?
পিপ্পারি

1
@ পিপ্পেরি আমি বলেছিলাম " পরিমিতভাবে ... টেম্পার -প্রুফ"। ;) ট্রেইল-ইরেজার কেবলমাত্র একমাত্র কাজই তা ইতিমধ্যে আচ্ছাদিত স্থলটিকে আচ্ছাদন করার সম্ভাবনা তৈরি করে; তবে এটি কেবল অনাবিষ্কৃত অঞ্চলে চলে যেতে পারে।
ডিএলসাস

6

Hoppemaur

সবার আগে আমি এই দুর্দান্ত চ্যালেঞ্জটি তৈরি করার জন্য ট্রিকোপলাক্সকে ধন্যবাদ জানাতে চাই, যা আমাকে এই সাইটে সাইন আপ করে এবং জাভাস্ক্রিপ্টে প্রোগ্রামিং শুরু করেছে। আমি আপনাকে ধন্যবাদ জানাতে চাই অন্য লোকেরা এখনও এই প্রশ্নের চ্যাটরুমে ঘুরে বেড়াচ্ছে, জিজ্ঞাসা করার ঠিক 3 মাস পরেও।

আমার বটটি প্রথম স্থানের জন্য কোনও গুরুতর প্রতিযোগী নয়, তবে একক রানী / স্ব এলোমেলোভাবে এলোমেলো হাঁটার পদ্ধতির, কিছুটা লাফানো ক্লাস্ট্রোফোবিক রানির মতো ।

আঁকা প্যাটার্ন সহ হম্প্পিমর বট বিশদ

কোড

//Hoppemaur
//å hoppe: to jump
//maur: ant

var WHITE = 1;
var OWN = 2;
var FOOD = 6;
var ESCAPE = 3;
var paint = 0;
var score = {0:2,1:-3,2:2,3:-3,4:-1,5:-3,6:2,7:-3,8:2}; 
// The ant should only walk diagonal (except when feeding)
var highest = 0;
var scoreindex;
var diagonals = [0, 2, 6, 8];
var diagonalsandself = [0, 2, 4, 6, 8]
var inversdiagonals = [8, 6, 2, 0];
var orthogonals = [1, 3, 5, 7];
var inverseorthogonals = [7, 5, 3, 1];
var rotate1orthogonals = [3, 1, 7, 5];
var rotate2orthogonals = [5, 7, 1, 3];

//checks if one of the diagonals or the own tile are painted
function checkforemptypattern() {
  for (var i=0; i<diagonalsandself.length; i++) {
    if (view[diagonalsandself[i]].color == OWN){
     return false;}
  }
  return true;
}

//counts the diagonals painted in the requestest colour
function checktrapped(pattern) {
  var diags=0;
  for (var i=0; i<diagonals.length; i++) {
    if (view[diagonals[i]].color == pattern){
     diags=diags+1;
    }
  }
return diags;
}

//Biggest threat to this ant is food on orthogonals,
//it messes up the pattern if not dealt with it
if (view[4].color !== FOOD){
    for (var i=0; i<orthogonals.length; i++) {
        if (view[orthogonals[i]].food) {
            return {cell:4, color:FOOD};
            }
        }
    }

if (view[4].color == FOOD){
    for (var i=0; i<orthogonals.length; i++) {
        if (view[orthogonals[i]].food) {
        if (!view[orthogonals[i]].ant){
            return {cell:orthogonals[i]};
            }
        }
        }
    }

//If food shows up on diagonals while out of pattern,
//before grabbing food, the pattern must be painted
for (var i=0; i<diagonals.length; i++){
    if (view[diagonals[i]].food){
        if (checkforemptypattern()){
            return {cell:4, color: OWN}
            }
        }
    }


//Otherwise, food can easily be grabbed if not ant in way
for (var i=0; i<9; i++) {
    if (view[i].food) {
        if(!view[i].ant){
        return {cell:i}
        }
    }
}


//After food has been grabbed orthogonal, back to food pile
if (view[4].color == WHITE){
    for (i=0; i<orthogonals.length; i++) {
        if (view[orthogonals[i]].color == FOOD && checktrapped(FOOD) == 0 && view[inverseorthogonals[i]].color !== FOOD && view[rotate1orthogonals[i]].color !== FOOD && view[rotate2orthogonals[i]].color !== FOOD){
                 if (!view[orthogonals[i]].ant){
                     return {cell:orthogonals[i]};
                     }
                 }
        }
    }

//First part of scoring
// Scoring to determine next move
// Scoring everything higher than own pattern and escape
for (var i=0; i<9; i++) {
  if (view[i].color !== OWN) {
      score[i] = score[i]+3;
  }
  if (view[i].color !== ESCAPE){
      score[i] = score[i]+5;
  }
}

// Scoring while in painted area (f.e. wildfire)

var l = 0;
for (var i=2; i<9; i++) {
                          var k = 0;
    for (var j=0; j<9; j++) {
                             if (view[j].color == i) {
            k=k+1;
            if (k > 6){
            paint=i;
            }
        if (view[j].color !==WHITE) {
          l=l+1;

        }
    }
}
}

if (paint !== OWN && l >7) {
    for (var i=0; i<diagonals.length; i++){
        if (view[diagonals[i]].color == OWN) {
            score[inversdiagonals[i]]=score[inversdiagonals[i]]+7;
            }
        if (view[diagonals[i]].color == WHITE) {
          score[diagonals[i]]=score[diagonals[i]]+7
        }
        }
    }


if (paint == OWN && l >7) {
    for (var i=0; i<diagonals.length; i++){
        if (view[diagonals[i]].color == ESCAPE) {
            score[inversdiagonals[i]]=score[inversdiagonals[i]]+7;
            }
        if (view[diagonals[i]].color == WHITE) {
          score[diagonals[i]]=score[diagonals[i]]+7
        }
        }
    }

// the following might lead to some traps?
// score diagonals adjactant to white higher
  if (view[1].color === WHITE) {
    score[0] = score[0]+1;
    score[2] = score[2]+1;
   }
  if (view[3].color === WHITE) {
    score[0] = score[0]+1;
    score[6] = score[6]+1;
   }
  if (view[5].color === WHITE) {
    score[2] = score[2]+1;
    score[8] = score[8]+1;
   }
  if (view[7].color === WHITE) {
    score[6] = score[6]+1;
    score[8] = score[8]+1;
   }


//Don't move next to others, they steal your food!
  if (view[0].ant || view[1].ant || view[2].ant){
      score[6] = score [6]+10;
      score[8] = score [8]+10;
  }

  if (view[0].ant || view[3].ant || view[6].ant){
      score[2] = score [2]+10;
      score[8] = score [8]+10;
  }

  if (view[6].ant || view[7].ant || view[8].ant){
      score[0] = score [0]+10;
      score[2] = score [2]+10;

  }
   if (view[2].ant || view[5].ant || view[8].ant){
      score[0] = score [0]+10;
      score[6] = score [6]+10;

  }
//don't step on others!
for (var i=0; i<9; i++) {
  if (i!==4 && view[i].ant) {
        score[i] = -5;
 }
}

//end of scoring, calculate best
for (var i=0; i<9; i++) {
  if (score[i] > highest) {
    highest = score[i];
    scoreindex = i;
    }
  }

//Basic enemy avoidance
for (var i=0; i<9; i++) {
  if (i!==4 && view[i].ant) {
        return {cell:scoreindex}
        }
  }

//basic movement

//when surrounded by other paint
if (paint == ESCAPE && l>7){
    if(view[4].color == OWN){
      return{cell:scoreindex}
    }
}

if (paint !== OWN && paint !== 0 && l>7){
  if(view[4].color !== OWN){
    return{cell:4, color:OWN}
  }
}


if (paint == OWN && l>7){
  if(view[4].color !== ESCAPE){
    return{cell:4, color:ESCAPE}
  }
}

//a) when off pattern
if (view[4].color !== OWN) {
    if (view[4].color == ESCAPE){
         if (checktrapped(ESCAPE)==4){
            return{cell:scoreindex}
            }
        }
        if (view[4].color == ESCAPE){
         if (checktrapped(ESCAPE)==3){
            return{cell:scoreindex}
            }
        }
    if (checkforemptypattern()) {
    return{cell:4, color:OWN};
    }

    //Am I trapped? Different possible traps follow here
    if (view[4].color !== ESCAPE){
         if (checktrapped(OWN)==4){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){
         if (checktrapped(OWN)==3 && checktrapped(ESCAPE)==1){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){
         if (checktrapped(OWN)==2 && checktrapped(ESCAPE)==1){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){
         if (checktrapped(OWN)==2 && checktrapped(ESCAPE)==2){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){
         if (checktrapped(OWN)==1 && checktrapped(ESCAPE)==2){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){
         if (checktrapped(OWN)==1 && checktrapped(ESCAPE)==1){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){ //when the orthogonals are painted, some other guy was here before and movement traps are likely
         if (view[1].color == OWN || view[7].color == OWN || view[3].color == OWN || view[5].color == OWN){
            return{cell:4, color:ESCAPE}
            }
    }
    if (view[4].color !== ESCAPE){ //when the orthogonals are painted, some other guy was here before and movement traps are likely
         if (view[1].color == ESCAPE || view[7].color == ESCAPE || view[3].color == ESCAPE || view[5].color == ESCAPE){
            return{cell:4, color:ESCAPE}
            }
    }
}

//b) when on pattern check surroundings for escape route
if (checktrapped(ESCAPE)==3){
    return{cell:4, color:ESCAPE}
}
if (checktrapped(ESCAPE)==4){
    return{cell:4, color:ESCAPE}
}

//otherwise just move on
return{cell:scoreindex}

ব্যাখ্যা

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

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

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

সর্বশেষে তবে কম নয়, বটটি কিছু সুন্দর বিমূর্ত নিদর্শন আঁকায়, যখন একা থাকে:

গেমের শেষে হপ্পিমুর বট ওভারভিউ প্যাটার্ন


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

ধন্যবাদ, @ ড্রাকো 18! আমি সেই পুরানো চ্যালেঞ্জগুলি পরীক্ষা করে দেখতে পারি, তবে আমি কলোনী পিঁপড়া বট তৈরির ব্যবস্থাপনার আগে নয় :-)
পেল লুন্ডকভিস্ট

6

গঠন

এই জমাটি একটি গিথুব সংগ্রহস্থলে হোস্ট করা হয় ।

var marcher_count;var gatherer_count;var excess_gatherers;var tcell;var lh_cell;var rh_cell;var ant_off;var alt_cell;var cell_off;function debug(message)
{}
const MARCHER_A=1;const MARCHER_B=2;const GATHERER=3;const QUEEN=5;const S_END=[6,5,7,4,0,2,1,3];const S_FRONT=[7,5,6,0,4,1,3,2];const S_SIDE=[7,3,5,1,6,2,0,4];const S_GATHERER=[7,6,5,4,0,3,2,1];const SCAN_MOVES=[0,1,2,3,5,6,7,8];const CORNERS=[0,2,6,8];const EDGES=[1,3,5,7];const CCW=[[0,3,6,7,8,5,2,1],[1,0,3,6,7,8,5,2],[2,1,0,3,6,7,8,5],[3,6,7,8,5,2,1,0],[4,4,4,4,4,4,4,4],[5,2,1,0,3,6,7,8],[6,7,8,5,2,1,0,3],[7,8,5,2,1,0,3,6],[8,5,2,1,0,3,6,7]];const NEARS=[[6,5,3,5,4,2,3,2,1],[5,6,5,4,5,4,2,3,2],[3,5,6,2,4,5,1,2,3],[5,4,2,6,5,3,5,4,2],[4,5,4,5,6,5,4,5,4],[2,4,5,3,5,6,2,4,5],[3,2,1,5,4,2,6,5,3],[2,3,2,4,5,4,5,6,5],[1,2,3,2,4,5,3,5,6]];const SAN_ORD=[[1,3,6,2,5,7,8],[0,2,5,3,6,8,7],[5,1,0,8,7,3,6],[6,0,1,7,8,2,5],[],[2,8,7,1,0,6,3],[3,7,8,0,1,5,2],[8,6,3,5,2,0,1],[7,5,2,6,3,1,0]];const D_MARCH=1;const D_FOOD=2;const D_STALLED=3;const D_GATHERER=4;const U_REALIGN=5;const U_SENTINEL=6;const U_READY=7;const U_PANIC=8;const PUPS=[[0,1,2,3,4,5,6,7,8],[1,1,0,0,0,1,1,0,1],[2,0,2,0,4,2,2,0,2],[3,0,0,3,4,3,3,0,3],[4,0,4,4,4,4,0,0,4],[5,1,2,3,4,5,5,0,5],[6,1,2,3,0,5,5,0,6],[7,0,0,0,0,0,0,7,7],[8,1,2,3,4,5,6,7,8]];const PDOWNS=[[0,1,2,3,4,5,6,7,8],[1,1,0,3,4,5,5,0,1],[2,0,2,3,4,5,5,0,2],[3,3,3,3,3,3,3,3,3],[4,4,4,3,4,0,0,0,4],[5,5,5,3,0,5,5,0,5],[6,5,5,3,0,5,5,0,6],[7,0,0,3,0,0,0,7,7],[8,1,2,3,4,5,6,7,8]];const PSIDES=[[0,1,2,3,4,5,6,7,8],[1,1,0,3,4,1,1,0,1],[2,0,2,0,4,5,5,0,2],[3,3,0,3,3,3,3,3,3],[4,4,4,3,4,0,0,0,4],[5,1,5,3,0,5,5,0,5],[6,1,5,3,0,5,5,0,6],[7,0,0,3,0,0,0,7,7],[8,1,2,3,4,5,6,7,8]];const INIT_SEED=3734978372;const FINAL_SEED=2338395782;const SRECOLOR_PROB=0.7;const SONSTRIDE_PROB=0.5;const QFSPAWNP_MAX=0.05;const QFSPAWNP_MIN=0.00;const QFSPAWNP_DECAY=0.005;const QBSPAWNP_MAX=0.65;const QBSPAWNP_MIN=0.55;const QBSPAWNP_DECAY=0.01;const QFORMP_MAX=0.5;const QFORMP_MIN=0.3;const QFORMP_DECAY=0.01;const DISCOLORT=35;const ERASET=20;const SOBSTRUCT_FUZZ=6;const SSTRIDE_FUZZ=6;const OBSTRUCT_QWT=3;const SPREFWT=2;var state=null;function rand_init()
{state=INIT_SEED;for(var cell=0;cell<9;cell++)
{var v=view[cell];state^=v.color;state^=v.food<<3;if(v.ant!==null)
{state^=v.ant.friend<<4;state^=v.ant.type<<5;state^=v.ant.food<<8;}
ant_rand();}
state^=FINAL_SEED;if(state===0)state=1;}
function ant_rand()
{if(state===null)rand_init();state^=state<<13;state^=state>>>17;state^=state<<5;return state>>>0;}
function rand_choice(prob)
{return ant_rand()/4294967296<prob;}
function rand_sub(array,num)
{var return_array=array.slice();for(var i=0;i<num;i++)
{var rand_index=i+ant_rand()%(array.length-i);var x_val=return_array[rand_index];return_array[rand_index]=return_array[i];return_array[i]=x_val;}
return return_array.slice(0,num);}
function rand_perm(array)
{var return_array=array.slice();for(var i=0;i<array.length-1;i++)
{var rand_index=i+ant_rand()%(array.length-i)
var x_val=return_array[rand_index];return_array[rand_index]=return_array[i];return_array[i]=x_val;}
return return_array;}
function index_sort(arr)
{var index_array=[];for(var i=0;i<arr.length;i++)index_array.push(i);index_array.sort((a,b)=>(arr[a]===arr[b])?(a-b):(arr[a]-arr[b]));return index_array;}
function this_ant()
{return view[4].ant;}
function c_at(cell)
{return view[cell].color;}
function is_ally(cell)
{return view[cell].ant!==null&&view[cell].ant.friend===true;}
function is_enemy(cell)
{return view[cell].ant!==null&&view[cell].ant.friend===false;}
function is_harvestable(cell)
{return is_enemy(cell)&&view[cell].ant.type===QUEEN&&view[cell].ant.food>0;}
function lchk(c)
{if(is_ally(CCW[c][6])&&view[CCW[c][6]].ant.type===GATHERER)
if(is_ally(CCW[c][5])&&view[CCW[c][5]].ant.type!==GATHERER)return D_GATHERER;if(is_ally(CCW[c][7])&&view[CCW[c][7]].ant.type===GATHERER&&is_ally(CCW[c][1]))return D_GATHERER;if(is_ally(CCW[c][5])&&view[CCW[c][5]].ant.type===GATHERER)
if(is_ally(CCW[c][3])&&c_at(4)===D_MARCH)return D_STALLED;if(view[CCW[c][6]].food===1&&is_ally(CCW[c][5])&&view[CCW[c][5]].ant.type!==GATHERER)return D_FOOD;if(view[CCW[c][7]].food===1&&is_ally(CCW[c][1])&&c_at(CCW[c][1])===D_FOOD)return D_FOOD;if(view[CCW[c][5]].food===1&&is_ally(CCW[c][3])&&view[CCW[c][3]].ant.type!==QUEEN&&c_at(4)===D_MARCH)return U_REALIGN;return null;}
function lchk2(c)
{if(is_ally(CCW[c][6])&&view[CCW[c][6]].ant.type===GATHERER)
if(is_ally(CCW[c][5])&&view[CCW[c][5]].ant.type!==GATHERER)return D_GATHERER;if(is_ally(CCW[c][7])&&view[CCW[c][7]].ant.type===GATHERER&&is_ally(CCW[c][1]))return D_GATHERER;if(is_ally(CCW[c][5])&&view[CCW[c][5]].ant.type===GATHERER)
if(is_ally(CCW[c][3])&&c_at(4)===D_MARCH)return D_STALLED;if(is_ally(CCW[c][2])&&view[CCW[c][2]].ant.type===GATHERER)
if(is_ally(CCW[c][1])&&view[CCW[c][1]].ant.type!==GATHERER)return D_GATHERER;if(is_ally(CCW[c][3])&&view[CCW[c][3]].ant.type===GATHERER)
if(is_ally(CCW[c][5])&&c_at(CCW[c][5])===D_GATHERER)return D_GATHERER;if(is_ally(CCW[c][1])&&view[CCW[c][1]].ant.type===GATHERER)
if(is_ally(CCW[c][7])&&c_at(4)===D_MARCH)return D_STALLED;if(view[CCW[c][6]].food===1&&is_ally(CCW[c][5])&&view[CCW[c][5]].ant.type!==GATHERER)return D_FOOD;if(view[CCW[c][7]].food===1&&is_ally(CCW[c][1])&&c_at(CCW[c][1])===D_FOOD)return D_FOOD;if(view[CCW[c][5]].food===1&&is_ally(CCW[c][3])&&view[CCW[c][3]].ant.type!==QUEEN&&c_at(4)===D_MARCH)return U_REALIGN;if(view[CCW[c][2]].food===1&&is_ally(CCW[c][1])&&view[CCW[c][1]].ant.type!==GATHERER)return D_FOOD;if(view[CCW[c][3]].food===1&&is_ally(CCW[c][5])&&c_at(CCW[c][5])===D_FOOD)return{cell:4,color:D_FOOD};if(view[CCW[c][1]].food===1&&is_ally(CCW[c][7])&&view[CCW[c][7]].ant.type!==QUEEN&&c_at(4)===D_MARCH)return U_REALIGN;return null;}
function sigc(output,order,c)
{if(c_at(4)===output)
for(cell_off of order)
{var tcell=CCW[c][cell_off];if(!is_ally(tcell)&&c_at(tcell)!==D_MARCH)
{if(view[tcell].food!==0&&view[tcell].color===D_FOOD)
{for(alt_cell of SCAN_MOVES)
{var n_wt=NEARS[tcell][alt_cell];if(n_wt>3&&n_wt<6&&is_ally(alt_cell))
if(view[alt_cell].ant.type===QUEEN||view[alt_cell].ant.type===GATHERER)
continue;}}
return{cell:tcell,color:D_MARCH};}}
return{cell:4,color:output};}
function is_gatherer_marcher(cell)
{if(!is_ally(cell)||view[cell].ant.food>0||view[cell].ant.type!==GATHERER)return false;if(this_ant().type===QUEEN)return true;lh_cell=CCW[cell][1];rh_cell=CCW[cell][7];if(is_ally(lh_cell)&&view[lh_cell].ant.type===QUEEN)return!is_ally(rh_cell)
else if(is_ally(rh_cell)&&view[rh_cell].ant.type===QUEEN)return!is_ally(lh_cell)
else return false;}
function is_like(cell)
{if(c_at(cell)===U_PANIC)return false;if(is_ally(CCW[cell][1])&&c_at(CCW[cell][1])===U_PANIC)return false;if(is_ally(CCW[cell][7])&&c_at(CCW[cell][7])===U_PANIC)return false;if(CORNERS.includes(cell)&&is_ally(cell))
{switch(view[cell].ant.type)
{case MARCHER_A:return view[cell].ant.food===0&&this_ant().type!==MARCHER_B;case MARCHER_B:return view[cell].ant.food===0&&this_ant().type!==MARCHER_A;case GATHERER:return is_gatherer_marcher(cell)&&this_ant().type!==GATHERER;case QUEEN:return true;default:return false;}}
return false;}
function is_other(cell)
{if(c_at(cell)===U_PANIC)return false;if(EDGES.includes(cell)&&is_ally(cell))
{switch(view[cell].ant.type)
{case MARCHER_A:return view[cell].ant.food===0&&this_ant().type!==MARCHER_A;case MARCHER_B:return view[cell].ant.food===0&&this_ant().type!==MARCHER_B;case GATHERER:return this_ant().type===QUEEN
case QUEEN:return true;default:return false;}}
return false;}
function view_corner()
{var scores=[0,0,0,0];for(var i=0;i<4;i++)
for(var j=0;j<8;j++)
{scores[i]*=2;var tcell=CCW[CORNERS[i]][j];if(is_ally(tcell)&&(is_like(tcell)||is_other(tcell)))scores[i]++;}
if(scores[0]>scores[1]&&scores[0]>scores[2]&&scores[0]>scores[3])return CORNERS[0];else if(scores[1]>scores[2]&&scores[1]>scores[3])return CORNERS[1];else if(scores[2]>scores[3])return CORNERS[2];else return CORNERS[3];}
const ONE_EDGE=10;const ONE_CORNER=11;const EE_BENT=20;const EE_STRAIGHT=21;const EC_LEFT=22;const EC_RIGHT=23;const EC_SKEWED=24;const EC_SPAWN=25;const CC_EDGED=26;const CC_LINE=27;const THREE_MARCH=30;const THREE_STAND=31;const THREE_RECOVER=32;const THREE_UNSTAND=33;const THREE_BLOCK=34;const THREE_HANG=35;const THREE_UNHANG=36;const THREE_SIDE=37;const FOUR_Z=40;const FOUR_STAIRS=41;const FOUR_BENT=42;function neighbor_type(top_left)
{var corners=[];for(tcell of CORNERS)
if(is_ally(tcell)&&is_like(tcell))corners.push(tcell);var edges=[];for(tcell of EDGES)
if(is_ally(tcell)&&is_other(tcell))edges.push(tcell);if(corners.length===1&&edges.length===0)return ONE_CORNER;if(corners.length===0&&edges.length===1)return ONE_EDGE;if(corners.length===0&&edges.length===2)return(edges[1]===CCW[edges[0]][4])?EE_STRAIGHT:EE_BENT;if(corners.length===2&&edges.length===0)return(corners[1]===CCW[corners[0]][4])?CC_LINE:CC_EDGED;else if(corners.length===1&&edges.length===1)
{if(edges[0]===CCW[top_left][1])return EC_LEFT;if(edges[0]===CCW[top_left][3])return EC_SPAWN;if(edges[0]===CCW[top_left][5])return EC_SKEWED;if(edges[0]===CCW[top_left][7])return EC_RIGHT;return null;}
else if(corners.length===1&&edges.length===2)
{if(edges.includes(CCW[top_left][1])&&edges.includes(CCW[top_left][3]))return THREE_MARCH;if(edges.includes(CCW[top_left][3])&&edges.includes(CCW[top_left][7]))return THREE_STAND;if(edges.includes(CCW[top_left][1])&&edges.includes(CCW[top_left][5]))return THREE_RECOVER;if(edges.includes(CCW[top_left][5])&&edges.includes(CCW[top_left][7]))return THREE_UNSTAND;if(edges.includes(CCW[top_left][1])&&edges.includes(CCW[top_left][7]))return THREE_BLOCK;return null;}
else if(corners.length===2&&edges.length===1)
{if(corners.includes(CCW[top_left][4])&&edges.includes(CCW[top_left][3]))return THREE_HANG;if(corners.includes(CCW[top_left][4])&&edges.includes(CCW[top_left][1]))return THREE_UNHANG;if(corners.includes(CCW[top_left][2])&&edges.includes(CCW[top_left][1]))return THREE_SIDE;}
else if(corners.length===2&&edges.length===2)
{if(edges.includes(CCW[top_left][3])&&edges.includes(CCW[top_left][7])&&corners.includes(CCW[top_left][4]))
return FOUR_Z;if(edges.includes(CCW[top_left][1])&&edges.includes(CCW[top_left][3])&&corners.includes(CCW[top_left][4]))
return FOUR_STAIRS;if(edges.includes(CCW[top_left][1])&&edges.includes(CCW[top_left][3])&&corners.includes(CCW[top_left][2]))
return FOUR_BENT;return null;}
return null;}
function sok(cand)
{if(cand===4)return true;if(view[cand].food!==0&&this_ant().food!==0)return false;if(view[cand].ant!==null)return false;return true;}
function spref(cand)
{var okscore=0;if(cand===4)okscore-=9;if(this_ant().type===GATHERER)
{for(tcell of SCAN_MOVES)
if(NEARS[cand][tcell]>1)
if(is_ally(tcell)&&view[tcell].ant.type===QUEEN)okscore-=1;}
else
{if(this_ant().food===0&&view[cand].food!==0)
{for(tcell of SCAN_MOVES)
if(is_ally(tcell)&&view[tcell].ant.food===0)
{if([MARCHER_A,MARCHER_B].includes(view[tcell].ant.type))
{var has_common_enemy=false;for(var i=0;i<9;i++)
if(is_enemy(i)&&NEARS[tcell][i]>=4)has_common_enemy=true;if(!has_common_enemy)
{var wt=(view[tcell].ant.type===this_ant().type)?1:-1;if(NEARS[4][tcell]===5)okscore+=wt;if(NEARS[4][tcell]===4)okscore-=wt;if(NEARS[cand][tcell]===5)okscore-=wt;if(NEARS[cand][tcell]===4)okscore+=wt;}}}
if(okscore>0)okscore=0;}}
return okscore*SPREFWT;}
function ssep()
{var has_ally=false;var cands=[0,0,0,0,0,0,0,0,0];for(var i=0;i<9;i++)cands[i]+=spref(i);for(tcell of SCAN_MOVES)
{if(is_ally(tcell))
{has_ally=true;var wt=(is_like(tcell)||is_other(tcell))?3:1;for(var i=0;i<9;i++)cands[i]-=NEARS[tcell][i]*wt;}}
if(!has_ally)return null;var prox_order=index_sort(cands);for(var i=8;i>=0;i--)
{var i_cell=prox_order[i];if(sok(i_cell))return{cell:i_cell};}
return null;}
function sstep(col)
{if(c_at(4)===1)return{cell:4,color:col};var cands=[0,0,0,0,0,0,0,0,0];for(tcell of SCAN_MOVES)
if(c_at(tcell)===col)
for(var i=0;i<9;i++)cands[i]-=NEARS[tcell][i];for(var i=0;i<9;i++)cands[i]+=spref(i);var prox_order=index_sort(cands);for(var i=8;i>=0;i--)
{var i_cell=prox_order[i];if(sok(i_cell))return{cell:i_cell};}
return{cell:4,color:col};}
function smove()
{for(tcell of rand_perm(SCAN_MOVES))
if(sok(tcell))return{cell:tcell};return{cell:4};}
function sdec_alone()
{var try_sep=ssep();if(try_sep!==null)return try_sep;var c=U_PANIC;for(tcell of rand_sub(SCAN_MOVES,7))
if(c_at(tcell)>1&&c_at(tcell)!==c)
{c=c_at(tcell);break;}
return sstep(c);}
function sdec_erase()
{var try_sep=ssep();if(try_sep!==null)return try_sep;for(tcell of rand_perm(SCAN_MOVES))
if(c_at(tcell)!==1)return{cell:tcell,color:1};if(c_at(4)!==1)return{cell:4,color:1};return sdec_alone();}
function sdec_discolor()
{if(c_at(1)!==c_at(6)&&c_at(6)!==1)return{cell:1,color:c_at(6)};if(c_at(2)!==c_at(3))return{cell:3,color:c_at(2)};var proximities=[0,0,0,0,0,0,0,0,0];for(var i=0;i<9;i++)proximities[i]+=ant_rand()%SOBSTRUCT_FUZZ+spref(i);for(tcell of SCAN_MOVES)
if(is_ally(tcell))
for(var i=0;i<9;i++)proximities[i]+=NEARS[tcell][i];var prox_order=index_sort(proximities);for(var i=8;i>=0;i--)
if(sok(prox_order[i]))return{cell:prox_order[i]};return smove();}
function sdec_stride()
{if(rand_choice(SONSTRIDE_PROB))
{var stride_scores=[0,0,0,0,0,0,0,0,0];for(tcell of SCAN_MOVES)
{for(var i=0;i<9;i++)
if(c_at(tcell)!==c_at(i)&&c_at(i)!==1)stride_scores[i]+=NEARS[tcell][i];}
for(var i=0;i<9;i++)
stride_scores[i]+=ant_rand()%SSTRIDE_FUZZ+spref(i);var prox_order=index_sort(stride_scores);for(var i=8;i>=0;i--)
if(sok(prox_order[i]))return{cell:prox_order[i]};}
return smove();}
function sdec_obstruct_textured()
{var proximities=[0,0,0,0,0,0,0,0,0];for(tcell of SCAN_MOVES)
{if(is_enemy(tcell))
{var wt=(view[tcell].ant.type===QUEEN)?OBSTRUCT_QWT:1;for(var i=0;i<9;i++)proximities[i]+=NEARS[tcell][i]*wt;}}
for(var i=0;i<9;i++)proximities[i]+=ant_rand()%SOBSTRUCT_FUZZ;var prox_order;if(rand_choice(SRECOLOR_PROB))
{prox_order=index_sort(proximities);for(var i=8;i>0;i--)
{var i_cell=prox_order[i];for(var j=0;j<i;j++)
{var j_cell=prox_order[j];if(c_at(i_cell)!==c_at(j_cell))return{cell:i_cell,color:c_at(j_cell)};}}}
for(tcell of SCAN_MOVES)
if(is_ally(tcell))
for(var i=0;i<9;i++)proximities[i]+=NEARS[tcell][i];for(var i=0;i<9;i++)proximities[i]+=spref(i);prox_order=index_sort(proximities);for(var i=8;i>=0;i--)
if(sok(prox_order[i]))return{cell:prox_order[i]};return{cell:4,color:1};}
function sdec_obstruct_flat()
{var proximities=[0,0,0,0,0,0,0,0,0];for(tcell of SCAN_MOVES)
{if(is_enemy(tcell))
{var wt=(view[tcell].ant.type===QUEEN)?OBSTRUCT_QWT:1;for(var i=0;i<9;i++)proximities[i]+=NEARS[tcell][i]*wt;}}
for(var i=0;i<9;i++)proximities[i]+=ant_rand()%SOBSTRUCT_FUZZ;var prox_order;if(rand_choice(SRECOLOR_PROB))
{prox_order=index_sort(proximities);for(var i=8;i>0;i--)
{var i_cell=prox_order[i];if(c_at(i_cell)!==D_MARCH)return{cell:i_cell,color:D_MARCH};}}
for(tcell of SCAN_MOVES)
if(is_ally(tcell))
for(var i=0;i<9;i++)proximities[i]+=NEARS[tcell][i];for(var i=0;i<9;i++)proximities[i]+=spref(i);prox_order=index_sort(proximities);for(var i=8;i>=0;i--)
if(sok(prox_order[i]))return{cell:prox_order[i]};return{cell:4,color:1};}
function saboteur()
{var colored_neighbors=0;for(tcell of SCAN_MOVES)
if(c_at(tcell)>1)colored_neighbors++;if(colored_neighbors<=2)return sdec_alone();else
{var num_enemies=0;for(tcell of SCAN_MOVES)
if(is_enemy(tcell))num_enemies++;var diversity=0;var counts=[0,0,0,0,0,0,0,0,0];for(var i=0;i<9;i++)
{diversity+=5-counts[c_at(i)];counts[c_at(i)]++;}
if(num_enemies>0)
{if(diversity>=ERASET)return sdec_obstruct_textured();else return sdec_obstruct_flat();}
else
{if(diversity>=DISCOLORT)return sdec_discolor();else if(diversity>=ERASET)return sdec_stride();else return sdec_erase();}}}
function gwatch(cand)
{if(cand.cell===4)return cand;if(cand.hasOwnProperty("color"))return cand;if(view[cand.cell].food!==0&&this_ant().food!==0)return sigc(U_PANIC,S_SIDE,0);if(view[cand.cell].ant!==null)return sigc(U_PANIC,S_SIDE,0);return cand;}
function egwatch(cand)
{if(cand.cell===4)return cand;if(cand.hasOwnProperty("color"))return cand;if(view[cand.cell].food!==0&&this_ant().food!==0)return gwatch(sdec_erase());if(view[cand.cell].ant!==null)return gwatch(sdec_erase());return cand;}
function gdec_ee_bent(c)
{return{cell:CCW[c][4]};}
function gdec_ec_left(c)
{if(c_at(c)===D_FOOD&&c_at(CCW[c][1])===D_FOOD)return{cell:CCW[c][7]};if(c_at(c)===D_STALLED&&c_at(CCW[c][1])===D_STALLED)return sigc(U_READY,S_GATHERER,c);if(c_at(c)===D_MARCH&&c_at(CCW[c][1])===D_MARCH)return sigc(D_MARCH,S_GATHERER,c);return sigc(c_at(4),S_GATHERER,c);}
function gdec_ec_right(c)
{if([D_MARCH,D_FOOD].includes(c_at(c))&&[D_MARCH,D_FOOD].includes(c_at(CCW[c][7])))
return{cell:CCW[c][6]};if(is_ally(c)&&view[c].ant.type===QUEEN)
return{cell:CCW[c][1]};if(c_at(c)===D_STALLED&&c_at(CCW[c][7])===D_STALLED)
return sigc(U_READY,S_GATHERER,c);return sigc(c_at(4),S_GATHERER,c);}
function gdec_cc_edged(c)
{if(view[CCW[c][2]].ant.type!==QUEEN)return saboteur();return{cell:CCW[c][1]};}
function gdec_three_block(c)
{if(c_at(CCW[c][7])==D_FOOD)return{cell:CCW[c][6]};return{cell:CCW[c][2]};}
function gdec_three_unstand(c)
{if(view[CCW[c][5]].ant.type!==QUEEN)return saboteur();return{cell:CCW[c][4]};}
function gdec_four_bent(c)
{return{cell:CCW[c][4]};}
function early_gatherer()
{var qcell=null;var food_count=0;for(tcell of SCAN_MOVES)
{if(is_ally(tcell)&&view[tcell].ant.type===QUEEN)qcell=tcell;else if(is_enemy(tcell))return saboteur();}
if(qcell===null)return saboteur();if(c_at(qcell)===D_FOOD)return{cell:CCW[qcell][7]};if(this_ant().food===0)
{for(tcell of rand_perm(CORNERS))
if(view[tcell].food>0&&NEARS[tcell][qcell]===5)
{if(c_at(tcell)===D_FOOD)return{cell:tcell};else return{cell:tcell,color:D_FOOD};}
for(tcell of rand_perm(EDGES))
if(view[tcell].food>0)
{if(c_at(tcell)!==D_FOOD&&NEARS[tcell][qcell]===4)
return{cell:tcell,color:D_FOOD};}}
return{cell:CCW[qcell][1]};}
function gatherer_retrieve()
{if(c_at(4)===U_PANIC)return saboteur();var c=view_corner();switch(neighbor_type(c))
{case EC_LEFT:return gwatch({cell:CCW[c][2]});case THREE_BLOCK:{if(c_at(CCW[c][7])===D_FOOD)return gwatch({cell:CCW[c][6]});return gwatch({cell:CCW[c][2]});}
case FOUR_BENT:return gwatch(sigc(c_at(4),S_FRONT,c));default:return early_gatherer();}}
function gatherer_return()
{if(c_at(4)===U_PANIC)return saboteur();var c=view_corner();switch(neighbor_type(c))
{case EC_LEFT:return gwatch({cell:CCW[c][2]});case THREE_BLOCK:return gwatch({cell:CCW[c][2]});case FOUR_BENT:return gwatch({cell:CCW[c][4]});default:return early_gatherer();}}
function gatherer_formation()
{if(c_at(4)===U_PANIC)return saboteur();var c=view_corner();switch(neighbor_type(c))
{case EC_LEFT:return gwatch(gdec_ec_left(c));case EC_RIGHT:return gwatch(gdec_ec_right(c));case CC_EDGED:return gwatch(gdec_cc_edged(c));case EE_BENT:return gwatch(gdec_ee_bent(c));case THREE_BLOCK:return gwatch(gdec_three_block(c));case THREE_UNSTAND:return gwatch(gdec_three_unstand(c));case FOUR_BENT:return gwatch(gdec_four_bent(c));default:return egwatch(early_gatherer());}}
function gatherer_decision()
{var marcher_count=0;var gatherer_count=0;var queen_pos=null;for(tcell of SCAN_MOVES)
if(is_ally(tcell))
{if(view[tcell].ant.type===MARCHER_A||view[tcell].ant.type===MARCHER_B)marcher_count++;if(view[tcell].ant.type===GATHERER)gatherer_count++;if(view[tcell].ant.type===QUEEN)queen_pos=tcell;}
if(gatherer_count>0)return saboteur();if(this_ant().food>0&&marcher_count>0)return gwatch(gatherer_return());else if(queen_pos!==null&&marcher_count>0)return gwatch(gatherer_formation());else if(marcher_count>0)return gwatch(gatherer_retrieve());else if(queen_pos!==null)return egwatch(early_gatherer());else return saboteur();}
function mdec_one_corner(c)
{if(view[c].ant.type===QUEEN)
return sigc(c_at(4),S_SIDE,c);else return saboteur();}
function mdec_one_edge(c)
{if([U_REALIGN,D_MARCH].includes(c_at(CCW[c][1])))
{if(view[CCW[c][2]].food===1)return{cell:c};if(is_ally(CCW[c][2])&&view[CCW[c][2]].ant.type===GATHERER)return{cell:c};}
return saboteur();}
function mdec_ee_bent(c)
{if(view[CCW[c][1]].ant.type===GATHERER&&view[CCW[c][3]].ant.type===QUEEN)return saboteur();if(view[CCW[c][1]].ant.type===QUEEN&&view[CCW[c][3]].ant.type===GATHERER)return saboteur();var u_sig=c_at(CCW[c][1]);var d_sig=c_at(CCW[c][3]);if(is_ally(c)&&view[c].ant.type===GATHERER)return sigc(c_at(4),S_SIDE,CCW[c][4]);var provisional=lchk(c);if(provisional!==null)
{if(provisional===U_REALIGN)return sigc(U_SENTINEL,S_END,c);return sigc(provisional,S_END,c);}
if(u_sig===D_STALLED)
{if([D_STALLED,U_READY,D_GATHERER].includes(d_sig)&&[D_STALLED,U_READY].includes(c_at(4)))
return sigc(D_STALLED,S_SIDE,c);if(d_sig===U_REALIGN&&c_at(4)===D_STALLED)
return sigc(D_STALLED,S_SIDE,c);}
if(view[CCW[c][1]].ant.type===QUEEN)
{var provisional=lchk(CCW[c][4]);if(provisional!==null)return sigc(provisional,S_END,CCW[c][4]);if(u_sig===D_GATHERER&&d_sig===U_REALIGN&&c_at(4)===D_GATHERER)
return sigc(D_GATHERER,S_END,CCW[c][4]);}
if(u_sig===U_SENTINEL)
{if(d_sig===U_REALIGN&&[D_MARCH,U_SENTINEL].includes(c_at(4)))return sigc(U_SENTINEL,S_SIDE,c);if(d_sig===D_STALLED&&[U_SENTINEL,D_STALLED].includes(c_at(4)))return sigc(U_SENTINEL,S_SIDE,c);if(d_sig===D_MARCH&&[U_SENTINEL,D_MARCH].includes(c_at(4)))return sigc(D_MARCH,S_SIDE,c);}
if(u_sig===D_GATHERER&&d_sig===D_STALLED&&c_at(4)===D_GATHERER)return sigc(D_STALLED,S_SIDE,c);return{cell:CCW[c][2]};}
function mdec_ee_straight(c)
{return sigc(U_REALIGN,S_SIDE,c);}
function mdec_ec_left(c)
{if(view[CCW[c][1]].ant.type===GATHERER&&view[c].ant.type===QUEEN)return saboteur();if(view[CCW[c][1]].ant.type===QUEEN&&view[c].ant.type===GATHERER)return saboteur();if(is_other(CCW[c][1])&&view[c].ant.type===QUEEN)return{cell:CCW[c][3]};var d_sig=PDOWNS[c_at(c)][c_at(CCW[c][1])];if(is_ally(CCW[c][4])&&view[CCW[c][4]].ant.type===GATHERER&&d_sig===D_STALLED&&c_at(4)===D_STALLED)
return sigc(D_STALLED,S_END,c);var provisional=lchk(CCW[c][4]);if(provisional!==null)
{if(provisional===U_REALIGN)return sigc(U_SENTINEL,S_END,CCW[c][4]);return sigc(provisional,S_END,CCW[c][4]);}
if(d_sig===U_REALIGN)
{if(c_at(4)===D_MARCH)return sigc(U_SENTINEL,S_END,CCW[c][4]);if(c_at(4)===U_SENTINEL)
{if(c_at(c)===D_MARCH)return{cell:CCW[c][2]};return sigc(U_SENTINEL,S_END,CCW[c][4]);}}
if(d_sig===D_STALLED)
{if([D_MARCH,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_END,CCW[c][4]);if(c_at(4)===U_SENTINEL)return sigc(U_SENTINEL,S_END,CCW[c][4]);}
if(d_sig===D_GATHERER)
{if(c_at(4)===D_FOOD)return sigc(D_GATHERER,S_END,CCW[c][4]);if(c_at(4)===D_GATHERER)return sigc(D_STALLED,S_END,CCW[c][4]);}
if(d_sig===U_READY)
{if(c_at(4)===D_STALLED)
{if(c_at(CCW[c][2])!==D_MARCH)return{cell:CCW[c][2],color:D_MARCH};return sigc(D_MARCH,S_END,CCW[c][4]);}
if(c_at(4)===U_SENTINEL)return sigc(D_MARCH,S_END,CCW[c][4]);}
return{cell:CCW[c][2]};}
function mdec_ec_right(c)
{if(view[c].ant.type===GATHERER&&view[CCW[c][7]].ant.type===QUEEN)
if(is_ally(CCW[c][4])&&view[CCW[c][4]].ant.type!==this_ant().type)return{cell:CCW[c][5]};var d_sig=PDOWNS[c_at(c)][c_at(CCW[c][7])];var provisional=lchk(CCW[c][4]);if(provisional!==null)
{if(provisional===U_REALIGN)return sigc(U_SENTINEL,S_END,CCW[c][4]);return sigc(provisional,S_END,CCW[c][4]);}
if(d_sig===D_MARCH)
{if(c_at(4)===D_MARCH)return sigc(D_MARCH,S_END,CCW[c][4]);if([D_FOOD,D_GATHERER,U_READY].includes(c_at(4)))return sigc(D_MARCH,S_END,CCW[c][4]);}
if(d_sig===D_FOOD)
{if([U_SENTINEL,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_END,CCW[c][4]);if([D_FOOD,D_GATHERER,U_READY].includes(c_at(4)))return sigc(D_STALLED,S_END,CCW[c][4]);}
if(d_sig===D_GATHERER)
{if([D_FOOD,D_GATHERER,U_READY].includes(c_at(4)))return sigc(D_MARCH,S_END,CCW[c][4]);if([U_SENTINEL,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_END,CCW[c][4]);}
if(d_sig===D_STALLED)
{if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_END,CCW[c][4]);if([D_FOOD,D_GATHERER,U_READY].includes(c_at(4)))return sigc(D_STALLED,S_END,CCW[c][4]);}
if(d_sig===U_READY)
{if(c_at(4)===D_STALLED)return sigc(D_MARCH,S_END,CCW[c][4]);if([D_FOOD,D_GATHERER,U_READY].includes(c_at(4)))return sigc(D_MARCH,S_END,CCW[c][4]);}
if(d_sig===U_REALIGN)
{if(c_at(4)===U_SENTINEL)return{cell:CCW[c][6]};if([D_FOOD,D_GATHERER,U_READY].includes(c_at(4)))return sigc(D_STALLED,S_END,CCW[c][4]);}
return sigc(d_sig,S_END,CCW[c][4]);}
function mdec_ec_spawn(c)
{if(view[c].ant.type===QUEEN&&c_at(c)===D_MARCH&&c_at(CCW[c][3])===D_STALLED)
if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_SIDE,c);return saboteur();}
function mdec_three_march(c)
{var d_sig=PDOWNS[c_at(c)][c_at(CCW[c][1])];var u_sig=c_at(CCW[c][3]);var provisional=lchk2(c);if(provisional!==null)return sigc(provisional,S_FRONT,c);if(u_sig===U_SENTINEL)
{if(d_sig===D_GATHERER&&[D_GATHERER,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,c);if(d_sig===D_STALLED&&[D_MARCH,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,c);}
if(u_sig===U_REALIGN)
{if(d_sig===U_REALIGN&&c_at(4)===U_REALIGN)
if(c_at(c)===U_SENTINEL)
{if(c_at(CCW[c][7])===D_MARCH)return sigc(U_REALIGN,S_FRONT,c);return{cell:CCW[c][2]};}
if(d_sig===D_FOOD&&[D_MARCH,D_FOOD].includes(c_at(4)))return sigc(D_FOOD,S_FRONT,c);if(d_sig===U_READY&&c_at(4)===D_STALLED)return sigc(D_MARCH,S_FRONT,c);if(d_sig===D_STALLED&&[D_MARCH,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,c);if(d_sig===D_GATHERER&&[D_GATHERER,D_STALLED].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,c);if(d_sig===D_MARCH&&c_at(4)===D_STALLED)return sigc(D_STALLED,S_FRONT,c);}
if(u_sig===D_MARCH)
{if(d_sig===D_FOOD&&c_at(4)===D_FOOD)return sigc(D_FOOD,S_FRONT,c);if(d_sig===U_REALIGN&&c_at(4)===D_MARCH)
if(c_at(c)===U_SENTINEL)return sigc(U_REALIGN,S_FRONT,c);if(d_sig===U_READY&&c_at(4)===U_READY)return sigc(D_MARCH,S_FRONT,c);}
if(u_sig===D_STALLED)
{if(d_sig===U_READY&&c_at(4)===D_STALLED)return sigc(U_READY,S_FRONT,c);if(d_sig===D_STALLED&&[D_STALLED,D_MARCH].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,c);if(d_sig===D_GATHERER&&c_at(4)===D_GATHERER)return sigc(D_STALLED,S_FRONT,c);if(d_sig===D_MARCH&&c_at(4)===D_STALLED)return sigc(D_STALLED,S_FRONT,c);if(d_sig===U_REALIGN&&[D_STALLED,D_MARCH].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,c);}
if(u_sig===D_GATHERER)
{if(d_sig===D_STALLED&&c_at(4)===D_GATHERER)
if(view[CCW[c][3]].ant.type===QUEEN)return sigc(D_STALLED,S_FRONT,c);if(d_sig===D_GATHERER&&c_at(4)===D_GATHERER)return sigc(D_GATHERER,S_FRONT,c);if(d_sig===D_FOOD&&c_at(4)===D_GATHERER)return sigc(D_FOOD,S_FRONT,c);}
if(u_sig===D_FOOD)
{if(d_sig===D_FOOD&&c_at(4)===D_FOOD)return sigc(D_FOOD,S_FRONT,c);if(d_sig===D_GATHERER&&c_at(4)===D_GATHERER)return sigc(D_GATHERER,S_FRONT,c);}
return{cell:CCW[c][2]};}
function mdec_three_stand(c)
{var provisional=lchk2(c);if(provisional!==null)return sigc(provisional,S_SIDE,c);var u_sig=c_at(CCW[c][3]);var d_sig=PSIDES[c_at(c)][c_at(CCW[c][7])];if(u_sig===U_REALIGN)
{if([D_MARCH,D_STALLED].includes(d_sig)&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);if(c_at(4)===U_REALIGN)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);}
if(u_sig===D_MARCH&&d_sig===U_REALIGN&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);if(u_sig===D_STALLED&&[D_STALLED,U_REALIGN].includes(d_sig)&&c_at(4)===D_STALLED)
return sigc(D_STALLED,S_SIDE,CCW[c][4]);return sigc(D_MARCH,S_SIDE,CCW[c][4]);}
function mdec_three_unstand(c)
{if(view[CCW[c][5]].ant.type===QUEEN)
{var provisional=lchk(c);if(provisional!==null)return sigc(provisional,S_FRONT,c);var d_sig=PUPS[c_at(c)][c_at(CCW[c][7])];return sigc(d_sig,S_FRONT,c);}
else
{var provisional=lchk(CCW[c][4]);if(provisional!==null)return sigc(provisional,S_FRONT,CCW[c][4]);var u_sig=c_at(CCW[c][5]);var d_sig=PDOWNS[c_at(c)][c_at(CCW[c][7])];if(u_sig===D_MARCH)
{if(d_sig===U_READY&&c_at(4)===U_READY)return sigc(D_MARCH,S_FRONT,CCW[c][4]);if(d_sig===D_FOOD&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);if([D_FOOD,D_GATHERER].includes(c_at(4)))return sigc(D_MARCH,S_FRONT,CCW[c][4]);}
if(u_sig===D_FOOD)
{if(d_sig===D_FOOD&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);if([D_FOOD,D_GATHERER].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(u_sig===D_GATHERER)
{if(d_sig===D_FOOD&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);if([D_FOOD,D_GATHERER].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(u_sig===D_STALLED)
{if(d_sig===U_READY)
{if(c_at(4)===D_STALLED)return sigc(U_READY,S_FRONT,CCW[c][4]);if(c_at(4)===D_GATHERER)return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(d_sig===D_FOOD)
{if(c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);if(c_at(4)===D_GATHERER)return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(d_sig===D_STALLED)
{if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_FRONT,CCW[c][4]);if(c_at(4)===D_GATHERER)return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(d_sig===D_GATHERER&&c_at(4)===D_GATHERER)return sigc(D_STALLED,S_FRONT,CCW[c][4]);if([D_MARCH,U_REALIGN].includes(d_sig)&&c_at(4)===D_GATHERER)
return sigc(D_STALLED,S_FRONT,CCW[c][4]);if(c_at(4)===D_FOOD)return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(u_sig===U_REALIGN)
{if(d_sig===D_FOOD&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);if([D_FOOD,D_GATHERER].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(u_sig===U_SENTINEL)
{if(d_sig===D_FOOD)
{if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_FRONT,CCW[c][4]);if(c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);}
if(d_sig===D_GATHERER&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_FRONT,CCW[c][4]);if(d_sig===D_MARCH&&c_at(4)===U_SENTINEL)return sigc(D_MARCH,S_FRONT,CCW[c][4]);if(d_sig===D_STALLED&&c_at(4)===U_SENTINEL)return sigc(D_STALLED,S_FRONT,CCW[c][4]);if(d_sig===U_READY&&c_at(4)===D_STALLED)return sigc(U_READY,S_FRONT,CCW[c][4]);if([D_FOOD,D_GATHERER].includes(c_at(4)))return sigc(D_STALLED,S_FRONT,CCW[c][4]);}
if(u_sig===U_READY)
{if(d_sig===D_FOOD&&c_at(4)===D_MARCH)return sigc(U_REALIGN,S_FRONT,CCW[c][4]);if([D_FOOD,D_GATHERER].includes(c_at(4)))return sigc(D_MARCH,S_FRONT,CCW[c][4]);}
return sigc(c_at(4),S_FRONT,CCW[c][4]);}}
function mdec_three_recover(c)
{return sigc(U_SENTINEL,S_FRONT,c);}
function mdec_three_hang(c)
{return sigc(c_at(4),S_SIDE,CCW[c][4]);}
function mdec_three_unhang(c)
{return sigc(c_at(4),S_SIDE,c);}
function mdec_four_z(c)
{var provisional=lchk2(CCW[c][4]);if(provisional!==null)return sigc(provisional,S_SIDE,CCW[c][4]);var u_sig=PSIDES[c_at(c)][c_at(CCW[c][7])];var d_sig=PSIDES[c_at(CCW[c][4])][c_at(CCW[c][3])];if(u_sig===D_FOOD)
{if([D_FOOD,D_STALLED,U_REALIGN].includes(d_sig)&&c_at(4)===U_REALIGN)
return sigc(U_REALIGN,S_SIDE,CCW[c][4]);if(d_sig===D_GATHERER&&[U_REALIGN,D_GATHERER].includes(c_at(4)))
return sigc(U_REALIGN,S_SIDE,CCW[c][4]);}
if(u_sig===D_STALLED)
{if(d_sig===U_REALIGN)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);if(d_sig===D_FOOD&&c_at(4)===U_REALIGN)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);}
if(u_sig===D_GATHERER)
{if(d_sig===U_REALIGN&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,CCW[c][4]);if(d_sig===D_FOOD&&[U_REALIGN,D_GATHERER].includes(c_at(4)))
return sigc(U_REALIGN,S_SIDE,CCW[c][4]);}
if(u_sig===U_REALIGN)
{if(d_sig===D_FOOD&&c_at(4)===U_REALIGN)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);if(d_sig===D_STALLED)return sigc(U_REALIGN,S_SIDE,CCW[c][4]);if(d_sig===D_GATHERER&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,CCW[c][4]);if(d_sig===U_READY&&c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,CCW[c][4]);}
if(u_sig===U_READY&&d_sig===U_REALIGN&&c_at(4)===U_REALIGN)
return sigc(D_MARCH,S_SIDE,CCW[c][4]);return sigc(D_MARCH,S_SIDE,CCW[c][4]);}
function mdec_four_stairs(c)
{var provisional=lchk2(c);if(provisional!==null)return sigc(provisional,S_SIDE,c);var u_sig=PSIDES[c_at(c)][c_at(CCW[c][1])];var d_sig=PSIDES[c_at(CCW[c][4])][c_at(CCW[c][3])];if(u_sig===D_MARCH)
{if(d_sig===D_FOOD)
{if(c_at(4)===D_MARCH)return sigc(D_FOOD,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);}
if(d_sig===U_READY)
{if(c_at(4)===U_READY)return sigc(D_MARCH,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);}
if(d_sig===D_STALLED)
{if(c_at(4)===D_MARCH)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===D_GATHERER&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);if([D_MARCH,U_REALIGN].includes(d_sig)&&c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);}
if(u_sig===D_FOOD)
{if(d_sig===D_MARCH)
{if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);if(c_at(4)===D_MARCH)return sigc(D_FOOD,S_SIDE,c);}
if(d_sig===U_READY)
{if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===D_GATHERER&&[U_REALIGN,D_GATHERER].includes(c_at(4)))return sigc(D_FOOD,S_SIDE,c);if([U_REALIGN,D_STALLED].includes(d_sig)&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(u_sig===D_STALLED)
{if(d_sig===D_STALLED)
{if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===D_MARCH)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);}
if(d_sig===D_MARCH)
{if(c_at(4)===D_MARCH)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===D_GATHERER)
{if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);if([D_STALLED,D_GATHERER].includes(c_at(4)))return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===U_READY)
{if(c_at(4)===D_STALLED)return sigc(U_READY,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);}
if(d_sig===U_REALIGN&&[U_REALIGN,D_MARCH].includes(c_at(4)))return sigc(D_STALLED,S_SIDE,c);if(d_sig===D_FOOD&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(u_sig===D_GATHERER)
{if(d_sig===D_STALLED)
{if([D_STALLED,D_GATHERER].includes(c_at(4)))return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===U_READY)
{if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===D_FOOD&&[D_GATHERER,U_REALIGN].includes(c_at(4)))return sigc(D_FOOD,S_SIDE,c);if([D_MARCH,U_REALIGN].includes(d_sig)&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);if(d_sig===D_GATHERER&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(u_sig===U_REALIGN)
{if(d_sig===U_REALIGN)
{if(c_at(4)===D_MARCH)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===D_STALLED)
{if(c_at(4)===D_MARCH)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(d_sig===D_MARCH&&c_at(4)===U_REALIGN)return sigc(D_MARCH,S_SIDE,c);if([D_FOOD,D_GATHERER,U_READY].includes(d_sig)&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);}
if(u_sig===U_READY)
{if(d_sig===D_MARCH)
{if(c_at(4)===U_READY)return sigc(D_MARCH,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(U_READY,S_SIDE,c);}
if([D_FOOD,D_GATHERER].includes(d_sig))
{if(c_at(4)===D_STALLED)return sigc(D_STALLED,S_SIDE,c);if(c_at(4)===U_REALIGN)return sigc(U_READY,S_SIDE,c);}
if(d_sig===D_STALLED&&c_at(4)===D_STALLED)return sigc(U_READY,S_SIDE,c);if(d_sig===U_REALIGN&&c_at(4)===U_REALIGN)return sigc(D_STALLED,S_SIDE,c);if(d_sig===U_READY&&c_at(4)===U_REALIGN)return sigc(U_READY,S_SIDE,c);}
return sigc(c_at(4),S_SIDE,c);}
function mwatch(cand)
{if(cand.cell===4)return cand;if(cand.hasOwnProperty("color"))return cand;if(view[cand.cell].food!==0)return sigc(D_FOOD,S_SIDE,0);if(is_harvestable(cand.cell))return sigc(D_FOOD,S_SIDE,0);if(view[cand.cell].ant!==null)return sigc(U_PANIC,S_SIDE,0);return cand;}
function marcher_decision()
{if(c_at(4)===U_PANIC||this_ant().food>0)return saboteur();var gatherer_count=0;var enemy_count=0;for(tcell of SCAN_MOVES)
{if(is_ally(tcell)&&view[tcell].ant.type===GATHERER)gatherer_count++;else if(is_enemy(tcell)&&!is_harvestable(tcell))enemy_count++;}
if(gatherer_count>1||enemy_count>0)return saboteur();var colored_neighbors=0;for(tcell of SCAN_MOVES)
if(c_at(tcell)>1)colored_neighbors++;if(colored_neighbors>5)return saboteur();var c=view_corner();switch(neighbor_type(c))
{case ONE_CORNER:return mwatch(mdec_one_corner(c));case ONE_EDGE:return mwatch(mdec_one_edge(c));case EE_BENT:return mwatch(mdec_ee_bent(c));case EE_STRAIGHT:return mwatch(mdec_ee_straight(c));case EC_LEFT:return mwatch(mdec_ec_left(c));case EC_RIGHT:return mwatch(mdec_ec_right(c));case EC_SPAWN:return mwatch(mdec_ec_spawn(c));case THREE_MARCH:return mwatch(mdec_three_march(c));case THREE_STAND:return mwatch(mdec_three_stand(c));case THREE_RECOVER:return mwatch(mdec_three_recover(c));case THREE_UNSTAND:return mwatch(mdec_three_unstand(c));case THREE_HANG:return mwatch(mdec_three_hang(c));case THREE_UNHANG:return mwatch(mdec_three_unhang(c));case FOUR_Z:return mwatch(mdec_four_z(c));case FOUR_STAIRS:return mwatch(mdec_four_stairs(c));default:return saboteur();}}
function opening_queen()
{for(tcell of rand_perm(SCAN_MOVES))
if(view[tcell].food===1)return{cell:tcell};var has_ally=false;var proxs=[0,0,0,0,0,0,0,0,0];for(tcell of SCAN_MOVES)
{if(view[tcell].ant!==null)
{has_ally=true;for(var i=0;i<9;i++)proxs[i]-=NEARS[tcell][i];}}
if(has_ally)
{var prox_order=index_sort(proxs);for(var i=8;i>=0;i--)
{var i_cell=prox_order[i];if(view[i_cell].ant===null&&view[i_cell].food===0)return{cell:i_cell};}}
if(this_ant().food>0)
{var num_ants=0;for(tcell of SCAN_MOVES)
if(view[tcell].ant!==null)num_ants++;if(num_ants===0)
{var is_clear=true;var num_black_corners=0;var black_corner=null;for(var tcell=0;tcell<9;tcell++)
{if(CORNERS.includes(tcell))
{if(c_at(tcell)===8)
{num_black_corners++;black_corner=tcell;}
else if(c_at(tcell)!==1)is_clear=false;}
else if(c_at(tcell)!==1)is_clear=false;}
if(num_black_corners===1&&is_clear)return{cell:CCW[black_corner][7],type:GATHERER};}}
if(c_at(4)!==8)return{cell:4,color:8};var cands=[0,0,0,0,9,0,0,0,0];for(tcell of SCAN_MOVES)
if(c_at(tcell)===8)
for(var i=0;i<9;i++)cands[i]-=NEARS[tcell][i];var cand_order=index_sort(cands);for(var i=8;i>=0;i--)
{var i_cell=cand_order[i];if(view[i_cell].ant===null&&view[i_cell].food===0)return{cell:i_cell};}
return{cell:4,color:8};}
function early_queen()
{var gcell=null;var ally_count=0;for(tcell of rand_perm(SCAN_MOVES))
{if(is_ally(tcell))
{ally_count++;if(view[tcell].ant.type===GATHERER&&EDGES.includes(tcell))gcell=tcell;}}
if(gcell===null)return opening_queen();for(tcell of rand_perm(CORNERS))
if(view[tcell].food>0&&NEARS[tcell][gcell]===5)
{if(c_at(tcell)===D_FOOD)return{cell:tcell};else return{cell:tcell,color:D_FOOD};}
for(tcell of rand_perm(EDGES))
if(view[tcell].food>0)
{if(c_at(tcell)!==D_FOOD&&NEARS[tcell][gcell]===4)
return{cell:tcell,color:D_FOOD};}
if(c_at(4)===D_FOOD)
{if(c_at(CCW[gcell][2])===D_FOOD&&view[CCW[gcell][2]].food===0)
return{cell:CCW[gcell][2],color:D_MARCH};return{cell:4,color:D_MARCH};}
if(c_at(CCW[gcell][6])===D_FOOD&&view[CCW[gcell][6]].food===0)
return{cell:CCW[gcell][6],color:D_MARCH};if(EDGES.includes(gcell)&&this_ant().food>2&&ally_count===1)
{var num_clear_cells=0;var num_down_food=0;var is_valid=true;for(var tcell=0;tcell<9;tcell++)
{if(c_at(tcell)===D_FOOD)
{num_down_food++;if(tcell!==4&&tcell!==gcell)is_valid=false;}
if(c_at(tcell)===D_MARCH)num_clear_cells++;}
if(is_valid&&num_down_food===1&&num_clear_cells===8)
{var food_factor=QFORMP_MAX-QFORMP_MIN
var food_coefficient=QFORMP_DECAY/food_factor
var actual_prob=food_factor/(food_coefficient*(this_ant().food-3)+1)+QFORMP_MIN;if(rand_choice(actual_prob))return{cell:CCW[gcell][1],type:rand_choice(.5)?MARCHER_A:MARCHER_B};else return{cell:gcell,color:D_MARCH};}}
return{cell:CCW[gcell][7]};}
function qwatch(cand)
{if(cand.hasOwnProperty("type")&&this_ant().food===0)return sigc(U_PANIC,S_SIDE,0);if(cand.hasOwnProperty("type")&&view[cand.cell].food!==0)return sigc(U_PANIC,S_SIDE,0);if(cand.cell===4)return cand;if(cand.hasOwnProperty("color"))return cand;if(is_enemy(cand.cell))return sigc(U_PANIC,S_SIDE,0);if(is_ally(cand.cell))return sigc(c_at(4),S_SIDE,0);return cand;}
function eqwatch(cand)
{if(cand.hasOwnProperty("type")&&this_ant().food===0)return qwatch(opening_queen());if(cand.hasOwnProperty("type")&&view[cand.cell].food!==0)return qwatch(opening_queen());if(cand.cell===4)return cand;if(cand.hasOwnProperty("color"))return cand;if(is_enemy(cand.cell))return qwatch(opening_queen());if(is_ally(cand.cell))return qwatch(opening_queen());return cand;}
function qdec_ee_straight(c)
{return sigc(c_at(4),S_SIDE,c);}
function qdec_ee_bent(c)
{return{cell:CCW[c][2]};}
function qdec_ec_skewed(c)
{if(view[CCW[c][5]].ant.type!==GATHERER)return opening_queen();if(this_ant().food>0&&view[c].ant.type===MARCHER_A)return{cell:CCW[c][7],type:MARCHER_B};if(this_ant().food>0&&view[c].ant.type===MARCHER_B)return{cell:CCW[c][7],type:MARCHER_A};return opening_queen();}
function qdec_ec_spawn(c)
{if(view[CCW[c][3]].ant.type!==GATHERER)return opening_queen();if(this_ant().food>0&&view[c].ant.type===MARCHER_A)return{cell:CCW[c][1],type:MARCHER_B};if(this_ant().food>0&&view[c].ant.type===MARCHER_B)return{cell:CCW[c][1],type:MARCHER_A};return opening_queen();}
function qdec_cc_edged(c)
{if(view[c].ant.type!==GATHERER)return opening_queen();if(this_ant().food>0&&view[CCW[c][2]].ant.type===MARCHER_A)return{cell:CCW[c][1],type:MARCHER_B};if(this_ant().food>0&&view[CCW[c][2]].ant.type===MARCHER_B)return{cell:CCW[c][1],type:MARCHER_A};return opening_queen();}
function qdec_three_march(c)
{var u_sig=PUPS[c_at(c)][c_at(CCW[c][1])];if(u_sig===D_STALLED)
{if(c_at(CCW[c][3])===D_MARCH&&[D_MARCH,D_GATHERER].includes(c_at(4)))
return sigc(D_STALLED,S_FRONT,c);if(c_at(CCW[c][3])===U_READY&&c_at(4)===D_STALLED)return sigc(U_READY,S_FRONT,c);}
if(u_sig===D_MARCH&&c_at(CCW[c][3])===U_READY&&c_at(4)===U_READY)
return sigc(D_MARCH,S_FRONT,c);if(u_sig===U_READY&&c_at(CCW[c][3])===U_REALIGN&&c_at(4)===U_READY)
if(c_at(CCW[c][1])===D_MARCH)return sigc(D_MARCH,S_FRONT,c);return sigc(c_at(4),S_FRONT,c);}
function qdec_three_stand(c)
{var u_sig=PUPS[c_at(c)][c_at(CCW[c][7])];if(u_sig===D_STALLED)
{if(c_at(CCW[c][3])===D_MARCH&&c_at(4)===D_GATHERER)return sigc(D_STALLED,S_FRONT,c);if(c_at(CCW[c][3])===U_READY&&c_at(4)===D_STALLED)return sigc(U_READY,S_FRONT,c);}
if(u_sig===D_MARCH&&c_at(CCW[c][3])===U_READY&&c_at(4)===U_READY)
return sigc(D_MARCH,S_FRONT,c);if(u_sig===U_READY&&c_at(CCW[c][3])===U_REALIGN&&c_at(4)===U_READY)
if(c_at(CCW[c][1])===D_MARCH)return sigc(D_MARCH,S_FRONT,c);return sigc(c_at(4),S_FRONT,c);}
function qdec_three_recover(c)
{var u_sig=PUPS[c_at(c)][c_at(CCW[c][1])];if(u_sig===D_FOOD)return sigc(D_FOOD,S_FRONT,c);if(this_ant().food>0&&[D_STALLED,U_READY].includes(u_sig))
{var food_factor=QFSPAWNP_MAX-QFSPAWNP_MIN
var food_coefficient=QFSPAWNP_DECAY/food_factor
var actual_prob=food_factor/(food_coefficient*(this_ant().food-1)+1)+QFSPAWNP_MIN;if(rand_choice(actual_prob))return{cell:CCW[c][3]};}
var provisional=lchk(c)
if(provisional!==null)return sigc(provisional,S_FRONT,c);return sigc(c_at(4),S_FRONT,c);}
function qdec_three_unstand(c)
{var u_sig=PUPS[c_at(c)][c_at(CCW[c][7])];if(this_ant().food>0&&u_sig===D_STALLED&&c_at(CCW[c][5])===D_MARCH&&c_at(4)===D_STALLED)
{var food_factor=QBSPAWNP_MAX-QBSPAWNP_MIN
var food_coefficient=QBSPAWNP_DECAY/food_factor
var actual_prob=food_factor/(food_coefficient*(this_ant().food-1)+1)+QBSPAWNP_MIN;if(rand_choice(actual_prob))return{cell:CCW[c][3]};}
if(u_sig===D_STALLED&&c_at(CCW[c][5])===U_READY&&c_at(4)===D_STALLED)
return sigc(U_READY,S_FRONT,c);return sigc(u_sig,S_FRONT,c);}
function qdec_three_block(c)
{var u_sig=PUPS[c_at(c)][c_at(CCW[c][1])];return sigc(u_sig,S_FRONT,c);}
function qdec_three_side(c)
{var u_sig=PUPS[c_at(CCW[c][1])][c_at(CCW[c][2])];return sigc(u_sig,S_FRONT,CCW[c][2]);}
function queen_wait()
{var c=view_corner();switch(neighbor_type(c))
{case ONE_EDGE:{if(this_ant().food>1)return{cell:CCW[c][3],type:GATHERER};}
break;case EC_LEFT:{var u_sig=PUPS[c_at(c)][c_at(CCW[c][1])];if(u_sig===D_GATHERER)return sigc(D_GATHERER,S_FRONT,c);if(u_sig===U_REALIGN&&[U_REALIGN,U_SENTINEL].includes(c_at(c)))
if([U_REALIGN,U_SENTINEL].includes(c_at(CCW[c][1])))
return eqwatch(early_queen());var provisional=lchk(c);if(provisional!==null)return sigc(provisional,S_FRONT,c);if(this_ant().food>1)
{if(c_at(CCW[c][3])!==D_MARCH)return{cell:CCW[c][3],color:D_MARCH};return{cell:CCW[c][3],type:GATHERER};}}
break;case EC_RIGHT:{var u_sig=PUPS[c_at(c)][c_at(CCW[c][7])];if(u_sig===D_GATHERER)return sigc(D_GATHERER,S_FRONT,c);if(u_sig===U_REALIGN&&[U_REALIGN,U_SENTINEL].includes(c_at(c)))
if([U_REALIGN,U_SENTINEL].includes(c_at(CCW[c][7])))
return eqwatch(early_queen());var provisional=lchk(c);if(provisional!==null)return sigc(provisional,S_FRONT,c);if(this_ant().food>1)
{if(c_at(CCW[c][5])!==D_MARCH)return{cell:CCW[c][5],color:D_MARCH};return{cell:CCW[c][5],type:GATHERER};}}
break;}
if(c_at(4)!==U_PANIC)return sigc(U_PANIC,S_SIDE,c);else return opening_queen();}
function queen_march()
{var c=view_corner();switch(neighbor_type(c))
{case EE_STRAIGHT:return qwatch(qdec_ee_straight(c));case EE_BENT:return qwatch(qdec_ee_bent(c));case EC_SKEWED:return qwatch(qdec_ec_skewed(c));case EC_SPAWN:return qwatch(qdec_ec_spawn(c));case CC_EDGED:return qwatch(qdec_cc_edged(c));case THREE_MARCH:return qwatch(qdec_three_march(c));case THREE_STAND:return qwatch(qdec_three_stand(c));case THREE_RECOVER:return qwatch(qdec_three_recover(c));case THREE_UNSTAND:return qwatch(qdec_three_unstand(c));case THREE_BLOCK:return qwatch(qdec_three_block(c));case THREE_SIDE:return qwatch(qdec_three_side(c));default:return eqwatch(early_queen());}}
function queen_decision()
{marcher_count=0;gatherer_count=0;excess_gatherers=0;for(tcell of SCAN_MOVES)
{if(is_ally(tcell))
{if(view[tcell].ant.type===MARCHER_A||view[tcell].ant.type===MARCHER_B)marcher_count++;if(view[tcell].ant.type===GATHERER)
{if(EDGES.includes(tcell)||is_gatherer_marcher(tcell))gatherer_count++;else excess_gatherers++;}}
else if(is_enemy(tcell))return opening_queen();}
if(marcher_count>0&&gatherer_count===1&&excess_gatherers===0)return qwatch(queen_march());else if(marcher_count>0&&gatherer_count===0&&excess_gatherers===0)return qwatch(queen_wait());else if(gatherer_count===1&&excess_gatherers===0)return eqwatch(early_queen());else return opening_queen();}
function main_decide()
{switch(this_ant().type)
{case QUEEN:return queen_decision();case GATHERER:return gatherer_decision();case MARCHER_A:case MARCHER_B:return marcher_decision();default:return sanitize(saboteur());}}
return main_decide();

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

এই জমা দেওয়ার লক্ষ্যটি একটি পিঁপড়ির একটি লাইন তৈরি করা যা অঞ্চলটি ছড়িয়ে দিতে পারে। রং রানিকে লাইন সমন্বয় করতে সহায়তা করতে সিগন্যাল হিসাবে ব্যবহৃত হয়, ট্রেইলমার্ক হিসাবে নয়।

এই জমাটিতে রানী ছাড়াও তিন ধরণের শ্রমিক ব্যবহৃত হয়:

  • প্রকার 1: গঠনের মার্চার, একটি পর্যায়
  • প্রকার 2: গঠনের মার্চার, বি পর্ব
  • প্রকার 3: সংগ্রহকারী
  • প্রকার 4: ভবিষ্যতের ব্যবহারের জন্য সংরক্ষিত

পিঁপড়াগুলি একটি সম্পূর্ণ-প্রস্থের তির্যক রেখায় তৈরি করা হয়েছে:

    A
    BA
     BA
      BA
       BA
        BA
         BA
          QG

প্রথম চার পিঁপড়া তৈরি করা পিঁপড়ারা হ'ল একত্রিতকারী এবং মার্চার, সমান সম্ভাবনা সহ এ বা বি, তারপরে প্রতিটি একটি। তারপরে, পিঁপড়াগুলি খাদ্য সন্ধানের পরে সম্ভাব্যতার সাথে তৈরি হয়, এ এবং বি এর মধ্যে বিকল্প হয়, গঠনে, রানী সংগ্রহকারী দুটি পদক্ষেপের মধ্যবর্তী স্থির করে, সর্বশেষে তৈরি হওয়া মার্চারের উপর নির্ভর করে।

প্রাথমিক পর্যায়ে

রানী যখন প্রস্ফুটিত হয়, তখন তিনি একটি বগ স্ট্যান্ডার্ড অর্ধ লাইটস্পিডযুক্ত সোজা-লাইনের হাঁটা সঞ্চালন করেন, তার পথটি অনুসরণ না করার চেষ্টা করে। এটি একবার তার এক টুকরো খাবার পেলে, তিনি একত্রিতকারীকে উত্সাহিত করেন। 3 টুকরো খাবার সংগ্রহের পরে, প্রতিটি অতিরিক্ত খাবারের জন্য রানীর কঠোর কোডিং গঠনের রুটিনে 3 জন কর্মীর স্প্যানিংয়ের মাঝারি সম্ভাবনা থাকে এবং লাইনটি বন্ধ হয়ে যায়।

সাধারণ আচরণ

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

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

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

খাদ্য সংগ্রহ

যখন খাবারের মুখোমুখি হয়, লাইনটি থামে। তবে, যেহেতু সিগন্যালগুলি কেবল লাইটস্পিডের উজানের ব্যবস্থা করতে পারে, তাই সিগন্যালের উপরের দিকে অগ্রসর হতে সময় লাগে, যার ফলে উপরের দিকে একটি সরলরেখায় বাঁকা হয়ে যায়। প্রান্তের পিঁপড়াগুলি একটি হুকের মধ্যে বাঁকিয়ে এটিকে পুরোপুরি সোজা হতে বাধা দেয় তবে সেগুলিও থামানো হয়।

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

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

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

লাইন বন্ধ

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

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

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

অতিরিক্ত

রানী লুটপাটের কাজ চলছে। শ্রমিকরা শত্রুদের রানীদের শত্রু কর্মীদের চেয়ে খাদ্য হিসাবে স্বীকৃতি দেবে, তবে ঠিক কীভাবে এটি পরবর্তীতে অনাকাঙ্ক্ষিত এবং নিরবচ্ছিন্ন হয়।

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

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

করতে

  • লজিকাল ক্রাফ্ট পরিষ্কার করুন
  • পরীক্ষা এবং পরিশোধন রানী লুটপাট
  • শত্রু কর্মীদের কাছাকাছি যেতে পারে কিনা দেখুন
  • সিগন্যাল রাষ্ট্র হ্রাস তদন্ত
  • শেষের কর্মী উদ্দেশ্যমূলকভাবে ছাঁটাই করা সহায়তা করে কিনা দেখুন

অব্যাহতি পত্র

1.0: প্রথম সংস্করণ জমা, প্রাথমিক প্রকাশের জন্য রাখা

1.0.1: আরও নিয়ন্ত্রকের সাথে সামঞ্জস্যপূর্ণ লজিকাল হ্রাস কার্যকর করা formed

1.1: ত্রুটি মামলার সাথে সম্পর্কিত একগুচ্ছ পদার্থের সংশোধন, যুক্তিযুক্ত উন্নত

1.1.1: অযোগ্যতা সমস্যা সমাধানের জন্য হটফিক্স

১.২: আরও অচলাবস্থার সরানো হয়েছে, সাবোটিউর এখন ওভারহুল হয়েছে

১.৩: কুইন স্প্যানিং রেট হ্রাস পেয়েছে, নাশকরা একটি টিউনআপ দিয়েছেন

১.৩.১: আরও রানী স্পোনরেট হ্রাস পেয়েছে এবং একটি অযোগ্য বগকে স্থির করেছে

1.4: প্যারামিটার টিউনিং


5

স্টিম্রোলার অ্যান্টস

/*Ants will try to move diagonally in the following fashion:
 * 2
 * 51
 *
 *Type 1 and queen are the two core ants
 */


switch (view[4].ant.type) {

  case 1: //Guiding ant
    //Look for queen, try to move diagonally
    if (view[7].ant && view[7].ant.friend && view[7].ant.type === 5 && !view[8].ant) return {cell: 8};
    else if (view[5].ant && view[5].ant.friend && view[5].ant.type === 5 && !view[2].ant) return {cell: 2};
    else if (view[3].ant && view[3].ant.friend && view[3].ant.type === 5 && !view[6].ant) return {cell: 6};
    else if (view[1].ant && view[1].ant.friend && view[1].ant.type === 5 && !view[0].ant) return {cell: 0};
    else return {cell: 4};
  case 2: //Other wing
    //Look for queen, try to move diagonally. If there is food, rotate the other way to start rotating procedure
    if (view[7].ant && view[7].ant.friend && view[7].ant.type === 5 && !view[6].ant) {
      if (view[6].food) {
        if (!view[8].ant) return {cell: 8};
        else return {cell: 4};
      } else return {cell: 6};
    } else if (view[5].ant && view[5].ant.friend && view[5].ant.type === 5 && !view[8].ant) {
      if (view[8].food) {
        if (!view[2].ant) return {cell: 2};
        else return {cell: 4};
      } else return {cell: 8};
    } else if (view[3].ant && view[3].ant.friend && view[3].ant.type === 5 && !view[0].ant) {
      if (view[0].food) {
        if (!view[6].ant) return {cell: 6};
        else return {cell: 4};
      } else return {cell: 0};
    } else if (view[1].ant && view[1].ant.friend && view[1].ant.type === 5 && !view[2].ant) {
      if (view[2].food) {
        if (!view[0].ant) return {cell: 0};
        else return {cell: 4};
      } else return {cell: 2};
    } else return {cell: 4};
  case 5: //Queen ant

    //If forever alone
    if (!view[1].ant && !view[3].ant && !view[5].ant && !view[7].ant) {
      if (view[4].color === 2) { //If on colored square, try to move
        if (view[0].color === 2 && !view[8].ant) return {cell: 8};
        else if (view[2].color === 2 && !view[6].ant) return {cell: 6};
        else if (view[6].color === 2 && !view[2].ant) return {cell: 2};
        else if (view[8].color === 2 && !view[0].ant) return {cell: 0};
        //Can't find color, or path is blocked? try diagonals regardless of color
        else if (!view[0].ant) return {cell: 0};
        else if (!view[2].ant) return {cell: 2};
        else if (!view[6].ant) return {cell: 6};
        else if (!view[8].ant) return {cell: 8};
        //Everything else failed? Stay put.
        else return {cell: 4};
      } else { //If not on colored square, look for food, or set current color to 2.
        if (view[4].ant.food >= 1) { //Try to make Guiding ant
          if (!view[1].ant && !view[1].food) return {cell: 1, type: 1};
          else if (!view[3].ant && !view[3].food) return {cell: 3, type: 1};
          else if (!view[5].ant && !view[5].food) return {cell: 5, type: 1};
          else if (!view[7].ant && !view[7].food) return {cell: 7, type: 1};
        }
        for (var i = 0; i < 9; i++) { //Look for food
          if (view[i].food) return {cell: i};
        }
        return {cell: 4, color:2};
      }
    } else { //Queen has partner
      //Make other wing
      if (view[4].ant.food >= 1) {
        if (view[1].ant && view[1].ant.friend && view[1].ant.type === 1 && !view[3].ant && !view[3].food && !view[5].ant) return {cell: 3, type: 2};
        else if (view[3].ant && view[3].ant.friend && view[3].ant.type === 1 && !view[7].ant && !view[7].food && !view[1].ant) return {cell: 7, type: 2};
        else if (view[5].ant && view[5].ant.friend && view[5].ant.type === 1 && !view[1].ant && !view[1].food && !view[7].ant) return {cell: 1, type: 2};
        else if (view[7].ant && view[7].ant.friend && view[7].ant.type === 1 && !view[5].ant && !view[5].food && !view[3].ant) return {cell: 5, type: 2};
      }

      //If food is orthogonal to Queen, stay put
      if (view[1].food || view[3].food || view[5].food || view[7].food) return {cell: 4};

      //Look for guiding type 1 ant, try to move diagonally
      else if (view[7].ant && view[7].ant.friend && view[7].ant.type === 1 && !view[6].ant) return {cell: 6};
      else if (view[5].ant && view[5].ant.friend && view[5].ant.type === 1 && !view[8].ant) return {cell: 8};
      else if (view[3].ant && view[3].ant.friend && view[3].ant.type === 1 && !view[0].ant) return {cell: 0};
      else if (view[1].ant && view[1].ant.friend && view[1].ant.type === 1 && !view[2].ant) return {cell: 2};
    }
  default: return {cell: 4};
}

এই পিঁপড়াগুলি ডেভের ফরেনসিক এন্টিগুলির মতো একই ধারণা থেকে কাজ করে । যাইহোক, তারা তির্যকভাবে সরানো হয় এবং 3 টি দলে চলে।

প্রথম পর্যায়: খাবার স্ক্যামাবল

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

পর্ব 2: 2 পিঁপড়া

কুইন একটি নতুন টাইপ 1 "গাইডিং" পিঁপড়া তৈরি করে, যা রানির সাথে ভাগ করে একসাথে তির্যকভাবে স্থানান্তরিত হয়। তারা প্রত্যেকে স্বীকৃত অংশটি কীভাবে স্ব স্ব অংশীদারদের তুলনায় আপেক্ষিক।

৩ য় পর্যায়: স্টিম্রোলিং

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

ঘোরানো হচ্ছে

টাইপ 2 পিঁপড়ে যদি দেখে যে এটি কিছু খাবারের মধ্যে চলে যাবে, তবে এটি পরিবর্তে অন্য দিকে চলে যাবে, যেখানে টাইপ 1 পিঁপড়া ব্যবহৃত হত। এর অর্থ হল যে সমস্ত পিঁপড়াগুলি যেদিকে চলে সেদিকে ঘুরবে এবং তাই পিঁপড়াগুলি তাদের প্রারম্ভিক বিন্দুতে গুটিয়ে যাওয়ার খুব কম সম্ভাবনা থাকা উচিত।

দ্রষ্টব্য: যদি কোনও কারণে (অন্য কোনও পিঁপড়ার সাথে সংঘর্ষ হতে পারে?) টাইপ 2 পিঁপড়া টাইপ 1 পিঁপড়ার আগে জন্মগ্রহণ করেছিল, তবে এই ঘূর্ণনের ফলে টাইপ 2 পিঁপড়া টাইপ 1 পিঁপড়ায় যাওয়ার চেষ্টা করবে। এটি সমাধানের জন্য, টাইপ 2 পিপীলিকাটি নিজেকে পিছনে ফেলে দেয় এবং রানিকে অন্য টাইপ 2 পিপড়া তৈরি করতে দেয়।


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

@ দিকনির্দেশনা পরিবর্তন সম্পর্কে অংশটিই আমাকে চিন্তিত করে। আমি যদি আমার কোনও কর্মীকে না হারিয়ে দিক পরিবর্তন করার কোনও উপায় খুঁজে পাই তবে অবশ্যই এই ধারণাটি কার্যকর হবে। যদি তা না হয় তবে আমি কখন একজন শ্রমিকের পিছনে চলে যাব এবং রাণী পরিবর্তনের দিকনির্দেশনার জন্য একটি চিহ্নিতকারী হিসাবে রঙিন চেষ্টা করব have
কে জাং

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

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

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

5

জেলি-মাছ

function clean(move) {
    if (move["color"] == undefined) {
        if (view[move["cell"]].ant != null) {
            move = {
                cell: 4
            }
        }
        if (move["type"] == undefined) {
            if (view[4].ant.type == 5 && move["cell"] != 4 && view[move["cell"]].color > 2) {
                move["color"] = 1
            }
            if (view[move["cell"]].food == 1 && view[4].ant.type < 5 && view[4].ant.food > 0) {
                move = {
                    cell: 4
                }
            }
        } else if (view[4].ant.type != 5 || view[4].ant.food == 0 || view[move["cell"]].food != 0) {
            move = {
                cell: 4
            }
        }
    }
    return move
}

function coord(cell) {
    var x = (cell % 3) - 1
    var y = 1 - (cell - (cell % 3)) / 3
    return {
        x: x,
        y: y
    }
}

function getcell(x, y) {
    return (x + 1) + (1 - y) * 3
}

var diags = [0, 2, 8, 6]

var colorcounts = [0, 0, 0, 0, 0, 0, 0, 0, 0];
for (var i = 0; i < 9; i++) {
    colorcounts[view[i].color]++
}

var queen = -1
for (var i = 0; i < 9; i++) {
    if (view[i].ant != null && view[i].ant.friend == true && view[i].ant.type == 5) {
        queen = i
    }
}

var guard = -1
for (var i = 0; i < 9; i++) {
    if (view[i].ant != null && view[i].ant.friend == true && view[i].ant.type == 1) {
        guard = i
    }
}

var forager = -1
for (var i = 0; i < 9; i++) {
    if (view[i].ant != null && view[i].ant.friend == true && view[i].ant.type == 2) {
        forager = i
    }
}

var black = -1
for (var i = 0; i < 9; i++) {
    if (view[i].color == 8) {
        black = i
    }
}

var yellow = -1
for (var i = 0; i < 9; i++) {
    if (view[i].color == 2) {
        yellow = i
    }
}


if (view[4].ant.type == 5) {
    if (forager >= 0 && view[forager].color == 8) {
        return clean({
            cell: forager,
            color: 2
        })
    }

    if (guard == -1) {
        if (view[4].color == 3) {
            if (view[4].ant.food > 1) {
                return clean({
                    cell: 0,
                    type: 2
                })
            }
            return clean({
                cell: 0,
                type: 1
            })
        }
        if (view[4].ant.food >= 3) {
            return clean({
                cell: 4,
                color: 3
            })
        }
        if (view[4].color == 1) {
            return clean({
                cell: 4,
                color: 2
            })
        }
        for (var i = 0; i < 9; i++) {
            if (view[i].food == 1) {
                return clean({
                    cell: i
                })
            }
        }
        for (var i = 0; i < 4; i++) {
            if (view[diags[i]].color != 2 && view[diags[(i + 2) % 4]].color == 2) {
                return clean({
                    cell: diags[i]
                })
            }
        }
        return clean({
            cell: 0
        })
    }

    var state = 3
    var max = 0
    for (var i = 3; i <= 4; i++) {
        if (colorcounts[i] > max) {
            max = colorcounts[i]
            state = i
        }
    }

    if (state == 3) {
        if (black >= 0 && forager == -1) {
            return clean({
                cell: black,
                type: 2
            })
        }
        if (forager >= 0 && view[forager].color != 2) {
            return clean({
                cell: 0,
                color: 8
            })
        }
        if (colorcounts[3] == 9) {
            return clean({
                cell: 4,
                color: 4
            })
        }
    }
    if (state == 4) {
        if (colorcounts[4] == 9) {
            return clean({
                cell: 4,
                color: 3
            })
        }
    }
    return clean({
        cell: 4
    })
}
if (view[4].ant.type == 1) {
    var dest = 0
    var destmap = [1, 0, 1, 1, 4, 1, 7, 8, 7]
    dest = destmap[queen]
    if (view[queen].color != view[dest].color && (view[queen].color == view[4].color || view[4].color == view[dest].color)) {
        if (queen < 4 && view[dest].color > 2 && view[dest].color < 5) {
            return clean({
                cell: queen,
                color: view[dest].color
            })
        }
        return clean({
            cell: dest,
            color: view[queen].color
        })
    }
    return clean({
        cell: dest
    })
}
if (view[4].ant.type == 2) {
    if (queen >= 0 && view[4].color == 8) {
        return clean({
            cell: 4
        })
    }
    var state = 3
    var max = 0
    for (var i = 5; i <= 7; i++) {
        if (colorcounts[i] > max) {
            max = colorcounts[i]
            state = i
        }
    }
    var flowx = 0
    var flowy = 0
    for (var i = 0; i < 9; i++) {
        for (var j = i + 1; j < 9; j++) {
            var loci = coord(i)
            var locj = coord(j)
            var dx = locj.x - loci.x
            var dy = locj.y - loci.y
            var cyc = 0
            if (view[i].color >= 5 && view[i].color <= 7 && view[j].color >= 5 && view[j].color <= 7) {
                var cyc = ((view[j].color - view[i].color) % 3 + 3) % 3
                if (cyc == 2) {
                    cyc = -1
                }
            } else if (view[i].color >= 5 && view[i].color <= 7) {
                cyc = 0.1
            } else {
                cyc = -0.1
            }
            flowx += cyc * dx / (dx * dx + dy * dy)
            flowy += cyc * dy / (dx * dx + dy * dy)

        }
    }
    if (flowx * flowx > flowy * flowy) {
        flowy = 0
    } else {
        flowx = 0
    }
    if (flowx < 0) {
        flowx = -1
    }
    if (flowy < 0) {
        flowy = -1
    }
    if (flowx > 0) {
        flowx = 1
    }
    if (flowy > 0) {
        flowy = 1
    }
    if (queen >= 0) {
        var locq = coord(queen)
        flowx = -locq.x
        flowy = -locq.y
        state = 5
    }
    if (view[4].ant.food > 0) {
        if (guard >= 0) {
            var destmap = [1, 0, 1, 1, 4, 1, 7, 8, 7]
            return clean({
                cell: destmap[guard]
            })
        }
        dest = getcell(-flowx, -flowy)
        if (dest != 7) {
            dest = 1
        }
        if (view[dest].color >= 5 && view[dest].color <= 7) {
            return clean({
                cell: dest
            })
        }
        if (view[dest - 1].color >= 5 && view[dest - 1].color <= 7) {
            return clean({
                cell: dest - 1
            })
        }
        return clean({
            cell: 4
        })
    }
    if (view[4].color >= 5 && view[4].color <= 7) {
        state = view[4].color
    }
    var nextc = ((state - 4) % 3 + 5)
    var prevc = ((state - 3) % 3 + 5)
    var centerdest
    centerdest = getcell(flowx, flowy)
    if (view[centerdest].color != state && view[centerdest].color != nextc) {
        return clean({
            cell: centerdest,
            color: nextc
        })
    }
    for (var dest = 1; dest < 9; dest++) {
        var locd = coord(dest)
        var net = locd.x * flowx + locd.y * flowy
        if (net > 0 && view[dest].color != view[centerdest].color) {
            return clean({
                cell: dest,
                color: view[centerdest].color
            })
        }
    }
    for (var dest = 0; dest < 9; dest++) {
        if (view[dest].food == 1) {
            if (view[dest].color >= 5 && view[dest].color <= 7) {
                return clean({
                    cell: dest
                })
            }
            return clean({
                cell: dest,
                color: state
            })
        }
    }
    if (centerdest == 4 && view[0].color >= 5 && view[0].color <= 7) {
        return clean({
            cell: 0
        })
    }
    if (centerdest > 0 && view[centerdest - 1].color >= 5 && view[centerdest - 1].color <= 7) {
        return clean({
            cell: centerdest - 1
        })
    }
    return clean({
        cell: centerdest
    })
}

এই বট ... ভাল না, তবে এটি বেশ কয়েকটি দুর্দান্ত কৌশল ব্যবহার করে যা আমি মনে করি আমার ভবিষ্যতের পিঁপড়ির বটগুলিতে অন্তর্ভুক্ত হবে। এর নামটি কলোনিটি গেম বোর্ডে তৈরি করা আকার থেকে আসে।

পদক্ষেপে মেডুসা

প্রথম পর্যায়: প্রাথমিক বিনিয়োগ

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

দ্বিতীয় ধাপ: উপনিবেশ

এখানে, তিন ধরণের পিঁপড়া বিভিন্ন ভূমিকা পালন করে:

রাণী

প্রহরীর সহায়তায় রানী আস্তে আস্তে দুটি রাজ্যের মধ্যে দোলা দেয়। বর্তমান অবস্থা এটিই নির্ধারণ করে যে কোনও নতুন প্রাপ্ত খাবারের টুকরোগুলিকে শ্রমিক হিসাবে পরিণত করা হবে কি না, সুতরাং প্রায় 50% খাবার কলোনীতে পুনরায় বিনিয়োগ করা হয়। রানীযুক্ত পুরো 3x3 অঞ্চলটি স্টোর সংরক্ষণ করতে ব্যবহৃত হয়, যাতে কোনও ক্ষয়কে পূর্বাবস্থায় ফেরা যায় এবং রাজ্য পুনরুদ্ধার করা যায়।

পাহারা

রক্ষী তার পুরো জীবন রানির সাথে সংলগ্নভাবে বেঁচে থাকে, এলোমেলোভাবে এটি প্রদক্ষিণ করে।

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

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

Foragers

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

একটি পালকের সাধারণ পথ:

ফোরগার পথ

লক্ষ্য করুন কীভাবে এটি সাধারণত একটি সরলরেখায় ভ্রমণ করে তবে মাঝে মধ্যে 90 ডিগ্রি পরিণত হয়। এটি এলোমেলোভাবে যেভাবে নিজের পাথের উপরে শুয়ে রয়েছে তার ফল এটি।


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

@ পেপারি কখনও কখনও এটি করে।
ফিনটপি

কেবলমাত্র r-> b-> g-> r চক্রটি চালিয়ে শ্রমিকদের আরও দক্ষতার সাথে ফিরিয়ে আনা সম্ভব হবে?
ক্যালকুলেটরফলাইন

@ থ্রিচোপ্লেক্স আমি বুঝতে পারি নি যে এটি এমন কিছু যা করার অনুমতি দেওয়া হয়নি। যাইহোক এখনই স্থির।
ফিনটপি

এটি "অযোগ্যতা" এর অধীনে ছিল: "একজন শ্রমিক উত্পাদন করার সেলটি খালি নয়" " তবে আমি এখন এটিকে কিছুটা আরও সুস্পষ্ট করে তোলার লক্ষ্যে সম্পাদনাটি সম্পাদনা করেছি: "একজন শ্রমিক উত্পাদন করার সেলটি খালি নয় (এতে খাবার বা পিঁপড় রয়েছে)"।
ট্রাইকোপ্লেক্স

5

ব্রাউনিয়ান জিগ

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

উত্তরের প্রথম কোড ব্লকটি স্বয়ংক্রিয়ভাবে গেমটিতে অন্তর্ভুক্ত:

// Full version that won't be disqualified for moving onto another ant

// Move to food if visible
for (var i=0; i<9; i+=1) {
    if (view[i].food) {
        return {cell:i}
    }
}

// Otherwise move to one of the diagonal cells if not occupied
for (var i=0; i<9; i+=2) {
    if (!view[i].ant) {
        return {cell:i}
    }
}

// Otherwise one of the vertical or horizontal cells if not occupied
for (var i=1; i<9; i+=2) {
    if (!view[i].ant) {
        return {cell:i}
    }
}

// Otherwise don't move at all
return {cell:4}

এখানে একটি সহজ সংস্করণ যা অন্যান্য পিঁপড়াদের জন্য যাচাই করে না, তবে অন্য পিঁপড়ার দিকে পা রাখার চেষ্টা করে অযোগ্য হয়ে উঠা অবধি অবধি অভিন্ন আচরণ রয়েছে:

// Basic version for an intuitive understanding

// Move to food if visible
for (var i=0; i<9; i+=1) {
    if (view[i].food) {
        return {cell:i}
    }
}

// Otherwise move "up and left", which will be a random direction
return {cell:0}

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

ইনপুটটির এলোমেলো অভিযোজন সত্ত্বেও সরলরেখার গতিবিধি উত্পাদন করার উদাহরণের জন্য দেখুন রোমানেসকো রোড


এটি রঙ চিহ্নিত করার প্রয়োজন হয় কেন?
সলোমন উকো

1
ভাল প্রশ্ন. নিয়ম বাছাইতে লোকদের কিছু দেওয়ার জন্য এটি কেবলমাত্র একটি প্রাথমিক উদাহরণ। এটি কেবল কোনও রঙ চিহ্নিত না করে দ্বিগুণ স্কোর করতে পারে, তবে উদাহরণ হিসাবে আমি চেয়েছিলাম যে এর পথটি বোঝার জন্য স্পষ্টভাবে দৃশ্যমান হোক।
ট্রাইকোপ্লাক্স

আমি দেখছি, বোধ হয়।
সলোমন উকো

আমি এখন রঙিন চিহ্নটি মুছে ফেলার জন্য সম্পাদনা করেছি, কারণ এটি ছিল একটি অপ্রয়োজনীয় (এবং অতিরিক্ত কাজ) dist রানী দৃশ্যমান হলে এখন খাবারে চলে যাবে এবং আরও জমি coverাকতে তির্যক পদক্ষেপের পক্ষে হবে। কোনও রঙই ব্যবহার হয় না।
ট্রাইকোপল্যাক্স

4

লা রেইন ব্লিও

var Queen = 5;
var QueenTrail = [];
var EnemyAnts = [];
var EnemyColors = [];
var QueenTrailColor = 7;
var QueenTrailColor2 = 8;
var QueensPosition = -1; //Future use...

var rotations =   
[ 0,1,2,
  3,4,5,
  6,7,8,

  6,3,0,
  7,4,1,
  8,5,2,

  8,7,6,
  5,4,3,
  2,1,0,

  2,5,8,
  1,4,7,
  0,3,6];

var moves = [];
getMoves();
return findBestMove();

function getMoves()
{
    var matchIdx = -1;
    //Initialization of current state
    for(ii = 0; ii < 9; ii++)
    {
        if(ii != 4)
        {
            if(view[ii].color == QueenTrailColor)
            {
                QueenTrail.push(ii);
            }
            else if(view[ii].color == QueenTrailColor2)
            {
                QueenTrail.push(ii);
            }
            else if(view[ii].color != 1)
            {
                EnemyColors.push(ii);
            }
        }

        if(ii != 4 && view[ii].ant != null)
        {
            if(view[ii].ant.friend)
            {
                if(view[ii].ant.type == Queen)
                {
                    QueensPosition = ii * ii;
                }
            }
            else
            {
                EnemyAnts.push(ii);
            }
        }
    }

    switch (view[4].ant.type) 
    {
        case Queen:
        {        
            //first get the food
            for (var ii = 0; ii < 9; ii++) 
            {
                if (view[ii].food > 0 && view[ii].ant == null) 
                {
                    moves.push(getCell(ii)) ;
                }
            }
            if(EnemyAnts.length == 0)
            {
                lm(AA(-QueenTrailColor),AA(4), {cell:4, color:QueenTrailColor});
            }

            if(QueenTrail.length >= 5 || EnemyAnts.length > 0)
            {
                lm(AA(-QueenTrailColor), AA(0,1,2),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,1,3),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,1,5),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,1,6),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,1,7),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,1,8),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,2,3),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,2,6),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,2,7),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,3,7),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,3,8),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,5,7),{cell:0});
                lm(AA(-QueenTrailColor), AA(1,2,7),{cell:1});
                lm(AA(-QueenTrailColor), AA(1,3,5),{cell:1});
                lm(AA(-QueenTrailColor), AA(0,1),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,2),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,3),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,5),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,7),{cell:0});
                lm(AA(-QueenTrailColor), AA(0,8),{cell:0});
                lm(AA(-QueenTrailColor), AA(1,3),{cell:1});
                lm(AA(-QueenTrailColor), AA(1,7),{cell:1});
            }
            if(QueenTrail.length == 4)
            {
                lmQT(AA(0,1,2,3),{cell:7});
                lmQT(AA(0,1,2,5),{cell:7});
                lmQT(AA(0,1,2,6),{cell:7});
                lmQT(AA(0,1,2,7),{cell:5});
                lmQT(AA(0,1,2,8),{cell:7});
                lmQT(AA(0,1,3,5),{cell:7});
                lmQT(AA(0,1,3,7),{cell:8});
                lmQT(AA(0,1,3,8),{cell:2});
                lmQT(AA(0,1,5,6),{cell:8});
                lmQT(AA(0,1,5,7),{cell:6});
                lmQT(AA(0,1,5,8),{cell:3});
                lmQT(AA(0,1,6,7),{cell:8});
                lmQT(AA(0,1,6,8),{cell:2});
                lmQT(AA(0,1,7,8),{cell:2});
                lmQT(AA(0,2,3,7),{cell:8});
                lmQT(AA(0,2,3,8),{cell:6});
                lmQT(AA(0,2,6,8),{cell:1});
                lmQT(AA(0,3,5,7),{cell:2});
                lmQT(AA(0,3,5,8),{cell:2});
                lmQT(AA(1,3,5,7),{cell:0});
            }
            if(QueenTrail.length == 1)
            {                
                lmQT(AA(0), {cell:8});
                lmQT(AA(1), {cell:7});
            }
            else if(QueenTrail.length == 0)
            {
                moves.push(getCell(1));
            }

            if(QueenTrail.length == 0) // starting out or someone is messing with us
            {
                moves.push( getCellColor(1, QueenTrailColor));
            }    
            else if (QueenTrail.length >= 5) //queen is stuck? move her randomly until we get a straight trail
            {    
                moves.push( getCellColor(1, QueenTrailColor2));
            }
            else if (QueenTrail.length >= 3)
            {
                lmQT(AA(0,1,2),{cell:3});
                lmQT(AA(0,1,3),{cell:7});
                lmQT(AA(0,1,5),{cell:3});
                lmQT(AA(0,1,6),{cell:7});
                lmQT(AA(0,1,7),{cell:3});
                lmQT(AA(0,1,8),{cell:3});
                lmQT(AA(0,2,3),{cell:6});
                lmQT(AA(0,2,6),{cell:3});
                lmQT(AA(0,2,7),{cell:1});
                lmQT(AA(0,3,7),{cell:8});
                lmQT(AA(0,3,8),{cell:5});
                lmQT(AA(0,5,7),{cell:6});
                lmQT(AA(1,2,7),{cell:0});
                lmQT(AA(1,3,5),{cell:6});
            }
            else if(QueenTrail.length == 2)
            {
                lmQT(AA(0,1),{cell:7});
                lmQT(AA(0,2),getCellColor(1, QueenTrailColor));
                lmQT(AA(0,3),{cell:6});
                lmQT(AA(0,5),{cell:1});
                lmQT(AA(0,7),{cell:3});
                lmQT(AA(0,8),{cell:3});
                lmQT(AA(1,3),{cell:6});
                lmQT(AA(1,7),{cell:0});
            }
            else if(QueenTrail.length == 1) //we are either going in a straight line or trapped?
            {    
                if(view[4].ant.food > 0)
                {
                    lmQT(AA(0), getCell(0));
                    //clear out the area for the ants
                    if(EnemyColors.length > 0)
                    {
                        moves.push( getCellColor(EnemyColors[0],1));
                    }
                }
                lmQT(AA(0), getCell(8));
                lmQT(AA(1), getCell(7));
                lmQT(AA(2), getCell(6));
            }
            break;
        }
    }
    moves.push( getCell(4));
}

function leftOfPos(x)
{
    if (x == 0)
    {
        return 3;
    }
    else if (x == 1)
    {
        return 0;
    }
    else if (x == 2)
    {
        return 1;
    }
    else if (x == 3)
    {
        return 6;
    }
    else if (x == 5)
    {
        return 2;
    }
    else if (x == 6)
    {
        return 7;
    }
    else if (x == 7)
    {
        return 8;
    }
    else if (x == 8)
    {
        return 5;
    }
}

function findBestMove() 
{
    var keeper = 0;
    for(var ii = 0; ii < moves.length ; ii++)
    {
        if(moves[ii].cell < 0 || moves[ii].cell > 8 || (moves[ii].cell != 4 && (moves[ii].color == null || moves[ii].color == 0) && view[moves[ii].cell].ant != null) || (view[moves[ii].cell].food > 0 && (view[4].ant.food > 0 && view[4].ant.type < 5))) 
        {
            continue;
        }
        else if(moves[ii].type != null && (view[moves[ii].cell].ant != null || view[moves[ii].cell].food > 0 || view[0].color == 1)) //semi random here. 
        {
            continue;
        }
        else
        {
            keeper = ii;
            break;
        }
    }
    return moves[keeper];
}

function lm(matchingColors, coords, matchCell)
{
    var matchTarget = coords.length ;
    var matchCount = [0,0,0,0];
    var returnVal = -1;
    for(var ii = 0; ii < coords.length; ii++)
    {        
        for(var jj = 0; jj < 4; jj++)
        {
            var actualIndex = rotations[coords[ii] + (jj * 9)];
            var foundMatch = false;
            for(var kk = 0; kk < matchingColors.length; kk++)
            {
                var matchingColor = matchingColors[kk];

                if(matchingColor >= 1 && matchingColor <= 8 && view[actualIndex].color == matchingColor)
                {
                    foundMatch = true;
                    break;
                }    
                else if(matchingColor < 0 && view[actualIndex].color != -matchingColor)
                {
                    foundMatch = true;
                    break;
                }
            }
            if(foundMatch)
            {
                matchCount[jj] = matchCount[jj] + 1;
                if(matchCount[jj] == matchTarget)
                {
                    matchCell.cell = rotations[matchCell.cell + (jj * 9)];
                    moves.push(matchCell);
                    returnVal = jj;
                }
            }
        }
    }
    return returnVal;
}

function lmQT(coords, matchCell)
{
    return lm(AA(QueenTrailColor, QueenTrailColor2), coords,matchCell);
}

function AA()
{
    return arguments;
}

function getCell(x)
{
    return {cell:x};
}

function getCellColor(x, y)
{
    return {cell:x, color:y};
}

নীল রানী একটি নীল পথ ছেড়ে যাবে, তিনি কালো এড়ানো এবং 'আটকে' থাকলে কালো টুকরো টুকরো করে ফেলে।

তিনি সমস্ত চারটি ঘূর্ণন ব্যবহার করে নির্দিষ্ট নীল / কালো "আকার" অনুসন্ধান করেন এবং সম্ভাব্য পদক্ষেপের একটি তালিকা তৈরি করেন। অযোগ্য ঘোষণাগুলি সরানো হয় এবং একক ফলাফল চয়ন করা হয় result রানী কিছুটা অনুমানযোগ্য তবে নির্দিষ্ট আকারগুলি এলোমেলো কারণ ঘটায়। প্রথমে খাবারটি আবিষ্কার করার পরে সে দিকনির্দেশ পরিবর্তন করবে যে অভিমুখীকরণটি পরিবর্তিত হবে যা প্রথমে আবিষ্কার হয়।


3
সাইটে স্বাগতম! :)
DJMcMayhem

এখানে থাকা ভাল!
কিছু রানার লোক

4

FireFlyMkII

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

    // maps current view's cells' indecies to the rotated cell's location's indecies for each direction
    var rotate = 
            [[0,1,2,3,4,5,6,7,8],
             [2,5,8,1,4,7,0,3,6],
             [8,7,6,5,4,3,2,1,0],
             [6,3,0,7,4,1,8,5,2]];

    // the colours that form the pattern of the trail back to the queen
    var TRAIL_COLOR_A = 8;
    var TRAIL_COLOR_B = 2;
    var TRAIL_COLOR_C = 5;
    var trailColours = [TRAIL_COLOR_A,TRAIL_COLOR_B,TRAIL_COLOR_C];
    var trailColoursLookUp = [-1,-1,1,-1,-1,2,-1,-1,0];

    var ORIENTATION_MARKER = 8;

    // Queens Modes
    var QUEEN_MODE_HUNTING_MOVING = 6;
    var QUEEN_MODE_HUNTING_PAINTING = 1;
    var QUEEN_MODE_RESETTING = 5;
    var QUEEN_MODE_RESETTING_SPAWNING = 3;
    var QUEEN_MODE_COUNTING_EVEN = 7;
    var QUEEN_MODE_COUNTING_ODD = 4;
    var QUEEN_MODE_NESTING = 2;

    // the number of non-blank (i.e. not colour 1 ) colours to used to encode the queen's worker spawn counter. Min of 1. Max of 7
    var SPAWN_COUNTER_NON_BLANK_COLOURS_COUNT = 7;


    // the maximum number that can be encoded using the queen's worker spawn counter
    var SPAWN_COUNTER_MAX = SPAWN_COUNTER_NON_BLANK_COLOURS_COUNT*SPAWN_COUNTER_NON_BLANK_COLOURS_COUNT*SPAWN_COUNTER_NON_BLANK_COLOURS_COUNT -1;//SPAWN_COUNTER_NON_BLANK_COLOURS_COUNT * SPAWN_COUNTER_USED_CELLS_COUNT_MAX;

    // the minimum game ticks between spawning a worker. Min of 0, Max of SPAWN_COUNTER_MAX
    var TICKS_BETWEEN_FOOD_RETURN_MAX = 50;

    // No Operation... i.e. stay put do nothing
    var NO_OP = {cell:4};

    var ANT_TYPE_WORKER = 1; 
    var ANT_TYPE_QUEEN = 5;

    var orientationMarkerRotation = -1;

    var i=0;
    var j=0;

    // returns true of the provided colour is a trail colour
function isTrailColour(colour)
    {
        return colour === trailColours[0] || colour === trailColours[1] || colour === trailColours[2];
    }

    // returns the colour of the colour in the trail away from queen
function nextTrailColor(currentTrailColour)
    {
        return trailColours[(trailColoursLookUp[currentTrailColour]+1)%3];
    }

    // returns the colour of the colour in the trail toward from queen
function prevTrailColor(currentTrailColour)
    {
        return trailColours[(3+trailColoursLookUp[currentTrailColour]-1)%3];
    }

    // RNG
function randomNumberGenerator(seed)
    {
        return (1103515245 * seed + 12345) % 2147483647;
    }

    // returns a positive random integer based on the provided ant's view and seed
function randomInt(view,seed)
    {
        for (var i=0;i<9;i++)
        {
            if (view[i].ant !=null)
            {
                seed=randomNumberGenerator(seed+view[i].ant.food);
                seed=randomNumberGenerator(seed+view[i].ant.type);
                seed=randomNumberGenerator(seed+(view[i].ant.friend?1:0));
            }
            seed=randomNumberGenerator(seed+view[i].color);
            seed=randomNumberGenerator(seed+view[i].food);
        }
        return seed<0?-seed:seed;
    }

    // SHUFFLE *NOT* IMPLEMENTED 
function shuffleIndecies(view,seed,range)
    {
        var indecies = new Array(range);

        for (var i=0;i<range;i++)
        {
            indecies[i]=i;
        }

        return indecies;
    }

function processOrientation(view)
    {
        // count orientation markers
        var orientationMarkerCount = 0;
        for (var i=0; i<rotate.length;i++)
        {
            if (view[rotate[i][1]].color === ORIENTATION_MARKER)
            {
                orientationMarkerCount++;
                orientationMarkerRotation = i;
            }
        }

        // corruption detected
        if (orientationMarkerCount >1)
        {
            return {cell:4, color: QUEEN_MODE_RESETTING};
        }

        // place the orientation marker
        if (orientationMarkerCount === 0)
        {
            return {cell:1, color: ORIENTATION_MARKER};
        }
        return null;
    }

function incrementSpawnCounter(view)
    {
        var action = processOrientation(view);
        if (action != null)
        {
            return action;
        }

        var newCount = decodeThreeCellsToInt(view) + 1;

        var MSD = view[rotate[orientationMarkerRotation][3]].color-1;
        var NSD = view[rotate[orientationMarkerRotation][7]].color-1;
        var LSD = view[rotate[orientationMarkerRotation][5]].color-1;

        var MSDisEven =(MSD & 1) ===0;
        var NSDisEven =(NSD & 1) ===0; 

        var MSDdelta =  Math.floor(newCount / 49) - MSD;
        var NSDdelta =  (MSDisEven ? Math.floor(Math.floor(newCount%49)/7) :( 6 - Math.floor(Math.floor(newCount%49)/7))) - NSD;
        var LSDdelta =  (((MSDisEven && NSDisEven) || (!MSDisEven && !NSDisEven)) ? Math.floor(newCount%7) :( 6 - Math.floor(newCount%7))) - LSD;

        // check for roll over 
        if (MSDdelta > 6)
        {
            return {cell:rotate[orientationMarkerRotation][3], color:1};
        }

        // Most Significant Digit (cell) update
        if (MSDdelta != 0)
        {
            return {cell:rotate[orientationMarkerRotation][3], color:(MSD+MSDdelta)+1};
        }

        // Next Significant Digit (cell) update
        if (NSDdelta != 0)
        {
            return {cell:rotate[orientationMarkerRotation][7], color:(NSD+NSDdelta)+1};
        }

        // Least Significant Digit (cell) update
        if (LSDdelta != 0)
        {
            return {cell:rotate[orientationMarkerRotation][5], color:(LSD+LSDdelta)+1};
        }

        return null;
    }

function decodeThreeCellsToInt(view)
    {
        var MSD = view[rotate[orientationMarkerRotation][3]].color-1;
        var NSD = view[rotate[orientationMarkerRotation][7]].color-1;
        var LSD = view[rotate[orientationMarkerRotation][5]].color-1;

        var MSDisEven =(MSD & 1) ===0;
        var NSDisEven =(NSD & 1) ===0; 
        return MSD * 49 + 
               (MSDisEven?NSD:6-NSD) * 7 + 
               ((MSDisEven && NSDisEven) || (!MSDisEven && !NSDisEven)?LSD:6-LSD);
    }
    // Performs a paint command to reset the queen's worker spawn counter to 0.
    // NOTE that is may take multiple calls on sequential game ticks to complete the reset.
    // returns null if the counter is reset
function resetSpawnCounter(view)
    {
        var orientationMarkerCount = 0;
        for (i=1; i<9; i+=2) 
        {
            if (view[i].color === ORIENTATION_MARKER && orientationMarkerCount ===0)
            {
                orientationMarkerCount++;
            }
            else if (view[i].color!=1)
            {
                return {cell:i, color:1};
            }
        }

        // place the orientation marker
        if (orientationMarkerCount === 0)
        {
            return {cell:1, color: ORIENTATION_MARKER};
        }

        return null;
    }


function spawnNewWorker(view,type,defaultAction)
    {
        // ensure that we do not try and create a worker when having no food
        if (view[4].ant.food > 0)
        {
            // now try to spawn an ant
            if (view[1].ant===null && view[1].food===0)
            {
                return {cell:1, type:type};
            }

            // previous spawn cell was blocked, try another 
            if (view[3].ant===null && view[3].food===0)
            {
                return {cell:3, type:type};
            }

            // previous spawn cell was blocked, try another
            if (view[5].ant===null && view[5].food===0)
            {
                return {cell:5, type:type};
            }

            // previous spawn cell was blocked, try another
            if (view[7].ant===null && view[7].food===0)
            {
                return {cell:7, type:type};
            }
        }
        return defaultAction;
    }

function isCellTrailToQueen(cell,currentAntCellColour)
    {
        // is cell containing our queen, or is the cell the next cell colour on the trail back
        return (cell.ant!=null && cell.ant.friend && cell.ant.type === ANT_TYPE_QUEEN) ||
                cell.color === prevTrailColor(currentAntCellColour);
    }

    // entry point into ant logic
function getAction(view)
    {
        var random = 1;
        var food = view[4].ant.food;
        var currentCellColour = view[4].color;

/////////////////////////////////////// QUEEN ///////////////////////////////////////
        if (view[4].ant.type === ANT_TYPE_QUEEN)
        {
            // move to visible food. this queen is greedy!
            for (i=0; i<9; i++) 
            {
                if (view[i].food>0) {
                    return {cell:i};
                }
            }

            // see if we have spawned a worker in the last few turns
            var workerSpawned = false;
            // look in orthogonal cells
            for (i=1; i<9; i+=2) 
            {
                // ant detected and is friendly and of worker type
                if (view[i].ant !=null && view[i].ant.friend && view[i].ant.type===ANT_TYPE_WORKER)
                {
                    workerSpawned=true;
                    break;
                }
            }

            var queenMode = currentCellColour;
            var foodModRemainder=1;

            var minFoodLatch = 0;
            if (food>=500) minFoodLatch = 500;
            else if (food>=400) minFoodLatch = 400;
            else if (food>=300) minFoodLatch = 300;
            else if (food>=200) minFoodLatch = 200;
            else if (food>=100) minFoodLatch = 100;
            else if (food>=50) minFoodLatch = 50;
            else if (food>=20) minFoodLatch = 30;
            else if (food>=20) minFoodLatch = 20;
            else if (food>=10) minFoodLatch = 10;
            else if (food>=5) minFoodLatch = 5;

            switch (queenMode)
            {
                case QUEEN_MODE_HUNTING_MOVING:
                {


                    // move to the cell mirror of the trail cell
                    for (i=0; i<9; i++) {
                        if (view[i].ant===null && view[i].color===QUEEN_MODE_HUNTING_MOVING) {
                            if (view[8-i].ant==null)
                            {
                                return {cell:8-i};
                            }
                        }
                    }

                    // Otherwise move to one of the diagonal cells if not occupied
                    for (i=0; i<9; i+=2) 
                    {
                        if (view[i].ant===null) 
                        {
                            return {cell:i};
                        }
                    }

                    // Otherwise move to one of the vertical or horizontal cells if not occupied
                    for (i=1; i<9; i+=2)
                    {
                        if (view[i].ant===null)
                        {
                            return {cell:i};
                        }
                    }
                    return {cell:4};
                }
                case QUEEN_MODE_HUNTING_PAINTING:
                {
                    // no food found, change to move mode
                    if (food ===0)
                    {
                        // Queenie places a trail
                        return {cell:4, color:QUEEN_MODE_HUNTING_MOVING};
                    }
                    // found food, now change to nesting mode
                    else
                    {
                        return {cell:4, color:QUEEN_MODE_NESTING};
                    }
                }

                // initialise colony
                case QUEEN_MODE_NESTING:
                {
                    // we have spawned a worker so change to counting mode
                    if (workerSpawned===true)
                    {
                        return {cell:4, color:QUEEN_MODE_COUNTING_ODD};
                    }

                    var action = processOrientation(view);
                    if (action != null)
                    {
                        return action;
                    }

                    // ensure that we have the initial band constructed around the queen
                    for (i=0; i<9; i+=2) 
                    {
                        if (i!=4 && view[i].color!=TRAIL_COLOR_A)
                        {
                            return {cell:i, color:TRAIL_COLOR_A};
                        }
                    }

                    // ensure that the counter cells are reset.
                    action = resetSpawnCounter(view);
                    if (action != null)
                    {
                        return action;
                    }

                    // spawn initial worker
                    return spawnNewWorker(view, ANT_TYPE_WORKER, NO_OP);
                }


                case QUEEN_MODE_RESETTING_SPAWNING:

                    // spawn the worker if we have not spawned a worker in the last few turns 
                    if (!workerSpawned===true)
                    {
                        return spawnNewWorker(view, ANT_TYPE_WORKER, NO_OP);
                    }
                    // must have spawned a worker previously, so reset the counter 
                    var action = resetSpawnCounter(view);

                    // still in process of resetting counter...
                    if (action != null)
                    {
                        return action;
                    }


                    // spawn counter as been reset. We will set the queen back to counting mode;
                    return {cell:4, color:food%2===0?QUEEN_MODE_COUNTING_EVEN:QUEEN_MODE_COUNTING_ODD};

                case QUEEN_MODE_RESETTING:

                    action = resetSpawnCounter(view);

                    // still in process of resetting counter...
                    if (action != null)
                    {
                        return action;
                    }


                    // spawn counter as been reset. We will set the queen back to counting mode;
                    return {cell:4, color:food%2===0?QUEEN_MODE_COUNTING_ODD:QUEEN_MODE_COUNTING_EVEN};

                case QUEEN_MODE_COUNTING_ODD:
                    foodModRemainder = 2;
                case QUEEN_MODE_COUNTING_EVEN:
                {
                    foodModRemainder--;

                    action = processOrientation(view);
                    if (action != null)
                    {
                        return action;
                    }

                    var spawnCounter = decodeThreeCellsToInt(view);

                    // repair any damage to the initial band constructed around the queen
                    for (i=0; i<9; i+=2) 
                    {
                        if (i!=4 && view[i].color!=TRAIL_COLOR_A)
                        {
                            return {cell:i, color:TRAIL_COLOR_A};
                        }
                    }

//                    // spawn interval time threshold as been reached and we have food to convert into workers...
//                    if (spawnCounter>=TICKS_BETWEEN_FOOD_RETURN_MAX && food>minFoodLatch)
//                    {
//                        // change to reset spawn counter mode to spawn a new worker
//                        return new Paint(4,QUEEN_MODE_RESETTING_SPAWNING);
//                    }
//
//                    // Check to see if a worker has just returned some food.
//                    if (food>0 && food%2 == foodModRemainder)
//                    {
//                        // change to reset spawn counter mode
//                        return new Paint(4,QUEEN_MODE_RESETTING);
//                    }

                    // Check to see if a worker has just returned some food.
                    if (food>0 && food%2 === foodModRemainder)
                    {

                        // spawn interval time threshold as been reached and we have food to convert into workers...
                        if (spawnCounter>=TICKS_BETWEEN_FOOD_RETURN_MAX && food>0)
                        {
                            // change to reset spawn counter mode to spawn a new worker
                            return {cell:4, color:QUEEN_MODE_RESETTING_SPAWNING};
                        }

                        // change to reset spawn counter mode
                        return {cell:4, color:QUEEN_MODE_RESETTING};
                    }


                    if (spawnCounter < SPAWN_COUNTER_MAX)
                    {
                        // simply increment the counter
                        return incrementSpawnCounter(view);
                    }

                    return NO_OP;
                }
                default:
                {
                }

            }


        }

/////////////////////////////////////// WORKER ///////////////////////////////////////



        var expectedNextPathColourToEdge = nextTrailColor(currentCellColour);

        // worker is looking for food
        if (food===0)
        {
/////////////////////////////////// WORKER HUNTNING //////////////////////////////////    

            // determine whether we are a recently spawned worker
            for (var i=1;i<9;i+=2)
            {
                // are we orthogonal to the queen?
                if (view[i].ant!=null && view[i].ant.friend && view[i].ant.type === ANT_TYPE_QUEEN)
                {
                    // test to see whether queen's counter has reset so worker is free to move
                    if (view[i].color === QUEEN_MODE_COUNTING_ODD || view[i].color === QUEEN_MODE_COUNTING_EVEN )
                    {
                        for (var j=1;j<9;j+=2)
                        {
                            if (view[j].ant===null && view[j].color===TRAIL_COLOR_A)
                            {
                                return {cell:j};
                            }
                        }
                    }
                    // wait until queen's counter has reset
                    return NO_OP;
                }
            }

//            // this is to try and unstick stuck ants... not overly well i might add
//            if (randomInt(view,1)%20==1)
//            {
//                // attempt to pick an empty random trail-cell
//                for (i = randomInt(view,666)%9;i>0;i--)
//                {
//                    if (view[i].ant==null && view[i].food==0 && isTrailColour(view[i].color))
//                    {
//                        return new Move(i);
//                    }
//                }
//            }

            // see if there is any food off band that is enclosed or almost enclosed by trail cells
            // if so, then move to claim the food
            if (view[1].food>0 &&
                isTrailColour(view[0].color) &&
                isTrailColour(view[2].color))
            {
                return {cell:1};
            }

            if (view[3].food>0 &&
                isTrailColour(view[0].color) &&
                isTrailColour(view[6].color))
            {
                return {cell:3};
            }

            if (view[5].food>0 &&
                isTrailColour(view[2].color) &&
                isTrailColour(view[8].color))
            {
                return {cell:5};
            }

            if (view[7].food>0 &&
                isTrailColour(view[6].color) &&
                isTrailColour(view[8].color))
            {
                return {cell:7};
            }


            // if not on trail, attempt see if cells surrounding are trail colours... and set our own cell accordingly
            if (!isTrailColour(currentCellColour))
            {
                for (var priority = 0; priority <4;priority++)
                {
                    // repeat for each rotation
                    var indecies = shuffleIndecies(view,random,4);
                    for (var j=0;j<4;j++)
                    {
                        var r = indecies[j];
                        switch(priority)
                        {
                        // C??  ...
                        // ???  .P.
                        // P?N  ...
                        case 0:
                            if (isTrailColour(view[rotate[r][0]].color) && 
                                nextTrailColor(view[rotate[r][0]].color) === view[rotate[r][8]].color &&
                                prevTrailColor(view[rotate[r][0]].color) === view[rotate[r][6]].color)
                            {
                                return {cell:4, color: view[rotate[r][6]].color};
                            }
                            break;

                        // ??C  ...
                        // ???  .C.
                        // N?C  ...
                        case 1:
                            if (isTrailColour(view[rotate[r][2]].color) && 
                                view[rotate[r][2]].color === view[rotate[r][8]].color &&
                                nextTrailColor(view[rotate[r][2]].color) === view[rotate[r][6]].color)
                            {
                                return {cell:4, color: view[rotate[r][2]].color};
                            }
                            break;

                        // C??  ...
                        // ???  .C.
                        // P??  ...
                        case 2:
                            if (isTrailColour(view[rotate[r][0]].color) && 
                                prevTrailColor(view[rotate[r][0]].color) === view[rotate[r][6]].color)
                            {
                                return {cell:4, color: view[rotate[r][0]].color};
                            }
                            break;

                        // C??  ...
                        // ???  .C.
                        // ???  ...
                        case 3:
                            if (isTrailColour(view[rotate[r][0]].color))
                            {
                                return {cell:4, color: view[rotate[r][0]].color};
                            }
                            break;
                        }
                    }
                }
                // we are completely lost! lets perform a random walk and hopefully find the surface again
                return {cell:view[2].ant === null?2:4};
            }

            // decide worker action...
            for (var priority = 0; priority <13;priority++)
            {
                // repeat for each rotation
                var indecies = shuffleIndecies(view,random,4);
                for (var j=0;j<4;j++)
                {
                    var r = indecies[j];
                    var cellToMoveTo =-1;

                    switch(priority)
                    {
                    /////// AVOID MOVING/PAINTING LOCK-STEP ///////

                    // X?X  ...
                    // ?C?  .M.
                    // C?W  ...

                    case 0:
                        if (view[rotate[r][6]].color === currentCellColour &&
                            !isTrailColour(view[rotate[r][0]].color) &&
                            !isTrailColour(view[rotate[r][2]].color) &&
                            view[rotate[r][8]].ant!=null &&
                            view[rotate[r][8]].ant.type!=ANT_TYPE_QUEEN) 
                        {
                            // step back on path back to queen
                            return NO_OP;
                        }
                        break;

                    /////// REPAIR PATH ///////

                    // P?X  ..C
                    // ?C?  ...
                    // C??  ...

                    case 1:
                        if (view[rotate[r][2]].color != currentCellColour &&
                            view[rotate[r][6]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][0]],currentCellColour))
                        {
                            return {cell:rotate[r][2], color:currentCellColour};
                        }
                        break;

                    // ??C  N..
                    // ?C?  ...
                    // X?P  ...

                    case 2:
                        if (view[rotate[r][2]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][8]],currentCellColour) &&
                            !isTrailColour(view[rotate[r][6]].color) &&
                            view[rotate[r][0]].color != expectedNextPathColourToEdge)
                        {
                            return {cell:rotate[r][0], color:expectedNextPathColourToEdge};
                        }
                        break;

                    // C?N  ...
                    // ?C?  .N.
                    // ??P  ...

                    case 3:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            view[rotate[r][2]].color === expectedNextPathColourToEdge &&
                            isCellTrailToQueen(view[rotate[r][8]],currentCellColour))
                        {
                            return {cell:4, color:expectedNextPathColourToEdge};
                        }
                        break;

                    // C??  N..
                    // ?C?  ...
                    // ??P  ...

                    case 4:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][8]],currentCellColour))
                        {
                            return {cell:rotate[r][0], color:expectedNextPathColourToEdge};
                        }
                        break;

                    /////// MOVING ///////

                    // C?P  ...
                    // ?C?  ...
                    // ??C  N..
                    case 5:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            view[rotate[r][8]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][2]],currentCellColour) &&
                            view[rotate[r][6]].color != expectedNextPathColourToEdge)
                        {

                            if (view[rotate[r][6]].ant === null)
                            {
                                return {cell:rotate[r][6], color:expectedNextPathColourToEdge};
                            }
                            else
                            {
                                return NO_OP;
                            }
                        }
                        break;

                    // C?P  ...
                    // ?C?  ...
                    // N?C  M..
                    case 6:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            view[rotate[r][8]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][2]],currentCellColour) &&
                            view[rotate[r][6]].color === expectedNextPathColourToEdge)
                        {
                            cellToMoveTo = rotate[r][6];
                        }
                        break;

                    // Special case. we need to first paint the cell prior to moving other wise will cause corruption
                    // C??  ...
                    // ?C?  ...
                    // C??  ..N
                    case 7:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            view[rotate[r][6]].color === currentCellColour &&
                            view[rotate[r][8]].color != expectedNextPathColourToEdge)
                        {
                            if (view[rotate[r][8]].ant === null)
                            {
                                return {cell:rotate[r][8], color:expectedNextPathColourToEdge};
                            }
                            else
                            {
                                return NO_OP;
                            }
                        }
                        break;
                    // C??  ...
                    // ?C?  ...
                    // C?N  ..M
                    case 8:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            view[rotate[r][6]].color === currentCellColour &&
                            view[rotate[r][8]].color === expectedNextPathColourToEdge)
                        {
                            cellToMoveTo = rotate[r][8];
                        }
                        break;
                    // C??  ..M
                    // ?C?  ...
                    // P?C  ...
                    case 9:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            view[rotate[r][8]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][6]],currentCellColour))
                        {
                            cellToMoveTo = rotate[r][2];
                        }
                        break;
                    // C??  ...
                    // ?C?  ...
                    // P??  ..M
                    case 10:
                        if (view[rotate[r][0]].color === currentCellColour &&
                            isCellTrailToQueen(view[rotate[r][6]],currentCellColour))
                        {
                            cellToMoveTo = rotate[r][8];
                        }
                        break;
                    // C??  ...
                    // ?C?  ...
                    // ???  M..
                    case 11:
                        if (view[rotate[r][0]].color === currentCellColour)

                        {
                            cellToMoveTo = rotate[r][6];
                        }
                        break;
                    // ???  ...
                    // ?C?  ...
                    // P??  ?.M
                    case 12:
                        if (isCellTrailToQueen(view[rotate[r][6]],currentCellColour))

                        {
                            cellToMoveTo = rotate[r][8];
                        }
                        break;
                    }
                    if (cellToMoveTo>-1)
                    {
                        return {cell:view[cellToMoveTo].ant === null?cellToMoveTo:4};
                    }
                }
            }
            return NO_OP;
        }

        // worker is transporting food
        else
        {
            // worker deadlock avoidance
            for (i=0; i<9; i+=2)
            {
                // does the cell have another ant in it?
                if (i!=4 && view[i].ant!=null && !(view[i].ant.type===ANT_TYPE_QUEEN && view[i].ant.friend))
                {
                    // attempt to pick an empty random trail-cell
                    for (i = randomInt(view,54321)%9;i>0;i--)
                    {
                        if (view[i].ant===null && view[i].food===0 && isTrailColour(view[i].color))
                        {
                            return {cell:i};
                        }
                    }

                    // no luck... just pick a random empty cell
                    for (i = randomInt(view,12345)%9;i>0;i--)
                    {
                        if (view[i].ant===null && view[i].food===0)
                        {
                            return {cell:i};
                        }
                    }

                    // deadlock unavoidable!
                    return NO_OP;
                }
            }

//            // this is to try and unstick stuck ants
//            if (randomInt(view,1)%20==1)
//            {
//                // attempt to pick an empty random trail-cell
//                for (i = randomInt(view,666)%9;i>0;i--)
//                {
//                    if (view[i].ant==null && view[i].food==0 && isTrailColour(view[i].color))
//                    {
//                        return new Move(i);
//                    }
//                }
//            }


            // decide move action
            for (var priority = 0; priority <14;priority++)
            {
                // repeat for each rotation
                var indecies = shuffleIndecies(view,random,4);
                for (var j=0;j<4;j++)
                {
                    var r = indecies[j];
                    var cellToMoveTo =-1;

                    switch(priority)
                    {
                        // PRE-EMPTIVE PATH PRUNING

                    // C?X  X..
                    // ?X?  ...
                    // P?X  ...
                    case 0:
                        if (isTrailColour(view[rotate[r][0]].color) &&
                            !isTrailColour(view[rotate[r][2]].color) &&
                            !isTrailColour(view[rotate[r][4]].color) && 
                            prevTrailColor(view[rotate[r][0]].color) === view[rotate[r][5]].color)
                        {
                            return {cell:rotate[r][0], color: 1};
                        }
                        break;


                        // ?C?  ...
                        // CXN  X..
                        // ?X?  ...
                        case 1:
                            if (!isTrailColour(view[rotate[r][4]].color) &&
                                !isTrailColour(view[rotate[r][7]].color) &&
                                isTrailColour(view[rotate[r][1]].color) && 
                                view[rotate[r][3]].color === view[rotate[r][1]].color &&
                                nextTrailColor(view[rotate[r][1]].color) === view[rotate[r][5]].color)
                            {
                                return {cell:rotate[r][3], color: 1};
                            }
                            break;

                        // ?C?  ...
                        // PXC  ..X
                        // ?X?  ...
                        case 2:
                            if (!isTrailColour(view[rotate[r][4]].color) &&
                                !isTrailColour(view[rotate[r][7]].color) &&
                                isTrailColour(view[rotate[r][1]].color) && 
                                view[rotate[r][5]].color === view[rotate[r][1]].color &&
                                prevTrailColor(view[rotate[r][1]].color) === view[rotate[r][3]].color)
                            {
                                return {cell:rotate[r][5], color: 1};
                            }
                            break;

                        // N??  ..N
                        // ?C?  ...
                        // C?C  ...

                        case 3:
                            if (isTrailColour(view[rotate[r][4]].color) &&
                                view[rotate[r][2]].color != expectedNextPathColourToEdge &&
                                view[rotate[r][8]].color === currentCellColour &&
                                view[rotate[r][0]].color === expectedNextPathColourToEdge &&
                                view[rotate[r][6]].color === currentCellColour)
                            {
                                return {cell:rotate[r][2], color:expectedNextPathColourToEdge};
                            }
                            break;

                        // N??  ...
                        // ?X?  .C.
                        // C?C  ...


                        case 4:
                            if (!isTrailColour(view[rotate[r][4]].color) && 
                                isTrailColour(view[rotate[r][8]].color) &&
                                view[rotate[r][0]].color === nextTrailColor(view[rotate[r][8]].color) &&
                                view[rotate[r][8]].color === view[rotate[r][6]].color)
                            {
                                return {cell:rotate[r][4], color:view[rotate[r][8]].color};
                            }
                            break;

                        // N??  ..C
                        // ?C?  ...
                        // C?P  ...

                        case 5:
                            if (isTrailColour(view[rotate[r][4]].color) && 
                                view[rotate[r][0]].color === expectedNextPathColourToEdge &&
                                view[rotate[r][6]].color === currentCellColour &&
                                isCellTrailToQueen(view[rotate[r][8]],currentCellColour) &&
                                view[rotate[r][2]].color != currentCellColour)
                            {
                                return {cell:rotate[r][2], color:currentCellColour};
                            }
                            break;

                        // C?N  ...
                        // ?X?  .N.
                        // ??P  ...

                        case 6:
                            if (!isTrailColour(view[rotate[r][4]].color) && 
                                isTrailColour(view[rotate[r][0]].color) && 
                                view[rotate[r][2]].color === nextTrailColor(view[rotate[r][0]].color) &&
                                view[rotate[r][8]].color === prevTrailColor(view[rotate[r][0]].color))
                            {
                                return {cell:rotate[r][4], color:nextTrailColor(view[rotate[r][0]].color)};
                            }
                            break;

                        // ??P  ...
                        // ?X?  .N.
                        // ??N  ...

                        case 7:
                            if (!isTrailColour(view[rotate[r][4]].color) && 
                                isTrailColour(view[rotate[r][2]].color) &&
                                nextTrailColor(view[rotate[r][2]].color) === view[rotate[r][8]].color)
                            {
                                return {cell:4, color:view[rotate[r][8]].color};
                            }
                            break;



                        // if we are on the corner of a trail band... move opposite to the apex
                        case 8:
                            if (isTrailColour(currentCellColour) &&
                                view[rotate[r][0]].color === currentCellColour &&
                                view[rotate[r][2]].color === currentCellColour)
                            {
                                if (randomInt(view,currentCellColour)%2 === 0)
                                {
                                    cellToMoveTo = rotate[r][0];
                                }
                                else
                                {
                                    cellToMoveTo = rotate[r][2];
                                }
                            }
                            break;

                        // if we on the opposite corner of a trail band... move back toward the apex
                        case 9:
                            if (isTrailColour(currentCellColour) &&
                                isCellTrailToQueen(view[rotate[r][0]],currentCellColour) &&
                                isCellTrailToQueen(view[rotate[r][2]],currentCellColour))
                            {
                                if (randomInt(view,currentCellColour)%2 === 0)
                                {
                                    cellToMoveTo = rotate[r][0];
                                }
                                else
                                {
                                    cellToMoveTo = rotate[r][2];
                                }
                            }
                            break;
                        // if an adjacent cell is a trail to the queen, move that way
                        case 10:
                            if (isTrailColour(currentCellColour) &&
                                isCellTrailToQueen(view[rotate[r][0]],currentCellColour))
                            {
                                cellToMoveTo = rotate[r][0];
                            }
                            break;
                        // if we are not on a trail and an adjacent cell is a trail, then move that way
                        case 11:
                            if (!isTrailColour(currentCellColour) && isTrailColour(view[rotate[r][8]].color))
                            {
                                cellToMoveTo = rotate[r][8];
                            }
                            break;
                        // are we on a cell between trail cells? if so then move onto a cell on the trail.
                        case 12:
                            if (isTrailColour(view[rotate[r][1]].color))
                            {
                                cellToMoveTo = rotate[r][1];
                            }
                            break;
                        // are we on a terminal trail cell? if so then move onto a cell on the trail.
                        case 13:
                            if (isTrailColour(view[rotate[r][0]].color))
                            {
                                cellToMoveTo = rotate[r][0];
                            }
                            break;

                    }
                    if (cellToMoveTo>-1)
                    {
                        if (view[cellToMoveTo].ant != null || view[cellToMoveTo].food > 0) continue;
                        return {cell:cellToMoveTo};
                    }
                }
            }
            return NO_OP;
        }

    }

    return getAction(view);

সংস্করণ 1

version1

এই প্রবেশের মূল ভিত্তিটি চিরকাল বিস্তৃত বর্গাকার সর্পিল অনুসন্ধান করবে। অনুসন্ধান বর্গ পরিধি পরিসীমা দ্রুত খাদ্য সরবরাহ এবং ঘেরে ফিরে যাওয়ার অনুমতি দেয় একটি তিনটি ব্যান্ড পুনরাবৃত্তি প্যাটার্ন তৈরি করবে।

ক্লাসিক ধাঁধা গেম বোল্ডারড্যাশের "অগ্নিনির্বাপক" শত্রু থেকে প্রবেশের নাম রয়েছে, তিনটি বর্ণের পুনরাবৃত্তি শত্রুর স্মরণ করিয়ে দেয়।

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

তবে পরবর্তী সংস্করণের জন্য আমি মনে করি আমি মৌলিকভাবে উপায় পরিবর্তন করব এবং পিঁপড়াগুলি সরিয়ে / পেইন্ট অর্ডার করব: পেইন্ট থেকে তারপর সরান, সরানোর পরে রঙ করুন। যদিও আমি নিশ্চিত হতে পারি না, আমি মনে করি কোষের রঙের প্যাটার্নের কিছু দুর্নীতি এমন কোষ থেকে ঘটছে যাগুলিতে পিঁপড়াগুলি সংলগ্ন পিঁপড়ার দ্বারা পুনরায় আঁকানো হচ্ছে। অর্ডার পরিবর্তন করা সেই ঝুঁকি হ্রাস করতে সহায়তা করবে ... তবে পেইন্টিংয়ের আগে আরও জটিল / ঝুঁকিপূর্ণ স্থানান্তরিত হবে।

সংস্করণ 2

সংস্করণ 2

এই সংস্করণটি উন্নততর, এটি এখন কর্মী পিঁপড় প্রতি ধাপে আরও অনুসন্ধানের জন্য 45 ডিগ্রি ঘোরানো হয়।

এটি এখন খাদ্য সংগ্রহ করে (এটি যদি বিঘ্নিত না হয়)

এটি অবশ্য মজবুত নয় এবং সহজেই পিঁপড়ের অন্যান্য ট্রেইলে বাধা হয়ে যায়। সুতরাং এটি বর্তমানে দাঁড়িয়ে হিসাবে এটি একটি ভাল প্রতিযোগী না।

তবে যখন একা ছেড়ে যায়, তখন এটি 300 জন শ্রমিকের সাথে সংগ্রহ করা গড় 700 টি খাবার।

সংস্করণ 2.1

কোনও খাবার না খেয়ে রানী কোনও কর্মী তৈরি করার চেষ্টা করবেন না তা নিশ্চিত করার জন্য সংযোজন তদন্ত যুক্ত করা হয়েছে।

সংস্করণ 2.1.1

২.১-এ স্থির করা হয়েছে (আমি আসলে পিঁপড়ার দৃষ্টিতে "খাদ্য" ক্ষেত্রটি ব্যবহার করি নি এবং তাই কোনও নাল বস্তুর উল্লেখ করছি।

সংস্করণ 2.1.1.1

/ আমার হাতে মাথা লুকায়

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

সংস্করণ ২.২

অবৈধ স্প্যান বাগটি পুনরায় পরিচয় করিয়ে দেওয়ার স্থির অনুলিপি অনুলিপি

সংস্করণ 2.2.1

শুরুতে স্থির সম্ভাব্য অবৈধ পদক্ষেপ যখন রানী খাবারের প্রথম টুকরোটি আবিষ্কার করার চেষ্টা করছে তখন স্ক্যাম্বল হয়ে যায়।


আপনার কৌশলটিও জিগুরাত: চুরির মতো একই দুর্বলতায় ভুগছে। আমি প্রায় 90 সেকেন্ডের মধ্যে ফায়ারফ্লিকে লক্ষ্য করতে ভ্যাম্পায়ারের জিগুরাত সনাক্তকরণ কোডটি টুইঙ্ক করতে পারি। এটি আক্ষরিকভাবে "কোডের 60 টি লাইন অনুলিপি করুন, কোডের 60 লাইন পেস্ট করুন, 3 নম্বর পরিবর্তন করুন"। যদিও, আমি এর পরিবর্তে জিগুরুরাট-আইডি কোডটি মডুলার তৈরি করতে পছন্দ করব ("এই রঙগুলির সাথে এটি করুন")।
ড্রাকো

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

@ ড্রাকো 18 হ্যাঁ, এই প্রাথমিক সংস্করণটির সাথে কয়েকটি ত্রুটি রয়েছে :-) তবে এটি থেকে শুরু করার জায়গা। চুরির হুমকির বিষয়ে: আমি এমন একটি প্রহরী পিপড়া তৈরির পরিকল্পনা করছি যা শত্রু চুরির রানি এবং "চুরি" করতে চাইবে। এটি ক্ষতি হ্রাস করা উচিত।
মোগি

ওহ, আমি বুঝতে পারি এটি শুরু করার জায়গা, কিছু পর্যবেক্ষণ করে। :)
Draco18s

1
হয়ে গেছে? আমি কি ভিতরে গিয়ে ভ্যাম্পিরিক ব্যাট দিয়ে জায়গাটি ভাঙতে পারি? : ডি
ড্রাকো

4

Mandelbrant

আমার সমস্ত উত্তরগুলিতে ফর্মিক ফাংশন ফ্রেমওয়ার্ক আকারে অনুরূপ নিম্ন-স্তরের যুক্তি রয়েছে।

"হাই-লেভেল লজিক স্টার্টস এখানে" ফ্রেমওয়ার্কের কোডটির সমাপ্তি চিহ্নিত করে।

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

// FORMIC FRAMEWORK \\
//  Version 7.0.4   \\
const QUEEN = 5;
const HERE = view[4];
const ME = HERE.ant;
const ORTHOGONALS = [1, 3, 5, 7];
const DIAGONALS = [0, 2, 6, 8];
const DIAGONALS_ORTHOGONALS = [0, 2, 6, 8, 1, 3, 5, 7];
const DIRECTIONS = [0, 1, 2, 3, 5, 6, 7, 8];
const CLOCKWISE_DIRECTIONS = [0, 1, 2, 5, 8, 7, 6, 3];
const ROTATIONS = [
    [0, 1, 2,
     3, 4, 5,
     6, 7, 8],

    [6, 3, 0,
     7, 4, 1,
     8, 5, 2],

    [8, 7, 6,
     5, 4, 3,
     2, 1, 0],

    [2, 5, 8,
     1, 4, 7,
     0, 3, 6]
];
const NEIGHBORS = [
    [1, 4, 3],
    [2, 5, 4, 3, 0],
    [5, 4, 1],
    [0, 1, 4, 7, 6],
    [0, 1, 2, 5, 8, 7, 6, 3],
    [8, 7, 4, 1, 2],
    [3, 4, 7],
    [6, 3, 4, 5, 8],
    [7, 4, 5]
];
const HORIZONTAL_FLIP = [2, 1, 0, 5, 4, 3, 8, 7, 6];
const VERTICAL_FLIP = [6, 7, 8, 3, 4, 5, 0, 1, 2];

const DEBUG_MODE = false;
const log = DEBUG_MODE ? console.log : () => { };

function cells(...indices) {
    return indices.map(i => view[i]);
}
function colors(...indices) {
    return cells(...indices).map(c => c.color);
}
function ants(...indices) {
    return cells(...indices).map(c => c.ant);
}

function isColor(color, index) {
    return view[index].color === color;
}
function isAnyColor(colors, index) {
    return colors.includes(view[index].color);
}
function hasFood(index) {
    return view[index].food === 1;
}
function hasAnt(qualifies, index) {
    const a = view[index].ant;
    return a && (!(qualifies instanceof Function) || qualifies(a));
}
function hasFriend(type, index) {
    return hasAnt(a => a.friend && (!type || a.type === type), index);
}
const hasAnyFriend = bind(hasFriend, null);
function bind(f, ...args) {
    return f.bind(null, ...args);
}

function noTransform() {
    return { revert() { }, detransformAction() { } };
}
function indexTransform(indices) {
    const revertedIndices = new Array(9);
    for (let i = 0; i < 9; ++i) {
        revertedIndices[indices[i]] = i;
    }

    view = indices.map(index => view[index]);

    return { revert() { view = revertedIndices.map(index => view[index]); }, detransformAction(action) { action.cell = indices[action.cell]; } };
}

const rotationTransformers = [noTransform, ...ROTATIONS.slice(1).map(r => bind(indexTransform, r))];

function bestTransformers(transformers, scorer) {
    let bestScore = 0;
    const bestIndices = [];
    const bestTransformers = [];
    for (let i = 0; i < transformers.length; ++i) {
        const t = transformers[i];
        const {revert} = t();
        const score = scorer();
        revert();
        if (score > bestScore) {
            bestScore = score;
            bestIndices.length = 0;
            bestTransformers.length = 0;
        }
        if (score >= bestScore) {
            bestIndices.push(i);
            bestTransformers.push(t);
        }
    }

    return {score: bestScore, indices: bestIndices, transformers: bestTransformers};
}
function* withBestTransformation(transformers, scorer, continuation) {
    const best = bestTransformers(transformers, scorer);
    if (best.score > 0) {
        const {revert, detransformAction} = best.transformers[0]();
        for (const output of continuation(best)) {
            if (isAction(output)) {
                detransformAction(output);
            }
            yield output;
        }
        revert();
    }
}
const withBestRotation = bind(withBestTransformation, rotationTransformers);

const wait = {cell: 4};
function move(index) {
    return index >= 0 && index < 9 && view[index].ant === null && (view[index].food === 0 || ME.food === 0 || ME.type === QUEEN) ? { cell: index } : null;
}
function moveMany(...indices) {
    return indices.map(move);
}
function paint(color, index) {
    return index >= 0 && index < 9 && color >= 1 && color <= 8 && view[index].color !== color ? { cell: index, color } : null;
}
function paintMany(colors, ...indices) {
    return pairMap(indices, colors, paint);
}
function spawn(type, index) {
    return index >= 0 && index < 9 && view[index].ant === null && view[index].food === 0 && ME.food > 0 && ME.type === QUEEN && type >= 1 && type <= 4 ? { cell: index, type } : null;
}
function spawnMany(types, ...indices) {
    return pairMap(indices, types, spawn);
}
function pairMap(mainArr, sideArr, func) {
    return mainArr.map((v, i) => func(sideArr[i % sideArr.length], v));
}

function isAction(value) {
    return value instanceof Object && value.cell !== undefined; // TODO: Make this more strict.
}

log('=== start logic ===');
for (const output of main()) {
    if (isAction(output)) {
        log('=== end logic ===');
        return output;
    }
}

throw 'Decision was omitted.';

function* main() {
    // HIGH-LEVEL LOGIC STARTS HERE \\

    // TARGET SIZE:  2^21 pixels -- SUPPORTED
    // STRETCH GOAL: 2497 x 996
    // MAX POSSIBLE: 2500 x 1000

    // How long the painting triplet will go on for until they begin returning to the shifting station.
    // This value should not exceed 997 for the painter to work in all cases, or 2497 if you don't care about being positioned vertically.
    // It also shouldn't be too low. The exact lowest value is unclear, but it's likely to be in the teens.
    const LENGTH = 6 * 11;

    // Which function will be used for painting in the pixels.
    const getPictureColorAt = mandelbrot;

    function notReallyRainbow(index) {
        return index % 6 + 2;
    }
    function fromColorString(index) {
        // Input your own color string ({ a, b, c, d, e, f, g, h } => { 8, 7, 6, 4, 5, 3, 2, 1 }).
        const colorString = '';

        return [8, 7, 6, 4, 5, 3, 2, 1][colorString.charCodeAt(index % colorString.length) - 'a'.charCodeAt(0)];
    }
    function mandelbrot(index) {
        const ESCAPE = 2 ** 2, MAX_I = 8 * 10 - 1;
        const x0 = (index % LENGTH) / (LENGTH - 1) * 3 - 2, y0 = Math.floor(index / LENGTH) / (Math.floor(LENGTH * 2 / 3) - 1) * 2 - 1;
        let x = 0, y = 0;
        for (let i = 0; i < MAX_I; ++i) {
            [x, y] = [x * x - y * y + x0, 2 * x * y + y0];
            if (x * x + y * y > ESCAPE) {
                return (i + 1) % 8 + 1;
            }
        }
        return 8;
    }

    // WARNING! Beyond likely lies awful code.
    // There are no more tunable parameters.
    // Continue reading at your own risk.

    const L1_OVERFLOW = 4096;
    const FILL_ORDER_INDEX = [1, 2, 3, 6];
    const FILL_ORDER_DIGIT = [0, 1, 2, 4];

    function parseNumber(...indices) {
        return indices.reduceRight((a, index) => (a << 3) + (index !== -1 ? view[index].color - 1 : 0), 0);
    }

    function colorAtDigit(n, d) {
        return ((n >>> (d * 3)) & 7) + 1;
    }

    function paintPictureFragment(number) {
        log(`initialized painter with ${number}`);
        return paint(getPictureColorAt(number), 0);
    }

    const COPIER = 1;
    const COUNTER = 2;
    const MAJOR = 3;
    const MINOR = 4;

    function* moveWait(index) {
        yield move(index);
        yield wait;
    }

    log(`type: ${ME.type}`);
    switch (ME.type) {
        case COPIER: {
            yield* withBestRotation(() => Math.max(hasFriend(QUEEN, 7) + hasFriend(MINOR, 3), hasFriend(QUEEN, 6) + hasFriend(MINOR, 0)) - 1, bind(moveWait, 5));
            yield* withBestRotation(bind(hasFriend, COUNTER, 7), function*() {
                if ([6, 3].findIndex(hasAnyFriend) === -1) {
                    yield paint(8, 3);
                    yield move(3);
                }
                yield wait;
            });
            yield* withBestRotation(bind(hasFriend, COUNTER, 8), function*() {
                const targetIndex = FILL_ORDER_INDEX[view[4].color - 3];
                yield paint(view[5].color, targetIndex);
                yield wait;
            });
            yield wait;
        }

        case COUNTER: {
            yield* withBestRotation(() => hasFriend(COPIER, 2) + hasFriend(MAJOR, 0) - 1, bind(moveWait, 5));
            yield* withBestRotation(bind(hasFriend, COPIER, 1), function*() {
                if (hasFriend(MAJOR, 0)) {
                    yield paint(view[6].color, 8);
                }
                yield wait;
            });
            yield* withBestRotation(bind(hasFriend, COPIER, 0), function*() {
                if (!hasAnyFriend(6)) {
                    const progress = view[0].color;
                    if (progress === 8) {
                        const number = parseNumber(8, 7, 4, 1) + 1;
                        yield* paintMany([1, 2, 3].map(bind(colorAtDigit, number)), 3, 5, 2);
                        yield paint(7, 0);
                    } else if (progress === 7) {
                        const number = parseNumber(8) + 1;
                        yield paint(colorAtDigit(number, 0), 4);
                        yield paint(6, 0);
                    } else {
                        const number = parseNumber(...progress === 6 ? [4, 3] : [7, 8], 5, 2) * LENGTH;
                        if (progress > 2) {
                            if (progress === 6) {
                                yield* paintMany(colors(4, 3), 7, 8);
                            } else if (progress === 5) {
                                yield* paintMany([5, 6].map(bind(colorAtDigit, number)), 3, 4);
                            }
                            yield paint(colorAtDigit(number, FILL_ORDER_DIGIT[progress - 3]), 1);
                            if (progress !== 3) {
                                yield paint(progress - 1, 0);
                            } else {
                                yield paint(number + 1 === L1_OVERFLOW ? 2 : 1, 0);
                            }
                        } else {
                            yield paint(colorAtDigit(number, 3), 1);
                            yield wait;
                        }
                    }
                }
            });
            yield wait;
        }

        case MAJOR: {
            yield* withBestRotation(bind(hasFriend, COPIER, 5), bind(moveWait, 6));
            yield* withBestRotation(() => hasFriend(QUEEN, 7) + hasFriend(MINOR, 1) - 1, bind(moveWait, 5));
            yield* withBestRotation(bind(hasFriend, QUEEN, 2), bind(moveWait, 1));
            yield* withBestRotation(bind(hasFriend, MINOR, 2), function*() {
                const number = parseNumber(-1, -1, -1, -1, 3, 4, 5) + (isColor(2, 1) ? L1_OVERFLOW : 0);
                yield* paintMany([4, 5, 6].map(bind(colorAtDigit, number)), 6, 7, 8);
                yield move(7);
            });
            yield wait;
        }

        case MINOR: {
            yield* withBestRotation(() => hasFriend(COPIER, 8) + hasFriend(QUEEN, 6) - hasFriend(MAJOR, 3) - 1, bind(moveWait, 7));
            yield* withBestRotation(() => hasFriend(MAJOR, 6) + hasFriend(QUEEN, 7) - 1, bind(moveWait, 3));
            yield* withBestRotation(() => hasFriend(MAJOR, 8) - hasFriend(QUEEN, 7), bind(moveWait, 5));
            yield* withBestRotation(() => hasFriend(MAJOR, 7) + hasFriend(QUEEN, 5) - 1, bind(moveWait, 1));
            yield* withBestRotation(bind(hasFriend, QUEEN, 6), function*() {
                if (hasFriend(MAJOR, 3)) {
                    yield wait;
                }
                const number = parseNumber(0, 1) + 1;
                yield* paintMany([0, 1].map(bind(colorAtDigit, number)), 3, 4);
                yield move(7);
            });
            yield wait;
        }

        case QUEEN: {
            if (DIRECTIONS.some(hasAnyFriend)) {
                yield* withBestRotation(bind(hasFriend, COPIER, 5), function*() {
                    if (!hasFriend(COUNTER, 7)) {
                        yield spawn(COUNTER, 8);
                    }
                    if (!hasFriend(MAJOR, 3) && !hasFriend(MAJOR, 0)) {
                        yield spawn(MAJOR, 6);
                    }
                    yield spawn(MINOR, 0);
                    if (!hasFriend(MAJOR, 0) && hasFriend(MAJOR, 3)) {
                        yield move(7);
                    }
                    yield wait;
                });

                yield* withBestRotation(bind(hasFriend, MAJOR, 2), function*() {
                    if (!hasFriend(MINOR, 8)) {
                        yield move(1);
                    }
                    yield wait;
                });

                yield* withBestRotation(bind(hasFriend, MINOR, 0), function*() {
                    if (hasFriend(MAJOR, 3)) {
                        yield move(1);
                        yield wait;
                    } else if (hasFriend(MAJOR, 6)) {
                        yield wait;
                    }
                });

                yield* withBestRotation(bind(hasFriend, MAJOR, 7), function*() {
                    if (!hasFriend(COPIER, 6)) {
                        yield paintPictureFragment(parseNumber(1, 2, 3, 5, 6, 7, 8));
                    }
                    yield wait;
                });

                yield* withBestRotation(bind(hasFriend, MINOR, 5), function*() {
                    if (isColor(3, 4)) {
                        const number = parseNumber(1, 2, 3, 5) + 1;
                        yield* paintMany([colorAtDigit(number, 2), number + 1 === L1_OVERFLOW ? 2 : 1, colorAtDigit(number, 3)], 6, 7, 8);
                        yield move(7);
                        yield wait;
                    } else {
                        const number = parseNumber(1, 2, 3, 5, 6, 7, 8);
                        yield paintPictureFragment(number);
                        if ((number + 1) % LENGTH === 0) {
                            yield move(8);
                            yield wait;
                        }
                        yield paint(3, 4);
                    }

                    throw 'illogical failure 1';
                });

                throw 'illogical failure 2';
            }

            yield* moveMany(...DIAGONALS_ORTHOGONALS.filter(hasFood));

            if (ME.food >= 4) {
                yield* spawnMany([COPIER], ...ORTHOGONALS);
            }

            yield* moveMany(...DIAGONALS_ORTHOGONALS.filter(bind(isColor, 1)), ...DIAGONALS_ORTHOGONALS); // TODO: Watch out for accidental entrapment.
            yield wait;
        }
    }
}

দরদালান

ম্যান্ডেলব্রোট পূর্ণ ক্ষুদ্র ম্যান্ডেলব্রোট


ব্যাখ্যা

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

ধাপ 1

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

দশা ২

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

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

3 পিঁপড়া (রানী এবং 2 শ্রমিক) পেইন্টিং লুপে যায়। এগুলি তাদের সাথে রঙের আকারে একটি 21-বিট (7 কোষ * 3 বিট প্রতি সেল) পূর্ণসংখ্যার বহন করে, যা পছন্দসই কোনও চিত্রের সূচীতে ব্যবহৃত হতে পারে। ডিফল্টরূপে, এই চিত্রটি ম্যান্ডেলব্রোট সেট। তদ্ব্যতীত, শীর্ষ-বাম ঘরটি পিক্সেল আঁকার জন্য সংরক্ষিত রয়েছে, এবং কেন্দ্রীয় ঘরটি এই ব্যাখ্যার আওতার বাইরে থাকা বিষয়গুলির জন্য সংরক্ষিত। ত্রিপলিটিকে তাদের গাইড করার জন্য কোনও রঙের প্রয়োজন নেই, যেহেতু তারা একে অপরকে খুঁজে বের করে প্রাচ্যকরণটি বের করে। প্রতিটি চক্র তারা পূর্ণসংখ্যাটি 1 টি সেল দ্বারা নীচের দিকে স্থানান্তর করে, প্রতিবার যখন এটি করে তখন এটি 1 দ্বারা বাড়িয়ে দেওয়া নিশ্চিত করে। আঁকা লাইনটির শেষে পৌঁছে গেলে লুপটি শেষ হয়, যা দ্বারা কনফিগার করা হয়LENGTHধ্রুব। এই মুহুর্তে, একটি 3-পিঁপড় সমন্বিত নৃত্য শুরু হয় এবং এর ফলশ্রুতি ত্রয়ীর একটি বিশ্রী প্রত্যাবর্তন কনফিগারেশনে শেষ হয়। নৃত্যের সময় রানীও ডান একটি কোষে স্থানান্তরিত হয়। পিঁপড়ার জোড়ায় অপেক্ষা না করা পর্যন্ত তারা উপরের দিকে যাত্রা করে।

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

তিনটি পিঁপড়া জুটিতে ফিরে আসে এবং আবার 5-পিঁপড়া নাচ শুরু করে যখন চক্রটি সম্পূর্ণ হয়।


এই এন্ট্রি পরামিতি বৈশিষ্ট্য। এটি বর্তমানে একটি ক্ষুদ্র ম্যান্ডেলব্রোট সেট আঁকার জন্য সুরযুক্ত। আপনি LENGTHছবিটির সামঞ্জস্য করতে পারেন , চিত্রের পেন্টিং ফাংশনটি সরিয়ে নিতে পারেন বা এমনকি নিজের রোল করতে পারেন। আনন্দ কর!

প্রস্তাবিত নিয়ামক: ডিজাইমার


পরিবর্তণের

সংস্করণ 1.0

  • প্রাথমিক প্রকাশ

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

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

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

1
কেন? কেন? কেন আপনি এই করবেন? ক্রিকি, এই চ্যালেঞ্জের উত্তর পোস্ট হয়েছে যখন আমি তিনটি আলাদা চাকরিতে
ড্রাকো 18

1
@ ড্রাকো 18 গুলি আমি এই চ্যালেঞ্জটিকে খুব বেশি ভালবাসি: পি
অ্যালিয়ন

3

একাকী নেকড়ে

আমার সমস্ত উত্তরগুলি একই স্তরের নিম্ন-স্তরের সহায়ক ফাংশনগুলি ভাগ করে নিচ্ছে। এই উত্তরের নির্দিষ্ট কোডটি দেখতে "উচ্চ-স্তরের যুক্তি এখানে সন্ধান করুন" অনুসন্ধান করুন।

// == Shared low-level helpers for all solutions ==

var QUEEN = 5;

var WHITE = 1;
var COL_MIN = WHITE;
var COL_LIM = 9;

var CENTRE = 4;

var NOP = {cell: CENTRE};

var DIR_FORWARDS = false;
var DIR_REVERSE = true;
var SIDE_RIGHT = true;
var SIDE_LEFT = false;

function sanity_check(movement) {
  var me = view[CENTRE].ant;
  if(!movement || movement.cell < 0 || movement.cell > 8) {
    return false;
  }
  if(movement.type) {
    if(movement.color) {
      return false;
    }
    if(movement.type < 1 || movement.type > 4) {
      return false;
    }
    if(view[movement.cell].ant || view[movement.cell].food) {
      return false;
    }
    if(me.type !== QUEEN || me.food < 1) {
      return false;
    }
    return true;
  }
  if(movement.color) {
    if(movement.color < COL_MIN || movement.color >= COL_LIM) {
      return false;
    }
    if(view[movement.cell].color === movement.color) {
      return false;
    }
    return true;
  }
  if(view[movement.cell].ant) {
    return false;
  }
  if(view[movement.cell].food + me.food > 1 && me.type !== QUEEN) {
    return false;
  }
  return true;
}

function as_array(o) {
  if(Array.isArray(o)) {
    return o;
  }
  return [o];
}

function best_of(movements) {
  var m;
  for(var i = 0; i < movements.length; ++ i) {
    if(typeof(movements[i]) === 'function') {
      m = movements[i]();
    } else {
      m = movements[i];
    }
    if(sanity_check(m)) {
      return m;
    }
  }
  return null;
}

function play_safe(movement) {
  // Avoid disqualification: no-op if moves are invalid
  return best_of(as_array(movement)) || NOP;
}

var RAND_SEED = (() => {
  var s = 0;
  for(var i = 0; i < 9; ++ i) {
    s += view[i].color * (i + 1);
    s += view[i].ant ? i * i : 0;
    s += view[i].food ? i * i * i : 0;
  }
  return s % 29;
})();

var ROTATIONS = [
  [0, 1, 2, 3, 4, 5, 6, 7, 8],
  [6, 3, 0, 7, 4, 1, 8, 5, 2],
  [8, 7, 6, 5, 4, 3, 2, 1, 0],
  [2, 5, 8, 1, 4, 7, 0, 3, 6],
];

function try_all(fns, limit, wrapperFn, checkFn) {
  var m;
  fns = as_array(fns);
  for(var i = 0; i < fns.length; ++ i) {
    if(typeof(fns[i]) !== 'function') {
      if(checkFn(m = fns[i])) {
        return m;
      }
      continue;
    }
    for(var j = 0; j < limit; ++ j) {
      if(checkFn(m = wrapperFn(fns[i], j))) {
        return m;
      }
    }
  }
  return null;
}

function identify_rotation(testFns) {
  // testFns MUST be functions, not constants
  return try_all(
    testFns,
    4,
    (fn, r) => fn(ROTATIONS[r]) ? ROTATIONS[r] : null,
    (r) => r
  );
}

function near(a, b) {
  return (
    Math.abs(a % 3 - b % 3) < 2 &&
    Math.abs(Math.floor(a / 3) - Math.floor(b / 3)) < 2
  );
}

function try_all_angles(solverFns) {
  return try_all(
    solverFns,
    4,
    (fn, r) => fn(ROTATIONS[r]),
    sanity_check
  );
}

function try_all_cells(solverFns, skipCentre) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i === CENTRE && skipCentre) ? null : fn(i)),
    sanity_check
  );
}

function try_all_cells_near(p, solverFns) {
  return try_all(
    solverFns,
    9,
    (fn, i) => ((i !== p && near(p, i)) ? fn(i) : null),
    sanity_check
  );
}

function ant_type_at(i, friend) {
  return (view[i].ant && view[i].ant.friend === friend) ? view[i].ant.type : 0;
}

function friend_at(i) {
  return ant_type_at(i, true);
}

function foe_at(i) {
  return ant_type_at(i, false);
}

function foe_near(p) {
  for(var i = 0; i < 9; ++ i) {
    if(foe_at(i) && near(i, p)) {
      return true;
    }
  }
  return false;
}

function move_agent(agents) {
  var me = view[CENTRE].ant;
  var buddies = [0, 0, 0, 0, 0, 0];
  for(var i = 0; i < 9; ++ i) {
    ++ buddies[friend_at(i)];
  }

  for(var i = 0; i < agents.length; i += 2) {
    if(agents[i] === me.type) {
      return agents[i+1](me, buddies);
    }
  }
  return null;
}

function grab_nearby_food() {
  return try_all_cells((i) => (view[i].food ? {cell: i} : null), true);
}

function go_anywhere() {
  return try_all_cells((i) => ({cell: i}), true);
}

function colours_excluding(cols) {
  var r = [];
  for(var i = COL_MIN; i < COL_LIM; ++ i) {
    if(cols.indexOf(i) === -1) {
      r.push(i);
    }
  }
  return r;
}

function generate_band(start, width) {
  var r = [];
  for(var i = 0; i < width; ++ i) {
    r.push(start + i);
  }
  return r;
}

function colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function(c) {
      return colours[(colours.indexOf(c) + 1) % colours.length];
    }
  };
}

function random_colour_band(colours) {
  return {
    contains: function(c) {
      return colours.indexOf(c) !== -1;
    },
    next: function() {
      return colours[RAND_SEED % colours.length];
    }
  };
}

function fast_diagonal(colourBand) {
  var m = try_all_angles([
    // Avoid nearby checked areas
    (rot) => {
      if(
        !colourBand.contains(view[rot[0]].color) &&
        colourBand.contains(view[rot[5]].color) &&
        colourBand.contains(view[rot[7]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // Go in a straight diagonal line if possible
    (rot) => {
      if(
        !colourBand.contains(view[rot[0]].color) &&
        colourBand.contains(view[rot[8]].color)
      ) {
        return {cell: rot[0]};
      }
    },

    // When in doubt, pick randomly but avoid doubling-back
    (rot) => (colourBand.contains(view[rot[0]].color) ? null : {cell: rot[0]}),

    // Double-back when absolutely necessary
    (rot) => ({cell: rot[0]})
  ]);

  // Lay a colour track so that we can avoid doubling-back
  // (and mess up our foes as much as possible)
  if(!colourBand.contains(view[CENTRE].color)) {
    var prevCol = m ? view[8-m.cell].color : WHITE;
    return {cell: CENTRE, color: colourBand.next(prevCol)};
  }

  return m;
}

function follow_edge(obstacleFn, side) {
  // Since we don't know which direction we came from, this can cause us to get
  // stuck on islands, but the random orientation helps to ensure we don't get
  // stuck forever.

  var order = ((side === SIDE_LEFT)
    ? [0, 3, 6, 7, 8, 5, 2, 1, 0]
    : [0, 1, 2, 5, 8, 7, 6, 3, 0]
  );
  return try_all(
    [obstacleFn],
    order.length - 1,
    (fn, i) => (fn(order[i+1]) && !fn(order[i])) ? {cell: order[i]} : null,
    sanity_check
  );
}

function start_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => ((
      !protectedCols.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 5 : 3]].color) &&
      !colourBand.contains(view[rot[right ? 2 : 0]].color) &&
      !colourBand.contains(view[rot[1]].color)
    )
      ? {cell: rot[right ? 5 : 3], color: colourBand.next(WHITE)}
      : null)
  ]);
}

function lay_dotted_path(colourBand, side, protectedCols) {
  var right = (side === SIDE_RIGHT);
  return try_all_angles([
    (rot) => {
      var ahead = rot[right ? 2 : 0];
      var behind = rot[right ? 8 : 6];
      if(
        colourBand.contains(view[behind].color) &&
        !protectedCols.contains(view[ahead].color) &&
        !colourBand.contains(view[ahead].color) &&
        !colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        return {cell: ahead, color: colourBand.next(view[behind].color)};
      }
    }
  ]);
}

function follow_dotted_path(colourBand, side, direction) {
  var forwards = (direction === DIR_REVERSE) ? 7 : 1;
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    // Cell on our side? advance
    (rot) => {
      if(
        colourBand.contains(view[rot[right ? 5 : 3]].color) &&
        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[0]].color) &&
        !colourBand.contains(view[rot[2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    },

    // Cell ahead and behind? advance
    (rot) => {
      var passedCol = view[rot[right ? 8 : 6]].color;
      var nextCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(passedCol) &&
        nextCol === colourBand.next(passedCol) &&

        // Prevent sticking / trickery
        !colourBand.contains(view[rot[right ? 3 : 5]].color) &&
        !colourBand.contains(view[rot[right ? 0 : 2]].color)
      ) {
        return {cell: rot[forwards]};
      }
    }
  ]);
}

function escape_dotted_path(colourBand, side, newColourBand) {
  var right = (side === SIDE_RIGHT);
  if(!newColourBand) {
    newColourBand = colourBand;
  }

  return try_all_angles([
    // Escape from beside the line
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        !colourBand.contains(view[rot[right ? 8 : 6]].color) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[rot[7]].color) ||
        colourBand.contains(view[rot[right ? 6 : 8]].color)
      ) {
        // not oriented, or in a corner
        return null;
      }
      return best_of([
        {cell: rot[right ? 0 : 2], color: newColourBand.next(approachingCol)},
        {cell: rot[right ? 3 : 5]},
        {cell: rot[right ? 0 : 2]},
        {cell: rot[right ? 6 : 8]},
        {cell: rot[right ? 2 : 0]},
        {cell: rot[right ? 8 : 6]},
        {cell: rot[right ? 5 : 3]}
      ]);
    },

    // Escape from inside the line
    (rot) => {
      if(
        !colourBand.contains(view[rot[7]].color) ||
        !colourBand.contains(view[rot[1]].color) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      return best_of([
        {cell: rot[3]},
        {cell: rot[5]},
        {cell: rot[0]},
        {cell: rot[2]},
        {cell: rot[6]},
        {cell: rot[8]}
      ]);
    }
  ]);
}

function latch_to_dotted_path(colourBand, side) {
  var right = (side === SIDE_RIGHT);

  return try_all_angles([
    (rot) => {
      var approachingCol = view[rot[right ? 2 : 0]].color;
      if(
        colourBand.contains(approachingCol) &&
        view[rot[right ? 8 : 6]].color === colourBand.next(approachingCol) &&
        !colourBand.contains(view[rot[right ? 5 : 3]].color)
      ) {
        // We're on the wrong side; go inside the line
        return {cell: rot[right ? 5 : 3]};
      }
    },

    // Inside the line? pick a side
    (rot) => {
      var passedCol = view[rot[7]].color;
      var approachingCol = view[rot[1]].color;
      if(
        !colourBand.contains(passedCol) ||
        !colourBand.contains(approachingCol) ||
        colourBand.contains(view[CENTRE].color)
      ) {
        return null;
      }
      if((approachingCol === colourBand.next(passedCol)) === right) {
        return best_of([{cell: rot[3]}, {cell: rot[6]}, {cell: rot[0]}]);
      } else {
        return best_of([{cell: rot[5]}, {cell: rot[2]}, {cell: rot[8]}]);
      }
    }
  ]);
}


// == High-level logic begins here ==


var COLOURS = random_colour_band(colours_excluding([1]));
return play_safe([
  grab_nearby_food,
  fast_diagonal.bind(null, COLOURS),
  go_anywhere,
  {cell: 1, color: COLOURS.next()}
]);

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

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

তত্ত্ব অনুসারে, এটি প্রতি ফ্রেমে 2.5 কোষকে কভার করে, যা ভয়ঙ্কর নয় এবং এটি আটকা পড়ে বা কোনওভাবেই এটিকে জড়িয়ে ফেলতে অসম্ভব অসম্ভব। এটি ব্ল্যাক হোল ব্যতীত সমস্ত কিছুর চেয়ে ভাল বলে মনে হচ্ছে (যদিও এটি এখন বদলে যেতে পারে যে ব্ল্যাক হোলের সাবটিউর রয়েছে)।

আমি এখনই উত্তর দিয়ে এই চ্যালেঞ্জ স্প্যামিং বন্ধ করার প্রতিশ্রুতি ...


সর্বশেষ আপডেটটি আরও ধরণের অঞ্চলগুলি থেকে দূরে সরিয়ে আচ্ছাদিত স্থলটিকে পুনরায় অনুসন্ধান করার সামান্য সম্ভাবনা তৈরি করে।


এগুলি স্প্যাম নয় যখন তারা সমস্ত স্বতন্ত্র এবং আকর্ষণীয় কৌশল!
ট্রিকোপলাক্স

ব্ল্যাক হোলের সাবোটিউর কোন প্রবেশিকা?
ড্রাকো 18

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

@ ডেভ বোট যেটি করে তা হল আন্তোম ওয়াকিং আর্টিস্ট
পিপিরি

3

রহস্যভেদ করা

এই বটটি নিয়মিতভাবে প্রায় 90 টি বোটকে পরাজিত করে প্রায় 90 টি খাদ্য গ্রহণ করে।

var ORTHOGONALS = [1,3,5,7];
var CORNERS = [0,2,6,8];
var CENTER = 4;

var QUEEN = 5;

var no_op = {cell:CENTER};
var me = view[4].ant;

var ants;
var food;
var friendlies;
var unfriendlies;
var colors;

var j = 0;
var i = 0;
var cell = 0;
var rotation;

var out;

init_arrays();
var seed = rSeed();

var response;

var adjacents_all = {0:[1,3,4],1:[0,2,3,4,5],2:[1,4,5],3:[0,1,4,6,7],4:[0,1,2,3,4,5,6,7,8],5:[1,2,4,7,8],6:[3,4,7],7:[3,4,5,6,8],8:[4,5,7]};
var adjacents_ortho = {0:[1,3],1:[0,2,4],2:[1,5],3:[0,4,6],4:[1,3,5,7],5:[2,4,8],6:[3,7],7:[4,6,8],8:[5,7]};
var adjacents_diag = {0:[4],1:[3,5],2:[4],3:[1,7],4:[0,2,6,8],5:[1,7],6:[4],7:[3,5],8:[4]};

function valid_move(move) {
  if(!move || move.cell == undefined || move.cell < 0 || move.cell > 8) {return false;}
  if(move.type) {
    if(move.color) {return false;}
    if(move.type < 1 || move.type > 4) {return false;}
    if(view[move.cell].ant || view[move.cell].food) {return false;}
    if(me.type != QUEEN || me.food < 1) {return false;}
    return true;
  }
  if(move.color) {
    if(move.color < 1 || move.color > 8) {return false;}
    return true;
  }
  if(view[move.cell].ant){return false;}
  if(view[move.cell].food && me.food&& me.type != 5) {return false;}
  return true;
}

function steal_then_road(){
  if(count(unfriendlies, 5)>=1 && me.food==0){
    //steal from a queen with more than 30 food
    if(ants[unfriendlies.indexOf(5)].food>30){
      for(i=0;i<adjacents_ortho[unfriendlies.indexOf(5)].length;i++){
        if(ants[adjacents_ortho[unfriendlies.indexOf(5)][i]]==null){
          return {cell:adjacents_ortho[unfriendlies.indexOf(5)][i]};
        }
      }
    }
  }
  return road();
}

function try_corners(){
  for(i=0;i<4;i++){
    if(view[CORNERS[i]].ant==null){
      return {cell:CORNERS[i]};
    }
  }
}

function try_ortho(){
  for(i=0;i<4;i++){
    if(view[ORTHOGONALS[i]].ant==null){
      return {cell:ORTHOGONALS[i]};
    }
  }
}

function corner_then_ortho(){
  if(try_corners()){return try_corners();}
  if(try_ortho()){return try_ortho();}
  return {cell:4}; //PANIC!
}

function ortho_then_corner(){
  if(try_ortho()){return try_ortho();}
  if(try_corners()){return try_corners();}
  return {cell:4}; //PANIC!
}

function road(color){
  if (colors[color] != color) {
      return {cell:CENTER,color:color};
    }
  for (i = 0; i < 9; i++) {
    if (colors[i] == color && ants[8 - i] == null && i != color) {
      return {cell:8-i};
    }
  }
}

function color_self(color){
  return {cell:4,color:color};
}

function make_valid_move(move){
  if(valid_move(move)){return move;}
  return no_op;
  //return{cell:seed%9,color:seed%7+1};
}

function count(array, element) {
  out = 0;
  for (j = 0; j < array.length; j++) {
    if (array[j] == element) {
      out++;
    }
  }
  return out;
}

function target_ant(ant_type, location) {
  for (i = 0; i < 4; i++) {
    if (ants[location] != null) {
      if (ants[location].type == ant_type) {
        return i;
      }
    }
    ants = rot_left(ants);
    friendlies = rot_left(friendlies);
    unfriendlies = rot_left(unfriendlies);
    food = rot_left(food);
    colors = rot_left(colors);
  }
}


function target_color(color, location) {
  for (i = 0; i < 4; i++) {
    if (colors[location] != null) {
      if (colors[location].type == color) {
        return i;
      }
    }
    ants = rot_left(ants);
    friendlies = rot_left(friendlies);
    unfriendlies = rot_left(unfriendlies);
    food = rot_left(food);
    colors = rot_left(colors);
  }
}

function init_arrays() {
    ants = new Array(9);
  for (cell = 0; cell < 9; cell++) {ants[cell] = view[cell].ant;}


  food = new Array(9);
  for (cell = 0; cell < 9; cell++) {food[cell] = view[cell].food;}

  colors = new Array(9);
  for (cell = 0; cell < 9; cell++) {colors[cell] = view[cell].color;}

  friendlies = new Array(9);
  for (cell = 0; cell < 9; cell++) {
    if (ants[cell] != null) {
      if (ants[cell].friend) {friendlies[cell] = ants[cell].type;}
    }
  }

  unfriendlies = new Array(9);
  for (cell = 0; cell < 9; cell++) {
    if (ants[cell] != null) {
      if (!ants[cell].friend) {unfriendlies[cell] = ants[cell].type;}
    }
  }
}

function rot_n_pos(pos, n) {
  for (i = 0; i < n; i++) {
    pos = [2, 5, 8, 1, 4, 7, 0, 3, 6][pos];
  }
  return pos;
}

function rot_left(a) {
  return [a[2], a[5], a[8], a[1], a[4], a[7], a[0], a[3], a[6]];
} 

function rot_right(a) {
  return [a[6], a[3], a[0], a[7], a[4], a[1], a[8], a[5], a[2]];
}

function rSeed(){
  out=23;
  for(i=0;i<9;i++){
    if(food[i]){
      out+=17;
    }
    out += 3 * colors[i];
    if(ants[i]){
      out *= 19;
    }
  }
  return out;
}

function get_response(){
  if (me.type == 5) { //Queen Case:
    return type5();
  }
  else if (me.type == 1) {
    return type1();
  }
  else if (me.type == 2) {
    return type2();
  }
  else if (me.type == 3) {
    return type3();
  }
  else if(me.type == 4){
    return type4();
}

function type5(){
  if (me.food == 0 && count(friendlies, 1) == 0 && count(friendlies, 2) == 0) {
    if (count(food, 1) > 0) {
      for (j = 0; j < 9; j++) {
        if (food[j]) {
          return {cell: j};
        }
      }
    }
    // travel up
    // color own cell if not 4

    if(road()){return road();}

    //move
    for (i = 0; i < 9; i++) {
      if (ants[i] == null && i != 4) {
        return {cell:i};
      }
    }
    return corner_then_ortho();
  }
  if (me.food >= 1 && count(friendlies, 1) == 0 && count(friendlies, 2) == 0) {
    if (ants[5] == null) {
      return {cell:5,type:1};
    }
    if (ants[1] == null) {
      return {cell:5, type:1};
    }
    if (ants[3] == null) {
      return {cell:5,type:1};
    }
    if (ants[7] == null) {
      return {cell:5, type:1};
    }
    return color_self(5);
  }
  if (me.food == 0 && count(friendlies, 1) == 1 && count(friendlies, 2) == 0) {
    if (friendlies.indexOf(1) % 2 == 0) {
      return ortho_then_corner();//PANIC!!! TODO: FIX
    }
    rotation = target_ant(1, 1);
    if (ants[0] == null) {
      return {cell: rot_n_pos(0, rotation)};
    } else {
      return corner_then_ortho;
    }
  }
  if (me.food >= 1 && count(friendlies, 1) == 1 && count(friendlies, 2) == 0) {
    if (friendlies.indexOf(1) % 2 == 0) {
      return corner_then_ortho(); //PANIC!!! TODO: FIX
    }
    rotation = target_ant(1, 1);
    if (ants[3] == null) {
      return {cell: rot_n_pos(3, rotation),type: 2};
    }
    if (ants[0] == null) {
      return { cell: rot_n_pos(0, rotation)};
    }
    return {cell: 4};
  }
  if (count(friendlies, 1) == 1 && count(friendlies, 2) == 1) {
    if (friendlies.indexOf(1) % 2 == 0) {
      return ortho_then_corner();
    }
    rotation = target_ant(1, 1);
    if(food[0] || food[8]){
      return no_op;
    }
    if(ants[5]!=null){
      if(ants[5].type == 2 && ants[2]==null){
        return {cell: rot_n_pos(2, rotation)};
      }
    }
    return corner_then_ortho();
  }
  return corner_then_ortho();
}

function type1(){
//right flank
  if (count(friendlies, 5) == 0 && count(friendlies, 2) == 0 && count(friendlies,1) == 1) {
    //no friends = destruction
    return steal_then_road();
  }
  if (count(friendlies, 5) == 1 && count(friendlies, 2) == 0 && count(friendlies,1) == 1) {
    if (friendlies.indexOf(5) % 2 == 0) {
      return ortho_then_corner();
    }
    rotation = target_ant(5, 3);
    if (ants[0] == null) {
      return {cell: rot_n_pos(0, rotation)};
    }
    return corner_then_ortho(); // PANIC!! TODO: FIX
  }
  if (count(friendlies, 5) == 1 && count(friendlies, 2) == 1 && count(friendlies,1) == 1) {
    if (friendlies.indexOf(5) % 2 == 0) {
      return ortho_then_corner(); 
    }
    rotation = target_ant(5, 3);
    if(friendlies[8] !=null){
      if(friendlies[8].type==2){
        if (ants[0] == null){
          return {cell: rot_n_pos(0, rotation)};
        }
      }
    }
    if (ants[0] != null) {
      if (ants[0].type == 2 && ants[6] == null) {
        return {cell: rot_n_pos(6, rotation)};
      }
    }
    if (ants[6] != null) {
      if (ants[6].type == 2 && ants[0] == null) {
        return {cell: rot_n_pos(0, rotation)};
      }
    }
    return corner_then_ortho();
  }
  return corner_then_ortho();
}

function type2(){
  //left flank
  if (count(friendlies, 5) == 0 && count(friendlies, 1) == 0  && count(friendlies,2) == 1) {
    return steal_then_road();
  }
  if (count(friendlies, 5) == 1 && count(friendlies, 1) == 0  && count(friendlies,2) == 1) {
    if (friendlies.indexOf(5) % 2 == 0) {
      return ortho_then_corner();
    }
    rotation = target_ant(5, 1);
    if (ants[0] == null) {
      return {cell: rot_n_pos(2, rotation)};
    }
    return corner_then_ortho();
    }
    if (count(friendlies, 5) == 1 && count(friendlies, 2) == 1) {
      return {cell: 4,color:2};
    }
    }
  return corner_then_ortho();
}

function type3(){}
function type4(){}

response = get_response();

return make_valid_move(response);

স্ট্র্যাটেজি।

প্রথম পর্যায়: রানী ঝাঁঝরি।

রানী রোমানেসকো রোডের অনুরূপ একটি কৌশল ব্যবহার করে খাবারের জন্য স্ক্যাম্বল করে ( road()ফাংশনটি ব্যবহার করে )। যখনই সে কোনও খাবার দেখে সে তা গ্রহণ করে এবং এক ধরণের 1 কর্মী তৈরি করে, পর্যায় 2 সক্রিয় করে।

দ্বিতীয় ধাপ: রানী-অংশীদার স্ক্যাম্বল।

রানী এবং অংশীদার একে অপরকে প্রাচ্য করতে ব্যবহার করে, তাই তারা আলোর গতিতে ভ্রমণ করে। তারা তাদের চারপাশের যে কোনও খাবার উপেক্ষা করে এবং যা তাদের হিট করে তা কেবল পায়। রানী যখন কোনও খাবার পান, তখন তিনি টাইপ 2 কর্মী তৈরি করেন, পর্যায় 3 সক্রিয় করে তোলেন।

পর্ব 3: পিয়ার্স।

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

শক্তি:

থ্রি-পিঁপড়া গঠন কোনও ট্রেইল তৈরি করে না, মোড়ানো করে না এবং আলোর গতিতে ভ্রমণ করে, প্রতি চাল হিসাবে গড়ে 0.1% * 3 = 0.003 খাবার পান। এটি প্রতি খেলায় গড়ে 0.003 * 30000 = 90 খাবারের সমান হয় যা সাধারণত পাওয়া যায়।

দুর্বলতা:

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

আর একটি দুর্বলতা হ'ল road()অ্যালগরিদম যা মনে হচ্ছে যে সমস্যাগুলি আমি ঠিক করতে কাজ করছি। ব্রাউনিয়ান গতিযুক্ত একটি রাস্তা ভাল নয়। এর অর্থ খুব ধীর শুরু এবং অস্বাস্থ্যকর পরিস্থিতি থেকে খারাপ অব্যাহতি।


এই পিঁপড়াগুলি প্রায় আমার মতোই pract স্টিমরোলার পিঁপড়াগুলির তবে আমার পরীক্ষায় এটি আরও খারাপ বলে মনে হয়। কেবলমাত্র তফাতটি আমি লক্ষ্য করছি যে আপনার পিঁপড়াগুলি ঘুরিয়ে দিচ্ছে যখন রানী অন্য কর্মীদের কাছে পৌঁছাতে পারে না এমন খাবার দেখেন, যখন আমার টার্নিং হয় যখন টাইপ 2 কর্মী কিছু খাবার মারবে। আমি মনে করি আপনার পিঁপড়াদেরও ভাল অভিনয় করা উচিত, তবে কেন কখনও কখনও এটি সম্পাদিত হয় তা আমি বুঝতে পারি না।
কে জাং

পছন্দ করেছেন আমার পরীক্ষায়, পিয়ার্স সাধারণত পিঁপড়ার একটি বড় হস্তক্ষেপ (ওয়াইল্ডফায়ার? ব্ল্যাক হোল?) মারে যখন এটি অকারণে দশটি নতুন পিঁপড়া তৈরি করে except কেবল সময় এবং পরীক্ষাই বলবে।
ফায়ার ফ্লেম 241

সম্পাদনা অনুসরণ করে পরবর্তী লিডারবোর্ডের জন্য প্রস্তুত বর্তমান টুর্নামেন্টে পুনরায় অন্তর্ভুক্ত।
ট্রিকোপলাক্স

2
আমি লক্ষ করেছি যে বিরল পরিস্থিতিতে এই প্যাটার্নটি একটি অন্তহীন লুপে আটকে যেতে পারে। বিশেষত, যদি খাবারের দুটি টুকরা থাকে যা 1 স্থান দ্বারা পৃথক করা হয়, এবং তারপরে রানী উভয়টির সংলগ্ন অবস্থানে প্রবেশ করে; এই ঘটনাটি যখন নিয়মিত ঘটে, সম্ভবতঃ কারণ এটি কেবল "এমন খাবারের প্রতি প্রতিক্রিয়া দেখায় যা আমরা ঘুরিয়ে না দিলে মিস হত" এবং "এমন খাবার নয় যা আমরা ঘুরিয়ে দিলে মিস হবে"
কামিল দ্রাকারী

3

একক রানী

var C = 5;

for(var i = 0; i<9; i++)
{
  if(view[i].food === 1)
    return {cell:i};
}


if(view[4].color != 5 && !view[0].ant && !view[1].ant && !view[2].ant && !view[3].ant && !view[5].ant && !view[6].ant && !view[7].ant && !view[8].ant)
  return {cell:4, color:C};

if(!view[0].ant && 
   view[0].color != C && view[8].color === C && view[1].color != C && view[3].color != C && view[2].color != C && view[6].color != C)

      return {cell:0};

if(!view[2].ant && 
   view[2].color != C && view[6].color === C && view[1].color != C && view[5].color != C  && view[0].color != C && view[8].color != C)

     return {cell:2};

if(!view[6].ant && 
   view[6].color != C && view[2].color ===  C && view[3].color != C && view[7].color != C  && view[0].color != C && view[8].color != C)

     return {cell:6};

if(!view[8].ant && 
   view[8].color != C && view[0].color === C && view[5].color != C && view[7].color != C  && view[2].color != C && view[6].color != C)

     return {cell:8};


if(!view[0].ant)
  return {cell:0};

if(!view[2].ant)
  return {cell:2};

if(!view[6].ant)
  return {cell:6};

if(!view[8].ant)
  return {cell:8};


return {cell:4};

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

লোন ওল্ফের (অনিচ্ছাকৃত) অনুরূপ কৌশল বলে মনে হচ্ছে।


3

অনুসন্ধানকারী

গ্যাং ছড়িয়ে!

এক্সপ্লোরার হ'ল একটি পাঁচ সদস্যের দল, যার লক্ষ্য যতদূর সম্ভব ছড়িয়ে দেওয়া, এখনও রানিকে খাবার ফিরিয়ে আনতে হবে।

রানী

রানী নিজেই একটি 3 স্টেজ সেটআপ ব্যবহার করে।

ধাপ 1.

ম্যাচের শুরুতে, এটি কোনও ভাল রানির মতো খাবারের জন্য বুনো ড্যাশ। এটি খাবারটি না পাওয়া পর্যন্ত এটি সরল লাইনে কেবল তির্যকভাবে পথ চালায়, তারপরে এলোমেলোভাবে দিক পরিবর্তন করে। এটিতে 4 টি খাবার থাকলে এটি দ্বিতীয় পর্যায়ে চলে যায়।

ধাপ ২.

এটি সম্ভবত 8 টির বেশি পদক্ষেপ নেবে না। এটি চারপাশে চারটি টাইলসকে চারটি অনন্য রঙের জন্য সেট করে এবং তাদের উপর পিঁপড়াগুলি তৈরি করে, তাদের নিজস্ব প্রকারগুলি দিয়ে। এগুলি সমস্ত ছড়িয়ে পড়ে যাওয়ার পরে, স্তর 3 এ স্থানান্তরিত হয়।

পর্যায় 3.

চারটি টাইল সঠিকভাবে সেট করা আছে তা নিশ্চিত করে, তিনটি পর্যায়টি ম্যাচের বাকি অংশের জন্য স্থির বসে।

শ্রমিকেরা

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

var me = view[4].ant
var turf = view[4].color

var queenHolder = 2 // "Queen Holder", the turf colour for the queen in stage 3.
var queenBuild = 7 // "Queen Build", the turf colour for the queen in stage 2.
var antTrail = [3, 4, 5, 6] // Various colours of the ant's trails.
var orth = [1, 3, 5, 7] // Orthogonal Directions.
var rotates = [[1,3,5,7],[3,7,1,5],[5,1,7,3],[7,5,3,1]] // These are the orthogonal directions rotated so 0 is the first position, used in the queen build stage.
var outside = [1,2,3,5,6,7,8] // Every tile but the center one.
var diag = [0,2,6,8] // Diagonal Directions.

// Define a move function to avoid throwing an error.
function move(dir){
    if(view[dir].ant)   // If we're going to move onto an ant.
        dir = 4 // Don't move anywhere.
    if(view[dir].food && me.type < 5 && me.food > 0)    // If we're going to over-eat.
        dir = 4 // Don't move anywhere.
    return {cell: dir}  // Build the move output.
}

if(me.type == 5){ // If we're the queen.
    var invDiag = [8,6,2,0] // Inverse of diagonals, using the indexing of diag. So 0 becomes 8, and such.
    if(turf == 1 || turf == 8){
        // Stage 1.
        // Find enough food to start a hive.
        for(var i=0; i < view.length; i++){ // Check every tile in view
            if(view[i].food){   // Is it food?
                return move(i)  // Move to it.
            }
        }
        if(me.food > 3) // Do we have 4 food?
            return {cell:4, color:queenBuild}   // Move to stage 2.
        if(turf == 1)   // Are we on a white tile?
            return {cell:4, color:8}    // Set the tile to black.
        for(var i=0; i < diag.length; i++)  // Check all diagonals.
            if(view[diag[i]].color == 8)    // Is it black?
                return move(invDiag[i]) // Move in the opposite direction. This creates a straight diagonal line.
        return move(2)  // When in doubt, move randomly diagonally.
    }else if(turf == queenBuild){
        // Stage 2.
        // Spawn ants around, and set up their movement paths.
        if(me.food < 1) // Have we used all our food?
            return {cell:4, color:queenHolder}  // Move to stage 3.

        var firstHolder = -1; // Stores which way we're facing.
        for(var i=0; i < orth.length; i++){ // Check orthogonals.
            if(view[orth[i]].color == antTrail[0]){ // Is it the first trail colour?
                firstHolder = i // THIS WAY UP
                break;
            }
        }
        if(firstHolder==-1) // No way is up?
            return {cell:1, color:antTrail[0]} // Set a random direction to up.

        var orthRot = rotates[firstHolder]  // Get the rotated orthogonal set for the current up direction.
        for(var i=0; i < orthRot.length; i++){  // For each of them.
            if(!view[orthRot[i]].ant)   // Is there an ant on this tile yet?
                return {cell:orthRot[i], type:(i+1)}    // If not, place one down with the correct type.
            if(view[orthRot[i]].color!=antTrail[i]) // Otherwise, is the turf set correctly yet?
                return {cell:orthRot[i], color:antTrail[i]} // If not, set the turf.
        }
        return {cell:4, color:queenHolder}; // After all's said and done, move to stage 3. Probably won't happen this way.
    }else if(turf == queenHolder){
        // Stage 3.
        // Sit still, ensure rails exist around.

        var firstHolder = -1;   // Same behavoir of which way is up from stage 2.
        for(var i=0; i < orth.length; i++){
            if(view[orth[i]].color == antTrail[0]){
                firstHolder = i
                break;
            }
        }
        if(firstHolder==-1)
            return {cell:1, color:antTrail[0]}

        var orthRot = rotates[firstHolder]
        for(var i=0; i < orthRot.length; i++)   // Basically stage 2 without the spawning of ants.
            if(view[orthRot[i]].color!=antTrail[i])
                return {cell:orthRot[i], color:antTrail[i]}

        return {cell:4, color:queenHolder}  // And if there's nothing better to do, waste your time.
    }else{
        return {cell:4, color:1}    // We're lost, go back to stage 1, and try again.
        // I could probably add logic to check if we're stage 3 or something, but meh.
    }

}else{  // If we're a worker!

    for(var i=0; i < orth.length; i++)  // Check around.
        if(view[orth[i]].ant && view[orth[i]].ant.type == 5 && view[orth[i]].ant.friend && view[orth[i]].color == queenBuild)   // Is there a queen, in build mode, around us?
            return move(4)  // Wait politely for her to finish.

    var col = antTrail[me.type-1] // Which colour I use.

    if(me.food < 1){    // If we have no food.
        for(i=0; i < orth.length; i++){ // Check Orthogonals
            if(view[orth[i]].food){ // Is there food there?
                if(turf != col) // If we're not standing on our trail.
                    return {cell: 4, color: col}    // Place our trail here, so we can still find our way back.
                return move(orth[i])    // Otherwise, move to the food!
            }
        }
    }

    if(turf == col) // If we're sitting on our trail.
        return move(2) // Move off it randomly

    var corq = (t)=>t.color == col || (t.ant && t.ant.type == 5 && t.ant.friend)    // Helper function, does this tile contain our trail or the queen?
    var corqorf = (t)=>corq(t) || t.food    // Helper function, odes this tile contain our trail, the queen, or a piece of food?
    var queenInView = false;
    for(var i=0; i < view.length; i++)  // Check the entire view.
        if(view[i].ant && view[i].ant.type == 5 && view[i].ant.friend) // Can we see the queen?
            queenInView = true; // Remember this.

    // Using food > 0 behavoir if we see a queen, makes it so that we don't accidentally build our path over the queen or something silly.

    if(me.food > 0 || queenInView){ // If we have food, or we can see the queen.
        // DON'T build paths, just orbit our path clockwise.
        var orthmov = [3,7,1,5] // Directions to move if we see a path on an orthogonal.
        var diagC = [3,1,7,5]   // Directions to move if we see a path on a diagonal.
        for(var i=0; i < orth.length; i++)  // For each Orthogonal, which takes preference.
            if(corqorf(view[orth[i]]))  // Is there the queen, a trail, or food here?
                return move(orthmov[i]) // move CW to it.
        for(var i=0; i < diag.length; i++)  // Ditto for Diagonals.
            if(corqorf(view[diag[i]]))
                return move(diagC[i])

    }else{
        // EXTEND paths, or continue orbiting clockwise.
        var orthM = [0,6,2,8]   // Directions a path should be when we check an orthogonal.
        var orthMo = [3,7,1,5]  // Directions to move if we see an orthogonal, and the diagonal is there.
        var diagC = [3,1,7,5]   // Directions to place a path if we only see an orthogonal.
        for(var i=0; i < orth.length; i++){ // In each Orthogonal.
            var v = view[orth[i]]
            if(corq(v)){    // Is there a trial?
                if(corq(view[orthM[i]]))    // Is there a trail in the after it position?
                    return move(orthMo[i])  // Move in the correct direction.
                return {cell:orthM[i], color:col}   // Place the trail in the after it position.
            }
        }
        for(var i=0; i < diag.length; i++)  // Check diagonals as a last resort.
            if(corq(view[diag[i]])) // Is there a path /HERE/?
                return {cell:diagC[i], color:col}   // Place the respective diagonal's orthogonal.

    }
    return move(2)  // When we're lost, scamper around. Just like Trail-eraser wants us to.
}

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

কারণ: খাবারের শীর্ষে নতুন কর্মী তৈরি করতে পারে না। ইনপুট: [{"রঙ": 7, "খাবার": 0, "পিপীলিকা": নাল}, {"রঙ": 1, "খাদ্য": 0, "পিপীলিকা: নাল}, color" রঙ ": 8, "খাবার": 0, "পিপীলিকা": নাল}, { "রঙ": 3, "খাবার": 1, "পিপীলিকা": নাল}, { "রঙ": 7, "খাবার": 0, "পিপীলিকা": { "খাবার": 1, "টাইপ": 5, "বন্ধু": সত্য}}, { "রঙ": 1, "খাবার": 0, "পিপীলিকা": নাল}, { "রঙ": 1, "খাবার ": 0," পিপীলিকা ": নাল}, {" রঙ ": 1," খাবার ": 0," পিপীলিকা ": নাল}, {" রঙ ": 7," খাবার ": 0," পিপীলিকা ": নাল} ] প্রতিক্রিয়া: {"সেল": 3, "প্রকার":

3

রোমানেসকো রোড

এই খেলোয়াড়টি কোনও কর্মী তৈরি করে না এবং রানী একটি সরলরেখায় চলে যায়, প্রতিটি কক্ষটি সেগুলিকে দেখে mar ইনপুট দৃশ্যমান কোষগুলির এলোমেলো প্রবণতা সত্ত্বেও সরলরেখার গতি সম্ভব, কারণ রানী তার সবেমাত্র চিহ্নিত চিহ্নিত ঘরটি দেখতে পারে এবং একটি সরল রেখা নিশ্চিত করার জন্য এটি বিপরীত দিকে চলে যায়।

উত্তরের প্রথম কোড ব্লকটি স্বয়ংক্রিয়ভাবে গেমটিতে অন্তর্ভুক্ত:

// Full version that won't be disqualified for moving onto another ant

var i

// Color own cell if white
if (view[4].color === 1) {
    return {cell:4, color:3}
}

// Otherwise move to food if visible
for (i=0; i<9; i++) {
    if (view[i].food) {
        return {cell:i}
    }
}

// Otherwise move to a white cell opposite a colored cell
for (i=0; i<9; i++) {
    if (view[i].color === 1 && view[8-i].color > 1 && !view[i].ant) {
        return {cell:i}
    }
}

// Otherwise move to an unoccupied cell
for (i=0; i<9; i++) {
    if (!view[i].ant) {
        return {cell:i}
    }
}

// Otherwise don't move at all
return {cell:4}

এখানে একটি সহজ সংস্করণ যা অন্যান্য পিঁপড়াদের জন্য যাচাই করে না, তবে অন্য পিঁপড়ার দিকে পা রাখার চেষ্টা করে অযোগ্য হয়ে উঠা অবধি অবধি অভিন্ন আচরণ রয়েছে:

// Basic version for an intuitive understanding

var i

// Color own cell if white
if (view[4].color === 1) {
    return {cell:4, color:3}
}

// Otherwise move to food if visible
for (i=0; i<9; i++) {
    if (view[i].food) {
        return {cell:i}
    }
}

// Otherwise move to a white cell opposite a colored cell
for (i=0; i<9; i++) {
    if (view[i].color === 1 && view[8-i].color > 1) {
        return {cell:i}
    }
}

// Otherwise move "left and up", which will be a random direction
return {cell:0}

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

একটি সরল রেখার চেয়ে এলোমেলো চলাচলের উত্পাদন উদাহরণের জন্য দেখুন ব্রাউনিয়ান জিগ


3

VinceAnt

আপনি কি মনে করেন যে নয় মাস পরেও আখড়াটি এখনও খানিকটা কোমল দেখাচ্ছে?

আপনি কি মনে করেন কি Antdom শিল্পী হাঁটা এবং এতিম সংকলন কর্মীরা আকর্ষণীয়ভাবে সাজানোর ক্ষেত্রে কিছুটা সাহায্য করতে পারেন?

তাহলে আপনি এটি পছন্দ করবেন!

একটি হাইওয়ে, ফ্যাশনযুক্ত

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

ক্লড এবং জিন

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

স্বভাবের দ্বারা, এই এন্ট্রি লাইটস্পিডকে পরাভূত করতে পারে না, তবে এটির সমস্ত বহির্মুখের জন্য বর্তমানের (এপ্রিল 2018) পঞ্চম প্রার্থীর মধ্যে প্রায় পঞ্চম ভাগের পক্ষে যুক্তিসঙ্গতভাবে ভাল করার আশা করা হচ্ছে।

মন্তব্য আন-golfed সোর্স কোড হয় GitHub , এবং আমি প্রতিটি চিত্রশিল্পী ধরন এবং শৈলী সেখানে একবার আমি কিছু চমৎকার স্ক্রিনশট সংগ্রহ বৃত্তাকার পেয়েছেন সম্পর্কে আরও বিস্তারিত যোগ করার পরিকল্পনা করছি।

var ANV=1;var AMK=2;var AGS=3;var AWM=4;var AQ=5;var THC=1;var THP=[0,0,0,0,0,0];THP[AMK]=19;THP[AGS]=17;THP[AWM]=15;var RM=15;var SPDAT =[0,AMK,AGS,0,AWM,0,AGS,AWM,0,AMK,0,AWM,AMK,0,AGS];var PW=1;var PY=2;var PP=3;var PC=4;var PR=5;var PG=6;var PB=7;var PK=8;var LCLR=PW;var LT=PY;var LLSF=PG;var TN=8;var POSC=4;var NOP={cell:POSC};var CCW=[6,7,8,5,2,1,0,3,6,7,8,5,2,1,0,3,6,7,8,5,2,1];
var xn=-1;var here=view[POSC];var mC=here.color;var myself=here.ant;var mT=myself.type;var mF=myself.food;var mS=(mT!=AQ&&mF>0);var dOK=[true,true,true,true,true,true,true,true,true];
var uo=true;var sL=[0,0,0,0,0,0,0,0,0];var sD=[0,0,0,0,0,0,0,0,0];var sN=[0,0,0,0,0,0,0,0,0];var sT=[0,0,0,0,0,0,0,0,0];var fdL=0;var fdD=0;var fdT=0;sT[mC]++;for (var i=0; i<TN; i+=2){var cell=view[CCW[i]];sD[cell.color]++;sN[cell.color]++;sT[cell.color]++;if (cell.food>0){fdD++;fdT++;if (mS){dOK[CCW[i]]=false;uo=false;}}}for (var i=1; i<TN; i+=2){var cell=view[CCW[i]];sL[cell.color]++;sN[cell.color]++;sT[cell.color]++;if (cell.food>0){fdL++;fdT++;if (mS){dOK[CCW[i]]=false;uo=false;}}}var aF=[0,0,0,0,0,0];var aLF=[0,0,0,0,0,0];var aUF=[0,0,0,0,0,0];var fT=0;var mQ=0;var aE=[0,0,0,0,0,0];var aLE=[0,0,0,0,0,0];var aUE=[0,0,0,0,0,0];var eT=0;for (var i=0; i<TN; i++){var cell=view[CCW[i]];if (cell.ant){if (cell.ant.friend){aF[cell.ant.type]++;fT++;if (cell.ant.type==AQ){xn=i&6;mQ=i&1;}if (cell.ant.food>0){aLF[cell.ant.type]++;} else {aUF[cell.ant.type]++;}} else {aE[cell.ant.type]++;eT++;if (cell.ant.food>0){aLE[cell.ant.type]++;} else {aUE[cell.ant.type]++;}}dOK[CCW[i]]=false;uo=false;}}switch (mT){case AQ:return (rQSs());case ANV:return (rNSs());case AMK:return (rMSs());case AGS:return (rGSs());case AWM:return (rWSs());default:return NOP;}function rQSs(){switch (aF[ANV]){case 0:return (rQScrSy());case 1:for (var i=0; i<TN; i++){var cell=view[CCW[i]];if (cell.ant&&cell.ant.friend&&cell.ant.type==ANV){xn=i&6;if (i&1){return (rQLsSy());} else {return (rQCSy());}}}break;default:return (rQCNSy());}return NOP;}function rNSs(){if (aF[AQ]>0){if (mQ==1){return (rSLSy());} else {return (rNRSy());}} else if ((mF==0)&&(fdT>0)){return (rPEgSy());} else {return (rPPgSy());}}function rMSs(){if ((aF[AQ]>0)&&(mF==0)){if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else {return NOP;}} else if ((mF>0)&&(aF[AQ]+aF[ANV]>0)){return NOP;} else if ((mF==0)&&(fdT>0)){return (rPEgSy());} else if (aF[AGS]+aF[AWM]>1){return (rPMgSy());} else if (aF[AGS]==1){return (rCPgSy());} else {return (rMPgSy());}}function rGSs(){if ((aF[AQ]>0)&&(mF==0)){if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else {return NOP;}} else if ((mF>0)&&(aF[AQ]+aF[ANV]>0)){return NOP;} else if ((mF==0)&&(fdT>0)){return (rPEgSy());} else if (aF[AMK]+aF[AWM]>1){return (rPMgSy());} else if (aF[AMK]==1){return (rJPgSy());} else {return (rGPgSy());}}function rWSs(){if ((aF[AQ]>0)&&(mF==0)){if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else {return NOP;}} else if ((mF>0)&&(aF[AQ]+aF[ANV]>0)){return NOP;} else if ((mF==0)&&(fdT>0)){return (rPEgSy());} else if (aF[AMK]+aF[AGS]>1){return (rPMgSy());} else {return (rWPgSy());}}function rQScrSy(){if (uo){if (fdT>0){return (rQSETc());} else if (mF>=THC){for (var i=0; i<TN; i+=2){if ((view[CCW[i]].color==LT)||(view[CCW[i+1]].color==LT)){return {cell:CCW[i+1],type:ANV};}}return {cell:1,type:ANV};} else if (mC!=LT){if ((mC==LCLR)||(sN[LCLR]>=TN-1)){return {cell:POSC,color:LT};} else {return (rQSTCTc());}} else if ((sN[LCLR]>=4)&&(sN[LT]==1)){for (var i=0; i<TN; i+=2){if ((view[CCW[i]].color==LT)||(view[CCW[i+1]].color==LT)){return {cell:CCW[i+4]};}}} else if (sN[LCLR]==TN){return {cell:0};} else {return (rQSATc());}} else {if ((fdT>0)&&(eT>0)&&(eT==aE[AQ])){return (rQSSTc());} else {return (rQSEvTc());}}return NOP;}function rQLsSy(){if ((sT[LCLR]<=2)&&(mF>1)&&(eT==0)){var artist=SPDAT[mF % RM];if ((artist!=0)&&(mF>=THP[artist])&&(aF[artist]<=1)){var tc=[6,2,4,5,3];for (var i=0; i<tc.length; i++){var c=CCW[xn+tc[i]];if (dOK[c]&&(view[c].food==0)){return {cell:c,type:artist};}}}}if ((eT==0)&&(fT==1)){if (view[CCW[xn+2]].food>0){return {cell:CCW[xn+2]};} else if ((view[CCW[xn+3]].food +view[CCW[xn+4]].food>0)&&(view[CCW[xn+1]].color!=LLSF)){return NOP;} else {return {cell:CCW[xn+2]};}} else if (dOK[CCW[xn+2]]&&dOK[CCW[xn+3]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn]]&&dOK[CCW[xn+7]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else {return NOP;}}function rQCNSy(){for (var i=0; i<TN; i++){var cell=view[CCW[i]];if (cell.ant&&cell.ant.friend&&cell.ant.type==ANV){if (i&1){if (dOK[CCW[i-1]]){return {cell:CCW[i-1]};} else if (dOK[CCW[i+1]]){return {cell:CCW[i+1]};} else if (dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else {return NOP;}} else {if (dOK[CCW[i+7]]){return {cell:CCW[i+7]};} else if (dOK[CCW[i+1]]){return {cell:CCW[i+1]};} else if (dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else {return NOP;}}}}return (rQCSy());}function rQCSy(){return NOP;}function rSLSy(){if ((eT==0)&&(fT==1)){if (view[CCW[xn]].food>0){return {cell:CCW[xn]};} else if (view[CCW[xn+7]].food +view[CCW[xn+6]].food>0){return {cell:POSC,color:LLSF};} else {return {cell:CCW[xn]};}} else if ((eT>0)&&view[CCW[xn+2]].ant&&!view[CCW[xn+2]].ant.friend){return {cell:POSC,color:LLSF};} else if ((fT>1)&&((view[CCW[xn+6]].ant&&view[CCW[xn+6]].ant.friend&&
(view[CCW[xn+6]].ant.food>0))||(view[CCW[xn+5]].ant&&view[CCW[xn+5]].ant.friend&&
(view[CCW[xn+5]].ant.food>0)))){return {cell:POSC,color:LLSF};} else {if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};}}return NOP;}function rNRSy(){if (view[CCW[xn+1]].ant&&view[CCW[xn+1]].ant.friend&&
(view[CCW[xn+1]].ant.type==mT)){if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else {return NOP;}} else if (view[CCW[xn+7]].ant&&view[CCW[xn+7]].ant.friend&&(view[CCW[xn+7]].ant.type==mT)){if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else {return NOP;}} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+2]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}}function rPPgSy(){if (aLF[AMK]+aLF[AGS] +aLF[AWM]>0){for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.food>0)){if (dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else if (dOK[CCW[i+3]]){return {cell:CCW[i+3]};} else if (dOK[CCW[i+5]]){return {cell:CCW[i+5]};}}}} else if (aF[mT]>0){return (rSPTc());}return (rPPgTc());}function rMPgSy(){if (aF[mT]>0){return (rSPTc());}return (rMPgTc());}function rGPgSy(){if (aF[mT]>0){return (rSPTc());}return (rGPgTc());}function rWPgSy(){if (aF[mT]>0){return (rSPTc());}return (rWPgTc());}function rCPgSy(){var phase=0;for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==AGS)){xn=i&6;phase=i&1;break;}}if ((phase==1)&&(mC==view[CCW[xn+7]].color)&&(view[CCW[xn]].color==view[CCW[xn+1]].color)){if (dOK[CCW[xn+3]]){return {cell:CCW[xn+3]};} else if (dOK[CCW[xn]]){return {cell:CCW[xn]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}} else {return {cell:CCW[xn+7],color:mC};}return NOP;}function rJPgSy(){var phase=0;for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==AMK)){xn=i&6;phase=i&1;break;}}if (phase==0){if (dOK[CCW[xn+7]]){return {cell:CCW[xn+7]};} else if (dOK[CCW[xn+1]]){return {cell:CCW[xn+1]};} else if (dOK[CCW[xn+4]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else if (dOK[CCW[xn+6]]){return {cell:CCW[xn+6]};} else {return NOP;}} else {return {cell:CCW[xn+3],color:mC};}return NOP;}function rPEgSy(){for (var i=0; i<TN; i++){if ((view[CCW[i]].food>0)&&dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}function rPMgSy(){for (var i=0; i<TN; i+=2){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type!=mT)){if (dOK[CCW[i+1]]&&!view[CCW[i+7]].ant&&!view[CCW[i+2]].ant&&!view[CCW[i+3]].ant){return {cell:CCW[i+1]};} else if (dOK[CCW[i+7]]&&!view[CCW[i+1]].ant&&
!view[CCW[i+6]].ant&&!view[CCW[i+5]].ant){return {cell:CCW[i+7]};}}}for (var i=1; i<TN; i+=2){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type!=mT)){if (dOK[CCW[i-1]]&&!view[CCW[i+6]].ant){return {cell:CCW[i-1]};} else if (dOK[CCW[i+1]]&&!view[CCW[i+2]].ant){return {cell:CCW[i+1]};}}}for (var i=0; i<TN; i++){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return {cell:POSC,color:view[CCW[0]].color};}function rQSETc(){if (mC!=LT){return {cell:POSC,color:LT};}for (var i=0; i<TN; i++){if (view[CCW[i]].food>0){return {cell:CCW[i]};}}return NOP;}function rQSSTc(){for (var i=0; i<TN; i++){if ((view[CCW[i]].food>0)&&(dOK[CCW[i]])){return {cell:CCW[i]};}}return NOP;}function rQSTCTc(){if ((mC!=LCLR)&&(sN[mC]>=4)){if (sN[LT]==0){return {cell:POSC,color:LT};} else if (sN[LT]>=3){return {cell:POSC,color:LT};} else {for (var i=0; i<TN; i++){if ((view[CCW[i]].color==LT)&&(view[CCW[i+2]].color!=LT)){return {cell:CCW[i+2],color:LT};}}return NOP;}} else if (sN[LT]==1){for (var i=0; i<TN; i++){if ((view[CCW[i]].color==LT)&&(view[CCW[i+4]].color!=LCLR)){if (view[CCW[i+1]].color==LCLR){return { cell:CCW[i+1]};} else if (view[CCW[i+7]].color==LCLR){return { cell:CCW[i+7]};} else {return {cell:POSC,color:LT};}}}return {cell:POSC,color:LT};} else {return {cell:POSC,color:LT};}return NOP;}function rQSATc(){for (var i=0; i<TN; i++){if ((view[CCW[i]].color==LCLR)&&(view[CCW[i+1]].color==LCLR)&&(view[CCW[i+2]].color==LCLR)){if ((view[CCW[i+3]].color==LCLR)&&(view[CCW[i+4]].color==LCLR)){return {cell:CCW[i+2]};}return {cell:CCW[i+1]};}}for (var i=TN-1; i>=0; i--){if (view[CCW[i]].color!=LT){return {cell:CCW[i]};}}for (var i=0; i<TN; i++){if (view[CCW[i]].color!=LT){return {cell:CCW[i],color:LCLR};}}return {cell:0,color:LCLR};}function rQSEvTc(){if (sN[LT]>0){for (var i=0; i<TN; i++){if (view[CCW[i]].color==LT){xn=i&6;}}if ( dOK[CCW[xn+7]]&&dOK[CCW[xn]]&&dOK[CCW[xn+1]]&&dOK[CCW[xn+2]]&&dOK[CCW[xn+3]] ){return {cell:CCW[xn+1]};} else if (dOK[CCW[xn+5]]&&dOK[CCW[xn+6]]&&dOK[CCW[xn+7]]&&dOK[CCW[xn]]&&dOK[CCW[xn+1]]){return {cell:CCW[xn+7]};} else if (dOK[CCW[xn+3]]&&dOK[CCW[xn+4]]&&dOK[CCW[xn+5]]){return {cell:CCW[xn+4]};} else if (dOK[CCW[xn+5]]&&dOK[CCW[xn+6]]&&dOK[CCW[xn+7]]){return {cell:CCW[xn+6]};} else if (dOK[CCW[xn+1]]&&dOK[CCW[xn+2]]&&dOK[CCW[xn+3]]){return {cell:CCW[xn+2]};} else if (dOK[CCW[xn+7]]&&dOK[CCW[xn]]&&dOK[CCW[xn+1]]){return {cell:CCW[xn]};} else {for (var i=0; i<TN; i++){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}} else {for (var i=0; i<TN; i++){if (dOK[CCW[i]]&&dOK[CCW[i+1]]&&dOK[CCW[i+2]]&&dOK[CCW[i+3]]&&dOK[CCW[i+4]]){return {cell:CCW[i+2]};}}for (var i=0; i<TN; i++){if (dOK[CCW[i]]&&dOK[CCW[i+1]]&&dOK[CCW[i+2]]){return {cell:CCW[i+1]};}}for (var i=0; i<TN; i++){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}return NOP;}function rPPgTc(){if (sL[mC]==0){return {cell:1,color:mC};}for (var i=1; i<TN; i+=2){if (view[CCW[i]].color==mC){xn=i&6;break;}}var col1=(mC+1) % 8+1;if ((view[CCW[xn+5]].color==mC)&&(view[CCW[xn+3]].color==col1)&&(view[CCW[xn+7]].color!=col1)){xn=(xn+4) % 8;}if (view[CCW[xn+7]].color!=col1){return {cell:CCW[xn+7],color:col1};} else if (view[CCW[xn]].color!=col1){return {cell:CCW[xn],color:col1};}var col2=(mC+5) % 8+1;if (view[CCW[xn+3]].color!=col2){return {cell:CCW[xn+3],color:col2};} else if (view[CCW[xn+2]].color!=col2){return {cell:CCW[xn+2],color:col2};} else if (view[CCW[xn+5]].color!=mC){return {cell:CCW[xn+5],color:mC};} else if (view[CCW[xn+4]].color!=col2){return {cell:CCW[xn+4],color:col2};} else if (dOK[CCW[xn+5]]){return {cell:CCW[xn+5]};} else {return (rWgPTc());}}function rMPgTc(){switch (sT[mC]){case 9:var col=((mC+2) % 8)+1;return {cell:CCW[0],color:col};case 8:for (var i=0; i<TN; i++){var col=view[CCW[i]].color;if (col!=mC){if (i==0){return {cell:POSC,color:col};} else if ((i==1)&&dOK[CCW[i+3]]){return {cell:CCW[i+3]};} else if ((i==2)&&dOK[CCW[i+5]]){return {cell:CCW[i+5]};} else {return {cell:CCW[i-1],color:col};}}}break;case 7:return rWgPTc();case 6:for (var i=0; i<TN; i++){if (view[CCW[i]].color!=mC){if ((i==0)&&dOK[CCW[i+5]]){return {cell:CCW[i+5]};} else if ((i==1)&&dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else {return {cell:CCW[i],color:mC};}}}break;case 5:case 4:case 3:for (var i=0; i<TN; i++){if (view[CCW[i]].color!=mC){return {cell:CCW[i],color:mC};}}break;case 2:case 1:default:for (var i=TN-1; i>=0; i--){var col=view[CCW[i]].color;if ((col==mC)&&(sT[view[CCW[i+4]].color]==7)&&dOK[CCW[i+4]]){return {cell:CCW[i+4]};}if (sT[col]>=3){return {cell:POSC,color:col};}}var col=view[CCW[1]].color;if (view[CCW[0]].color!=col){return {cell:CCW[0],color:col};} else if (view[CCW[2]].color!=col){return {cell:CCW[2],color:col};}break;}return (rWgPTc());}function rGPgTc(){var col=0;for (var c0=view[CCW[0]].color; c0<view[CCW[0]].color+8; c0++){var c=(c0 % 8)+1;if (sN[c]==0){col=c;}}if (col==0){return (rWgPTc());}for (var i=0; i<TN; i++){if (sN[view[CCW[i]].color]>1){return {cell:CCW[i],color:col};}}return (rWgPTc());}function rWPgTc(){var col=((mC+6) % 8)+1;if (sT[mC]==9){return {cell:CCW[0],color:col};}var myRand=(view[CCW[0]].color+sT[view[CCW[2]].color]) % 3;
switch (myRand){case 0:for (var i=0; i<TN; i+=2){if (dOK[CCW[i]]){return {cell:CCW[i]};}}break;case 1:if (view[CCW[1]].color!=view[CCW[7]].color){return {cell:CCW[1],color:view[CCW[7]].color};} else if (view[CCW[5]].color!=view[CCW[3]].color){return {cell:CCW[5],color:view[CCW[3]].color};}break;case 2:if (view[CCW[5]].color!=view[CCW[3]].color){return {cell:CCW[5],color:view[CCW[3]].color};} else if (view[CCW[1]].color!=view[CCW[7]].color){return {cell:CCW[1],color:view[CCW[7]].color};}break;default:break;}for (var i=1; i<TN; i+=2){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return (rWgPTc());}function rSPTc(){for (var i=0; i<TN; i++){if (view[CCW[i]].ant&&view[CCW[i]].ant.friend&&
(view[CCW[i]].ant.type==mT)){if (dOK[CCW[i+4]]){return {cell:CCW[i+4]};} else if (dOK[CCW[i+3]]){return {cell:CCW[i+3]};} else if (dOK[CCW[i+5]]){return {cell:CCW[i+5]};} else if (dOK[CCW[i+2]]){return {cell:CCW[i+2]};} else if (dOK[CCW[i+6]]){return {cell:CCW[i+6]};} else if (dOK[CCW[i+1]]){return {cell:CCW[i+1]};}}}return NOP;}function rWgPTc(){for (var i=0; i<TN; i++){if (dOK[CCW[i]]){return {cell:CCW[i]};}}return NOP;}

উপভোগ করুন!

** v1.0.1 এখন কঠোর-মোড নিয়ন্ত্রণকারীদের সাথে সামঞ্জস্যপূর্ণ।

** v1.0.2 একটি অযোগ্যতা টাইপ সংশোধন করে


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

অ্যালিয়ন দ্য ভিনসঅ্যান্ট চিত্রশিল্পীরা মাঝে মধ্যে অন্যের মধ্যে উইন্ডমিল পিঁপড়াকে বিভ্রান্ত করার ব্যবস্থা করে এবং শত্রু কর্মীদের বাধা দেয় বা স্লাইডিং মাইনার বা উইন্ডমিল খনিবিদদের ভুল জায়গায় নতুন রেলপথ শুরু করতে বাধ্য করে - তবে যদি লাইটস্পিডও একই গেমসে খেলছে, তবে লাইটস্পিডও উপকৃত হবে ...
GNiklasch

গঠনের অনিশ্চিত সংস্করণ শত্রু কর্মীদের কাছাকাছি থাকা এবং তাদের আবর্জনা দিয়ে আচ্ছন্ন করার চেষ্টা করে, তবে এটি সর্বদা রেল endingণদানের দিকে পরিচালিত করে না। এমনকি এটি করার পরেও, এটি অস্বাভাবিক কিছু নয় যে এটি রানির কাছে এবং নেভিগেট করার জন্য অন্যান্য শ্রমিকদের দক্ষতার উপর চাপ সৃষ্টি করে। আমার কাছ থেকে এটি গ্রহণ করুন, রেল বাসাগুলি বিভ্রান্ত করা বেশ শক্ত।
eaglgenes101

@ থ্রিচোপ্লেক্স স্থির - দুঃখিত এবং ধন্যবাদ!
GNiklasch

2

HalfThere

if(view[4].ant.type==5&&view[4].food>1)
{
    for(var i = 0; i<9; i++)
    {
        if(!view[i].ant)
        {
            return{cell:i,type: 1};
        }
    }
}
if(view[4].color != 3){
    return {cell: 4, color: 3};
}
for(var i = 0; i<9; i++)
{
    if(view[i].food==1)
    {
        return({cell:i})
    }

}


var i, j
var orthogonals = [1, 3, 7, 5]  // These are the non-diagonal cells



// Otherwise move to a white cell opposite a colored cell
for (i=0; i<4; i++) {
    j = (i+2) % 4
    if (view[orthogonals[i]].color === 1 &&
        view[orthogonals[j]].color > 1 && !view[orthogonals[i]].ant) {
        return {cell:orthogonals[i]}
    }
}

// Otherwise move to one of the vertical or horizontal cells if not occupied
for (i=1; i<9; i+=2) {
    if (!view[i].ant) {
        return {cell:i}
    }
}

// Otherwise move to one of the diagonal cells if not occupied
for (i=0; i<9; i+=2) {
    if (!view[i].ant) {
        return {cell:i}
    }
}


for(var i = 0; i<9; i++)
{
    if(view[i].color==1)
    {
        return {cell:i};
    }
}
for(var i = 0; i<9; i++)
{
    if(view[i].ant==null)
    {
        return {cell:i};
    }
}

এই বটটি অর্ধেক আছে ... মূলত এটি কেবল একটি রেখা তৈরি করে এবং একটি সরলরেখায় যায় এবং কিন্ডা যদি অন্য কোনও লাইন দেখেন তবে চারপাশে ড্রপ হয়।

এটি অগ্রগতি কাজ একটি কাজ।


এটি বহিরাগত পরিস্থিতিতে খাদ্যে শ্রমিক তৈরি করার জন্য অযোগ্য ঘোষণা করতে পারে
পিপ্পারি

@ পিপারি আসলে এটি করতে পারে না। কখনও কর্মী করে না: /
ক্রিস্টোফার

আসলে, এটা না, কারণ "কর্মী তৈরি করুন 'যুক্তিবিজ্ঞান শুধু মৃত কোড ইশারা মূল্য পারেন এখনও।
pppery

আমি মৃত view[4].food > 1চেক দ্বারা বিভ্রান্ত হয়ে পড়েছিলাম , যা আমি নিজেই একবার ভুল করেছিলাম
পিপ্পারি

1
পরিবর্তন view[4].food > 1করার জন্য view[4].ant.food > 1প্রথমে লাইন
pppery
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.