Commits

Pierre-Marie de Rodat committed 4afd622

Test: greatly improved tiny bot to move randomly, even vertically.

This bot still hangs sometimes, but should not crash. When it appears to be
stuck somewhere, just restart it.

Comments (0)

Files changed (1)

     def __init__(self, username):
         super(MyClient, self).__init__(username)
         self.is_ready = threading.Event()
+        self.speed = 0
 
     def connect(self, address):
         super(MyClient, self).connect(address)
     def handle_spawnposition(self, packet):
         super(MyClient, self).handle_spawnposition(packet)
 
+    def handle_playerpositionlook(self, packet):
+        super(MyClient, self).handle_playerpositionlook(packet)
+        print '\x1b[34mGot playerpositionlook… centering and changing direction\x1b[0m'
+        self.player.center()
+        self.generate_destination()
+
     def handle_chat(self, packet):
         pass
 
     def handle_gravity(self):
         p = self.player
         chunk = p.get_chunk()
+        if chunk is None:
+            return False
+
         x, y, z = (
-            int(p.x) & 0xF, int(p.y), int(p.z) & 0xF
+            int(p.x) & 0xF, int(math.floor(p.y)), int(p.z) & 0xF
         )
-        print 'Before:', p.y
         bottom = chunk.get((x, y, z))
         under = chunk.get((x, y - 1, z))
+        print 'Blocks where I am: %s/%s' % (hex(bottom.type), hex(under.type))
         stable = False
+
         if bottom.type == 0 and under.type == 0:
-            print 'Im falling'
+            print '\x1b[32mFloating in void, going down\x1b[0m (to %s)' % p.y
             p.set_position(y=p.y - 0.3)
             p.on_ground = False
         elif bottom.type != 0:
-            print 'Im in solid, going up'
+            print '\x1b[32m*IN* the ground: going up\x1b[0m (to %s)' % p.y
             p.set_position(y=p.y + 0.1)
         elif under.type != 0:
-            print 'Im on ground'
+            print '\x1b[32mOn the ground\x1b[0m (%s, %s, %s)' % (p.x, p.y, p.z)
+            p.set_position(y=y)
             p.on_groud = True
             stable = True
-        print 'After:', p.y
+
         self.put_packet(p.get_position_packet())
         return stable
 
+    def generate_destination(self):
+        possible_destinations = [
+            (-1, 0, 0), (1, 0, 0), (0, 0, -1), (0, 0, 1),
+            (-1, -1, 0), (1, -1, 0), (0, -1, -1), (0, -1, 1),
+            (-1, 1, 0), (1, 1, 0), (0, 1, -1), (0, 1, 1),
+        ]
+        random.shuffle(possible_destinations)
+        for dx, dy, dz in possible_destinations:
+            dest_x = self.player.x + dx
+            dest_y = self.player.y + dy
+            dest_z = self.player.z + dz
+            if not self.is_walkable(dest_x, dest_y, dest_z):
+                continue
+            self.speed = 0.4
+            self.dx, self.dy, self.dz = dx, dy, dz
+            self.wanted_position = (dest_x, dest_y, dest_z)
+            self.start_position = (self.player.x, self.player.y, self.player.z)
+            print '\x1b[31mChanging direction\x1b[0m: %s, %s, %s' % (
+                dest_x, dest_y, dest_z
+            )
+            return True
+        print '\x1b[31mNo possible destination...\x1b[0m'
+        self.speed = 0
+        return False
+
+    def is_walkable(self, x, y, z):
+        x, y, z = int(x), int(y), int(z)
+        chunk = self.map.get((x >> 4, z >> 4))
+        if chunk is None:
+            return False
+        bx, by, bz = (x & 0x0F, y, z & 0x0F)
+        top, bottom, under = (
+            chunk.get((bx, by + 1, bz)),
+            chunk.get((bx, by, bz)),
+            chunk.get((bx, by - 1, bz)),
+        )
+        print 'Destination (%s, %s, %s) contains %s %s %s' % (
+            x, y, z,
+            top.type, bottom.type, under.type
+        )
+        return (top.type == 0 and bottom.type == 0 and under.type != 0)
+
+    def walk(self):
+        if not self.handle_gravity():
+            return False
+        if self.speed == 0:
+            self.generate_destination()
+            return False
+
+        if (
+            abs(self.player.x - self.wanted_position[0]) < 0.2 and
+            abs(self.player.z - self.wanted_position[2]) < 0.2
+        ):
+            # We arrived!
+            print self.player.x, self.wanted_position[0]
+            print self.player.y, self.wanted_position[1]
+            print self.player.z, self.wanted_position[2]
+            return True
+        nx, ny, nz = (
+            self.player.x + self.dx * self.speed,
+            self.player.y,
+            self.player.z + self.dz * self.speed
+        )
+
+        if self.is_walkable(nx, ny, nz):
+            # We stand on the ground and the destination is free: we can walk!
+            self.player.set_position(x=nx, y=ny, z=nz)
+            print 'Walking to (%s, %s, %s)' % (nx, ny, nz)
+        elif self.is_walkable(nx, ny + self.dy, nz):
+            self.player.set_position(x=nx, y=ny + self.dy, z=nz)
+            self.dy = 0
+            print 'Walking to (%s, %s, %s) (changed Y!)' % (nx, ny, nz)
+        else:
+            # The previously planned destination has become unreachable: go
+            # back to the center of the block then chose a new destination.
+            print 'I can no longer walk in this direction'
+            self.player.set_position(
+                x=self.start_position[0],
+                y=self.start_position[1],
+                z=self.start_position[2],
+            )
+            self.player.center()
+            self.generate_destination()
+        self.put_packet(self.player.get_position_packet())
+        return False
+
 
 
 def main():
     try:
         c.connect((host, int(port)))
         c.is_ready.wait()
-        speed = 0.3
-        dx, dz = 0, speed
-        p = c.player
         while True:
-            stable = c.handle_gravity()
-            nx, nz = p.x + dx, p.z + dz
-            chunk = c.map.get((int(nx) >> 4, int(nz) >> 4))
-            can_walk = False
-            if stable and chunk is not None:
-                print 'my chunk is not None'
-                x, y, z = (
-                    int(nx) & 0xF,
-                    int(p.y),
-                    int(nz) & 0xF
-                )
-                top, bottom, under = (
-                    chunk.get((x, y + 1, z)),
-                    chunk.get((x, y, z)),
-                    chunk.get((x, y - 1, z)),
-                )
-                can_walk = (
-                    top.type == 0 and bottom.type == 0 and under.type != 0
-                )
-            else:
-                print 'my chunk is None'
-            if can_walk:
-                # The way is free: walk
-                print 'I can walk!'
-                p.set_position(x=nx, z=nz)
-                c.put_packet(p.get_position_packet())
-            elif stable:
-                print '\x1b[31mChanging direction\x1b[0m'
-                p.set_position(x=nx, z=nz)
-                direction = random.random() * math.pi
-                dx = math.sin(direction) * speed
-                dz = math.cos(direction) * speed
-            time.sleep(.1)
+            if c.walk():
+                print '\x1b[33mArrived!\x1b[0m'
+                c.generate_destination()
+            time.sleep(.2)
         c.put_packet(packet.Disconnect(reason='Goodbye!'))
         time.sleep(1)
         c.close()