| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- import collections
- import numpy as np
- import tetrominos
- FIELD_WIDTH = 10
- FIELD_HEIGHT = 20
- COMMAND_NONE = 0
- COMMAND_LEFT = 1
- COMMAND_RIGHT = 2
- COMMAND_ROTATE = 3
- def tetromino_to_field_at(tetromino, row, col):
- col_offset = col + tetromino.col_offset
- row_offset = row + tetromino.row_offset
- if col_offset < 0 or row_offset < 0:
- return None
- if col_offset + tetromino.data.shape[1] > FIELD_WIDTH:
- return None
- if row_offset + tetromino.data.shape[0] > FIELD_HEIGHT:
- return None
- array = tetromino.data
- left_zeros = np.zeros(shape=(array.shape[0], col_offset),
- dtype=np.byte, order="C")
- right_zeros = np.zeros(shape=(array.shape[0],
- FIELD_WIDTH-col_offset-array.shape[1]),
- 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.byte, order="C")
- bottom_zeros = np.zeros(shape=(FIELD_HEIGHT - row_offset - array.shape[0],
- FIELD_WIDTH),
- dtype=np.byte, order="C")
- array = np.concatenate((top_zeros, array, bottom_zeros), axis=0)
- return array
- GameState = collections.namedtuple('GameState',
- ['grid', 'current_piece', 'next_piece',
- 'rotation', 'row', 'col', 'score'])
- def initial_game_state(current_piece, next_piece):
- return GameState(grid=np.zeros(shape=(FIELD_HEIGHT,FIELD_WIDTH),
- dtype=np.byte, order="C"),
- current_piece=current_piece,
- next_piece=next_piece,
- rotation=0, row=0, col=0, score=0)
- def is_game_state_valid(game_state):
- tetromino_array = tetromino_to_field_at(
- tetrominos.SHAPES[game_state.current_piece][game_state.rotation],
- game_state.row, game_state.col)
- if tetromino_array is None:
- return False
- total_field = np.add(game_state.grid, tetromino_array)
- if np.any(np.vectorize(lambda x: x > 1)(total_field)):
- return False
- return True
- def get_game_state_field(game_state):
- tetromino_array = tetromino_to_field_at(
- tetrominos.SHAPES[game_state.current_piece][game_state.rotation],
- game_state.row, game_state.col)
- total_field = np.add(game_state.grid, tetromino_array)
- total_field = np.add(total_field, tetromino_array)
- return total_field
- def game_state_shift(game_state, col_offset):
- next_game_state = GameState(grid=game_state.grid,
- current_piece=game_state.current_piece,
- next_piece=game_state.next_piece,
- rotation=game_state.rotation,
- row=game_state.row,
- col=game_state.col + col_offset,
- score=game_state.score)
- if is_game_state_valid(next_game_state):
- return next_game_state
- return game_state
- def game_state_land(game_state):
- while True:
- next_game_state = GameState(grid=game_state.grid,
- current_piece=game_state.current_piece,
- next_piece=game_state.next_piece,
- rotation=game_state.rotation,
- row=game_state.row + 1,
- col=game_state.col,
- score=game_state.score)
- if is_game_state_valid(next_game_state):
- game_state = next_game_state
- else:
- break
- return game_state
- def game_state_rotate(game_state):
- next_game_state = GameState(grid=game_state.grid,
- current_piece=game_state.current_piece,
- next_piece=game_state.next_piece,
- rotation=(game_state.rotation + 1) % 4,
- row=game_state.row,
- col=game_state.col,
- score=game_state.score)
- if is_game_state_valid(next_game_state):
- return next_game_state
- return game_state
- def advance_game_state_down(game_state):
- next_game_state = GameState(grid=game_state.grid,
- current_piece=game_state.current_piece,
- next_piece=game_state.next_piece,
- rotation=game_state.rotation,
- row=game_state.row + 1,
- col=game_state.col,
- score=game_state.score)
- if is_game_state_valid(next_game_state):
- return next_game_state
- return None
- def advance_game_state_piece(game_state, next_piece):
- tetromino_array = tetromino_to_field_at(
- tetrominos.SHAPES[game_state.current_piece][game_state.rotation],
- game_state.row, game_state.col)
- next_grid = np.add(game_state.grid, tetromino_array)
- next_game_state = GameState(grid=next_grid,
- current_piece=game_state.next_piece,
- next_piece=next_piece,
- rotation=0, row=0, col=0,
- score=game_state.score)
- return next_game_state
- 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.byte, order="C")
- next_score = game_state.score
- for row in range(FIELD_HEIGHT-1, -1,-1):
- if np.all(game_state.grid[row,:]):
- next_score += 1
- else:
- next_grid[next_grid_row,:] = game_state.grid[row,:]
- next_grid_row -= 1
- next_game_state = GameState(grid=next_grid,
- current_piece=game_state.current_piece,
- next_piece=game_state.next_piece,
- rotation=game_state.rotation,
- row=game_state.row,
- col=game_state.col,
- score=next_score)
- return next_game_state
- def advance_game_state(game_state, next_piece_func):
- next_game_state = advance_game_state_down(game_state)
- is_game_running = True
- if next_game_state is None:
- next_game_state = advance_game_state_piece(game_state, next_piece_func())
- next_game_state = advance_game_state_purge_lines(next_game_state)
- if not is_game_state_valid(next_game_state):
- is_game_running = False
- if not is_game_running:
- return game_state, False
- return next_game_state, True
|