bot_example.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. while True:
  87. builder = flatbuffers.Builder()
  88. wire_protocol.CommandRequest.Start(builder)
  89. wire_protocol.CommandRequest.AddCommand(
  90. builder,
  91. wire_protocol.Command.Command.GetGameState)
  92. req = wire_protocol.CommandRequest.End(builder)
  93. builder.Finish(req)
  94. socket.send(builder.Output())
  95. rsp_buf = socket.recv()
  96. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  97. grid = rsp.GameState().GridAsNumpy()
  98. grid = grid.reshape((rsp.GameState().Rows(), rsp.GameState().Cols()))
  99. state = game_state.GameState()
  100. state.data = game_state.GameStateData(
  101. grid = grid,
  102. current_piece = rsp.GameState().CurrentPiece(),
  103. next_piece = rsp.GameState().NextPiece(),
  104. rotation = rsp.GameState().PieceRotation(),
  105. row = rsp.GameState().PieceRow(),
  106. col = rsp.GameState().PieceCol(),
  107. score = rsp.GameState().Score())
  108. state.next_piece_func = dummy_next_piece_func
  109. next_moves = create_shifts_and_rotates(state)
  110. if len(next_moves) > 0:
  111. best_moves = sorted(next_moves, key=lambda x: x.value, reverse=True)
  112. best_move = best_moves[0]
  113. command = wire_protocol.Command.Command.Rotate
  114. for _ in range(best_move.rotate_count):
  115. builder = flatbuffers.Builder()
  116. wire_protocol.CommandRequest.Start(builder)
  117. wire_protocol.CommandRequest.AddCommand(builder, command)
  118. req = wire_protocol.CommandRequest.End(builder)
  119. builder.Finish(req)
  120. socket.send(builder.Output())
  121. rsp_buf = socket.recv()
  122. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  123. command = wire_protocol.Command.Command.ShiftRight
  124. if best_move.col_offset < 0:
  125. command = wire_protocol.Command.Command.ShiftLeft
  126. for _ in range(abs(best_move.col_offset)):
  127. builder = flatbuffers.Builder()
  128. wire_protocol.CommandRequest.Start(builder)
  129. wire_protocol.CommandRequest.AddCommand(builder, command)
  130. req = wire_protocol.CommandRequest.End(builder)
  131. builder.Finish(req)
  132. socket.send(builder.Output())
  133. rsp_buf = socket.recv()
  134. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  135. builder = flatbuffers.Builder()
  136. wire_protocol.CommandRequest.Start(builder)
  137. wire_protocol.CommandRequest.AddCommand(
  138. builder, wire_protocol.Command.Command.Land)
  139. req = wire_protocol.CommandRequest.End(builder)
  140. builder.Finish(req)
  141. socket.send(builder.Output())
  142. rsp_buf = socket.recv()
  143. rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
  144. if __name__ == "__main__":
  145. main()