Created
December 29, 2014 17:56
-
-
Save benjamingorman/99877df5c539e867272d to your computer and use it in GitHub Desktop.
Robot functions for use with botchallenge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botchallenge import * | |
import math | |
from hilbert import Hilbert | |
from copy import copy | |
rob = Robot("Normangorman", "europe.botchallenge.net") | |
print("Connected") | |
def smart_range(a, b): | |
if a == b: | |
return [] | |
elif a < b: | |
return range(a,b) | |
else: | |
return range(a,b,-1) | |
def sign(x): | |
if x < 0: | |
return -1 | |
else: | |
return 1 | |
def get_loc_path(loc_a, loc_b): | |
# Enumerate all the points between locations a and b | |
locs = [] | |
p = loc_a | |
dx = sign(loc_b.x_coord - loc_a.x_coord) | |
dy = sign(loc_b.y_coord - loc_a.y_coord) | |
dz = sign(loc_b.z_coord - loc_a.z_coord) | |
while p.x_coord != loc_b.x_coord: | |
p.x_coord += dx | |
locs.append( copy(p) ) | |
while p.y_coord != loc_b.y_coord: | |
p.y_coord += dy | |
locs.append( copy(p) ) | |
while p.z_coord != loc_b.z_coord: | |
p.z_coord += dz | |
locs.append( copy(p) ) | |
return locs | |
def force_goto_loc(r, loc): | |
print("Forcing path to: ", loc) | |
r_loc = r.get_location() | |
locs = get_loc_path(r_loc, loc) | |
for p in locs: | |
r_loc = r.get_location() | |
# print(p) | |
# The robot was not able to move correctly - something went wrong | |
if force_move(r, r_loc.direction(p)) == False: | |
print("ERROR force_goto_loc: force_move returned False") | |
return | |
print("Finished moving.") | |
def safe_goto_loc(r, loc): | |
print("Safely moving to: ", loc) | |
locs = get_loc_path(r.get_location(), loc) | |
next_dir = r.get_location().direction(locs[0]) | |
# Sample the block type, then move to it - mining the block if it is solid | |
prev_bid = r.get_block_type( next_dir ) | |
force_move(r, next_dir) | |
for i in range(1, len(locs)): | |
next_dir = locs[i-1].direction(locs[i]) | |
next_bid = r.get_block_type(next_dir) | |
# The robot was not able to move correctly - something went wrong | |
if force_move(r, next_dir) == False: | |
print("ERROR safe_goto_loc: force_move returned False") | |
return | |
# Some blocks don't drop what they are - convert accordingly | |
if prev_bid == BlockType.GRASS: | |
prev_bid = BlockType.DIRT | |
prev_dir = locs[i].direction(locs[i-1]) | |
# Replace the block behind | |
if r.place(prev_dir, prev_bid) == False: | |
print("ERROR safe_goto_loc: could not replace block with id: ", prev_bid) | |
prev_bid = next_bid | |
print ("Finished moving.") | |
def goto_owner(r): | |
safe_goto_loc(r, r.get_owner_location()) | |
def force_move(r, d): | |
if r.is_block_solid(d): | |
r.mine(d) | |
# it must be bedrock | |
if r.is_block_solid(d): | |
print("ERROR force_move: encountered bedrock") | |
return False | |
# else the block is transparent, so move to it | |
else: | |
r.move(d) | |
return True | |
def forward(r, n): | |
for _ in range(n): | |
force_move(r, Dir.FORWARD) | |
def tunnel_forward(r, n): | |
def tunnel_unit(): | |
force_move(r, Dir.UP) | |
force_move(r, Dir.FORWARD) | |
force_move(r, Dir.DOWN) | |
force_move(r, Dir.FORWARD) | |
# if n is odd | |
if n % 2 != 0: | |
for _ in range(math.floor(n/2)): | |
tunnel_unit() | |
force_move(r, Dir.UP) | |
force_move(r, Dir.DOWN) | |
# else n is even | |
else: | |
for _ in range(math.floor(n/2) - 1): | |
tunnel_unit() | |
force_move(r, Dir.UP) | |
force_move(r, Dir.FORWARD) | |
force_move(r, Dir.DOWN) | |
def fill_to_loc(r, loc, bt): | |
r_loc = r.get_location() | |
print("Filling from ", r_loc, " to ", loc) | |
locs = get_loc_path(r_loc, loc) | |
prev_loc = locs[0] | |
for i in range(1, len(locs)): | |
new_loc = locs[i] | |
force_move(r, new_loc) | |
d = new_loc.direction(prev_loc) | |
if r.place(d, bt) == False: | |
print("ERROR fill_to_loc: block placement unsuccessful") | |
return | |
prev_loc = new_loc | |
def hilbert_fractal_locs(start_loc, num_dims, size): | |
hil = Hilbert(num_dims, size) | |
locs = [] | |
for i in range(0, size**num_dims-1): | |
p = hil.point(i) | |
print("p: ", p) | |
x = p[0] * 2 + start_loc.x_coord | |
y = p[1] * 2 + start_loc.y_coord | |
z = p[2] * 2 + start_loc.z_coord | |
locs.append( Location(x,y,z) ) | |
return locs | |
def make_3d_hilbert_fractal(r, start_loc, size): | |
print("Starting hilbert fractal at:", start_loc) | |
force_goto_loc(r, start_loc) | |
locs = hilbert_fractal_locs(start_loc, 3, size) | |
for i in range(0, len(locs) - 2): | |
print(locs[i]) | |
fill_to_loc(r, locs[i+1], BlockType.COBBLESTONE) | |
print("Finished hilbert fractal") | |
def clear_area(r, loc_a, loc_b): | |
ax = loc_a.x_coord | |
ay = loc_a.y_coord | |
az = loc_a.z_coord | |
bx = loc_b.x_coord | |
by = loc_b.y_coord | |
bz = loc_b.z_coord | |
xs = range(ax, bx) if ax < bx else range(bx, ax) | |
ys = range(ay, by) if ay < by else range(by, ay) | |
zs = range(az, bz) if az < bz else range(bz, az) | |
locs = [Location(x,y,z) for x in xs for y in ys for z in zs] | |
for loc in locs: | |
force_goto_loc(r, loc) | |
def count_inventory_item(r, bid): | |
inv = r.get_inventory() | |
maybe_items = [item for item in inv if item[0] == bid] | |
if len(maybe_items) == 0: | |
return 0 | |
else: | |
return maybe_items[0][1] | |
def adjacent_blocks(r): | |
dirs = [ | |
Dir.UP, | |
Dir.DOWN, | |
Dir.NORTH, | |
Dir.EAST, | |
Dir.SOUTH, | |
Dir.WEST | |
] | |
blocks = [] | |
for d in dirs: | |
blocks.append( r.get_block_type(d) ) | |
return blocks | |
def loc_plus_dir(loc, d): | |
x = loc.x_coord | |
y = loc.y_coord | |
z = loc.z_coord | |
if d == Dir.UP: | |
return Location(x,y+1,z) | |
elif d == Dir.DOWN: | |
return Location(x,y-1,z) | |
elif d == Dir.EAST: | |
return Location(x+1,y,z) | |
elif d == Dir.WEST: | |
return Location(x-1,y,z) | |
elif d == Dir.NORTH: | |
return Location(x,y,z-1) | |
elif d == Dir.SOUTH: | |
return Location(x,y,z+1) | |
def hunt(r, bid): | |
# Mine all adjacent occurences of bid | |
# Won't get any that are diagonal to the other blocks | |
# robot.find_type_nearby(..) puts far too much load on the server to be | |
# useful. | |
print("Hunting for: ", bid) | |
dirs = [ | |
Dir.UP, | |
Dir.DOWN, | |
Dir.NORTH, | |
Dir.EAST, | |
Dir.SOUTH, | |
Dir.WEST | |
] | |
locs = [] | |
def check_adjacents(): | |
for d in dirs: | |
if r.get_block_type(d) == bid: | |
locs.append( loc_plus_dir(r.get_location(), d) ) | |
check_adjacents() | |
while len(locs) > 0: | |
force_goto_loc(r, locs.pop()) | |
check_adjacents() | |
def mine_ores(r, diamond_goal): | |
# First mine down to level 10 | |
start_loc = r.get_location() | |
start_loc.y_coord = 10 | |
safe_goto_loc(r, start_loc) | |
# Side length for spiral which will be dug: this is incremented at every | |
# iteration. | |
s = 1 | |
r.turn(Dir.NORTH) | |
rare_blocks = [ | |
BlockType.DIAMOND_ORE, | |
BlockType.GOLD_ORE, | |
BlockType.IRON_ORE, | |
BlockType.OBSIDIAN, | |
BlockType.REDSTONE_ORE, | |
BlockType.LAPIS_ORE, | |
BlockType.COAL_ORE | |
] | |
while True: | |
for bid in rare_blocks: | |
if bid in adjacent_blocks(r): | |
# Allows pockets of rare blocks to be mined: | |
# Save the current location and return to it after mining | |
# a pocket. | |
start_loc = r.get_location() | |
hunt(r, bid) | |
force_goto_loc(r, start_loc) | |
diamond_count = count_inventory_item(r, BlockType.DIAMOND) | |
if diamond_count >= diamond_goal: | |
print("Diamond goal reached... returning to owner.") | |
goto_owner(r) | |
return | |
# Mine in an ever-increasing spiral | |
forward(r, s) | |
r.turn(Dir.RIGHT) | |
s += 1 | |
print("Robot turned right again, spiral side length: ", s) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment