Chương trình của bạn sẽ điều khiển một robot khai thác tìm kiếm dưới lòng đất các khoáng sản có giá trị. Robot của bạn sẽ báo cho bộ điều khiển nơi bạn muốn di chuyển và đào, và bộ điều khiển sẽ cung cấp phản hồi về trạng thái robot của bạn.
Ban đầu, robot của bạn sẽ được cung cấp một bản đồ hình ảnh của mỏ với một số trục khai thác đã có, và một tệp dữ liệu chỉ định giá trị và độ cứng của các khoáng chất trong mỏ. Robot của bạn sau đó sẽ di chuyển qua các trục tìm kiếm các khoáng chất có giá trị để khai thác. Robot của bạn có thể đào xuyên trái đất, nhưng bị làm chậm bởi đá cứng.
Robot trở lại với hàng hóa có giá trị nhất sau ca làm việc 24 giờ sẽ là người chiến thắng. Nó có vẻ là một thách thức phức tạp nhưng thật đơn giản để tạo ra một robot khai thác cơ bản (xem câu trả lời Robot khai thác mẫu bên dưới).
Hoạt động
Chương trình của bạn sẽ được khởi động bởi bộ điều khiển với hình ảnh mỏ, dữ liệu khoáng sản và tên tệp thiết bị. Robot có thể sử dụng hình ảnh mỏ và dữ liệu khoáng sản để tìm quặng có giá trị và tránh đá cứng. Robot cũng có thể muốn mua thiết bị từ danh sách thiết bị.
ví dụ: python driller.py mineimage.png minerals.txt equipmentlist.txt
Sau khoảng thời gian khởi tạo 2 giây, bộ điều khiển giao tiếp với chương trình robot thông qua stdin và stdout. Robot phải phản hồi bằng một hành động trong vòng 0,1 giây sau khi nhận được thông báo trạng thái.
Mỗi lượt, bộ điều khiển gửi cho robot một dòng trạng thái:
timeleft cargo battery cutter x y direction
ví dụ: 1087 4505 34.65 88.04 261 355 right
Số nguyên timeleft
là giây trò chơi còn lại trước khi kết thúc ca. Các
cargo
là giá trị số nguyên của các khoáng chất bạn đã khai thác cho đến nay ít hơn những gì bạn đã trả tiền cho các thiết bị. Các battery
cấp độ là một tỷ lệ phần trăm số nguyên của sạc pin còn lại của bạn. Mức cutter
nguyên là độ sắc nét hiện tại của dao cắt theo phần trăm của giá trị tiêu chuẩn. Các giá trị x
và y
là các số nguyên dương với vị trí robot được tham chiếu từ góc trên cùng bên trái tại (0, 0). Hướng là hướng hiện tại mà robot đang đối mặt (trái, phải, lên, xuống).
Khi robot của bạn nhận được đầu vào 'endshift' hoặc 'fail', chương trình của bạn sẽ sớm bị chấm dứt. Bạn có thể muốn robot của mình ghi dữ liệu gỡ lỗi / hiệu suất vào một tệp trước tiên.
Có 4 lệnh có thể bộ điều khiển sẽ chấp nhận. direction
left|right|up|down
sẽ hướng robot của bạn theo hướng đó và cần 15 giây trò chơi. move <integer>
sẽ hướng dẫn robot của bạn di chuyển hoặc đào nhiều đơn vị về phía trước, điều này sẽ mất thời gian tùy thuộc vào độ cứng của vết cắt khoáng chất và độ sắc nét của máy cắt của bạn (xem bên dưới). buy <equipment>
sẽ cài đặt thiết bị được chỉ định và khấu trừ chi phí từ giá trị hàng hóa của bạn, nhưng chỉ khi robot ở trên bề mặt (giá trị y <= giá trị y bắt đầu). Cài đặt thiết bị mất 300 giây trò chơi. Lệnh đặc biệt snapshot
ghi hình ảnh mỏ hiện tại vào đĩa và không mất thời gian chơi. Bạn có thể sử dụng ảnh chụp nhanh để gỡ lỗi robot của mình hoặc tạo hình động.
Robot của bạn sẽ bắt đầu với 100 pin và độ sắc nét của máy cắt. Di chuyển và xoay sử dụng một lượng nhỏ pin. Đào sử dụng nhiều hơn và là một chức năng của độ cứng của khoáng chất và độ sắc nét hiện tại của máy cắt. Khi robot của bạn đào vào khoáng chất, máy cắt sẽ mất độ sắc nét, tùy thuộc vào thời gian thực hiện và độ cứng của khoáng chất. Nếu robot của bạn có đủ giá trị hàng hóa, nó có thể quay trở lại bề mặt để mua pin hoặc máy cắt mới. Lưu ý rằng thiết bị chất lượng cao có hiệu quả ban đầu hơn 100%. Pin có chuỗi "pin" trong tên và (bất ngờ) máy cắt có "máy cắt" trong tên.
Các mối quan hệ sau xác định di chuyển và cắt:
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
Lưu ý rằng việc di chuyển 1 đơn vị mà không cắt bất kỳ khoáng chất nào sẽ mất 1 trò chơi thứ hai và sử dụng 0,0178 pin. Vì vậy, robot có thể lái 5600 đơn vị trong 93 phút trò chơi với một lần sạc 100 tiêu chuẩn, nếu nó không cắt giảm khoáng sản hoặc quay đầu.
MỚI: Robot rộng 11 pixel nên sẽ cắt tối đa 11 pixel với mỗi pixel chuyển động. Nếu có ít hơn 11 pixel để cắt, robot sẽ mất ít thời gian hơn để di chuyển và gây ra ít hao mòn hơn cho máy cắt. Nếu một màu pixel không được chỉ định trong tệp dữ liệu khoáng sản, thì đó là không gian trống có độ cứng bằng 0 và giá trị bằng không.
Việc chạy bị chấm dứt khi hết thời gian, pin robot cạn kiệt, một phần của robot vượt quá ranh giới hình ảnh, một lệnh bất hợp pháp được gửi hoặc hết thời gian liên lạc với robot.
Điểm của bạn là giá trị cuối cùng của hàng hóa robot. Bộ điều khiển sẽ xuất điểm của bạn và hình ảnh bản đồ cuối cùng. Đầu ra stderr của chương trình của bạn được ghi vào tệp robot.log. Nếu robot của bạn chết, lỗi nghiêm trọng có thể nằm trong nhật ký.
Dữ liệu mỏ
thiết bị.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
hình ảnh của tôi:
Hình ảnh của tôi có thể có một kênh alpha, nhưng điều này không được sử dụng.
Bộ điều khiển
Bộ điều khiển nên hoạt động với Python 2.7 và yêu cầu thư viện PIL. Tôi đã được thông báo rằng Python Python là một bản tải xuống thân thiện với Windows để có được mô-đun hình ảnh PIL.
Khởi động bộ điều khiển với chương trình robot, cfg.py, tệp hình ảnh và dữ liệu trong thư mục hiện tại. Dòng lệnh được đề xuất là:
python controller.py [<interpreter>] {<switches>} <robotprogram>
Ví dụ: python controller.py java underminer.class
Bộ điều khiển sẽ ghi một tệp robot.log và một tệp Finalmine.png vào cuối quá trình chạy.
#!/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()
Tệp cấu hình được liên kết (không được thay đổi):
# 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'
Định dạng câu trả lời
Các câu trả lời phải có tiêu đề bao gồm ngôn ngữ lập trình, tên robot và điểm cuối cùng (như Python 3 , Tunnel Terror , 1352 ). Phần thân câu trả lời phải có mã của bạn và hình ảnh bản đồ mỏ cuối cùng. Các hình ảnh hoặc hình ảnh động khác cũng được chào đón. Người chiến thắng sẽ là robot có số điểm tốt nhất.
Các quy tắc khác
- Các sơ hở phổ biến đều bị cấm.
- Nếu bạn sử dụng trình tạo số ngẫu nhiên, bạn phải mã hóa hạt giống trong chương trình của mình để chương trình của bạn chạy được. Một số người khác phải có khả năng chạy chương trình của bạn và có được hình ảnh và điểm số cuối cùng của tôi.
- Chương trình của bạn phải được lập trình cho bất kỳ hình ảnh của tôi. Bạn không được mã hóa chương trình của mình cho các tệp dữ liệu này hoặc kích thước hình ảnh, bố cục khoáng sản, bố cục đường hầm, v.v ... Nếu tôi nghi ngờ robot vi phạm quy tắc này, tôi có quyền thay đổi tệp hình ảnh và / hoặc tệp dữ liệu.
Chỉnh sửa
- Giải thích quy tắc trả lời 0,1 giây.
- Mở rộng trên các tùy chọn dòng lệnh và robot bắt đầu.
- Đã thêm phiên bản điều khiển mới với khả năng bắt lỗi tốt hơn.
- Đã thêm ghi chú robot.log.
- Giải thích độ cứng và giá trị khoáng sản mặc định.
- Giải thích về pin vs thiết bị cắt.
- Làm robot kích thước 11 rõ ràng.
- Đã thêm tính toán cho thời gian, hao mòn máy cắt và pin.