소스 검색

Added reading playfield to the wire protocol

Alexey Dorokhov 3 년 전
부모
커밋
c700c9b95b
8개의 변경된 파일153개의 추가작업 그리고 11개의 파일을 삭제
  1. 18 1
      bot_example.py
  2. 19 2
      competitive_tetris.py
  3. 6 6
      game.py
  4. 1 1
      tetrominos.py
  5. 8 0
      wire_protocol.fbs
  6. 1 0
      wire_protocol/Command.py
  7. 15 1
      wire_protocol/CommandResponse.py
  8. 85 0
      wire_protocol/Playfield.py

+ 18 - 1
bot_example.py

@@ -8,6 +8,7 @@ import time
 import random
 import zmq
 import flatbuffers
+import numpy as np
 
 import wire_protocol.Command
 import wire_protocol.CommandRequest
@@ -29,7 +30,7 @@ def main():
                     wire_protocol.Command.Command.ShiftLeft,
                     wire_protocol.Command.Command.ShiftRight,
                     wire_protocol.Command.Command.Rotate,
-                    wire_protocol.Command.Command.Land,
+                    #wire_protocol.Command.Command.Land,
                     ]))
         req = wire_protocol.CommandRequest.End(builder)
         builder.Finish(req)
@@ -37,6 +38,22 @@ def main():
 
         rsp_buf = socket.recv()
         rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
+
+        builder = flatbuffers.Builder()
+        wire_protocol.CommandRequest.Start(builder)
+        wire_protocol.CommandRequest.AddCommand(
+                builder,
+                wire_protocol.Command.Command.GetGameState)
+        req = wire_protocol.CommandRequest.End(builder)
+        builder.Finish(req)
+        socket.send(builder.Output())
+
+        rsp_buf = socket.recv()
+        rsp = wire_protocol.CommandResponse.CommandResponse.GetRootAs(rsp_buf)
+
+        cells = rsp.Playfield().CellsAsNumpy()
+        cells = cells.reshape((rsp.Playfield().Rows(), rsp.Playfield().Cols()))
+        print(f"cells = \n{cells}\n")
         time.sleep(0.24)
 
 

+ 19 - 2
competitive_tetris.py

@@ -13,6 +13,7 @@ import game
 import wire_protocol.Command
 import wire_protocol.CommandRequest
 import wire_protocol.CommandResponse
+import wire_protocol.Playfield
 import wire_protocol.CommandResponseError
 
 pygame.font.init()
@@ -134,6 +135,7 @@ def main(win):
             req = wire_protocol.CommandRequest.CommandRequest.GetRootAs(req_buf)
 
             error_code = wire_protocol.CommandResponseError.CommandResponseError.OK
+            cells = None
 
             if req.Command() == wire_protocol.Command.Command.ShiftLeft:
                 game_state = game.game_state_shift(game_state, -1)
@@ -143,18 +145,33 @@ def main(win):
                 game_state = game.game_state_rotate(game_state)
             elif req.Command() == wire_protocol.Command.Command.Land:
                 game_state = game.game_state_land(game_state)
+            elif req.Command() == wire_protocol.Command.Command.GetGameState:
+                cells = game.get_game_state_field(game_state)
             else:
                 error_code = wire_protocol.CommandResponseError.CommandResponseError.UNKNOWN_COMMAND
 
             builder = flatbuffers.Builder()
+            playfield = None
+            if cells is not None:
+                wire_protocol.Playfield.StartCellsVector(builder, cells.size)
+                builder.head -= cells.size
+                builder.Bytes[builder.head:(builder.head + cells.size)] = cells.tobytes()
+                cells_vector = builder.EndVector(cells.size)
+
+                wire_protocol.Playfield.Start(builder)
+                wire_protocol.Playfield.AddRows(builder, cells.shape[0])
+                wire_protocol.Playfield.AddCols(builder, cells.shape[1])
+                wire_protocol.Playfield.AddCells(builder, cells_vector)
+                playfield = wire_protocol.Playfield.End(builder)
+
             wire_protocol.CommandResponse.Start(builder)
             wire_protocol.CommandResponse.AddError(builder, error_code)
+            if playfield is not None:
+                wire_protocol.CommandResponse.AddPlayfield(builder, playfield)
             rsp = wire_protocol.CommandResponse.End(builder)
             builder.Finish(rsp)
             socket.send(builder.Output())
 
-
-
         is_game_running = True
         if frame_time >= 500:
             game_state, is_game_running = game.advance_game_state(

+ 6 - 6
game.py

@@ -23,17 +23,17 @@ def tetromino_to_field_at(tetromino, row, col):
 
     array = tetromino.data
     left_zeros = np.zeros(shape=(array.shape[0], col_offset),
-                          dtype=np.int32, order="C")
+                          dtype=np.byte, order="C")
     right_zeros = np.zeros(shape=(array.shape[0],
                                   FIELD_WIDTH-col_offset-array.shape[1]),
-                           dtype=np.int32, order="C")
+                           dtype=np.byte, order="C")
     array = np.concatenate((left_zeros, array, right_zeros), axis=1)
 
     top_zeros = np.zeros(shape=(row_offset,FIELD_WIDTH),
-                         dtype=np.int32, order="C")
+                         dtype=np.byte, order="C")
     bottom_zeros = np.zeros(shape=(FIELD_HEIGHT - row_offset - array.shape[0],
                                    FIELD_WIDTH),
-                            dtype=np.int32, order="C")
+                            dtype=np.byte, order="C")
     array = np.concatenate((top_zeros, array, bottom_zeros), axis=0)
     return array
 
@@ -45,7 +45,7 @@ GameState = collections.namedtuple('GameState',
 
 def initial_game_state(current_piece, next_piece):
     return GameState(grid=np.zeros(shape=(FIELD_HEIGHT,FIELD_WIDTH),
-                                   dtype=np.int32, order="C"),
+                                   dtype=np.byte, order="C"),
                      current_piece=current_piece,
                      next_piece=next_piece,
                      rotation=0, row=0, col=0, score=0)
@@ -144,7 +144,7 @@ def advance_game_state_piece(game_state, next_piece):
 def advance_game_state_purge_lines(game_state):
     next_grid_row = FIELD_HEIGHT-1
     next_grid = np.zeros(shape=(FIELD_HEIGHT,FIELD_WIDTH),
-                                dtype=np.int32, order="C")
+                                dtype=np.byte, order="C")
     next_score = game_state.score
     for row in range(FIELD_HEIGHT-1, -1,-1):
         if np.all(game_state.grid[row,:]):

+ 1 - 1
tetrominos.py

@@ -9,7 +9,7 @@ def convert_to_array(tetromino):
     rows = len(tetromino)
     cols = len(tetromino[0])
     array_tetromino = np.zeros(shape=(rows,cols),
-                               dtype=np.int32, order="C")
+                               dtype=np.byte, order="C")
     for row_index, row in enumerate(tetromino):
         for col_index, col in enumerate(row):
             array_tetromino[row_index,col_index] = 0 if col == '.' else 1

+ 8 - 0
wire_protocol.fbs

@@ -5,6 +5,7 @@ enum Command : short {
   ShiftRight = 1,
   Rotate = 2,
   Land = 3,
+  GetGameState = 4,
 }
 
 enum CommandResponseError : short {
@@ -16,8 +17,15 @@ table CommandRequest {
   command:Command;
 }
 
+table Playfield {
+  rows:short;
+  cols:short;
+  cells:[ubyte];
+}
+
 table CommandResponse {
   error:CommandResponseError;
+  playfield:Playfield;
 }
 
 root_type CommandRequest;

+ 1 - 0
wire_protocol/Command.py

@@ -7,3 +7,4 @@ class Command(object):
     ShiftRight = 1
     Rotate = 2
     Land = 3
+    GetGameState = 4

+ 15 - 1
wire_protocol/CommandResponse.py

@@ -31,12 +31,26 @@ class CommandResponse(object):
             return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos)
         return 0
 
-def CommandResponseStart(builder): builder.StartObject(1)
+    # CommandResponse
+    def Playfield(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            x = self._tab.Indirect(o + self._tab.Pos)
+            from wire_protocol.Playfield import Playfield
+            obj = Playfield()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+def CommandResponseStart(builder): builder.StartObject(2)
 def Start(builder):
     return CommandResponseStart(builder)
 def CommandResponseAddError(builder, error): builder.PrependInt16Slot(0, error, 0)
 def AddError(builder, error):
     return CommandResponseAddError(builder, error)
+def CommandResponseAddPlayfield(builder, playfield): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(playfield), 0)
+def AddPlayfield(builder, playfield):
+    return CommandResponseAddPlayfield(builder, playfield)
 def CommandResponseEnd(builder): return builder.EndObject()
 def End(builder):
     return CommandResponseEnd(builder)

+ 85 - 0
wire_protocol/Playfield.py

@@ -0,0 +1,85 @@
+# automatically generated by the FlatBuffers compiler, do not modify
+
+# namespace: wire_protocol
+
+import flatbuffers
+from flatbuffers.compat import import_numpy
+np = import_numpy()
+
+class Playfield(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Playfield()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsPlayfield(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+    # Playfield
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Playfield
+    def Rows(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos)
+        return 0
+
+    # Playfield
+    def Cols(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos)
+        return 0
+
+    # Playfield
+    def Cells(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # Playfield
+    def CellsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # Playfield
+    def CellsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Playfield
+    def CellsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+def PlayfieldStart(builder): builder.StartObject(3)
+def Start(builder):
+    return PlayfieldStart(builder)
+def PlayfieldAddRows(builder, rows): builder.PrependInt16Slot(0, rows, 0)
+def AddRows(builder, rows):
+    return PlayfieldAddRows(builder, rows)
+def PlayfieldAddCols(builder, cols): builder.PrependInt16Slot(1, cols, 0)
+def AddCols(builder, cols):
+    return PlayfieldAddCols(builder, cols)
+def PlayfieldAddCells(builder, cells): builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(cells), 0)
+def AddCells(builder, cells):
+    return PlayfieldAddCells(builder, cells)
+def PlayfieldStartCellsVector(builder, numElems): return builder.StartVector(1, numElems, 1)
+def StartCellsVector(builder, numElems):
+    return PlayfieldStartCellsVector(builder, numElems)
+def PlayfieldEnd(builder): return builder.EndObject()
+def End(builder):
+    return PlayfieldEnd(builder)