File: robot.py

package info (click to toggle)
pyro5 5.16-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,124 kB
  • sloc: python: 14,328; makefile: 161; sh: 66; javascript: 62
file content (123 lines) | stat: -rw-r--r-- 3,917 bytes parent folder | download | duplicates (2)
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