最高のエントリーと@TheBestOne(優秀なスポーツマンシップ!)からの200バウンティを獲得するための@kuroinekoへのお祝い。
反対派のプログラムが行う前に、できるだけ多くの画像に色を付けるプログラムを書いてください。
簡単なルール
- プログラムには、画像、色、整数Nが与えられます。
- 各ターンには、他のプログラムからピクセルの更新が送信され、N個の更新を要求されます。
- 色のピクセルの隣にある任意の白いピクセルを更新できます。
- 最も多くのピクセルを追加したプログラムが勝ちます。
ルールの詳細
プログラムには、PNG画像のファイル名、ホームカラー、および数値Nが与えられます。数値Nは、プログラムが各ターンに色付けできるピクセルの最大数です。
例: MyProg arena.png (255,0,0) 30
入力画像は、辺が20〜1000ピクセルの長方形になります。黒、白、カラーのピクセルで構成されます。あなたのプログラムは白のシーケンスを選ぶかもしれません新しいピクセルごとに、自分の色の4つの隣接ピクセルのうち少なくとも1つを持たなければならないという条件で、ピクセルのして独自の色に。画像には最初、少なくとも1ピクセルの色があります。また、プログラムが割り当てられていない色のピクセルがある場合もあります。アルファチャネルは使用されません。
あなたの目標は、敵をブロックし、できるだけ多くのピクセルに色を書き込むことです。
各ターンは、STDINで1行以上のメッセージ行を受け入れ、STDOUTでピクセル座標で構成される行を書き込みます。STDOUTをバッファなしとして割り当てるか、毎回STDOUTバッファをフラッシュすることを忘れないでください。
各ターンに呼び出されるプレイヤーの順序はランダムに割り当てられます。これは、対戦相手(またはプログラム)が連続して2ターンを持っている可能性があることを意味します。
プログラムにはcolour (N,N,N) chose X,Y X,Y ... X,Y
、プレーヤープログラムによって入力されたピクセルを説明する情報メッセージが送信されます。プレーヤーが移動を行わない場合、または有効な移動を行わない場合、そのプレーヤーの移動に関するメッセージは送信されません。プログラムには、受け入れられた独自の移動に関するメッセージも送信されます(少なくとも1つの有効な移動を指定した場合)。ピクセル0,0は、画像の左上隅にあります。
を受け取るpick pixels
と、プログラムはX,Y X,Y ... X,Y
最大Nピクセルを出力します( '\ n'のみで構成される空の文字列が許可されます)。ピクセルは、プロットの順序でなければなりません。ピクセルが無効の場合、ピクセルは無視され、プレーヤーへのレポートには含まれません。プログラムの開始後、初期化するのに2秒かかりますが、各ターンで答えを返すのに0.1秒しかかかりません。0.1秒後に送信されたピクセル更新は、障害を記録します。5つの障害の後、プログラムは中断され、更新またはpick pixels
要求は送信されません。
ジャッジプログラムが、中断されていないすべてのプレーヤープログラムから空または無効なピクセルの選択を受け取ると、画像は完了したと見なされ、プログラムに「終了」というメッセージが送信されます。「終了」を受け取った後、プログラムを終了する必要があります。
得点
審査員は、画像が完成した後にポイントを獲得します。スコアは、更新されたピクセル数をそのラウンドの平均ピクセルキャプチャで割ったもので、パーセンテージで表されます。
プレーヤーによって画像に追加されるピクセルの数はAです。すべての Pプレーヤーによって追加されるピクセルの合計数はTです。
avg = T/P
score = 100*A/avg
投稿スコア
参照相手「The Blob」が与えられます。回答ごとに、ボットに名前、言語、および参照対戦相手に対するスコア(アリーナ1から4の平均)でタイトルを付けます。戦闘の写真やアニメーションもいいでしょう。勝者は、参照ボットに対して最高のスコアを獲得したプログラムです。
The Blobの勝ち方が簡単すぎると判明した場合は、より強力な参照相手と2回目のラウンドを追加することができます。
また、4つ以上のプレーヤープログラムを試すこともできます。回答として投稿された他のボットに対してボットをテストすることもできます。
裁判官
裁判官プログラムは、共通のPython Imaging Library(PIL)を必要とし、LinuxのOSパッケージマネージャーから簡単にインストールできる必要があります。PILはWindows 7の64ビットPythonでは動作しないという報告がありますので、このチャレンジを開始する前にPILが動作するかどうかを確認してください(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-参照相手
# 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 vs Blob
この戦いは予測可能な結果でした:
Bot blob.py with colour (255, 0, 0) scored 89.2883333333
Bot blob.py with colour (0, 255, 0) scored 89.365