ขอแสดงความยินดีกับ @kuroineko เพื่อผลงานที่ดีที่สุดและได้รับรางวัล 200 รางวัลจาก @TheBestOne (นักกีฬายอดเยี่ยม!)
เขียนโปรแกรมให้มีสีมากที่สุดของภาพก่อนที่โปรแกรมฝ่ายค้านจะทำ
กฎโดยย่อ
- โปรแกรมของคุณจะได้รับรูปภาพสีของคุณและจำนวนเต็ม N
- ทุกครั้งที่คุณได้รับการอัปเดตพิกเซลจากโปรแกรมอื่น ๆ และถามถึงการอัพเดท N ของคุณ
- คุณสามารถอัปเดตพิกเซลสีขาวที่อยู่ถัดจากพิกเซลสีของคุณ
- โปรแกรมที่เพิ่มจำนวนพิกเซลมากที่สุดชนะ
กฎในรายละเอียด
โปรแกรมของคุณจะได้รับชื่อไฟล์ภาพ PNG, สีบ้านและตัวเลข N จำนวน N คือจำนวนพิกเซลสูงสุดที่โปรแกรมของคุณอาจใช้สีในแต่ละตา
ตัวอย่าง: MyProg arena.png (255,0,0) 30
ภาพอินพุตจะเป็นรูปสี่เหลี่ยมผืนผ้าที่มีด้านข้างยาวระหว่าง 20 ถึง 1,000 พิกเซล มันจะประกอบด้วยพิกเซลสีดำสีขาวและสี โปรแกรมของคุณอาจเลือกลำดับพิกเซลสีขาวเป็นสีของคุณเองโดยมีเงื่อนไขว่าพิกเซลใหม่แต่ละพิกเซลต้องมีพิกเซลเพื่อนบ้านอย่างน้อยหนึ่งในสี่ของพิกเซลสีของคุณเอง รูปภาพจะมีสีของคุณอย่างน้อยหนึ่งพิกเซล นอกจากนี้ยังอาจมีพิกเซลสีที่ไม่ได้กำหนดโปรแกรมไว้ ไม่ได้ใช้ช่องอัลฟา
เป้าหมายของคุณคือเพื่อป้องกันคู่ต่อสู้ของคุณและเขียนสีของคุณเป็นพิกเซลมากเท่าที่คุณสามารถ
แต่ละเทิร์นโปรแกรมของคุณจะยอมรับ 1 หรือมากกว่าหนึ่งบรรทัดข้อความบน STDIN และเขียนบรรทัดที่ประกอบด้วยพิกัดพิกเซลบน STDOUT จำไว้ว่าให้กำหนด STDOUT เป็น unbuffered หรือล้างบัฟเฟอร์ STDOUT ในแต่ละเทิร์น
ลำดับของผู้เล่นที่เรียกว่าเทิร์นแต่ละเทิร์นจะถูกสุ่มเลือก ซึ่งหมายความว่าฝ่ายตรงข้าม (หรือโปรแกรมของคุณ) อาจมี 2 รอบติดต่อกัน
โปรแกรมของคุณจะถูกส่งcolour (N,N,N) chose X,Y X,Y ... X,Y
ข้อความข้อมูลที่อธิบายพิกเซลที่กรอกในโปรแกรมเครื่องเล่น หากผู้เล่นไม่มีการเคลื่อนไหวหรือไม่มีการเคลื่อนไหวที่ถูกต้องคุณจะไม่ได้รับข้อความเกี่ยวกับการเคลื่อนไหวของผู้เล่น โปรแกรมของคุณจะถูกส่งข้อความเกี่ยวกับการเคลื่อนไหวที่คุณยอมรับ (ถ้าคุณระบุการเคลื่อนไหวที่ถูกต้องอย่างน้อยหนึ่งครั้ง) พิกเซล 0,0 อยู่ที่มุมซ้ายบนของภาพ
เมื่อได้รับpick pixels
โปรแกรมของคุณจะแสดงผลX,Y X,Y ... X,Y
ได้สูงสุด N พิกเซล (อนุญาตให้ใช้สตริงที่ว่างซึ่งประกอบด้วย '\ n' เท่านั้น) พิกเซลจะต้องอยู่ในลำดับของการลงจุด หากพิกเซลไม่ถูกต้องพิกเซลนั้นจะถูกละเว้นและจะไม่อยู่ในรายงานต่อผู้เล่น โปรแกรมของคุณมีเวลา 2 วินาทีในการเริ่มต้นหลังจากที่เริ่ม แต่เพียง 0.1 วินาทีเพื่อตอบด้วยคำตอบทุกเทิร์นมิฉะนั้นมันจะพลาดเทิร์นนั้น การอัปเดตพิกเซลที่ส่งหลังจาก 0.1 วินาทีจะบันทึกข้อผิดพลาด หลังจาก 5 ข้อผิดพลาดโปรแกรมของคุณถูกระงับและจะไม่ถูกส่งการปรับปรุงหรือpick pixels
การร้องขอ
เมื่อโปรแกรมการตัดสินได้รับตัวเลือกพิกเซลที่ว่างเปล่าหรือไม่ถูกต้องจากทุกโปรแกรมของผู้เล่นที่ไม่ถูกระงับภาพจะถูกพิจารณาว่าสมบูรณ์และโปรแกรมจะถูกส่งข้อความ "exit" โปรแกรมจะต้องยุติลงหลังจากได้รับ "ทางออก"
เกณฑ์การให้คะแนน
ผู้ตัดสินจะทำคะแนนหลังจากภาพเสร็จสมบูรณ์ คะแนนของคุณจะเป็นจำนวนพิกเซลที่อัปเดตแล้วหารด้วยการจับพิกเซลเฉลี่ยรอบนั้นซึ่งแสดงเป็นเปอร์เซ็นต์
จำนวนพิกเซลที่เพิ่มลงในภาพโดยเครื่องเล่นของคุณคือ A จำนวนพิกเซลทั้งหมดที่เพิ่มโดยเครื่องเล่น P ทั้งหมดคือ T
avg = T/P
score = 100*A/avg
โพสต์คะแนน
มีการให้คู่ต่อสู้อ้างอิง "The Blob" สำหรับแต่ละคำตอบให้ตั้งชื่อบอทของคุณด้วยชื่อภาษาและคะแนนของคุณ (โดยเฉลี่ยที่เกิดเหตุ 1 ถึง 4) กับคู่ต่อสู้อ้างอิง รูปภาพหรืออนิเมชั่นของหนึ่งในการต่อสู้ของคุณก็ดีเช่นกัน ผู้ชนะคือโปรแกรมที่มีคะแนนสูงสุดเทียบกับบอตอ้างอิง
ถ้า Blob พิสูจน์ให้ชนะง่ายเกินไปฉันอาจเพิ่มรอบที่สองพร้อมกับคู่ต่อสู้อ้างอิงที่แข็งแกร่งกว่า
คุณอาจต้องการทดสอบกับโปรแกรมผู้เล่น 4 โปรแกรมขึ้นไป คุณสามารถทดสอบบอตของคุณจากบอตอื่น ๆ ที่โพสต์เป็นคำตอบ
ผู้พิพากษา
โปรแกรมผู้ตัดสินต้องใช้ Python Imaging Library (PIL) ทั่วไปและควรติดตั้งได้ง่ายจากตัวจัดการแพ็คเกจระบบปฏิบัติการของคุณบน Linux ฉันมีรายงานว่า PIL ใช้งานไม่ได้กับ 64 บิต Python บน Windows 7 ดังนั้นโปรดตรวจสอบว่า PIL จะทำงานให้คุณก่อนที่จะเริ่มการท้าทายนี้หรือไม่ (อัปเดต 2015-01-25)
#!/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'),
]
The Blob - คู่ต่อสู้อ้างอิง
# 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')
อารีน่า 1
อารีน่า 2
อารีน่า 3
สนามกีฬา 4
ตัวอย่างการต่อสู้ - Blob กับ Blob
การต่อสู้ครั้งนี้มีผลลัพธ์ที่คาดการณ์ได้:
Bot blob.py with colour (255, 0, 0) scored 89.2883333333
Bot blob.py with colour (0, 255, 0) scored 89.365