Programınız, yeraltında değerli mineralleri araştıran bir maden robotunu kontrol edecektir. Robotunuz denetleyiciye nereye taşımak ve kazmak istediğinizi söyler ve denetleyici robot durumunuz hakkında geri bildirim sağlar.
Başlangıçta robotunuza bazı madencilik şaftları bulunan madenin bir görüntü haritası ve madendeki minerallerin değerini ve sertliğini belirten bir veri dosyası verilecektir. Robotunuz daha sonra madenler için değerli mineraller arayan şaftlarda hareket edecektir. Robotunuz dünyayı kazabilir, ancak sert kaya tarafından yavaşlatılır.
24 saatlik vardiyadan sonra en değerli kargo ile geri dönen robot kazanan olacak. Karmaşık bir meydan okuma gibi görünebilir, ancak temel bir madencilik robotu yapmak basittir (aşağıdaki Örnek Madencilik Robotu cevabına bakın).
Operasyon
Programınız mayın görüntüsü, mineral verileri ve ekipman dosya adları ile kontrolör tarafından başlatılacaktır. Robotlar maden cevheri ve mineral verilerini değerli cevher bulmak ve sert kayalardan kaçınmak için kullanabilirler. Robot ayrıca ekipman listesinden ekipman satın almak isteyebilir.
Örneğin: python driller.py mineimage.png minerals.txt equipmentlist.txt
2 saniyelik başlatma süresinden sonra, kontrolör robot programı ile stdin ve stdout aracılığıyla iletişim kurar. Robotlar, bir durum mesajı aldıktan sonra 0,1 saniye içinde bir eylemle yanıt vermelidir.
Her dönüşte, kontrolör robota bir durum satırı gönderir:
timeleft cargo battery cutter x y direction
Örneğin: 1087 4505 34.65 88.04 261 355 right
Tam sayı timeleft
, vardiya sonundan önce kalan oyun saniye sayısıdır.
cargo
Şu ana kadar daha az ekipman için ne ödemiş mayınlı olan minerallerin tamsayı değeridir. battery
Seviye Kalan pil şarj bir tamsayı yüzdesidir. Tam cutter
sayı seviyesi, standart değerin yüzdesi olarak kesicinin mevcut keskinliğidir. x
vey
değerler (0, 0) de sol üst köşesinden başvurulan robot pozisyonuyla pozitif tam sayılardır. Yön, robotun baktığı geçerli yöndür (sol, sağ, yukarı, aşağı).
Robotunuz 'son kaydırma' veya 'başarısız' girişi aldığında, programınız yakında sonlandırılacak. Robotunuzun önce bir dosyaya hata ayıklama / performans verileri yazmasını isteyebilirsiniz.
Denetleyicinin kabul edeceği 4 olası komut vardır. direction
left|right|up|down
robotunuzu bu yöne yönlendirecek ve 15 oyun-saniye gerektirecektir. move <integer>
robotunuza, kesilen minerallerin sertliğine ve kesicinizin keskinliğine bağlı olarak zaman alan birçok birimi ileriye doğru hareket ettirmesi veya kazması talimatını verecektir (aşağıya bakınız). buy <equipment>
belirtilen ekipmanı kuracak ve maliyeti kargo değerinizden düşecektir, ancak yalnızca robot yüzeydeyse (y değeri <= başlangıç y değeri). Ekipman kurulumu 300 oyun saniyesini alır. Özel komut snapshot
, geçerli mayın görüntüsünü diske yazar ve oyun süresi almaz. Robotunuzda hata ayıklamak veya animasyonlar oluşturmak için anlık görüntüleri kullanabilirsiniz.
Robotunuz 100 pil ve 100 kesici keskinliğiyle başlayacaktır. Taşıma ve tornalama az miktarda pil gücü kullanır. Kazma çok daha fazlasını kullanır ve minerallerin sertliğinin ve kesicinin mevcut keskinliğinin bir fonksiyonudur. Robotunuz mineralleri kazdıkça, kesici zamanın ve minerallerin sertliğine bağlı olarak keskinliğini kaybedecektir. Robotunuzun yeterli kargo değeri varsa, yeni bir pil veya kesici satın almak için yüzeye dönebilir. Yüksek kaliteli ekipmanın ilk etkinliği% 100'den fazladır. Piller adında "pil" dizesine ve (sürpriz) kesicilerin adında "kesici" dizeye sahiptir.
Aşağıdaki ilişkiler hareket etmeyi ve kesmeyi tanımlar:
timecutting = sum(hardness of pixels cut) * 100 / cutter
cutterwear = 0.01 for each second cutting
cutters will not wear below 0.1 sharpness
timemoving = 1 + timecutting
batterydrain = 0.0178 for each second moving
changing direction takes 15 seconds and drains 0.2 from the battery
installing new equipment takes 300 seconds
Herhangi bir mineral kesmeden 1 birim hareket etmenin 1 oyun saniye sürdüğünü ve pili 0,0178 kullandığını unutmayın. Böylece robot, mineralleri kesmiyor veya dönmüyorsa, standart bir 100 şarjla 93 oyun dakikada 5600 üniteyi kullanabilir.
YENİ: Robot 11 piksel genişliğindedir, bu nedenle her hareket pikseli ile 11 piksele kadar keser. Kesilecek 11 pikselden daha az varsa, robotun hareket etmesi daha az zaman alacak ve kesicide daha az aşınmaya neden olacaktır. Mineral veri dosyasında bir piksel rengi belirtilmezse, sıfır sertlik ve sıfır değerinde boş alan olur.
Süre bittiğinde, robot pili bittiğinde, robotun bir kısmı görüntü sınırını aştığında, geçersiz bir komut gönderildiğinde veya robot iletişimi zaman aşımına uğradığında çalışma sonlandırılır.
Puanınız robot kargonun son değeridir. Kontrolör puanınızı ve son harita görüntüsünü verir. Programınızın stderr çıktısı robot.log dosyasına kaydedilir. Robotunuz ölürse, ölümcül hata günlükte olabilir.
Maden Verileri
equipment.txt:
Equipment_Name Cost Initial_Value
std_cutter 200 100
carbide_cutter 600 160
diamond_cutter 2000 250
forcehammer_cutter 7200 460
std_battery 200 100
advanced_battery 500 180
megapower_battery 1600 320
nuclear_battery 5200 570
mineraldata.txt:
Mineral_Name Color Value Hardness
sandstone (157,91,46) 0 3
conglomerate (180,104,102) 0 12
igneous (108,1,17) 0 42
hard_rock (219,219,219) 0 15
tough_rock (146,146,146) 0 50
super_rock (73,73,73) 0 140
gem_ore1 (0,255,0) 10 8
gem_ore2 (0,0,255) 30 14
gem_ore3 (255,0,255) 100 6
gem_ore4 (255,0,0) 500 21
mayın görüntü:
Mayın görüntüsü alfa kanalına sahip olabilir, ancak bu kullanılmaz.
Kontrol eden, denetleyici
Denetleyici Python 2.7 ile çalışmalı ve PIL kitaplığı gerektirir. Python Yastık'ın PIL görüntü modülünü almak için Windows dostu bir indirme olduğu konusunda bilgilendirildim.
Denetleyiciyi geçerli dizindeki robot programı, cfg.py, resim ve veri dosyalarıyla başlatın. Önerilen komut satırı:
python controller.py [<interpreter>] {<switches>} <robotprogram>
Örneğin: python controller.py java underminer.class
Denetleyici, çalışmanın sonunda bir robot.log dosyası ve bir finalmine.png dosyası yazar.
#!/usr/bin/env python
# controller.py
# Control Program for the Robot Miner on PPCG.
# Tested on Python 2.7 on Ubuntu Linux. May need edits for other platforms.
# V1.0 First release.
# V1.1 Better error catching
import sys, subprocess, time
# Suggest installing Pillow here if you don't have PIL already
from PIL import Image, ImageDraw
from cfg import *
program = sys.argv[1:]
calltext = program + [MINEIMAGE, MINERALFILE, EQUIPMENTFILE]
errorlog = open(ERRORFILE, 'wb')
process = subprocess.Popen(calltext,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=errorlog)
image = Image.open(MINEIMAGE)
draw = ImageDraw.Draw(image)
BLACK, ORANGE, WHITE = (0,0,0), (255,160,160), (255,255,255)
W,H = image.size
dirmap = dict(right=(1,0), left=(-1,0), up=(0,-1), down=(0,1))
# read in mineral file (Name, Color, Value, Hardness):
data = [v.split() for v in open(MINERALFILE)][1:]
mineralvalue = dict((eval(color), int(value)) for
name, color, value, hard in data)
hardness = dict((eval(color), int(hard)) for
name, color, value, hard in data)
# read in the equipment list:
data = [v.split() for v in open(EQUIPMENTFILE)][1:]
equipment = dict((name, (int(cost), float(init))) for
name, cost, init in data)
# Set up simulation variables:
status = 'OK'
rx, ry, direction = START_X, START_Y, START_DIR # center of robot
cargo, battery, cutter = 0, 100.0, 100.0
clock = ENDSHIFT
size = ROBOTSIZE / 2
msgfmt = '%u %u %u %u %u %u %s'
snapnum = 1
def mkcutlist(x, y, direc, size):
dx, dy = dirmap[direc]
cx, cy = x+dx*(size+1), y+dy*(size+1)
output = [(cx, cy)]
for s in range(1, size+1):
output += [ (cx+dy*s, cy+dx*s), (cx-dy*s, cy-dx*s)]
return output
def send(msg):
process.stdin.write((msg+'\n').encode('utf-8'))
process.stdin.flush()
def read():
return process.stdout.readline().decode('utf-8')
time.sleep(INITTIME)
while clock > 0:
try:
start = time.time()
send(msgfmt % (clock, cargo, battery, cutter, rx, ry, direction))
inline = read()
if time.time() - start > TIMELIMIT:
status = 'Move timeout'
break
except:
status = 'Robot comslink failed'
break
# Process command:
movecount = 0
try:
arg = inline.split()
cmd = arg.pop(0)
if cmd == 'buy':
if ry <= START_Y and arg and arg[0] in equipment:
cost, initperc = equipment[arg[0]]
if cost <= cargo:
cargo -= cost
if 'battery' in arg[0]:
battery = initperc
elif 'cutter' in arg[0]:
cutter = initperc
clock -= 300
elif cmd == 'direction':
if arg and arg[0] in dirmap:
direction = arg[0]
clock -= 15
battery -= 0.2
elif cmd == 'move':
if arg and arg[0].isdigit():
movecount = abs(int(arg[0]))
elif cmd == 'snapshot':
image.save('snap%04u.png' % snapnum)
snapnum += 1
except:
status = 'Robot command malfunction'
break
for move in range(movecount):
# check image boundaries
dx, dy = dirmap[direction]
rx2, ry2 = rx + dx, ry + dy
print rx2, ry2
if rx2-size < 0 or rx2+size >= W or ry2-size < 0 or ry2+size >= H:
status = 'Bounds exceeded'
break
# compute time to move/cut through 1 pixel
try:
cutlist = mkcutlist(rx2, ry2, direction, size)
colors = [image.getpixel(pos)[:3] for pos in cutlist]
except IndexError:
status = 'Mining outside of bounds'
break
work = sum(hardness.get(c, 0) for c in colors)
timetaken = work * 100 / cutter
cutter = max(0.1, cutter - timetaken / 100)
clock -= 1 + int(timetaken + 0.5)
battery -= (1 + timetaken) / 56
if battery <= 0:
status = 'Battery exhausted'
break
cargo += sum(mineralvalue.get(c, 0) for c in colors)
draw.rectangle([rx-size, ry-size, rx+size+1, ry+size+1], BLACK, BLACK)
rx, ry = rx2, ry2
draw.rectangle([rx-size, ry-size, rx+size+1, ry+size+1], ORANGE, WHITE)
if clock <= 0:
break
if status != 'OK':
break
del draw
image.save('finalmine.png')
if status in ('Battery exhausted', 'OK'):
print 'Score = %s' % cargo
send('endshift')
else:
print 'Error: %s at clock %s' % (status, clock)
send('failed')
time.sleep(0.3)
process.terminate()
Bağlı yapılandırma dosyası (değiştirilmeyecek):
# This is cfg.py
# Scenario files:
MINEIMAGE = 'testmine.png'
MINERALFILE = 'mineraldata.txt'
EQUIPMENTFILE = 'equipment.txt'
# Mining Robot parameters:
START_X = 270
START_Y = 28
START_DIR = 'down'
ROBOTSIZE = 11 # should be an odd number
ENDSHIFT = 24 * 60 * 60 # seconds in an 24 hour shift
INITTIME = 2.0
TIMELIMIT = 0.1
ERRORFILE = 'robot.log'
Yanıt Biçimi
Cevaplar programlama dili, robot adı ve final skorunu içeren bir başlığa sahip olmalıdır ( Python 3 , Tünel Terörü , 1352 gibi) ). Cevap gövdesinin kodu ve son maden haritası resmi olmalıdır. Diğer resimler veya animasyonlar da kabul edilir. Kazanan en iyi puanı alan robot olacak.
Diğer Kurallar
- Ortak boşluklar yasaktır.
- Rastgele bir sayı üreteci kullanıyorsanız, program çalıştırmanızın tekrar üretilebilmesi için programınızdaki bir tohumu kodlamalısınız. Başka biri programınızı çalıştırıp aynı son mayın imajını ve skorunu elde edebilmelidir.
- Programınız herhangi bir mayın görüntüsü için programlanmalıdır . Programınızı bu veri dosyaları veya bu görüntü boyutu, mineral düzeni, tünel düzeni vb. İçin kodlamamalısınız. Bir robotun bu kuralı ihlal ettiğinden şüpheleniyorsam, mayın görüntüsünü ve / veya veri dosyalarını değiştirme hakkını saklı tutarım.
Düzenlemeler
- 0.1 saniyelik yanıt kuralı açıklandı.
- Robot başlatma komut satırı seçenekleri ve dosyalarında genişletildi.
- Daha iyi hata yakalama özelliğine sahip yeni denetleyici sürümü eklendi.
- Robot.log notu eklendi.
- Açıklanan varsayılan mineral sertliği ve değeri.
- Açıklayıcı pil vs kesici ekipman.
- Robot boyutunu 11 açık hale getirdi.
- Zaman, kesici aşınması ve pil için hesaplamalar eklendi.