1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
class Wall(object):
"""an obstructing static wall"""
def __init__(self, position):
self.x, self.y = position
def __getstate__(self):
return self.x, self.y
def __setstate__(self, state):
self.x, self.y = state
class Robot(object):
"""represents a robot moving on a grid."""
def __init__(self, name, grid_dimensions, position, direction=(0, 0), strength=5):
self.name = name
self.x, self.y = position
self.dx, self.dy = direction
self.gridw, self.gridh = grid_dimensions
self.strength = strength
def __str__(self):
return "ROBOT '%s'; pos(%d,%d); dir(%d,%d); strength %d" % (self.name, self.x, self.y, self.dx, self.dy, self.strength)
@staticmethod
def dict_to_robot(classname, data):
assert classname == "robot.Robot"
return Robot(data["name"], data["grid_dimensions"], data["position"], data["direction"], data["strength"])
@staticmethod
def robot_to_dict(robot):
return {
"__class__": "robot.Robot",
"name": robot.name,
"grid_dimensions": (robot.gridw, robot.gridh),
"position": (robot.x, robot.y),
"direction": (robot.dx, robot.dy),
"strength": robot.strength,
}
def move(self, world=None):
# minmax to avoid moving off the sides
x = min(self.gridw - 1, max(0, self.x + self.dx))
y = min(self.gridh - 1, max(0, self.y + self.dy))
if x == self.x and y == self.y:
return
if world and self.__process_collision(x, y, world):
return
self.x, self.y = x, y
def __process_collision(self, newx, newy, world):
other = world.collides(newx, newy)
if not other:
return False # we didn't hit anything
self.dx, self.dy = 0, 0 # come to a standstill when we hit something
if isinstance(other, Wall):
self.strength -= 1 # hit wall, decrease our strength
if self.strength <= 0:
print("[server] %s killed himself!" % self.name)
world.remove(self)
self.died(None, world)
else:
other.strength -= 1 # hit other robot, decrease other robot's strength
self.collision(other)
if other.strength <= 0:
world.remove(other)
other.died(self, world)
print("[server] %s killed %s!" % (self.name, other.name))
return True
def killed(self, victim, world):
"""you can override this to react on kills"""
pass
def collision(self, other):
"""you can override this to react on collisions between bots"""
pass
def emote(self, text):
"""you can override this"""
print("[server] %s says: '%s'" % (self.name, text))
class World(object):
"""the world the robots move in (Cartesian grid)"""
def __init__(self, width, height):
self.width = width
self.height = height
self.all = []
self.robots = []
def add_wall(self, wall):
self.all.append(wall)
def add_robot(self, bot):
self.all.append(bot)
self.robots.append(bot)
def collides(self, x, y):
for obj in self.all:
if obj.x == x and obj.y == y:
return obj
return None
def remove(self, obj):
self.all.remove(obj)
self.robots.remove(obj)
def dump(self):
line = b' ' * self.width
grid = [bytearray(line) for _ in range(self.height)]
for obj in self.all:
grid[obj.y][obj.x] = ord('R') if isinstance(obj, Robot) else ord('#')
return grid
def __getstate__(self):
return self.width, self.height, self.all, self.robots
def __setstate__(self, state):
self.width, self.height, self.all, self.robots = state
|