#!/usr/bin/python class Tetromino(): TYPES = ['i','a', 'b', 'c', 'o', 'd', 't', 's', 'z', 'j', 'l'] def __init__(self, state, letter): # assert that there are rows assert len(state) > 0 # assert rows and columns form a rectangle assert len({len(row) for row in state}) == 1 self.state = state self.letter = letter @staticmethod def ITetromino(): #ok return Tetromino( [ ['I', 'I', 'I', 'I'] ], 'i' ) @staticmethod def ATetromino(): #ok return Tetromino( [ ['A', 'A', 'A'] ], 'a' ) @staticmethod def BTetromino(): #ok return Tetromino( [ ['B', 'B',] ], 'b' ) @staticmethod def CTetromino(): #ok return Tetromino( [ ['C'] ], 'c' ) @staticmethod def OTetromino(): #ok return Tetromino( [ ['O', 'O'], ['O', 'O'] ], 'o' ) @staticmethod def DTetromino(): #ok return Tetromino( [ ['D', 'D'], [' ', 'D'] ], 'd' ) @staticmethod def TTetromino(): #ok return Tetromino( [ ['T', 'T', 'T'], [' ', 'T', ' '] ], 't' ) @staticmethod def STetromino(): #ok return Tetromino( [ [' ', 'S', 'S'], ['S', 'S', ' '] ], 's' ) @staticmethod def ZTetromino(): #ok return Tetromino( [ ['Z', 'Z', ' '], [' ', 'Z', 'Z'] ], 'z' ) @staticmethod def JTetromino(): #ok return Tetromino( [ ['J', 'J', 'J'], [' ', ' ', 'J'] ], 'j' ) @staticmethod def LTetromino(): return Tetromino( [ [' ', ' ', 'L'], ['L', 'L', 'L'] ], 'l' ) @staticmethod def create(letter): assert letter.lower() in Tetromino.TYPES return getattr(Tetromino, '{}Tetromino'.format(letter.upper()))() def __str__(self): return "\n".join(["".join(x) for x in self.state]) def __getitem__(self, key): return self.state[key] def copy(self): return Tetromino([row[:] for row in self.state], self.letter) def width(self): return len(self.state[0]) def height(self): return len(self.state) def rotate(self, change): while change < 0: change += 4 change = (change % 4) assert 0 <= change and change <= 3 if change == 0: return None elif change == 1: self.rotate_right() elif change == 2: self.flip() elif change == 3: self.rotate_left() else: raise Exception('This should never happen!') def rotate_right(self): self.state = list(zip(*self.state[::-1])) return self def rotate_left(self): self.state = list(reversed(list(zip(*self.state)))) return self def flip(self): self.state = [row[::-1] for row in self.state[::-1]] return self def get_offset_column(self, rotation, mode): if mode == 1: offset_map= { 'i': {0: 8, 1: 9, 2: 8, 3: 9}, 'a': {0: 9, 1: 9, 2: 9, 3: 9}, 'b': {0: 9, 1: 9, 2: 9, 3: 9}, 'c': {0: 10, 1: 10, 2: 10, 3: 10}, 'o': {0: 9, 1: 9, 2: 9, 3: 9}, 'd': {0: 9, 1: 9, 2: 9, 3: 9}, 't': {0: 9, 1: 9, 2: 8, 3: 9}, 's': {0: 9, 1: 9, 2: 9, 3: 9}, 'z': {0: 9, 1: 9, 2: 9, 3: 9}, 'j': {0: 8, 1: 9, 2: 9, 3: 9}, 'l': {0: 8, 1: 9, 2: 9, 3: 9} } elif mode == 2: offset_map= { 'i': {0: 9, 1: 8, 2: 9, 3: 8}, 'a': {0: 9, 1: 9, 2: 9, 3: 9}, 'b': {0: 9, 1: 9, 2: 9, 3: 9}, 'c': {0: 10, 1: 10, 2: 10, 3: 10}, 'o': {0: 9, 1: 9, 2: 9, 3: 9}, 'd': {0: 9, 1: 9, 2: 9, 3: 9}, 't': {0: 9, 1: 9, 2: 9, 3: 8}, 's': {0: 9, 1: 9, 2: 9, 3: 9}, 'z': {0: 9, 1: 9, 2: 9, 3: 9}, 'j': {0: 9, 1: 8, 2: 9, 3: 9}, 'l': {0: 9, 1: 8, 2: 9, 3: 9} } elif mode == 3: offset_map= { 'i': {0: 8, 1: 9, 2: 8, 3: 9}, 'a': {0: 9, 1: 9, 2: 9, 3: 9}, 'b': {0: 9, 1: 9, 2: 9, 3: 9}, 'c': {0: 10, 1: 10, 2: 10, 3: 10}, 'o': {0: 9, 1: 9, 2: 9, 3: 9}, 'd': {0: 9, 1: 9, 2: 9, 3: 9}, 't': {0: 9, 1: 9, 2: 8, 3: 9}, 's': {0: 9, 1: 9, 2: 9, 3: 9}, 'z': {0: 9, 1: 9, 2: 9, 3: 9}, 'j': {0: 8, 1: 9, 2: 9, 3: 9}, 'l': {0: 8, 1: 9, 2: 9, 3: 9} } else: #mode == 4: offset_map = { 'i': {0: 8, 1: 9, 2: 8, 3: 9}, 'a': {0: 9, 1: 9, 2: 9, 3: 9}, 'b': {0: 9, 1: 9, 2: 9, 3: 9}, 'c': {0: 10, 1: 10, 2: 10, 3: 10}, 'o': {0: 9, 1: 9, 2: 9, 3: 9}, 'd': {0: 9, 1: 9, 2: 9, 3: 9}, 't': {0: 9, 1: 9, 2: 8, 3: 9}, 's': {0: 9, 1: 9, 2: 9, 3: 9}, 'z': {0: 9, 1: 9, 2: 9, 3: 9}, 'j': {0: 8, 1: 9, 2: 9, 3: 9}, 'l': {0: 8, 1: 9, 2: 9, 3: 9} } return offset_map.get(self.letter)[rotation] if __name__ == '__main__': t = Tetromino.LTetromino() print(t) print() t.rotate_right() print(t) print() t.rotate_right() print(t) print() t.rotate_left() print(t) print(t.height()) print(t.width()) t.flip() print(t)