def mcts_do_action(n, a): global tetris_game if tetris_game == None: tetris_game = Tetris() state = n.get_status() nodes = state["tiles"] current = state["current"] score = state["score"] step = state["step"] tetris_game.apply_status_by_ai(nodes = nodes, _current=current[0], _next=current[1], _score=score, _step=step) reward_func(tetris_game, False) onehot_action = [0] * 40 onehot_action[a] = 1 gameover = run_func(tetris_game, onehot_action, None) reward, info = reward_func(tetris_game, gameover) q = math.exp(reward) s1 = status_func(tetris_game) # q, info = mcts_calulate_status_q(tetris_game) n1 = mcts_node(s1, _action = a, _initQ = q, _over = gameover, _parent = n) n.add_child(a, n1) # if print_info: # print("add child %d -> %d(%d/%f) -> %d, i: %s" % (n.get_id(), current[0], a, n1.getQ(), n1.get_id(), info)) return n1
def __init__(self): self.game = Tetris() self.last_damage = 0 def clear_callback(payload): self.last_damage = payload[0] self.game.on('clear', clear_callback)
def __init__(self, horizon=-1, drop_interval=1000, mode='human'): # Init tetris game core self.tetris = Tetris(horizon) self.mode = mode self.game_started = False self.drop_interval = drop_interval self.first_game = True self.next_queue_items = [] self.game_over_banner = None self.shape_block_border = int(GUI_HEIGHT/400) self.shape_block_unit = int(GUI_HEIGHT/20) self.shape_block_size = int(GUI_HEIGHT/20) - 2*self.shape_block_border self.next_queue_offset = self.shape_block_unit*4+2*self.shape_block_border
def play_train(with_ui=False, force_init=False, init_with_gold=False, train_count=0, learn_rate=0, is_master=False, ui_tick=0): robot.init_model(train=True, forceinit=force_init, init_with_gold=init_with_gold, learning_rate=learn_rate) game = Tetris() ui = None if with_ui: if ui_tick == 0: ui_tick = 100 ui = TetrisUI(game, ui_tick) try: if train_count == 0: robot.train(game, as_master=is_master, ui=ui) else: robot.train(game, train_steps=train_count, as_master=is_master, ui=ui) except KeyboardInterrupt: print("user exit") robot.save_model() if ui != None: del ui del game
class SessionTetris(Session): def __init__(self): self.game = Tetris() self.last_damage = 0 def clear_callback(payload): self.last_damage = payload[0] self.game.on('clear', clear_callback) def act(self, a): action = game.controller.keys[a] for key in self.game.controller.keys: if key in autorepeat_keys: key_pressed = key in self.game.controller.pressed_keys and \ self.game.controller.pressed_keys[key][0] == True if key != action and key_pressed: self.game.controller.keyup(key) elif key == action and not key_pressed: self.game.controller.keydown(key) else: if key == action: self.game.controller.keydown(key) self.game.controller.keyup(key) def get_state(self): playfield = self.game.playfield_dropping playfield = list( [[0 if playfield[y][x] is not None else 1 for x in range(10)] for y in range(20)]) holdnext = self.game.holding_piece + self.game.drop.next_n_piece(5) holdnext = list([piece.rotation_shape for piece in holdnext]) return playfield, holdnext def get_reward(self): return self.last_damage / 12 def update(self): self.game.update() return self.game.finished
def play_ai(): game = Tetris() robot.init_model() ui = TetrisUI(game, 250) try: ui.loop(ai_model=robot) except KeyboardInterrupt: print("user exit") del ui del game
def play_ai_without_ui(count): if count == 0: count = 10 game = Tetris() robot.init_model() mcts.print_info = True scores = [] for i in range(count): while not game.gameover(): robot.run_game(game) # sleep(0.5) scores.append(game.score()) print("game over, score: %d, step: %d" % (game.score(), game.step())) game.reset() del game print("max: %d, min: %d, avg: %d" % (max(scores), min(scores), float(sum(scores)) / len(scores)))
def start_game(is_opponent=False): pygame.init() game = Tetris() game.start_game() if is_opponent: opponent = Tetris(name='Opponent') game.connect_opponent(opponent) opponent.start_game() opponent.connect_opponent(game) screen = display.set_mode((1280, 720), pg_locals.DOUBLEBUF) vis = Visualizer(game, screen) display.set_caption('NenwTris') clock = time.Clock() key_mapping = { pg_locals.K_LEFT: Controller.key_left, pg_locals.K_RIGHT: Controller.key_right, pg_locals.K_x: Controller.key_spin_cw, pg_locals.K_z: Controller.key_spin_ccw, pg_locals.K_c: Controller.key_hold, pg_locals.K_DOWN: Controller.key_softdrop, pg_locals.K_SPACE: Controller.key_harddrop } game_delay = 0 opponent_delay = 0 events = [] def handle_event(ev): if ev.type == pg_locals.QUIT: pygame.quit() sys.exit() elif ev.type == pg_locals.KEYDOWN: if ev.key in key_mapping: if not game_paused: game.controller.keydown(key_mapping[ev.key]) else: events.append(ev) elif ev.type == pg_locals.KEYUP: if ev.key in key_mapping: if not game_paused: game.controller.keyup(key_mapping[ev.key]) else: events.append(ev) while True: game_paused = game_delay > 0 for ev in event.get(): handle_event(ev) for i in range(len(events)): handle_event(events.pop(0)) if game_delay <= 0: game.update() else: game_delay -= 1 if is_opponent: if opponent_delay <= 0: opponent.update() else: opponent_delay -= 1 game_delay_delta, opponent_delay_delta = vis.update() opponent_delay += opponent_delay_delta else: game_delay_delta, = vis.update() game_delay += game_delay_delta clock.tick(60)
if __name__ == '__main__': from game import Tetris tetris = Tetris(10, 20, True, []) while True: tetris.run()
return maxQ_batch, maxAction_batch def train_getValidAction(status): #根据不同的形状,这里可以优化,不是所有形状都需要探索0~40 current = status["current"] if current == 1: #方块,不用旋转 return range(10) elif current == 0 or current == 3 or current == 4: #长条和两个S return range(20) else: return range(40) _simulator = Tetris() def train_simlutate_status_for_model_input(status, action): global _simulator # def apply_status_by_ai(self, nodes, _current, _next, _score, _step) _simulator.apply_status_by_ai(nodes=status["tiles"], _current=status["current"], _next=status["next"], _score=status["score"], _step=status["step"]) image_from = train_capture_model_input_image(_simulator) next_index = _simulator.next_index() train_run_game(_simulator, action, None) image_to = train_capture_model_input_image(_simulator) return image_from, image_to, next_index
def play(): game = Tetris() ui = TetrisUI(game) ui.loop() del ui del game
def main(): # initializing the pygame module pygame.init() # general information pygame.display.set_caption('Tetris') # creating screen screen = pygame.display.set_mode((GAME_WIDTH, GAME_HEIGHT)) screen.fill(BACKGROUND_COLOR) pygame.display.flip() running = True clock = pygame.time.Clock() # creating tetris object tetris = Tetris() tetris.field.draw() # showing the 'playground' surface on screen screen.blit(tetris.field.surface, FIELD_POSITION) while running: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == tetris.get_block_down_event: # dropping the block one square down tetris.current_block.drop(1) if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: running = False main() if tetris.is_running: # movement keys if event.key == pygame.K_RIGHT or event.key == pygame.K_d: tetris.current_block.move_x(1) if event.key == pygame.K_LEFT or event.key == pygame.K_a: tetris.current_block.move_x(-1) if event.key == pygame.K_DOWN or event.key == pygame.K_s: tetris.current_block.drop(1) if event.key == pygame.K_UP or event.key == pygame.K_w: tetris.current_block.rotate() if not tetris.is_running: tetris.start() if tetris.is_running: # checks if new block is on a solid square which would cause game over for coord in tetris.current_block.square_coords: if tetris.solid_coords[coord[1]][coord[0]] == 1: print('GAME OVER') return # removing solid row for row in tetris.solid_coords: # checks if a row is completely solid if row.count(1) == len(row): # removes that row tetris.solid_coords.remove([1] * 10) # inserts a new row at the top tetris.solid_coords.insert(0, [0] * 10) # re-drawing the field tetris.field.draw() # draws solid squares for y, row in enumerate(tetris.solid_coords): for x, column in enumerate(tetris.solid_coords[y]): # checks if a square belongs to the position if column == 1: tetris.field.draw_rectangle((255, 255, 204), x, y) # drawing the block on the field tetris.field.draw_block(tetris.current_block) # checks if the current block became solid if tetris.current_block.solid: tetris.round += 1 print(tetris.round) print(tetris.get_speed) pygame.time.set_timer(tetris.get_block_down_event, tetris.get_speed) # adding coordinates from the current block to solid squares for coord in tetris.current_block.square_coords: tetris.solid_coords[coord[1]][coord[0]] = 1 # creating a new block tetris.create_new_block() # updating the field on the main surface screen.blit(tetris.field.surface, FIELD_POSITION) pygame.display.flip()
class GameGUI(object): """ Tetris game GUI environment that draws tetris board. modes: human: interactive mode played by human agent: played by RL agents """ def __init__(self, horizon=-1, drop_interval=1000, mode='human'): # Init tetris game core self.tetris = Tetris(horizon) self.mode = mode self.game_started = False self.drop_interval = drop_interval self.first_game = True self.next_queue_items = [] self.game_over_banner = None self.shape_block_border = int(GUI_HEIGHT/400) self.shape_block_unit = int(GUI_HEIGHT/20) self.shape_block_size = int(GUI_HEIGHT/20) - 2*self.shape_block_border self.next_queue_offset = self.shape_block_unit*4+2*self.shape_block_border def init_gui(self): # Init windows and tetris board canvas self.window = Tk() self.window.title("Tetris") self.window.geometry('%dx%d' % (GUI_WIDTH, GUI_HEIGHT)) self.main_board = Canvas( self.window, width=GUI_WIDTH/2, height=GUI_HEIGHT) self.main_board.pack(side=tk.LEFT) self.main_board.config(bg='black') # Init menu menubar = Menu(self.window) self.window.config(menu=menubar) tetrismenu = Menu(menubar) menubar.add_cascade(label = "Tetris", menu = tetrismenu) tetrismenu.add_command(label="Start", command=self.start_game) tetrismenu.add_command(label="Quit", command=self.window.quit) # game over banner self.game_over_banner = None # Init side board self.side_board = Canvas( self.window, width=GUI_WIDTH/2, height=GUI_HEIGHT) self.side_board.pack(side=tk.LEFT) self.side_board.config(bg='white') # help text help_text = """a : move left d : move right s : move down w : hard drop j : rotate counter-clockwise k : rotate clockwise l : hold""" if self.mode == 'human': self.side_board.create_text(int(GUI_WIDTH*11/32), 80, text=help_text) # Display score self.score = self.side_board.create_text(int(GUI_WIDTH/4), GUI_HEIGHT-12, text="Score: 0000000000", font="Helvetica 16 bold") # Next queue backgrounds self.side_board.create_rectangle(0,0, self.shape_block_unit*4, self.shape_block_unit*4, outline=BLACK, fill=BLACK) self.side_board.create_rectangle(0, self.next_queue_offset, self.shape_block_unit*4, self.shape_block_unit*4+self.next_queue_offset, outline=BLACK, fill=BLACK) self.side_board.create_rectangle(0, 2*self.next_queue_offset, self.shape_block_unit*4, self.shape_block_unit*4+2*self.next_queue_offset, outline=BLACK, fill=BLACK) # Bind events if self.mode == 'human': self.window.bind("<KeyPress>", self.gui_key_stroke) def close(self): self.window.destroy() def get_env(self): return self.tetris def update_score(self): score_str = "Score: {:010d}".format(self.tetris.get_score()) self.side_board.itemconfig(self.score, text=score_str) def gui_key_stroke(self, key): if key.char == 'a': #print("move left") _, _, done = self.tetris.step(1) elif key.char == 's': #print("move down") _, _, done = self.tetris.step(3) elif key.char == 'd': #print("move right") _, _, done = self.tetris.step(2) elif key.char == 'w': #print("hard drop") _, _, done = self.tetris.step(4) elif key.char == 'j': #print("rotate counter clock-wise") _, _, done = self.tetris.step(5) elif key.char == 'k': #print("rotate clock-wise") _, _, done = self.tetris.step(6) elif key.char == 'l': #print("hold") _, _, done = self.tetris.step(7) else: return if done: self.game_over() def draw_mainboard(self, main_board): # first delete all old items on main board self.main_board.delete(tk.ALL) # draw rectangles according to game state for i, v in enumerate(main_board): for j, c in enumerate(v): left = self.shape_block_unit*i+self.shape_block_border right = left+self.shape_block_size-self.shape_block_border top = self.shape_block_unit*j+self.shape_block_border bottom = top+self.shape_block_size-self.shape_block_border # Line of four if c == 1: self.main_board.create_rectangle(left, top, right, bottom, outline=BLUE, fill=BLUE) # S-shape (orientation 1) elif c == 2: self.main_board.create_rectangle(left, top, right, bottom, outline=RED, fill=RED) # S-shape (orientation 2) elif c == 3: self.main_board.create_rectangle(left, top, right, bottom, outline=LIGHTBLUE, fill=LIGHTBLUE) # T-shape elif c == 4: self.main_board.create_rectangle(left, top, right, bottom, outline=ORANGE, fill=ORANGE) # L-shape (orientation 1) elif c == 5: self.main_board.create_rectangle(left, top, right, bottom, outline=GREEN, fill=GREEN) # L-shape (orientation 2) elif c == 6: self.main_board.create_rectangle(left, top, right, bottom, outline=PURPLE, fill=PURPLE) # Cube elif c == 7: self.main_board.create_rectangle(left, top, right, bottom, outline=YELLOW, fill=YELLOW) else: self.main_board.create_rectangle(left, top, right, bottom, fill="black") def draw_nextqueue(self, next_queue): # first clear old items for i in self.next_queue_items: self.side_board.delete(i) self.next_queue_items.clear() # draw rectangles according to game state for queueid in range(1,4): shape = next_queue[-1*queueid] for i, line in enumerate(shape): for j, c in enumerate(line): left = self.shape_block_unit*i+self.shape_block_border right = left+self.shape_block_size-self.shape_block_border top = self.shape_block_unit*j+self.shape_block_border+(queueid-1)*self.next_queue_offset bottom = top+self.shape_block_size-self.shape_block_border item = None # Line of four if c == 1: item = self.side_board.create_rectangle(left, top, right, bottom, outline=BLUE, fill=BLUE) # S-shape (orientation 1) elif c == 2: item = self.side_board.create_rectangle(left, top, right, bottom, outline=RED, fill=RED) # S-shape (orientation 2) elif c == 3: item = self.side_board.create_rectangle(left, top, right, bottom, outline=LIGHTBLUE, fill=LIGHTBLUE) # T-shape elif c == 4: item = self.side_board.create_rectangle(left, top, right, bottom, outline=ORANGE, fill=ORANGE) # L-shape (orientation 1) elif c == 5: item = self.side_board.create_rectangle(left, top, right, bottom, outline=GREEN, fill=GREEN) # L-shape (orientation 2) elif c == 6: item = self.side_board.create_rectangle(left, top, right, bottom, outline=PURPLE, fill=PURPLE) # Cube elif c == 7: item = self.side_board.create_rectangle(left, top, right, bottom, outline=YELLOW, fill=YELLOW) if item is not None: self.next_queue_items.append(item) def draw(self): last_run = time.time() * 1000 if self.game_started: mb, nq, score = self.tetris.render(mode='gui') self.draw_mainboard(mb) self.draw_nextqueue(nq) self.update_score() draw_time = time.time() * 1000 - last_run next_run = max(int(1000/FPS-draw_time), 0) self.window.after(next_run, self.draw) def auto_drop(self): self.tetris.step(3) self.window.after(self.drop_interval, self.auto_drop) def play(self): self.init_gui() self.draw() if self.mode == 'human': self.window.mainloop() else: self.start_game() self.window.update() def update_window(self): self.window.update() def start_game(self): self.game_started = True if self.game_over_banner is not None: self.main_board.delete(self.game_over_banner) if self.first_game and self.mode == 'human': self.auto_drop() self.first_game = False return self.tetris.reset() def game_over(self): self.game_over_banner = self.main_board.create_text(GUI_WIDTH/4, GUI_HEIGHT/2, text="Game Over", fill="white", font="Helvetica 40 bold") self.game_started = False