โปรแกรมของคุณจะควบคุมหุ่นยนต์ขุดเพื่อค้นหาแร่ธาตุที่มีค่า หุ่นยนต์ของคุณจะบอกคอนโทรลเลอร์ว่าคุณต้องการย้ายและขุดที่ใดและคอนโทรลเลอร์จะให้ข้อเสนอแนะเกี่ยวกับสถานะหุ่นยนต์ของคุณ
ในขั้นแรกหุ่นยนต์ของคุณจะได้รับแผนที่รูปภาพของเหมืองที่มีเพลาขุดอยู่แล้วและไฟล์ข้อมูลที่ระบุค่าและความแข็งของแร่ในเหมือง หุ่นยนต์ของคุณจะเคลื่อนที่ผ่านเพลาเพื่อค้นหาแร่ธาตุที่มีค่าสำหรับการขุด หุ่นยนต์ของคุณสามารถขุดผ่านพื้นโลกได้ แต่ถูกทำให้ช้าลงด้วยฮาร์ดร็อค
หุ่นยนต์ที่กลับมาพร้อมกับสินค้าที่มีค่าที่สุดหลังจากเปลี่ยน 24 ชั่วโมงจะเป็นผู้ชนะ มันอาจจะเป็นความท้าทายที่ซับซ้อน แต่ก็เป็นเรื่องง่ายที่จะสร้างหุ่นยนต์ขุดขั้นพื้นฐาน
การทำงาน
โปรแกรมของคุณจะเริ่มโดยผู้ควบคุมพร้อมรูปเหมืองข้อมูลแร่และชื่อไฟล์อุปกรณ์ หุ่นยนต์สามารถใช้ข้อมูลภาพและแร่ของเหมืองเพื่อค้นหาแร่ที่มีค่าและหลีกเลี่ยงฮาร์ดร็อค หุ่นยนต์อาจต้องการซื้ออุปกรณ์จากรายการอุปกรณ์
เช่น: python driller.py mineimage.png minerals.txt equipmentlist.txt
หลังจากช่วงเวลาเริ่มต้น 2 วินาทีตัวควบคุมจะสื่อสารกับโปรแกรมหุ่นยนต์ผ่าน stdin และ stdout หุ่นยนต์จะต้องตอบสนองด้วยการกระทำภายใน 0.1 วินาทีหลังจากได้รับข้อความสถานะ
ในการเลี้ยวแต่ละครั้งผู้ควบคุมจะส่งสายสถานะของหุ่นยนต์:
timeleft cargo battery cutter x y direction
เช่น: 1087 4505 34.65 88.04 261 355 right
จำนวนเต็มtimeleft
เป็นวินาทีของเกมที่เหลือก่อนสิ้นสุดกะ นี่
cargo
คือค่าจำนวนเต็มของแร่ธาตุที่คุณขุดจนน้อยกว่าที่คุณจ่ายสำหรับอุปกรณ์ battery
ระดับร้อยละจำนวนเต็มของค่าใช้จ่ายแบตเตอรี่ที่เหลืออยู่ cutter
ระดับจำนวนเต็มคือความคมชัดในปัจจุบันของเครื่องตัดเป็นร้อยละของค่ามาตรฐาน x
และy
ค่าเป็นจำนวนเต็มบวกกับตำแหน่งของหุ่นยนต์ที่อ้างอิงจากมุมซ้ายด้านบนที่ (0, 0) ทิศทางคือทิศทางปัจจุบันที่หุ่นยนต์หัน (ซ้าย, ขวา, ขึ้น, ลง)
เมื่อหุ่นยนต์ของคุณได้รับอินพุต 'endshift' หรือ 'ล้มเหลว' โปรแกรมของคุณจะถูกยกเลิกในไม่ช้า คุณอาจต้องการให้โรบอตของคุณเขียนข้อมูลการดีบัก / ประสิทธิภาพลงในไฟล์ก่อน
มี 4 คำสั่งที่เป็นไปได้ที่ผู้ควบคุมจะยอมรับ direction
left|right|up|down
จะชี้หุ่นยนต์ของคุณไปในทิศทางนั้นและต้องใช้เวลา 15 เกมวินาที move <integer>
จะสั่งให้หุ่นยนต์ของคุณเคลื่อนที่หรือขุดที่หลาย ๆ หน่วยไปข้างหน้าซึ่งต้องใช้เวลาขึ้นอยู่กับความแข็งของแร่ธาตุที่ตัดและความคมของเครื่องตัดของคุณ (ดูด้านล่าง) buy <equipment>
จะติดตั้งอุปกรณ์ที่ระบุและหักค่าใช้จ่ายจากมูลค่าการขนส่งสินค้าของคุณ แต่เฉพาะในกรณีที่หุ่นยนต์อยู่ที่พื้นผิว (ค่า y <<ค่าเริ่มต้น y) การติดตั้งอุปกรณ์ใช้เวลา 300 เกมต่อวินาที คำสั่งพิเศษsnapshot
เขียนอิมเมจของทุ่นระเบิดปัจจุบันลงดิสก์และไม่ต้องใช้เวลาเล่นเกม คุณสามารถใช้สแน็ปช็อตเพื่อดีบักหุ่นยนต์ของคุณหรือสร้างภาพเคลื่อนไหว
หุ่นยนต์ของคุณจะเริ่มต้นด้วย 100 แบตเตอรี่และ 100 คมตัด การเคลื่อนย้ายและเปลี่ยนใช้พลังงานแบตเตอรี่เล็กน้อย ขุดใช้มากขึ้นและเป็นฟังก์ชั่นของความแข็งของแร่ธาตุและความคมชัดในปัจจุบันของเครื่องตัด เมื่อหุ่นยนต์ของคุณขุดเข้าไปในแร่ธาตุเครื่องตัดจะสูญเสียความคมชัดขึ้นอยู่กับเวลาและความแข็งของแร่ธาตุ หากหุ่นยนต์ของคุณมีมูลค่าสินค้าเพียงพออาจส่งผลให้พื้นผิวซื้อแบตเตอรี่หรือคัตเตอร์ใหม่ได้ โปรดทราบว่าอุปกรณ์ที่มีคุณภาพสูงมีประสิทธิภาพเริ่มต้นมากกว่า 100% แบตเตอรี่มีสตริง "แบตเตอรี่" ในชื่อและตัวตัด (ประหลาดใจ) มี "ตัวตัด" ในชื่อ
ความสัมพันธ์ต่อไปนี้กำหนดการเคลื่อนที่และการตัด:
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
โปรดทราบว่าการเคลื่อนที่ 1 หน่วยโดยไม่ต้องตัดแร่ใด ๆ จะใช้เวลา 1 เกมและใช้แบตเตอรี่ 0.0178 ดังนั้นหุ่นยนต์สามารถขับ 5600 หน่วยใน 93 นาทีเกมต่อการชาร์จ 100 มาตรฐานหากไม่ได้ตัดแร่หรือหมุน
ใหม่: หุ่นยนต์มีความกว้าง 11 พิกเซลดังนั้นจะตัดได้ถึง 11 พิกเซลในแต่ละพิกเซลของการเคลื่อนไหว หากมีการตัดน้อยกว่า 11 พิกเซลหุ่นยนต์จะใช้เวลาในการเคลื่อนย้ายน้อยลงและทำให้เครื่องตัดสึกหรอน้อยลง หากไม่ได้ระบุสีพิกเซลในไฟล์ข้อมูลแร่ธาตุจะเป็นพื้นที่ว่างที่ไม่มีความกระด้างและค่าศูนย์
การรันจะสิ้นสุดลงเมื่อเวลาหมดแบตเตอรี่หุ่นยนต์จะหมดส่วนหนึ่งของหุ่นยนต์จะเกินขอบเขตภาพคำสั่งที่ผิดกฎหมายถูกส่งหรือหมดเวลาการสื่อสารของหุ่นยนต์
คะแนนของคุณคือมูลค่าสุดท้ายของการขนส่งหุ่นยนต์ ตัวควบคุมจะส่งออกคะแนนและภาพแผนที่สุดท้ายของคุณ เอาต์พุต stderr ของโปรแกรมของคุณถูกบันทึกไว้ในไฟล์ robot.log หากหุ่นยนต์ของคุณตายข้อผิดพลาดร้ายแรงอาจอยู่ในบันทึก
ข้อมูลเหมือง
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
ภาพของฉัน:
รูปภาพของฉันอาจมีช่องอัลฟา แต่ไม่ได้ใช้
ผู้ควบคุม
คอนโทรลเลอร์ควรทำงานกับ Python 2.7 และต้องการไลบรารี PIL ฉันได้รับแจ้งว่า Python Pillow เป็นการดาวน์โหลดที่เป็นมิตรกับ Windows เพื่อรับโมดูลภาพ PIL
เริ่มตัวควบคุมด้วยโปรแกรมหุ่นยนต์, cfg.py, รูปภาพและไฟล์ข้อมูลในไดเรกทอรีปัจจุบัน บรรทัดคำสั่งที่แนะนำคือ:
python controller.py [<interpreter>] {<switches>} <robotprogram>
เช่น: python controller.py java underminer.class
คอนโทรลเลอร์จะเขียนไฟล์ robot.log และไฟล์ finalmine.png เมื่อสิ้นสุดการรัน
#!/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()
ไฟล์กำหนดค่าที่เชื่อมโยง (ไม่เปลี่ยนแปลง):
# 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'
รูปแบบคำตอบ
คำตอบควรมีชื่อเรื่องรวมถึงภาษาการเขียนโปรแกรมชื่อหุ่นยนต์และคะแนนสุดท้าย (เช่นPython 3 , Tunnel Terror , 1352 ) เนื้อหาคำตอบควรมีรหัสและภาพแผนที่เหมืองสุดท้ายของคุณ ภาพหรือภาพเคลื่อนไหวอื่น ๆ ก็ยินดีเช่นกัน ผู้ชนะจะเป็นหุ่นยนต์ที่มีคะแนนดีที่สุด
กฎอื่น ๆ
- ช่องว่างทั่วไปเป็นสิ่งต้องห้าม
- หากคุณใช้ตัวสร้างตัวเลขสุ่มคุณต้องเข้ารหัสฮาร์ดโค้ดในโปรแกรมของคุณเพื่อให้การรันโปรแกรมของคุณสามารถทำซ้ำได้ บุคคลอื่นจะต้องสามารถเรียกใช้โปรแกรมของคุณและได้รับภาพและคะแนนขั้นสุดท้ายของเหมืองเดียวกัน
- โปรแกรมของคุณจะต้องมีโปรแกรมสำหรับใด ๆภาพเหมือง คุณไม่ต้องเขียนโค้ดโปรแกรมของคุณสำหรับไฟล์ข้อมูลเหล่านี้หรือนี้ขนาดของภาพ, รูปแบบเกลือแร่, รูปแบบอุโมงค์ ฯลฯ หากฉันสงสัยว่าหุ่นยนต์จะทำลายกฎนี้ผมขอสงวนสิทธิ์ในการเปลี่ยนแปลงภาพเหมืองและ / หรือไฟล์ข้อมูล
การแก้ไข
- อธิบายกฎการตอบสนอง 0.1 วินาที
- ขยายจากตัวเลือกและไฟล์บรรทัดคำสั่งเริ่มต้นของหุ่นยนต์
- เพิ่มเวอร์ชั่นคอนโทรลเลอร์ใหม่พร้อมข้อผิดพลาดที่ดีขึ้น
- เพิ่มโน้ต robot.log
- ความแข็งและค่าแร่เริ่มต้นที่อธิบายได้
- อุปกรณ์เทียบกับเครื่องตัดแบตเตอรี่ที่อธิบายได้
- ทำให้หุ่นยนต์มีขนาด 11 อย่างชัดเจน
- เพิ่มการคำนวณเวลาการสึกหรอของเครื่องตัดและแบตเตอรี่