import tetromino as tetr import copy, random import time as tim from time import sleep #random.seed(10430) class Tetromino: def __init__(self, shape_id, direction):#IJLOSTZ self.shape_id = shape_id self.array = tetr.data[shape_id][direction] self.direction = direction def __str__(self): s = '╔' + '═' * len(self.array[0]) + '╗\n' for row in self.array: s += '║' for cell in row: if cell > 0: s += '█' else: s += ' ' s += '║\n' s += '╚' + '═' * len(self.array[0]) + '╝' return s class Grid: def __init__(self, width, height): self.array = [[0 for j in range(0, width)] for i in range(0, height)] self.width = width self.height = height def __str__(self): return stringify(self.array) def copy(self): new = Grid(self.width, self.height) new.array = copyx(self.array) return new def add(self, obj, row, column, simulate=False): array = copyx(self.array) if type(obj) != type([]): obj = obj.array for r in range(0, len(obj)): for c in range(0, len(obj[r])): if obj[r][c] > 0: if 0 <= row+r <= self.height - 1 and 0 <= column+c <= self.width - 1: if array[row+r][column+c] > 0: return False array[row+r][column+c] = obj[r][c] else: return False if simulate: return array self.array = array return True def fitness(self, lines): global modes weights = [-0.510066, 0.76066, -0.35663, -0.184483] # Aggregrate Lines Hole Bumpiness aggregrate = 0 for c in range(0, self.width): for r in range(0, self.height): if self.array[r][c]: aggregrate += self.height - r break hole = 0 for c in range(0, self.width): covered = False for r in range(0, self.height): if (not covered) and self.array[r][c] > 0: covered = True if self.array[r][c] == 0 and covered: hole += 1 bumpiness = 0 for r in range(0, self.height): if self.array[r][0]: height = self.height - r break else: height = 0 last = height for c in range(1, self.width): for r in range(0, self.height): if self.array[r][c]: height = self.height - r break else: height = 0 delta = abs(last - height) bumpiness += delta last = height f = weights[0] * aggregrate + weights[1] * lines + weights[2] * hole + weights[3] * bumpiness if modes == 3: print(aggregrate, lines, hole, bumpiness, f) return f def simulate_peice(self, peice_id, direction, column): global modes simulation = self.copy() lines = 0 empty_line = [0 for i in range(0, self.width)] if not simulation.add(Tetromino(peice_id, direction), 0, column, True): return False row = 0 while simulation.add(Tetromino(peice_id, direction), row, column, True): row += 1 row -= 1 simulation.add(Tetromino(peice_id, direction), row, column) for row_id in range(0, self.height): if complete_line(simulation.array[row_id]): for mov_row_id in range(row_id, -1, -1): simulation.array[mov_row_id] = simulation.array[mov_row_id-1][:] simulation.array[0] = empty_line[:] lines += 1 if modes == 3: print(direction, column, lines, end=' ') return (simulation, lines) def display_simulation(self, peice_id, direction, column, time): global next_peice simulation = self.copy() lines = 0 empty_line = [0 for i in range(0, self.width)] if not simulation.add(Tetromino(peice_id, direction), 0, column, True): return row = 0 step = True while step: step = simulation.add(Tetromino(peice_id, direction), row, column, True) if step: print(Tetromino(next_peice, 0), '\nScore:', score, '\n', stringify(step), sep='') sleep(time) row += 1 row -= 1 simulation.add(Tetromino(peice_id, direction), row, column) for row_id in range(0, self.height): if complete_line(simulation.array[row_id]): for mov_row_id in range(row_id, -1, -1): simulation.array[mov_row_id] = simulation.array[mov_row_id-1][:] simulation.array[0] = empty_line[:] lines += 1 print(Tetromino(next_peice, 0), '\nScore:', score, '\n', simulation, sep='') def stringify(array): s = '╔' + '═' * len(array[0]) + '╗\n' for row in array: s += '║' for cell in row: #s += ['□','▣','▤', '▥', '▦', '▧', '▨', '▩'][cell] if cell == 0: s += ' ' else: #s += str(cell) s += '█' s += '║\n' s += '╚' + '═' * len(array[0]) + '╝' return s def copyx(array): result = [] for row in array: result.append(row[:]) return result def complete_line(line): for cell in line: if cell < 1: return False return True bag = [] def random_peice(): global bag if len(bag) == 0: bag = [0,1,2,3,4,5,6] random.shuffle(bag) return bag.pop() time = 1 modes = int(input('display mode (0: points, 1: boards, 2: animation, 3: debug):')) if modes == 2: time = 1/float(input('framerate (fps)?')) board = Grid(10, 22) if modes > 0: print(board) score = 0 peice_id = random_peice() next_peice = random_peice() mode = input('lookahead (Y/n)?').upper().startswith('N') itr = 0 while True: last = board.copy() best = [-10000, 0, 5, '', 0]#fitness, rotation, column, simulation for column in range(-2, board.width): for rotation in [0,1,2,3]: result = board.simulate_peice(peice_id, rotation, column) if result: if mode: fitness = result[0].fitness(result[1]) if not mode: for Column in range(-2, board.width): for Rotation in [0,1,2,3]: resultb = result[0].simulate_peice(next_peice, Rotation, Column) if resultb: fitness = resultb[0].fitness(resultb[1]) if fitness > best[0]: best = [fitness, rotation, column, result[0].copy(), result[1] + resultb[1]] if fitness > best[0] and mode: best = [fitness, rotation, column, result[0].copy(), result[1]] board = best[3] if board == '': print(''' █████ █ █ █ ███████ █ █ █ █ ██ ██ █ █ █ █ █ █ █ █ █ █ ████ █ █ █ █ █ █████ █ █ ███████ █ █ █ █ █ █ █ █ █ █ █████ █ █ █ █ ███████ ███████ █ █ ███████ ██████ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █████ ██████ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ███████ █ ███████ █ █ ''') break if modes > 1: last.display_simulation(peice_id, best[1], best[2], time) if modes == 1: print(score, '\n', board, sep='') peice_id = next_peice next_peice = random_peice() score += 10*best[4] itr += 1 if itr%100 == 0 and modes == 0: print('score: ', score, sep='') file = open('tetris scores.txt', 'a') print(tim.ctime(), itr, score, sep='\t', file=file) print('\n', board, '\n') file.close() input('')