bot_example.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #!/usr/bin/python3
  2. """
  3. Competitive tetris bot example
  4. """
  5. import time
  6. import random
  7. import zmq
  8. import flatbuffers
  9. import numpy as np
  10. import wire_protocol.Command
  11. import wire_protocol.CommandRequest
  12. import wire_protocol.CommandResponse
  13. import wire_protocol.CommandResponseError
  14. import game_state
  15. def dummy_next_piece_func():
  16. return 0
  17. def cell_strength(field, row, col):
  18. neighbour_count = 0
  19. for r in range(row-1, row+2):
  20. for c in range(col-1, col+2):
  21. if (r < 0 or r >= field.shape[0] or
  22. c < 0 or c >= field.shape[1]):
  23. # walls are neighbours
  24. neighbour_count += 1
  25. elif field[r][c] > 0:
  26. neighbour_count += 1
  27. if field[row][col]:
  28. return neighbour_count * row
  29. else:
  30. return -neighbour_count * row
  31. def field_heuristic(field):
  32. result = 0.0
  33. for r in range(field.shape[0]):
  34. for c in range(field.shape[1]):
  35. result += cell_strength(field, r, c)
  36. return result
  37. class ShiftAndRotate:
  38. def __init__(self, rotate_count, col_offset, value, state):
  39. self.rotate_count = rotate_count
  40. self.col_offset = col_offset
  41. self.value = value
  42. self.state = state
  43. def shift_state(state, shift):
  44. if shift == 0:
  45. return state
  46. if shift < 0:
  47. for _ in range(abs(shift)):
  48. next_state = state.shift_left()
  49. if next_state is None:
  50. return None
  51. state = next_state
  52. else:
  53. for _ in range(shift):
  54. next_state = state.shift_right()
  55. if next_state is None:
  56. return None
  57. state = next_state
  58. return state
  59. def create_shifts_and_rotates(state):
  60. shift_and_rotates = []
  61. for rotate_count in range(5):
  62. rotate_state = state
  63. for _ in range(rotate_count):
  64. rotate_state = rotate_state.rotate()
  65. if rotate_state is None:
  66. break
  67. if rotate_state is None:
  68. continue
  69. for col_offset in range(-game_state.FIELD_WIDTH, game_state.FIELD_WIDTH+1):
  70. next_state = shift_state(rotate_state, col_offset)
  71. if next_state is not None:
  72. final_state, is_running = next_state.land().advance()
  73. if is_running:
  74. value = (field_heuristic(final_state.data.grid) +
  75. final_state.data.score*10000.0)
  76. shift_and_rotates.append(ShiftAndRotate(
  77. rotate_count,
  78. col_offset,
  79. value,
  80. final_state))
  81. return shift_and_rotates
  82. def main():
  83. context = zmq.Context()
  84. socket = context.socket(zmq.REQ)
  85. socket.connect("tcp://localhost:5555")
  86. builder = flatbuffers.Builder()
  87. wire_protocol.CommandRequest.Start(builder)
  88. wire_protocol.CommandRequest.AddCommand(
  89. builder,
  90. wire_protocol.Command.Command.StartGame)
  91. req = wire_protocol.CommandRequest.End(builder)
  92. builder.Finish(req)
  93. socket.send(builder.Output())
  94. rsp_buf = socket.recv()
  95. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  96. while True:
  97. builder = flatbuffers.Builder()
  98. wire_protocol.CommandRequest.Start(builder)
  99. wire_protocol.CommandRequest.AddCommand(
  100. builder,
  101. wire_protocol.Command.Command.GetGameState)
  102. req = wire_protocol.CommandRequest.End(builder)
  103. builder.Finish(req)
  104. socket.send(builder.Output())
  105. rsp_buf = socket.recv()
  106. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  107. if rsp.Error() != wire_protocol.CommandResponseError.CommandResponseError.OK:
  108. return
  109. grid = rsp.GameState().GridAsNumpy()
  110. grid = grid.reshape((rsp.GameState().Rows(), rsp.GameState().Cols()))
  111. state = game_state.GameState()
  112. state.data = game_state.GameStateData(
  113. grid = grid,
  114. current_piece = rsp.GameState().CurrentPiece(),
  115. next_piece = rsp.GameState().NextPiece(),
  116. rotation = rsp.GameState().PieceRotation(),
  117. row = rsp.GameState().PieceRow(),
  118. col = rsp.GameState().PieceCol(),
  119. score = rsp.GameState().Score())
  120. state.next_piece_func = dummy_next_piece_func
  121. millis_before_down = rsp.GameState().MillisBeforeDown()
  122. next_moves = create_shifts_and_rotates(state)
  123. if len(next_moves) > 0:
  124. best_moves = sorted(next_moves, key=lambda x: x.value, reverse=True)
  125. best_move = best_moves[0]
  126. command = wire_protocol.Command.Command.Rotate
  127. for _ in range(best_move.rotate_count):
  128. builder = flatbuffers.Builder()
  129. wire_protocol.CommandRequest.Start(builder)
  130. wire_protocol.CommandRequest.AddCommand(builder, command)
  131. req = wire_protocol.CommandRequest.End(builder)
  132. builder.Finish(req)
  133. socket.send(builder.Output())
  134. rsp_buf = socket.recv()
  135. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  136. if rsp.Error() != wire_protocol.CommandResponseError.CommandResponseError.OK:
  137. return
  138. command = wire_protocol.Command.Command.ShiftRight
  139. if best_move.col_offset < 0:
  140. command = wire_protocol.Command.Command.ShiftLeft
  141. for _ in range(abs(best_move.col_offset)):
  142. builder = flatbuffers.Builder()
  143. wire_protocol.CommandRequest.Start(builder)
  144. wire_protocol.CommandRequest.AddCommand(builder, command)
  145. req = wire_protocol.CommandRequest.End(builder)
  146. builder.Finish(req)
  147. socket.send(builder.Output())
  148. rsp_buf = socket.recv()
  149. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  150. if rsp.Error() != wire_protocol.CommandResponseError.CommandResponseError.OK:
  151. return
  152. builder = flatbuffers.Builder()
  153. wire_protocol.CommandRequest.Start(builder)
  154. wire_protocol.CommandRequest.AddCommand(
  155. builder, wire_protocol.Command.Command.Land)
  156. req = wire_protocol.CommandRequest.End(builder)
  157. builder.Finish(req)
  158. socket.send(builder.Output())
  159. rsp_buf = socket.recv()
  160. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  161. if rsp.Error() != wire_protocol.CommandResponseError.CommandResponseError.OK:
  162. return
  163. if __name__ == "__main__":
  164. main()