7 Commits 4fd3fdd472 ... 08fdbd345d

Tác giả SHA1 Thông báo Ngày
  Taddeus Kroes 08fdbd345d Commit old experimental strategy change to not lose it 1 tháng trước cách đây
  Taddeus Kroes 9bdd07929d Add some additional screenshots 1 tháng trước cách đây
  Taddeus Kroes ee26eec7b0 Tweak key delays 6 năm trước cách đây
  Taddeus Kroes 8776c3a951 Don't drop held blocks blindly but score all destinations liek with regular moves 6 năm trước cách đây
  Taddeus Kroes 470e972cdb Cleanup / assertions 6 năm trước cách đây
  Taddeus Kroes ade56874fc Optimized for squared distance to prioritize direct grouping more 6 năm trước cách đây
  Taddeus Kroes bd8e499b57 Improve loop detection 6 năm trước cách đây
7 tập tin đã thay đổi với 31 bổ sung30 xóa
  1. 5 9
      bot.py
  2. 3 3
      interaction.py
  3. BIN
      screens/board24.png
  4. BIN
      screens/board25.png
  5. BIN
      screens/board26.png
  6. BIN
      screens/board99.png
  7. 23 18
      strategy.py

+ 5 - 9
bot.py

@@ -11,6 +11,7 @@ from strategy import State
 
 
 MAX_SPEED_ROWS = 3
+MAX_LOOP = 6
 
 
 def save_screenshot(win):
@@ -34,7 +35,7 @@ if __name__ == '__main__':
 
         listen_keys({'s': lambda: save_screenshot(win)})
 
-        buf = deque([], maxlen=4)
+        buf = deque([], maxlen=MAX_LOOP)
 
         def vprint(*args, **kwargs):
             if verbose:
@@ -81,7 +82,7 @@ if __name__ == '__main__':
 
             if state.held == NOBLOCK and any(map(newstate.loops, buf)):
                 vprint('\rloop detected, wait for a bit...', end='')
-                time.sleep(0.03)
+                time.sleep(0.030)
             elif newstate.moves:
                 vprint('moves:', newstate.keys())
                 vprint('score:', newstate.score)
@@ -91,16 +92,11 @@ if __name__ == '__main__':
                 vprint_state(newstate)
 
                 press_keys(win, newstate.keys())
-
-                #keys_delay = len(newstate.moves) * 2 * KEY_DELAY
-                #moves_delay = max(0, newstate.delay() - keys_delay)
-                #vprint('wait for',  moves_delay, 'ms')
-                #time.sleep(moves_delay / 1000)
-                time.sleep(0.080)
+                time.sleep(0.050)
             elif state.nrows - 2 <= MAX_SPEED_ROWS:
                 vprint('no moves, speed up')
                 press_keys(win, 'l')
-                time.sleep(0.030)
+                time.sleep(0.015)
             else:
                 vprint('no moves')
 

+ 3 - 3
interaction.py

@@ -10,7 +10,7 @@ BOARD_X = 367
 BOARD_Y = 129
 BOARD_WIDTH = 420
 BOARD_HEIGHT = 638
-KEY_DELAY = 14  # milliseconds
+KEY_DELAY = 1 / 60  # 1 frame assuming 60 FPS
 
 
 disp = display.Display()
@@ -60,11 +60,11 @@ def press_keys(window, keys):
 
         ext.xtest.fake_input(disp, X.KeyPress, keycode)
         disp.sync()
-        time.sleep(KEY_DELAY / 1000)
+        time.sleep(KEY_DELAY)
 
         ext.xtest.fake_input(disp, X.KeyRelease, keycode)
         disp.sync()
-        time.sleep(KEY_DELAY / 1000)
+        time.sleep(KEY_DELAY)
 
 
 def listen_keys(handlers):

BIN
screens/board24.png


BIN
screens/board25.png


BIN
screens/board26.png


BIN
screens/board99.png


+ 23 - 18
strategy.py

@@ -81,6 +81,8 @@ class State:
         return 0
 
     def holes(self):
+        #return self.imbalance()
+
         start_row = self.empty_rows()
         score = 0
         for col in range(COLUMNS):
@@ -217,7 +219,7 @@ class State:
             if block != NOBLOCK:
                 colors.setdefault(block, []).append(i)
 
-        return sum(dist(i, j)
+        return sum(dist(i, j) ** 2
                    for blocks in colors.values()
                    for i, j in combinations(blocks, 2))
 
@@ -232,15 +234,26 @@ class State:
 
         return -points
 
+    def imbalance(self):
+        colsizes = tuple(self.nrows - skip
+                         for col, skip in enumerate(self.colskip))
+                         #if not self.colbusy(col))
+        mean = sum(colsizes) / len(colsizes)
+        return sum((size - mean) ** 2 for size in colsizes)
+
     def gen_moves(self):
-        yield self
+        if self.held == NOBLOCK:
+            yield self
 
-        for src in self.gen_shift(not self.colbusy(self.exa)):
-            yield from src.gen_stationary()
+            for src in self.gen_shift(True):
+                yield from src.gen_stationary()
 
-            for get in src.gen_get():
-                for dst in get.gen_shift(False):
-                    yield from dst.gen_put()
+                for get in src.gen_get():
+                    for dst in get.gen_shift(False):
+                        yield from dst.gen_put()
+        else:
+            for dst in self.gen_shift(True):
+                yield from dst.gen_put()
 
     def gen_shift(self, allow_noshift):
         if allow_noshift:
@@ -303,21 +316,11 @@ class State:
                 if avail >= 2:
                     yield swap.move(GRAB, SWAP, DROP)
 
-    def force(self, *moves):
-        state = self.move(*moves)
-        state.score = ()
-        return state
-
     def solve(self):
         assert self.exa is not None
 
-        if self.held != NOBLOCK:
-            return self.force(DROP)
-
         pool = deque(self.gen_moves())
-
-        if len(pool) == 0:
-            return self.force()
+        assert len(pool) > 0
 
         best_score = ()
 
@@ -333,6 +336,7 @@ class State:
 
             for i in range(len(pool)):
                 state = pool.popleft()
+                assert state.held == NOBLOCK
                 if state.score == best:
                     pool.append(state)
 
@@ -387,6 +391,7 @@ class State:
     def loops(self, prev):
         return self.moves and \
                self.exa == prev.exa and \
+               self.held == prev.held and \
                self.moves == prev.moves and \
                self.score == prev.score