রঙের চিত্র যুদ্ধ


33

সেরা প্রবেশের জন্য @ কুরোইনকোকে অভিনন্দন এবং @ দ্য বেস্টওন (দুর্দান্ত ক্রীড়াবিদ!) থেকে 200 বন্টি জয়ের জন্য

বিরোধী প্রোগ্রামগুলি করার আগে যতটা সম্ভব একটি চিত্র রঙ করতে একটি প্রোগ্রাম লিখুন।

সংক্ষেপে বিধি

  • আপনার প্রোগ্রামকে একটি চিত্র, আপনার রঙ এবং পূর্ণসংখ্যা এন দেওয়া হবে।
  • প্রতিটি টার্নে আপনাকে অন্যান্য প্রোগ্রাম দ্বারা পিক্সেল আপডেট পাঠানো হয় এবং আপনার এন আপডেটের জন্য বলা হয়।
  • আপনার রঙের একটি পিক্সেলের পাশে থাকা কোনও সাদা পিক্সেল আপডেট করতে পারেন।
  • যে প্রোগ্রামটি সর্বাধিক পিক্সেল জয় করেছে।

বিধি বিধি

আপনার প্রোগ্রামকে একটি পিএনজি চিত্র ফাইলের নাম, বাড়ির রঙ এবং একটি নম্বর এন দেওয়া হবে N

উদাহরণ: MyProg arena.png (255,0,0) 30

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

আপনার লক্ষ্য হ'ল আপনার প্রতিপক্ষকে অবরুদ্ধ করুন এবং আপনার রঙটি যতটা সম্ভব পিক্সেলে লিখুন।

প্রতিটি টার্ন আপনার প্রোগ্রামটি STDIN- এ 1 বা একাধিক বার্তা লাইন গ্রহণ করবে এবং STDOUT এ পিক্সেল স্থানাঙ্কের সমন্বয়ে একটি লাইন লিখবে। STDOUT আনবুফার্ড হিসাবে নির্ধারণ করতে বা প্রতিটি টার্নে STDOUT বাফারটি ফ্লাশ করুন।

প্রতিটি টার্ন নামে পরিচিত প্লেয়ারদের ক্রম এলোমেলোভাবে বরাদ্দ করা হবে। এর অর্থ হ'ল প্রতিপক্ষের (বা আপনার প্রোগ্রাম) একক সারিতে 2 টি পালা থাকতে পারে।

আপনার প্রোগ্রামটিতে এমন colour (N,N,N) chose X,Y X,Y ... X,Yতথ্য বার্তাগুলি প্রেরণ করা হবে যা প্লেয়ার প্রোগ্রাম দ্বারা পূর্ণ পিক্সেলগুলি বর্ণনা করে। যদি কোনও খেলোয়াড় কোনও পদক্ষেপ না নেয় বা কোনও বৈধ চালনা না করে তবে আপনাকে সেই খেলোয়াড়ের চাল সম্পর্কে কোনও বার্তা প্রেরণ করা হবে না। আপনার প্রোগ্রামটি আপনার নিজস্ব গৃহীত পদক্ষেপগুলি সম্পর্কে একটি বার্তাও প্রেরণ করা হবে (যদি আপনি কমপক্ষে একটি বৈধ পদক্ষেপ নির্দিষ্ট করে থাকেন)। পিক্সেল 0,0 চিত্রের উপরের বাম কোণে রয়েছে।

পাওয়ার পরে pick pixels, আপনার প্রোগ্রামটি X,Y X,Y ... X,Yএন পিক্সেল পর্যন্ত আউটপুট দেবে (খালি স্ট্রিংটিতে কেবল একটি '\ n' থাকা অনুমোদিত)) পিক্সেলগুলি প্লট করার ক্ষেত্রে অবশ্যই হবে। যদি কোনও পিক্সেল অবৈধ হয় তবে তা উপেক্ষা করা হবে এবং খেলোয়াড়দের প্রতিবেদনে থাকবে না। আপনার প্রোগ্রামটি শুরু হওয়ার পরে আরম্ভের জন্য 2 সেকেন্ড রয়েছে, তবে প্রতি বারের সাথে একটি উত্তর দিয়ে উত্তর দিতে কেবল 0.1 সেকেন্ড রয়েছে বা এটি সেই পরিবর্তনটি মিস করবে। 0.1 সেকেন্ডের পরে পাঠানো একটি পিক্সেল আপডেট ত্রুটি রেকর্ড করবে। 5 টি ত্রুটির পরে আপনার প্রোগ্রামটি স্থগিত করা হয়েছে এবং আপডেট বা pick pixelsঅনুরোধগুলি প্রেরণ করা হবে না ।

যখন বিচারক প্রোগ্রামটি প্রতিটি অ-স্থগিত প্লেয়ার প্রোগ্রাম থেকে একটি খালি বা অবৈধ পিক্সেল পছন্দ পান, তখন চিত্রটি সম্পূর্ণ বিবেচনা করা হবে এবং প্রোগ্রামগুলি "প্রস্থান" বার্তা প্রেরণ করা হবে। প্রোগ্রামগুলি "প্রস্থান" পাওয়ার পরে শেষ করতে হবে।

স্কোরিং

চিত্রটি সম্পূর্ণ হওয়ার পরে বিচারক পয়েন্ট স্কোর করবেন। আপনার স্কোর শতাংশ হিসাবে প্রকাশিত, সেই রাউন্ডে গড়ে পিক্সেল ক্যাপচার দ্বারা বিভক্ত আপডেট হওয়া আপনার পিক্সেলের সংখ্যা হবে।

আপনার প্লেয়ার দ্বারা চিত্রটিতে যুক্ত পিক্সেলের সংখ্যা হ'ল সমস্ত পি প্লেয়ারের দ্বারা যুক্ত পিক্সেলের মোট সংখ্যা টি T avg = T/P score = 100*A/avg

স্কোর পোস্টিং

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

যদি ব্লবটি মারতে খুব সহজ প্রমাণিত হয় তবে আমি শক্তিশালী রেফারেন্স প্রতিপক্ষের সাথে দ্বিতীয় রাউন্ড যুক্ত করতে পারি।

আপনি 4 বা ততোধিক প্লেয়ার প্রোগ্রাম ব্যবহার করতেও পছন্দ করতে পারেন। আপনি উত্তর হিসাবে পোস্ট করা অন্যান্য বটের বিরুদ্ধেও আপনার বট পরীক্ষা করতে পারেন।

বিচারক

জাজ প্রোগ্রামে সাধারণ পাইথন ইমেজিং লাইব্রেরি (পিআইএল) প্রয়োজন এবং লিনাক্সে আপনার ওএস প্যাকেজ ম্যানেজারের কাছ থেকে ইনস্টল করা সহজ হওয়া উচিত। আমার কাছে একটি প্রতিবেদন রয়েছে যে পিআইএল উইন্ডোজ on-তে 64৪ বিট পাইথন নিয়ে কাজ করে না, সুতরাং দয়া করে এই চ্যালেঞ্জটি শুরু করার আগে পিআইএল আপনার পক্ষে কাজ করবে কিনা তা পরীক্ষা করুন (2015-01-29 আপডেট হয়েছে)

#!/usr/bin/env python
# Judge Program for Image Battle challenge on PPCG.
# Runs on Python 2.7 on Ubuntu Linux. May need edits for other platforms.
# V1.0 First release.
# V1.1 Added Java support
# V1.2 Added Java inner class support
# usage: judge cfg.py
import sys, re, random, os, shutil, subprocess, datetime, time, signal
from PIL import Image

ORTH = ((-1,0), (1,0), (0,-1), (0,1))
def place(loc, colour):
    # if valid, place colour at loc and return True, else False
    if pix[loc] == (255,255,255):
        plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
        if any(pix[p]==colour for p in plist if 0<=p[0]<W and 0<=p[1]<H):
            pix[loc] = colour
            return True
    return False

def updateimage(image, msg, bot):
    if not re.match(r'(\s*\d+,\d+)*\s*', msg):
        return []
    plist = [tuple(int(v) for v in pr.split(',')) for pr in msg.split()]
    plist = plist[:PIXELBATCH]
    return [p for p in plist if place(p, bot.colour)]

class Bot:
    botlist = []
    def __init__(self, name, interpreter=None, colour=None):
        self.prog = name
        self.botlist.append(self)
        callarg = re.sub(r'\.class$', '', name)  # Java fix
        self.call = [interpreter, callarg] if interpreter else [callarg]
        self.colour = colour
        self.colstr = str(colour).replace(' ', '')
        self.faults = 0
        self.env = 'env%u' % self.botlist.index(self)
        try: os.mkdir(self.env)
        except: pass
        if name.endswith('.class'): # Java inner class fix
            rootname = re.sub(r'\.class$', '', name)
            for fn in os.listdir('.'):
                if fn.startswith(rootname) and fn.endswith('.class'):
                    shutil.copy(fn, self.env)
        else:
            shutil.copy(self.prog, self.env)
        shutil.copy(imagename, self.env)
        os.chdir(self.env)
        args = self.call + [imagename, self.colstr, `PIXELBATCH`]
        self.proc = subprocess.Popen(args, stdin=subprocess.PIPE, 
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        os.chdir('..')
    def send(self, msg):
        if self.faults < FAULTLIMIT:
            self.proc.stdin.write(msg + '\n')
            self.proc.stdin.flush()
    def read(self, timelimit):
        if self.faults < FAULTLIMIT:
            start = time.time()
            inline = self.proc.stdout.readline()
            if time.time() - start > timelimit:
                self.faults += 1
                inline = ''
            return inline.strip()
    def exit(self):
        self.send('exit')

from cfg import *
for i, (prog, interp) in enumerate(botspec):
    Bot(prog, interp, colourspec[i])

image = Image.open(imagename)
pix = image.load()
W,H = image.size

time.sleep(INITTIME)
total = 0
for turn in range(1, MAXTURNS+1):
    random.shuffle(Bot.botlist)
    nullbots = 0
    for bot in Bot.botlist:
        bot.send('pick pixels')
        inmsg = bot.read(TIMELIMIT)
        newpixels = updateimage(image, inmsg, bot)
        total += len(newpixels)
        if newpixels:
            pixtext = ' '.join('%u,%u'%p for p in newpixels)
            msg = 'colour %s chose %s' % (bot.colstr, pixtext)
            for msgbot in Bot.botlist:
                msgbot.send(msg)
        else:
            nullbots += 1
    if nullbots == len(Bot.botlist):
        break
    if turn % 100 == 0: print 'Turn %s done %s pixels' % (turn, total)
for msgbot in Bot.botlist:
    msgbot.exit()

counts = dict((c,f) for f,c in image.getcolors(W*H))
avg = 1.0 * sum(counts.values()) / len(Bot.botlist)
for bot in Bot.botlist:
    score = 100 * counts[bot.colour] / avg
    print 'Bot %s with colour %s scored %s' % (bot.prog, bot.colour, score)
image.save(BATTLE+'.png')

উদাহরণ কনফিগার - cfg.py

BATTLE = 'Green Blob vs Red Blob'
MAXTURNS = 20000
PIXELBATCH = 10
INITTIME = 2.0
TIMELIMIT = 0.1
FAULTLIMIT = 5

imagename = 'arena1.png'

colourspec = (0,255,0), (255,0,0)

botspec = [
    ('blob.py', 'python'),
    ('blob.py', 'python'),
    ]

ব্লব - রেফারেন্স প্রতিপক্ষ

# Blob v1.0 - A reference opponent for the Image Battle challenge on PPCG.
import sys, os
from PIL import Image

image = Image.open(sys.argv[1])
pix = image.load()
W,H = image.size
mycolour = eval(sys.argv[2])
pixbatch = int(sys.argv[3])

ORTH = ((-1,0), (1,0), (0,-1), (0,1))
def canchoose(loc, colour):
    if pix[loc] == (255,255,255):
        plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
        if any(pix[p]==colour for p in plist if 0<=p[0]<W and 0<=p[1]<H):
            return True
    return False

def near(loc):
    plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
    pboard = [p for p in plist if 0<=p[0]<W and 0<=p[1]<H]
    return [p for p in pboard if pix[p] == (255,255,255)]

def updateimage(image, msg):
    ctext, colourtext, chose, points = msg.split(None, 3)
    colour = eval(colourtext)
    plist = [tuple(int(v) for v in pr.split(',')) for pr in points.split()]
    for p in plist:
        pix[p] = colour
        skin.discard(p)
        if colour == mycolour:
            for np in near(p):
                skin.add(np)

board = [(x,y) for x in range(W) for y in range(H)]
skin = set(p for p in board if canchoose(p, mycolour))

while 1:
    msg = sys.stdin.readline()
    if msg.startswith('colour'):
        updateimage(image, msg.strip())
    if msg.startswith('pick'):
        plen = min(pixbatch, len(skin))
        moves = [skin.pop() for i in range(plen)]
        movetext = ' '.join('%u,%u'%p for p in moves)
        sys.stdout.write(movetext + '\n')
        sys.stdout.flush()
    if msg.startswith('exit'):
        break

image.save('blob.png')

এরিনা ঘ

arena1.png

এরিনা 2

arena2.png

এরিনা 3

arena3.png

এরিনা 4

arena4.png

একটি উদাহরণ যুদ্ধ - ব্লব বনাম ব্লব

এই যুদ্ধের একটি অনুমানযোগ্য ফলাফল ছিল:

Bot blob.py with colour (255, 0, 0) scored 89.2883333333
Bot blob.py with colour (0, 255, 0) scored 89.365

উদাহরণ যুদ্ধ


আপনি কি নিশ্চিত যে এটি [পাহাড়ের রাজা] হওয়া উচিত নয়?
জাস্টিন

আমি এটা সম্পর্কে চিন্তা। বটগুলি একে অপরের সাথে সরাসরি যুদ্ধ করে না। তারা রেফারেন্স বট যুদ্ধ। এটি কি কোথাও বাতিল করে দেয়?
লজিক নাইট

হ্যাঁ, এটি যেমন কোনও কোথাও নয়, আমি আপনাকে জিজ্ঞাসা করছিলাম যে আপনি যদি নিশ্চিত হন যে আপনি একে অপরের চেয়ে রেফারেন্স বটের সাথে লড়াই করতে চেয়েছিলেন।
জাস্টিন

1
@TheBestOne, যুক্ত জাভা সমর্থন। যদিও জাভা প্রোগ্রামের সাথে অবিচলিত। যদি এটি কাজ না করে তবে আমাকে জানান।
লজিক নাইট

1
10 পিক্সেল যথাযথভাবে স্থাপন করা হয়েছে, সুতরাং পরে পিক্সেলগুলি পূর্ববর্তী পিক্সেল স্থানের উপর নির্ভর করতে পারে। আপনার পরামর্শ অনুসারে তারা একে অপরকে তৈরি করতে পারে।
লজিক নাইট

উত্তর:


17

কালারফাইটার - সি ++ - প্রাতঃরাশের জন্য কয়েকটা গিলে খায়

সম্পাদনা

  • কোড পরিষ্কার
  • একটি সহজ কিন্তু কার্যকর অপ্টিমাইজেশন যুক্ত
  • কিছু জিআইএফ অ্যানিমেশন যুক্ত করেছে

Godশ্বর আমি সাপকে ঘৃণা করি (কেবল ভান করে তারা মাকড়সা, ইন্ডি)

আসলে আমি পাইথনকে ভালবাসি। আমি আশা করি আমি যদি অলস ছেলের চেয়ে কম থাকতাম এবং এটি সঠিকভাবে শিখতে শুরু করি তবেই এটি।

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

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

একটি ছোটখাট উন্নতি হ'ল প্রতিটি বোটের জন্য একটি ফাইলে স্ট্যাডার আউটপুট স্থাপন করা। এটি পোস্ট-মর্টেম ডিবাগিংয়ের জন্য ট্রেসিং সহজ করবে।

এই ছোটখাটো সমস্যা ব্যতীত আমি বিচারককে ব্যবহার করতে খুব সহজ এবং আনন্দদায়ক বলে মনে করি।
কুডোস আরও একটি উদ্ভাবনী এবং মজাদার চ্যালেঞ্জের জন্য।

কোড

#define _CRT_SECURE_NO_WARNINGS // prevents Microsoft from croaking about the safety of scanf. Since every rabid Russian hacker and his dog are welcome to try and overflow my buffers, I could not care less.
#include "lodepng.h"
#include <vector>
#include <deque>
#include <iostream>
#include <sstream>
#include <cassert>   // paranoid android
#include <cstdint>   // fixed size types
#include <algorithm> // min max

using namespace std;

// ============================================================================
// The less painful way I found to teach C++ how to handle png images
// ============================================================================
typedef unsigned tRGB;
#define RGB(r,g,b) (((r) << 16) | ((g) << 8) | (b))
class tRawImage {
public:
    unsigned w, h;

    tRawImage(unsigned w=0, unsigned h=0) : w(w), h(h), data(w*h * 4, 0) {}
    void read(const char* filename) { unsigned res = lodepng::decode(data, w, h, filename); assert(!res);  }
    void write(const char * filename)
    {
        std::vector<unsigned char> png;
        unsigned res = lodepng::encode(png, data, w, h, LCT_RGBA); assert(!res);
        lodepng::save_file(png, filename);
    }
    tRGB get_pixel(int x, int y) const
    {
        size_t base = raw_index(x,y);
        return RGB(data[base], data[base + 1], data[base + 2]);
    }
    void set_pixel(int x, int y, tRGB color)
    {
        size_t base = raw_index(x, y);
        data[base+0] = (color >> 16) & 0xFF;
        data[base+1] = (color >>  8) & 0xFF;
        data[base+2] = (color >> 0) & 0xFF;
        data[base+3] = 0xFF; // alpha
    }
private:
    vector<unsigned char> data;
    void bound_check(unsigned x, unsigned y) const { assert(x < w && y < h); }
    size_t raw_index(unsigned x, unsigned y) const { bound_check(x, y); return 4 * (y * w + x); }
};

// ============================================================================
// coordinates
// ============================================================================
typedef int16_t tCoord;

struct tPoint {
    tCoord x, y;
    tPoint operator+  (const tPoint & p) const { return { x + p.x, y + p.y }; }
};

typedef deque<tPoint> tPointList;

// ============================================================================
// command line and input parsing
// (in a nice airtight bag to contain the stench of C++ string handling)
// ============================================================================
enum tCommand {
    c_quit,
    c_update,
    c_play,
};

class tParser {
public:
    tRGB color;
    tPointList points;

    tRGB read_color(const char * s)
    {
        int r, g, b;
        sscanf(s, "(%d,%d,%d)", &r, &g, &b);
        return RGB(r, g, b);
    }

    tCommand command(void)
    {
        string line;
        getline(cin, line);

        string cmd = get_token(line);
        points.clear();

        if (cmd == "exit") return c_quit;
        if (cmd == "pick") return c_play;

        // even more convoluted and ugly than the LEFT$s and RIGHT$s of Apple ][ basic...
        if (cmd != "colour")
        {
            cerr << "unknown command '" << cmd << "'\n";
            exit(0);
        }
        assert(cmd == "colour");
        color = read_color(get_token(line).c_str());
        get_token(line); // skip "chose"
        while (line != "")
        {
            string coords = get_token(line);
            int x = atoi(get_token(coords, ',').c_str());
            int y = atoi(coords.c_str());
            points.push_back({ x, y });
        }
        return c_update;
    }

private:
    // even more verbose and inefficient than setting up an ADA rendezvous...
    string get_token(string& s, char delimiter = ' ')
    {
        size_t pos = 0;
        string token;
        if ((pos = s.find(delimiter)) != string::npos)
        {
            token = s.substr(0, pos);
            s.erase(0, pos + 1);
            return token;
        }
        token = s; s.clear(); return token;
    }
};

// ============================================================================
// pathing
// ============================================================================
class tPather {

public:
    tPather(tRawImage image, tRGB own_color)
        : arena(image)
        , w(image.w)
        , h(image.h)
        , own_color(own_color)
        , enemy_threat(false)
    {
        // extract colored pixels and own color areas
        tPointList own_pixels;
        color_plane[neutral].resize(w*h, false);
        color_plane[enemies].resize(w*h, false);
        for (size_t x = 0; x != w; x++)
        for (size_t y = 0; y != h; y++)
        {
            tRGB color = image.get_pixel(x, y);
            if (color == col_white) continue;
            plane_set(neutral, x, y);
            if (color == own_color) own_pixels.push_back({ x, y }); // fill the frontier with all points of our color
        }

        // compute initial frontier
        for (tPoint pixel : own_pixels)
        for (tPoint n : neighbour)
        {
            tPoint pos = pixel + n;
            if (!in_picture(pos)) continue;
            if (image.get_pixel(pos.x, pos.y) == col_white)
            {
                frontier.push_back(pixel);
                break;
            }
        }
    }

    tPointList search(size_t pixels_required)
    {
        // flood fill the arena, starting from our current frontier
        tPointList result;
        tPlane closed;
        static tCandidate pool[max_size*max_size]; // fastest possible garbage collection
        size_t alloc;
        static tCandidate* border[max_size*max_size]; // a FIFO that beats a deque anytime
        size_t head, tail;
        static vector<tDistance>distance(w*h); // distance map to be flooded
        size_t filling_pixels = 0; // end of game  optimization

    get_more_results:

        // ready the distance map for filling
        distance.assign(w*h, distance_max);

        // seed our flood fill with the frontier
        alloc = head = tail = 0;
        for (tPoint pos : frontier)
        {
            border[tail++] = new (&pool[alloc++]) tCandidate (pos);
        }

        // set already explored points
        closed = color_plane[neutral]; // that's one huge copy

        // add current result
        for (tPoint pos : result)
        {
            border[tail++] = new (&pool[alloc++]) tCandidate(pos);
            closed[raw_index(pos)] = true;
        }

        // let's floooooood!!!!
        while (tail > head && pixels_required > filling_pixels)
        {
            tCandidate& candidate = *border[head++];
            tDistance  dist = candidate.distance;
            distance[raw_index(candidate.pos)] = dist++;
            for (tPoint n : neighbour)
            {
                tPoint pos = candidate.pos + n;
                if (!in_picture (pos)) continue;
                size_t index = raw_index(pos);
                if (closed[index]) continue;
                if (color_plane[enemies][index])
                {
                    if (dist == (distance_initial + 1)) continue; // already near an enemy pixel

                    // reached the nearest enemy pixel
                    static tPoint trail[max_size * max_size / 2]; // dimensioned as a 1 pixel wide spiral across the whole map
                    size_t trail_size = 0;

                    // walk back toward the frontier
                    tPoint walker = candidate.pos;
                    tDistance cur_d = dist;
                    while (cur_d > distance_initial)
                    {
                        trail[trail_size++] = walker;
                        tPoint next_n;
                        for (tPoint n : neighbour)
                        {
                            tPoint next = walker + n;
                            if (!in_picture(next)) continue;
                            tDistance prev_d = distance[raw_index(next)];
                            if (prev_d < cur_d)
                            {
                                cur_d = prev_d;
                                next_n = n;
                            }
                        }
                        walker = walker + next_n;
                    }

                    // collect our precious new pixels
                    if (trail_size > 0)
                    {
                        while (trail_size > 0)
                        {
                            if (pixels_required-- == 0) return result;       // ;!; <-- BRUTAL EXIT
                            tPoint pos = trail[--trail_size];
                            result.push_back (pos);
                        }
                        goto get_more_results; // I could have done a loop, but I did not bother to. Booooh!!!
                    }
                    continue;
                }

                // on to the next neighbour
                closed[index] = true;
                border[tail++] = new (&pool[alloc++]) tCandidate(pos, dist);
                if (!enemy_threat) filling_pixels++;
            }
        }

        // if all enemies have been surrounded, top up result with the first points of our flood fill
        if (enemy_threat) enemy_threat = pixels_required == 0;
        tPathIndex i = frontier.size() + result.size();
        while (pixels_required--) result.push_back(pool[i++].pos);
        return result;
    }

    // tidy up our map and frontier while other bots are thinking
    void validate(tPointList moves)
    {
        // report new points
        for (tPoint pos : moves)
        {
            frontier.push_back(pos);
            color_plane[neutral][raw_index(pos)] = true;
        }

        // remove surrounded points from frontier
        for (auto it = frontier.begin(); it != frontier.end();) 
        {
            bool in_frontier = false;
            for (tPoint n : neighbour)
            {
                tPoint pos = *it + n;
                if (!in_picture(pos)) continue;
                if (!(color_plane[neutral][raw_index(pos)] || color_plane[enemies][raw_index(pos)]))
                {
                    in_frontier = true;
                    break;
                }
            }
            if (!in_frontier) it = frontier.erase(it); else ++it; // the magic way of deleting an element without wrecking your iterator
        }       
    }

    // handle enemy move notifications
    void update(tRGB color, tPointList points)
    {
        assert(color != own_color);

        // plot enemy moves
        enemy_threat = true;
        for (tPoint p : points) plane_set(enemies, p);

        // important optimization here :
        /*
         * Stop 1 pixel away from the enemy to avoid wasting moves in dogfights.
         * Better let the enemy gain a few more pixels inside the surrounded region
         * and use our precious moves to get closer to the next threat.
         */
        for (tPoint p : points) for (tPoint n : neighbour) plane_set(enemies, p+n);

        // if a new enemy is detected, gather its initial pixels
        for (tRGB enemy : known_enemies) if (color == enemy) return;
        known_enemies.push_back(color);
        tPointList start_areas = scan_color(color);
        for (tPoint p : start_areas) plane_set(enemies, p);
    }

private:
    typedef uint16_t tPathIndex;

    typedef uint16_t tDistance;
    static const tDistance distance_max     = 0xFFFF;
    static const tDistance distance_initial = 0;

    struct tCandidate {
        tPoint pos;
        tDistance distance;
        tCandidate(){} // must avoid doing anything in this constructor, or pathing will slow to a crawl
        tCandidate(tPoint pos, tDistance distance = distance_initial) : pos(pos), distance(distance) {}
    };

    // neighbourhood of a pixel
    static const tPoint neighbour[4];

    // dimensions
    tCoord w, h; 
    static const size_t max_size = 1000;

    // colors lookup
    const tRGB col_white = RGB(0xFF, 0xFF, 0xFF);
    const tRGB col_black = RGB(0x00, 0x00, 0x00);
    tRGB own_color;
    const tRawImage arena;
    tPointList scan_color(tRGB color)
    {
        tPointList res;
        for (size_t x = 0; x != w; x++)
        for (size_t y = 0; y != h; y++)
        {
            if (arena.get_pixel(x, y) == color) res.push_back({ x, y });
        }
        return res;
    }

    // color planes
    typedef vector<bool> tPlane;
    tPlane color_plane[2];
    const size_t neutral = 0;
    const size_t enemies = 1;
    bool plane_get(size_t player, tPoint p) { return plane_get(player, p.x, p.y); }
    bool plane_get(size_t player, size_t x, size_t y) { return in_picture(x, y) ? color_plane[player][raw_index(x, y)] : false; }
    void plane_set(size_t player, tPoint p) { plane_set(player, p.x, p.y); }
    void plane_set(size_t player, size_t x, size_t y) { if (in_picture(x, y)) color_plane[player][raw_index(x, y)] = true; }
    bool in_picture(tPoint p) { return in_picture(p.x, p.y); }
    bool in_picture(int x, int y) { return x >= 0 && x < w && y >= 0 && y < h; }
    size_t raw_index(tPoint p) { return raw_index(p.x, p.y); }
    size_t raw_index(size_t x, size_t y) { return y*w + x; }

    // frontier
    tPointList frontier;

    // register enemies when they show up
    vector<tRGB>known_enemies;

    // end of game optimization
    bool enemy_threat;
};

// small neighbourhood
const tPoint tPather::neighbour[4] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

// ============================================================================
// main class
// ============================================================================
class tGame {
public:
    tGame(tRawImage image, tRGB color, size_t num_pixels)
        : own_color(color)
        , response_len(num_pixels)
        , pather(image, color)
    {}

    void main_loop(void)
    {
        // grab an initial answer in case we're playing first
        tPointList moves = pather.search(response_len);
        for (;;)
        {
            ostringstream answer;
            size_t        num_points;
            tPointList    played;

            switch (parser.command())
            {
            case c_quit: 
                return;

            case c_play:
                // play as many pixels as possible
                if (moves.size() < response_len) moves = pather.search(response_len);
                num_points = min(moves.size(), response_len);
                for (size_t i = 0; i != num_points; i++)
                {
                    answer << moves[0].x << ',' << moves[0].y;
                    if (i != num_points - 1) answer << ' '; // STL had more important things to do these last 30 years than implement an implode/explode feature, but you can write your own custom version with exception safety and in-place construction. It's a bit of work, but thanks to C++ inherent genericity you will be able to extend it to giraffes and hippos with a very manageable amount of code refactoring. It's not anyone's language, your C++, eh. Just try to implode hippos in Python. Hah!
                    played.push_back(moves[0]);
                    moves.pop_front();
                }
                cout << answer.str() << '\n';

                // now that we managed to print a list of points to stdout, we just need to cleanup the mess
                pather.validate(played);
                break;

            case c_update:
                if (parser.color == own_color) continue; // hopefully we kept track of these already
                pather.update(parser.color, parser.points);
                moves = pather.search(response_len); // get cracking
                break;
            }
        }
    }

private:
    tParser parser;
    tRGB    own_color;
    size_t  response_len;
    tPather pather;
};

void main(int argc, char * argv[])
{
    // process command line
    tRawImage raw_image; raw_image.read (argv[1]);
    tRGB my_color = tParser().read_color(argv[2]);
    int num_pixels               = atoi (argv[3]);

    // init and run
    tGame game (raw_image, my_color, num_pixels);
    game.main_loop();
}

এক্সিকিউটেবল বিল্ডিং

আমি পিএনজি চিত্রগুলি পড়তে LODEpng.cpp এবং LODEpng.h ব্যবহার করেছি
অর্ধ ডজন লাইব্রেরি তৈরি না করে কীভাবে কোনও ছবি পড়তে হয় এই मंदির সি ++ ভাষা শেখানোর সবচেয়ে সহজ উপায় সম্পর্কে।
মূল এবং বব এর মামার সাথে LODEpng.cpp সংকলন করুন এবং লিংক দিন।

আমি এমএসভিসি ২০১৩3 দিয়ে সংকলন করেছি, তবে যেহেতু আমি কেবল কয়েকটি এসটিএল বেসিক পাত্রে (ডেক এবং ভেক্টর) ব্যবহার করেছি, এটি জিসিসি দিয়ে কাজ করতে পারে (যদি আপনি ভাগ্যবান হন)।
যদি এটি না হয় তবে আমি একটি মিনিজিডব্লু বিল্ড চেষ্টা করতে পারি , তবে সত্যি বলতে আমি সি ++ বহনযোগ্যতার সমস্যা নিয়ে ক্লান্ত হয়ে পড়ছি।

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

সোয়িলারের বিরুদ্ধে ফলাফল

arena1 arena2 arena3 arena4

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

মূলত, এটি একটি সাধারণ ব্রুট-ফোর্স ফিলিফিল পাথিং।

প্লেয়ারের রঙের সীমান্ত (অর্থাত পিক্সেলগুলিতে কমপক্ষে একটি সাদা প্রতিবেশী রয়েছে) ক্লাসিক দূরত্ব-বন্যার অ্যালগরিদম সম্পাদন করতে বীজ হিসাবে ব্যবহৃত হয়।

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

পছন্দসই দৈর্ঘ্যের প্রতিক্রিয়ার জন্য পর্যাপ্ত পয়েন্ট সংগ্রহ না করা অবধি প্রক্রিয়াটি পুনরাবৃত্তি হবে।

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

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

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

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

রঙ-প্রতি-রঙের ভিত্তিতে শত্রু হ্যান্ডলিং বট সহযোগিতা (পিক্সেল স্থানাঙ্ক ব্যবহার করে একটি গোপন স্বীকৃতি স্বাক্ষর পাস করার জন্য) দুটি উদাহরণও পেতে পারে।
মজার মত শোনাচ্ছে, আমি সম্ভবত চেষ্টা করব :)।

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

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

পারফরম্যান্স সমস্যা

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

গতি ভারী সংকলন-নির্ভর। সাধারণত জিএনইউ মাইক্রোসফ্টকে 30% ব্যবধানে পরাজিত করে (আমি 3 টি পাথিং সম্পর্কিত কোডের চ্যালেঞ্জগুলিতে লক্ষ্য করেছি এমন ম্যাজিক নম্বর) তবে এই মাইলেজটি অবশ্যই আলাদা হতে পারে।

কোডটি তার বর্তমান অবস্থায় সবেমাত্র আখরায়ের ঘাম ভেঙে 4.. উইন্ডোজ পারফিউটারটি 4 থেকে 7% সিপিইউ ব্যবহারের বিষয়ে রিপোর্ট করে, সুতরাং এটি 100 মিমি প্রতিক্রিয়া সময়সীমার মধ্যে 1000x1000 মানচিত্রের সাথে মোকাবিলা করতে সক্ষম হওয়া উচিত।

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

যেহেতু ওপি বাধ্যতামূলকভাবে আখড়ার আকারের সীমা নির্ধারণ করেছে, তাই আমি কিছু গণিতও করেছি এবং দেখেছি যে স্থির ডাটা স্ট্রাকচার সর্বাধিক (অর্থাৎ 1.000.000 পিক্সেল) মাত্রিক কয়েক ডজন মেগাবাইটের বেশি গ্রহণ করবে না, যা আপনার গড় পিসি প্রাতঃরাশের জন্য খায়।
প্রকৃতপক্ষে উইন under এর অধীনে এবং এমএসভিসি ২০১৩ এর সাথে সংকলিত, কোডটি আখরোট 4 তে প্রায় 14 এমবি খরচ করে, যখন সুইলারের দুটি থ্রেড 20Mb এর বেশি ব্যবহার করছে।

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

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

পারফরম্যান্সগুলি উপস্থিত থাকলে আমি নৃশংস সিনট্যাক্স এবং বহনযোগ্যতা (অর্থাত্ মাইক্রোসফ্ট বনাম জিএনইউ) সমস্যাগুলি মোকাবিলা করতে পারি, তবে অবশ্যই এটি ঘটেনি।

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

সুতরাং শেষ পর্যন্ত আমি এসটিএল কনটেইনারগুলি কোডের অ-সমালোচিত অংশগুলিতে রেখে দিয়েছিলাম এবং আমার নিজের পাশবিক বরাদ্দকারী এবং ফিফো দুটি দুটি সার্কা 1970 টি অ্যারে এবং তিনটি স্বাক্ষরবিহীন শর্টস দিয়ে তৈরি করেছি।

গিলে গিলে ফেলা

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

একটি সহজ তবে কার্যকর অপ্টিমাইজেশন

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

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

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

আপনি উন্নতি দেখতে পাচ্ছেন
(যদিও সমস্ত রান তত সফল নয়, আপনি আরও মসৃণ রূপরেখা লক্ষ্য করতে পারেন):

আগে পরে


1
কি দারুন. আমি ভেবেছিলাম যে কিছুই সোয়িলারকে মারবে না। দুর্দান্ত বর্ণনা সহ দুর্দান্ত সমাধান। আমার মনে আছে কে ওআরসি সিটি ভাল পুরানো দিনগুলি থেকে, তবে তারপরে সি অন্ধকার দিকে চলে গেল। আমি মনে করি আপনাদের ভালো লাগবে পাইথন
লজিক নাইট 10

চ্যালেঞ্জ মোকাবেলা করার জন্য এটি একটি সত্যিকারের আনন্দ ছিল ... তাই ... চ্যালেঞ্জিং এবং মজাদার। এটি আমাকে LODEpng পূর্ণ স্কেলের এই ছোট মণিটি পরীক্ষা করার অনুমতি দিয়েছে এবং ফলাফলগুলি এতটাই প্রতিশ্রুতিযুক্ত যে আমি পিএনজি রেসারটি আবার ঘুরে দেখতে পারি, আবার এই কুখ্যাত পোস্ট-ইনক্রিমেন্ট সি-এর সাথে আমার প্রেম / ঘৃণার সম্পর্কের পরীক্ষা করে

1
সময়সীমার মধ্যে রাখার জন্য গিলে ফেলার সময়টি কিছুটা ভুল। মাল্টি-থ্রেডিংয়ের জন্য এটি আংশিক। ভাল করেছ!! আমি মনে করি আমি আমার বোনাস দ্বিগুণ করব ...
TheNumberOne

1
বালিশে 64-বিটের জন্য ডাউনলোড রয়েছে। এটি ঠিক পিল হিসাবে ব্যবহার করা যেতে পারে।
TheNumberOne

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

21

গভীরতা-প্রথম ব্লব বনাম ব্লব

ভাষা = পাইথন (3.2)

স্কোর = 111.475388276 153.34210035

আপডেট: এখন এক ধরণের গ্রিড প্যাটার্ন উত্পাদন Setকরার pop()পদ্ধতিটি পেতে একটি কাস্টম ক্লাস ব্যবহার করে শত্রু থেকে চিত্রের বড় অংশগুলি কাটা শুরুতে আচ্ছাদিত ক্ষেত্রটিকে তাত্পর্যপূর্ণভাবে উন্নত করে। দ্রষ্টব্য: আমি এটির জন্য একটি 12 x 12 গ্রিড ব্যবহার করছি যা গ্রিড আকারের এলোমেলো নমুনার মধ্যে যা arena3 (আপডেটের আগে সবচেয়ে খারাপ স্কোর পেয়েছে) এর জন্য সেরা ফলাফল দিয়েছে বলে মনে হচ্ছে তবে এটি সম্ভবত আরও অনুকূল গ্রিডের আকারটি দেওয়া রঙ্গিন নির্বাচনের জন্য বিদ্যমান।

যতটা সম্ভব নিজস্ব রঙিন পয়েন্ট দ্বারা সীমাবদ্ধ এমন সম্ভাব্য পয়েন্টগুলি বাছাইয়ের পক্ষে করার জন্য আমি রেফারেন্স বটটিতে একটি সাধারণ পরিবর্তনের জন্য গিয়েছিলাম। উন্নতি হতে পারে এটি সম্ভাব্য পয়েন্টগুলি বাছাইয়ের পক্ষেও পরিণত হতে পারে যা যতটা সম্ভব শত্রু বর্ণের পয়েন্ট দ্বারা সীমাবদ্ধ।

dfblob.py:

import sys, os
from PIL import Image

class RoomyIntPairHashSet:
    def __init__(self, firstMax, secondMax):
        self.m1 = firstMax
        self.m2 = secondMax
        self.set = [set() for i in range((firstMax - 1) * (secondMax - 1) + 1)]
        self.len = 0

    def add(self, tup):
        subset = self.set[self.gettuphash(tup)]
        self.len -= len(subset)
        subset.add(tup)
        self.len += len(subset)

    def discard(self, tup):
        subset = self.set[self.gettuphash(tup)]
        self.len -= len(subset)
        subset.discard(tup)
        self.len += len(subset)

    def pop(self):
        for s in self.set:
            if len(s) > 0:
                self.len -= 1
                return s.pop()
        return self.set[0].pop()

    def gettuphash(self, tup):
        return (tup[0] % self.m1) * (tup[1] % self.m2)

    def __len__(self):
        return self.len

gridhashwidth = 12
gridhashheight = 12
image = Image.open(sys.argv[1])
pix = image.load()
W,H = image.size
mycolour = eval(sys.argv[2])
pixbatch = int(sys.argv[3])

ORTH = ((-1,0), (1,0), (0,-1), (0,1))
def canchoose(loc, virtualneighbors, colour, num_neighbors):
    if pix[loc] == (255,255,255):
        plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
        actual_num_neighbors = 0
        for p in plist:
            if 0<=p[0]<W and 0<=p[1]<H and pix[p]==colour or p in virtualneighbors:
                actual_num_neighbors += 1
        return num_neighbors == actual_num_neighbors
    return False

def near(loc, exclude):
    plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
    pboard = [p for p in plist if 0<=p[0]<W and 0<=p[1]<H]
    return [p for p in pboard if pix[p] == (255,255,255) and p not in exclude]

def updateimage(image, msg):
    ctext, colourtext, chose, points = msg.split(None, 3)
    colour = eval(colourtext)
    plist = [tuple(int(v) for v in pr.split(',')) for pr in points.split()]
    for p in plist:
        pix[p] = colour
        for i in range(len(skins)):
            skins[i].discard(p)
        if colour == mycolour:
            for np in near(p, []):
                for j in range(len(skins)):
                    skins[j].discard(np)
                    if canchoose(np, [], mycolour, j + 1):
                        skins[j].add(np)


board = [(x,y) for x in range(W) for y in range(H)]
skins = []
for i in range(1, 1 + len(ORTH)):
    skin = RoomyIntPairHashSet(gridhashwidth, gridhashheight)
    skins.append(skin)
    for p in board:
        if canchoose(p, [], mycolour, i):
            skin.add(p)

while 1:
    msg = sys.stdin.readline()
    print("got message "+ msg, file=sys.stderr)
    if msg.startswith('colour'):
        print("updating image", file=sys.stderr)
        updateimage(image, msg.strip())
        print("updated image", file=sys.stderr)
    if msg.startswith('pick'):
        moves = []
        print("picking moves", file=sys.stderr)
        virtualskins = [RoomyIntPairHashSet(gridhashwidth, gridhashheight) for i in range(len(skins))]
        for i in range(pixbatch):
            for j in range(len(skins)):
                if len(virtualskins[j]) > 0 or len(skins[j]) > 0:
                    move = None
                    if len(virtualskins[j]) > 0:
                        move = virtualskins[j].pop()
                    else:
                        move = skins[j].pop()
                    moves.append(move)
                    print("picking move (%u,%u) " % move, file=sys.stderr)
                    for p in near(move, moves):
                        for k in range(len(skins)):
                            virtualskins[k].discard(p)
                            if canchoose(p, moves, mycolour, k + 1):
                                virtualskins[k].add(p)
                    break
        movetext = ' '.join('%u,%u'%p for p in moves)
        print("picked %u moves" % (len(moves)), file=sys.stderr)
        sys.stdout.write(movetext + '\n')
        sys.stdout.flush()
    if msg.startswith('exit') or len(msg) < 1:
        break

image.save('dfblob.png')

পাইথন ৩.২ (এবং অ্যানিমেশন তৈরির জন্য পর্যায়ক্রমে আয়নার চিত্র সংরক্ষণের চিত্রগুলিতে একটি অশোধিত লগিং কার্যকারিতা যুক্ত করতে) আসল বিচারককে কিছুটা পরিবর্তন করা হয়েছে:

import sys, re, random, os, shutil, subprocess, datetime, time, signal, io
from PIL import Image

ORTH = ((-1,0), (1,0), (0,-1), (0,1))
def place(loc, colour):
    # if valid, place colour at loc and return True, else False
    if pix[loc] == (255,255,255):
        plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
        if any(pix[p]==colour for p in plist if 0<=p[0]<W and 0<=p[1]<H):
            pix[loc] = colour
            return True
    return False

def updateimage(image, msg, bot):
    if not re.match(r'(\s*\d+,\d+)*\s*', msg):
        return []
    plist = [tuple(int(v) for v in pr.split(',')) for pr in msg.split()]
    plist = plist[:PIXELBATCH]
    return [p for p in plist if place(p, bot.colour)]

class Bot:
    botlist = []
    def __init__(self, name, interpreter=None, colour=None):
        self.prog = name
        self.botlist.append(self)
        callarg = re.sub(r'\.class$', '', name)
        self.call = [interpreter, callarg] if interpreter else [callarg]
        self.colour = colour
        self.colstr = str(colour).replace(' ', '')
        self.faults = 0
        self.env = 'env%u' % self.botlist.index(self)
        try: os.mkdir(self.env)
        except: pass
        shutil.copy(self.prog, self.env)
        shutil.copy(imagename, self.env)
        os.chdir(self.env)
        args = self.call + [imagename, self.colstr, str(PIXELBATCH)]
        errorfile = 'err.log'
        with io.open(errorfile, 'wb') as errorlog:
            self.proc = subprocess.Popen(args, stdin=subprocess.PIPE, 
                stdout=subprocess.PIPE, stderr=errorlog)
        os.chdir('..')
    def send(self, msg):
        if self.faults < FAULTLIMIT:
            self.proc.stdin.write((msg+'\n').encode('utf-8'))
            self.proc.stdin.flush()
    def read(self, timelimit):
        if self.faults < FAULTLIMIT:
            start = time.time()
            inline = self.proc.stdout.readline().decode('utf-8')
            if time.time() - start > timelimit:
                self.faults += 1
                inline = ''
            return inline.strip()
    def exit(self):
        self.send('exit')

from cfg import *
for i, (prog, interp) in enumerate(botspec):
    Bot(prog, interp, colourspec[i])

image = Image.open(imagename)
pix = image.load()
W,H = image.size
os.mkdir('results')

time.sleep(INITTIME)
total = 0
for turn in range(1, MAXTURNS+1):
    random.shuffle(Bot.botlist)
    nullbots = 0
    for bot in Bot.botlist:
        bot.send('pick pixels')
        inmsg = bot.read(TIMELIMIT)
        newpixels = updateimage(image, inmsg, bot)
        total += len(newpixels)
        if newpixels:
            pixtext = ' '.join('%u,%u'%p for p in newpixels)
            msg = 'colour %s chose %s' % (bot.colstr, pixtext)
            for msgbot in Bot.botlist:
                msgbot.send(msg)
        else:
            nullbots += 1
    if nullbots == len(Bot.botlist):
        break
    if turn % 100 == 0:
        print('Turn %s done %s pixels' % (turn, total))
        image.save("results/"+BATTLE+str(turn//100).zfill(3)+'.png')
for msgbot in Bot.botlist:
    msgbot.exit()

counts = dict((c,f) for f,c in image.getcolors(W*H))
avg = 1.0 * sum(counts.values()) / len(Bot.botlist)
for bot in Bot.botlist:
    score = 100 * counts[bot.colour] / avg
    print('Bot %s with colour %s scored %s' % (bot.prog, bot.colour, score))
image.save(BATTLE+'.png')

অঙ্গনের ফলাফল অনুসরণ। ডিএফব্লব বটকে সমস্ত অঙ্গনের জন্য লাল রঙ দেওয়া হয়েছিল।

এরিনা 1:

Bot dfblob.py with colour (255, 0, 0) scored 163.75666666666666
Bot blob.py with colour (0, 255, 0) scored 14.896666666666667

1

এরিনা 2:

Bot blob.py with colour (0, 255, 0) scored 17.65563547726219
Bot dfblob.py with colour (255, 0, 0) scored 149.57006774236964

2

এরিনা 3:

Bot blob.py with colour (0, 255, 0) scored 21.09758208782965
Bot dfblob.py with colour (255, 0, 0) scored 142.9732433108277

3

এরিনা 4:

Bot blob.py with colour (0, 255, 0) scored 34.443810082244205
Bot dfblob.py with colour (255, 0, 0) scored 157.0684236785121

4


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

পাইথন 3 তে পিআইএল ব্যবহার করতে, আপনি কি বালিশ ব্যবহার করছেন ?
ট্রাইকোপলাক্স

@githubphagocyte হ্যাঁ
সামায়োনু

এই জিআইএফগুলি তৈরি করতে আপনি কোন সফ্টওয়্যার ব্যবহার করেছেন?
TheNumberOne

1
@TheBestOne আমি ব্যবহৃত করে ImageMagick বিশেষভাবে কমান্ড convert -delay 5 -loop 0 result*.png animated.gifযদিও GIFs কিছু পরে নিজে কেটে এখানে আপলোড করার ছিল
SamYonnou

18

গিলে ফেলার ভেল্কি দেখায়

ভাষা = জাভা

স্কোর = 162,3289512601408075 169,4020975612382575

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

আপডেট: চারপাশে অনেক দ্রুত। অগ্রাধিকার আপডেট করতে অন্য থ্রেড ব্যবহার করে। সর্বদা .1 সেকেন্ডের মধ্যে ফিরে আসে। স্কোর না বাড়িয়ে পরাজিত করা অসম্ভব হওয়া উচিত MAX_TURNS

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

public class Swallower {

    static final byte MY_TYPE = 1;
    static final byte BLANK_TYPE = 0;
    static final byte NEUTRAL_TYPE = 2;
    static final byte ENEMY_TYPE = 3;
    private static final int WHITE = Color.WHITE.getRGB();
    private static final int MAX_TIME = 50;
    private final int color;
    private final int N;
    private final int width;
    private final int height;
    private final BufferedReader in;
    Lock borderLock;
    private final PriorityBlockingQueue<Pixel> border;
    private final Set<Pixel> borderSet;
    private final Thread updater;

    Lock imageLock;
    volatile byte[][] image;
    Lock priorityLock;
    volatile int[][] priority;
    volatile boolean updating;
    volatile private boolean exit;

    class Pixel implements Comparable<Pixel> {

        int x;
        int y;

        public Pixel(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int compareTo(Pixel o) {
            return priority() - o.priority();
        }

        private int priority() {
            priorityLock.lock();
            int p = priority[x][y];
            priorityLock.unlock();
            return p;
        }

        public byte type() {
            imageLock.lock();
            byte i = image[x][y];
            imageLock.unlock();
            return i;
        }

        public boolean isBorder() {
            if (type() != BLANK_TYPE){
                return false;
            }
            for (Pixel p : pixelsAround()){
                if (p.type() == MY_TYPE){
                    return true;
                }
            }
            return false;
        }

        public void setType(byte newType) {
            imageLock.lock();
            image[x][y] = newType;
            imageLock.unlock();
        }

        public void setPriority(int newPriority) {
            borderLock.lock();
            boolean contains = borderSet.remove(this);
            if (contains){
                border.remove(this);
            }
            priorityLock.lock();
            priority[x][y] = newPriority;
            priorityLock.unlock();
            if (contains){
                border.add(this);
                borderSet.add(this);
            }
            borderLock.unlock();
        }

        public List<Pixel> pixelsAround() {
            List<Pixel> pixels = new ArrayList<>(4);
            if (x > 0){
                pixels.add(new Pixel(x - 1, y));
            }
            if (x < width - 1){
                pixels.add(new Pixel(x + 1, y));
            }
            if (y > 0){
                pixels.add(new Pixel(x, y - 1));
            }
            if (y < height - 1){
                pixels.add(new Pixel(x, y + 1));
            }
            return pixels;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Pixel pixel = (Pixel) o;

            return x == pixel.x && y == pixel.y;

        }

        @Override
        public int hashCode() {
            int result = x;
            result = 31 * result + y;
            return result;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedImage image = ImageIO.read(new File(args[0]));
        int color = parseColorString(args[1]);
        int N = Integer.parseInt(args[2]);
        new Swallower(image, color, N).start();
    }

    private void start() throws IOException {
        updater.start();
        try {
            while (true) {
                String input = in.readLine();
                if (input.equals("exit")) {
                    exit = true;
                    if (!updating) {
                        updater.interrupt();
                    }
                    return;
                } else if (input.startsWith("colour")) {
                    updateImage(input);
                } else if (input.equals("pick pixels")) {
                    if (updating) {
                        try {
                            synchronized (Thread.currentThread()){
                                Thread.currentThread().wait(MAX_TIME);
                            }
                        } catch (InterruptedException ignored) {
                        }
                    }
                    for (int i = 0; i < N && !border.isEmpty(); i++) {
                        borderLock.lock();
                        Pixel p = border.poll();
                        borderSet.remove(p);
                        borderLock.unlock();
                        if (!p.isBorder()){
                            i--;
                            continue;
                        }
                        updateImage(MY_TYPE, p);
                        System.out.print(p.x + "," + p.y + " ");
                    }
                    System.out.println();
                }
            }
        } catch (Throwable e){
            exit = true;
            if (!updating){
                updater.interrupt();
            }
            throw e;
        }
    }

    private void updateImage(byte type, Pixel... pixels) {
        for (Pixel pixel : pixels){
            pixel.setType(type);
            if (type == MY_TYPE){
                pixel.setPriority(Integer.MAX_VALUE);
            } else {
                pixel.setPriority(0);
            }
        }
        for (Pixel pixel : pixels){
            for (Pixel p : pixel.pixelsAround()){
                if (p.type() == BLANK_TYPE){
                    addPixelToUpdate(p);
                }
                if (type == MY_TYPE && p.isBorder()){
                    borderLock.lock();
                    if (borderSet.add(p)){
                        border.add(p);
                    }
                    borderLock.unlock();
                }
            }
        }
    }

    private synchronized void addPixelToUpdate(Pixel p) {
        if (pixelsToUpdateSet.add(p)) {
            pixelsToUpdate.add(p);
            if (!updating){
                updater.interrupt();
            }
        }
    }

    Queue<Pixel> pixelsToUpdate;
    Set<Pixel> pixelsToUpdateSet;

    private void update(){
        while (true){
            if (exit){
                return;
            }
            if (pixelsToUpdate.isEmpty()){
                try {
                    updating = false;
                    while (!exit) {
                        synchronized (Thread.currentThread()) {
                            Thread.currentThread().wait();
                        }
                    }
                } catch (InterruptedException ignored){}
                continue;
            }
            updating = true;
            Pixel pixel = pixelsToUpdate.poll();
            if (pixel.type() != BLANK_TYPE){
                continue;
            }
            pixelsToUpdateSet.remove(pixel);
            updatePixel(pixel);
        }
    }

    private void updatePixel(Pixel pixel) {
        int originalPriority = pixel.priority();
        int minPriority = Integer.MAX_VALUE;
        List<Pixel> pixelsAround = pixel.pixelsAround();
        for (Pixel p : pixelsAround){
            int priority = p.priority();
            if (priority < minPriority){
                minPriority = priority;
            }
        }
        if (minPriority >= originalPriority){
            pixel.setPriority(Integer.MAX_VALUE);
            pixelsToUpdate.addAll(pixelsAround.stream().filter(p -> p.type() == 0 && p.priority() != Integer.MAX_VALUE).filter(pixelsToUpdateSet::add).collect(Collectors.toList()));
        } else {
            pixel.setPriority(minPriority + 1);
            for (Pixel p : pixelsAround){
                if (p.type() == 0 && p.priority() > minPriority + 2){
                    if (pixelsToUpdateSet.add(p)){
                        pixelsToUpdate.add(p);
                    }
                }
            }
        }

    }

    private void updateImage(String input) {
        String[] inputs = input.split("\\s");
        int color = parseColorString(inputs[1]);
        byte type;
        if (color == this.color){
            return;
        } else {
            type = ENEMY_TYPE;
        }
        Pixel[] pixels = new Pixel[inputs.length - 3];
        for (int i = 0; i < inputs.length - 3; i++){
            String[] coords = inputs[i + 3].split(",");
            pixels[i] = new Pixel(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]));
        }
        updateImage(type, pixels);
    }

    private static int parseColorString(String input) {
        String[] colorString = input.split("[\\(\\),]");
        return new Color(Integer.parseInt(colorString[1]), Integer.parseInt(colorString[2]), Integer.parseInt(colorString[3])).getRGB();
    }

    private Swallower(BufferedImage image, int color, int N){
        this.color = color;
        this.N = N;
        this.width = image.getWidth();
        this.height = image.getHeight();
        this.image = new byte[width][height];
        this.priority = new int[width][height];
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                int pixelColor = image.getRGB(x,y);
                priority[x][y] = Integer.MAX_VALUE;
                if (pixelColor == WHITE){
                    this.image[x][y] = BLANK_TYPE;
                } else if (pixelColor == this.color){
                    this.image[x][y] = MY_TYPE;
                } else {
                    this.image[x][y] = NEUTRAL_TYPE;
                }
            }
        }
        border = new PriorityBlockingQueue<>();
        borderSet = Collections.synchronizedSet(new HashSet<>());
        borderLock = new ReentrantLock();
        priorityLock = new ReentrantLock();
        imageLock = new ReentrantLock();
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                Pixel pixel = new Pixel(x,y);
                if (pixel.type() == BLANK_TYPE){
                    if (pixel.isBorder()){
                        if (borderSet.add(pixel)){
                            border.add(pixel);
                        }
                    }
                }
            }
        }
        in = new BufferedReader(new InputStreamReader(System.in));
        updating = false;
        updater = new Thread(this::update);
        pixelsToUpdate = new ConcurrentLinkedQueue<>();
        pixelsToUpdateSet = Collections.synchronizedSet(new HashSet<>());
        exit = false;
    }

}

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

এই বট এটি যুক্ত করতে পারে এমন পিক্সেলের একটি অগ্রাধিকার সারি বজায় রাখে। শত্রু পিক্সেলের অগ্রাধিকার 0 হয় a ফাঁকা পিক্সেলের অগ্রাধিকার চারপাশের সর্বনিম্ন অগ্রাধিকারের চেয়ে 1 টি বেশি is অন্যান্য সমস্ত পিক্সেলের ইন্টিজারের অগ্রাধিকার রয়েছে MA MAX_VALUE। আপডেটেটর থ্রেড পিক্সেলের অগ্রাধিকারগুলি ক্রমাগত আপডেট করে চলেছে। প্রতিটি টার্ন সর্বনিম্ন এন পিক্সেল অগ্রাধিকার সারিতে পপ করা হয়।

গ্রিন ব্লব বনাম রেড সোয়িলার

ব্লবের স্কোর = 1.680553372583887225

গ্রাহকের স্কোর = 169.4020975612382575

এরিনা 1:

Bot Blob.py with colour (0, 255, 0) scored 1.2183333333333333
Bot Swallower.class with colour (255, 0, 0) scored 177.435

এখানে চিত্র বর্ণনা লিখুন

এরিনা 2:

Bot Swallower.class with colour (255, 0, 0) scored 149.57829253338517
Bot Blob.py with colour (0, 255, 0) scored 0.5159187091564356

এখানে চিত্র বর্ণনা লিখুন

এরিনা 3:

Bot Blob.py with colour (0, 255, 0) scored 0.727104853136361
Bot Swallower.class with colour (255, 0, 0) scored 163.343720545521

এখানে চিত্র বর্ণনা লিখুন

এরিনা 4:

Bot Swallower.class with colour (255, 0, 0) scored 187.25137716604686
Bot Blob.py with colour (0, 255, 0) scored 4.260856594709419

এখানে চিত্র বর্ণনা লিখুন

সবুজ সোয়িলার বনাম রেড ব্লব

ব্লবের স্কোর = 1.6852943642218457375

গ্রাহকের স্কোর = 169.3923095387498625 86

এরিনা 1:

Bot Blob.py with colour (255, 0, 0) scored 1.3166666666666667
Bot Swallower.class with colour (0, 255, 0) scored 177.33666666666667

এখানে চিত্র বর্ণনা লিখুন

এরিনা 2:

Bot Swallower.class with colour (0, 255, 0) scored 149.57829253338517
Bot Blob.py with colour (255, 0, 0) scored 0.49573058575466195

এখানে চিত্র বর্ণনা লিখুন

এরিনা 3:

Bot Swallower.class with colour (0, 255, 0) scored 163.14367053301788
Bot Blob.py with colour (255, 0, 0) scored 0.9271548656394868

এখানে চিত্র বর্ণনা লিখুন

এরিনা 4:

Bot Swallower.class with colour (0, 255, 0) scored 187.51060842192973
Bot Blob.py with colour (255, 0, 0) scored 4.0016253388265675

এখানে চিত্র বর্ণনা লিখুন

লাল গ্রাসকারী বনাম সবুজ গভীরতা প্রথম ব্লব

গ্রাহকের স্কোর = 157.0749775233111925

গভীরতা প্রথম ব্লবের স্কোর = 18.192783547939744

এরিনা 1:

Bot Swallower.class with colour (255, 0, 0) scored 173.52166666666668
Bot dfblob.py with colour (0, 255, 0) scored 5.131666666666667

এখানে চিত্র বর্ণনা লিখুন

এরিনা 2:

Bot dfblob.py with colour (0, 255, 0) scored 17.25635925887156
Bot Swallower.class with colour (255, 0, 0) scored 149.57829253338517

এখানে চিত্র বর্ণনা লিখুন

এরিনা 3:

Bot Swallower.class with colour (255, 0, 0) scored 153.59801488833747
Bot dfblob.py with colour (0, 255, 0) scored 10.472810510319889

এখানে চিত্র বর্ণনা লিখুন

এরিনা 4:

Bot dfblob.py with colour (0, 255, 0) scored 39.91029775590086
Bot Swallower.class with colour (255, 0, 0) scored 151.60193600485545

এখানে চিত্র বর্ণনা লিখুন

সবুজ সোয়িলার বনাম রেড গভীরতা প্রথম ব্লব

গ্রাহকের স্কোর = 154.3368355651281075

গভীরতা প্রথম ব্লবের স্কোর = 18.84463249420435425

এরিনা 1:

Bot Swallower.class with colour (0, 255, 0) scored 165.295
Bot dfblob.py with colour (255, 0, 0) scored 13.358333333333333

এখানে চিত্র বর্ণনা লিখুন

এরিনা 2:

Bot dfblob.py with colour (255, 0, 0) scored 8.91118721119768
Bot Swallower.class with colour (0, 255, 0) scored 149.57829253338517

এখানে চিত্র বর্ণনা লিখুন

এরিনা 3:

Bot Swallower.class with colour (0, 255, 0) scored 157.01136822667206
Bot dfblob.py with colour (255, 0, 0) scored 7.059457171985304

এখানে চিত্র বর্ণনা লিখুন

এরিনা 4:

Bot dfblob.py with colour (255, 0, 0) scored 46.0495522603011
Bot Swallower.class with colour (0, 255, 0) scored 145.4626815004552

এখানে চিত্র বর্ণনা লিখুন

গ্রিন ব্লব বনাম রেড গভীরতার প্রথম ব্লব বনাম ব্লু সোয়িলার:

ব্লবের স্কোর = 6.347962032393275525

গভীরতা প্রথম ব্লবের স্কোর = 27.34842554331698275

গ্রাহকের স্কোর = 227.720728953415375

এরিনা 1:

Bot Swallower.class with colour (0, 0, 255) scored 242.54
Bot Blob.py with colour (0, 255, 0) scored 1.21
Bot dfblob.py with colour (255, 0, 0) scored 24.3525

এখানে চিত্র বর্ণনা লিখুন

এরিনা 2:

Bot dfblob.py with colour (255, 0, 0) scored 17.828356088588478
Bot Blob.py with colour (0, 255, 0) scored 0.9252889892479551
Bot Swallower.class with colour (0, 0, 255) scored 224.36743880007776

এখানে চিত্র বর্ণনা লিখুন

এরিনা 3:

Bot dfblob.py with colour (255, 0, 0) scored 7.105141670032893
Bot Swallower.class with colour (0, 0, 255) scored 226.52057245080502
Bot Blob.py with colour (0, 255, 0) scored 12.621905476369092

এখানে চিত্র বর্ণনা লিখুন

এরিনা 4:

Bot dfblob.py with colour (255, 0, 0) scored 60.10770441464656
Bot Blob.py with colour (0, 255, 0) scored 10.634653663956055
Bot Swallower.class with colour (0, 0, 255) scored 217.45490456277872

এখানে চিত্র বর্ণনা লিখুন

এখানে কয়েকটি পরিবর্তন সহ স্যাম ইয়োনুর বিচারক যাতে আপনি ফাইল এবং আদেশটি আলাদাভাবে নির্দিষ্ট করেন:

import sys, re, random, os, shutil, subprocess, datetime, time, signal, io
from PIL import Image

ORTH = ((-1,0), (1,0), (0,-1), (0,1))
def place(loc, colour):
    # if valid, place colour at loc and return True, else False
    if pix[loc] == (255,255,255):
        plist = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
        if any(pix[p]==colour for p in plist if 0<=p[0]<W and 0<=p[1]<H):
            pix[loc] = colour
            return True
    return False

def updateimage(image, msg, bot):
    if not re.match(r'(\s*\d+,\d+)*\s*', msg):
        return []
    plist = [tuple(int(v) for v in pr.split(',')) for pr in msg.split()]
    plist = plist[:PIXELBATCH]
    return [p for p in plist if place(p, bot.colour)]

class Bot:
    botlist = []
    def __init__(self, progs, command=None, colour=None):
        self.prog = progs[0]
        self.botlist.append(self)
        self.colour = colour
        self.colstr = str(colour).replace(' ', '')
        self.faults = 0
        self.env = 'env%u' % self.botlist.index(self)
        try: os.mkdir(self.env)
        except: pass
        for prog in progs:
            shutil.copy(prog, self.env)
        shutil.copy(imagename, self.env)
        os.chdir(self.env)
        args = command + [imagename, self.colstr, str(PIXELBATCH)]
        errorfile = 'err.log'
        with io.open(errorfile, 'wb') as errorlog:
            self.proc = subprocess.Popen(args, stdin=subprocess.PIPE, 
                stdout=subprocess.PIPE, stderr=errorlog)
        os.chdir('..')
    def send(self, msg):
        if self.faults < FAULTLIMIT:
            self.proc.stdin.write((msg+'\n').encode('utf-8'))
            self.proc.stdin.flush()
    def read(self, timelimit):
        if self.faults < FAULTLIMIT:
            start = time.time()
            inline = self.proc.stdout.readline().decode('utf-8')
            if time.time() - start > timelimit:
                self.faults += 1
                inline = ''
            return inline.strip()
    def exit(self):
        self.send('exit')

from cfg import *
for i, (progs, command) in enumerate(botspec):
    Bot(progs, command, colourspec[i])

image = Image.open(imagename)
pix = image.load()
W,H = image.size
resultdirectory = 'results of ' + BATTLE
os.mkdir(resultdirectory)

time.sleep(INITTIME)
total = 0
image.save(resultdirectory+'/'+'result000.png')
for turn in range(1, MAXTURNS+1):
    random.shuffle(Bot.botlist)
    nullbots = 0
    for bot in Bot.botlist:
        bot.send('pick pixels')
        inmsg = bot.read(TIMELIMIT)
        newpixels = updateimage(image, inmsg, bot)
        total += len(newpixels)
        if newpixels:
            pixtext = ' '.join('%u,%u'%p for p in newpixels)
            msg = 'colour %s chose %s' % (bot.colstr, pixtext)
            for msgbot in Bot.botlist:
                msgbot.send(msg)
        else:
            nullbots += 1
    if nullbots == len(Bot.botlist):
        break
    if turn % 100 == 0:
        print('Turn %s done %s pixels' % (turn, total))
        image.save(resultdirectory+'/result'+str(turn//100).zfill(3)+'.png')
image.save(resultdirectory+'/result999.png')
for msgbot in Bot.botlist:
    msgbot.exit()

resultfile = io.open(resultdirectory+'/result.txt','w')
counts = dict((c,f) for f,c in image.getcolors(W*H))
avg = 1.0 * sum(counts.values()) / len(Bot.botlist)
for bot in Bot.botlist:
    score = 100 * counts[bot.colour] / avg
    print('Bot %s with colour %s scored %s' % (bot.prog, bot.colour, score))
    print('Bot %s with colour %s scored %s' % (bot.prog, bot.colour, score), file=resultfile)
image.save(BATTLE+'.png')

সিএফজি উদাহরণ:

BATTLE = 'Green DepthFirstBlob vs Red Swallower @ arena1'
MAXTURNS = 20000
PIXELBATCH = 10
INITTIME = 2.0
TIMELIMIT = .1
FAULTLIMIT = 5

imagename = 'arena1.png'

colourspec = (0,255,0), (255,0,0)

botspec = [
    (['DepthFirstBlob.py'], ['python', 'DepthFirstBlob.py']),
    (['Swallower.class','Swallower$Pixel.class'], ['java', 'Swallower']),
    ]

দ্রষ্টব্য: যে কেউ যে গ্রাহককে গ্রাস করতে পারে সে 100 খ্যাতি লাভ করে। আপনি যদি এটিতে সফল হন তবে নীচের মন্তব্যে পোস্ট করুন।


2
অনুরোধ হিসাবে @ githubphagocyte।
TheNumberOne

1
বিচারকের পরিবর্তন নিয়ে সুন্দর কাজ। পৃথক পৃথক ফাইল অনুলিপি এবং আদেশ একটি ভাল ধারণা, এবং ত্রুটি লগিং খারাপভাবে প্রয়োজন ছিল।
লজিক নাইট

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

1
@ গিথুব্যাগগোসাইট সংশোধন করা হয়েছে
TheNumberOne

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

6

এলোমেলো, ভাষা = জাভা, স্কোর = 0.43012126100275

এই প্রোগ্রামটি এলোমেলোভাবে পর্দায় পিক্সেল রাখে। কিছু (সমস্ত না থাকলে) পিক্সেলগুলি বৈধ হবে না। সাইড নোটে, এটির চেয়ে দ্রুততর প্রোগ্রাম তৈরি করা কঠিন হওয়া উচিত।

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;

public class Random {

    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

    static int n;

    static int height;

    static int width;

    public static void main(String[] args) throws Exception{
        BufferedImage image = ImageIO.read(new File(args[0]));
        height = image.getHeight();
        width = image.getWidth();
        n = Integer.parseInt(args[2]);
        while (true){
            String input = in.readLine();
            if (input.equals("exit")){
                return;
            }
            if (!input.equals("pick pixels")){
                continue;
            }
            for (int i = 0; i < n; i++){
                System.out.print((int) (Math.random() * width) + ",");
                System.out.print((int) (Math.random() * height) + " ");
            }
            System.out.println();
        }
    }
}

এরিনা 1:

1

এরিনা 2:

2

এরিনা 3:

3

এরিনা 4:

4


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