Beispiel #1
0
    def make_children(self, children, piece, held, next_can_hold, put_hold):

        maximum = float('-inf')
        ind = -1

        for i in range(len(children)):
            # unpack that child
            x, y, rot, moveset = children[i]

            # create new board and execute moves
            new_board = self.board.get_copy()

            new_piece = Block(piece)
            new_piece.execute_moves(moveset, self.board)
            new_piece.set(new_board)

            # calculate points
            new_lines = self.lines_sent
            combo_id = -1
            new_combos_so_far = self.combos_so_far + 1

            lines_cleared = new_board.clear_lines()

            if lines_cleared == 0:
                new_combos_so_far = 0
            else:
                is_tspin = tspin_detect(moveset)
                is_perf_clear = perf_clear_detect(new_board)
                combo_id = 1 if is_tspin else 0 if is_perf_clear else -1

                if is_tspin and is_perf_clear:
                    combo_id = 2

                new_lines += next_points(
                    self.combos_so_far - 1,
                    lines_cleared if lines_cleared != 4 else 0,
                    lines_cleared == 4, is_tspin, is_perf_clear,
                    combo_id == self.last_combo_id)

            # create the new node
            new_node = Tree_node(new_board, held, new_lines, new_combos_so_far,
                                 combo_id, next_can_hold)

            self.add_child(
                ([encode_move('hold')] if put_hold else []) + moveset,
                new_node)

            ranking = new_node.get_rank()
            if ranking > maximum:
                maximum = ranking
                ind = i

        return (maximum, ind)
Beispiel #2
0
	def make_nodes(self, children, piece_type, held_piece, q, is_held):

		for child in children:

			x, y, rot, moveset = child

			new_board = self.board.get_copy()

			new_piece = Block(piece_type)
			new_piece.execute_moves(moveset, self.board)
			new_piece.set(new_board)

			new_lines = self.lines_sent
			combo_id = -1
			new_combos_so_far = self.combos_so_far + 1

			lines_cleared = new_board.clear_lines()
			if lines_cleared == 0:
				new_combos_so_far = 0
			else:
				is_tspin = tspin_detect(moveset)
				is_perf_clear = perf_clear_detect(new_board)
				combo_id = 1 if is_tspin else 0 if is_perf_clear else -1

				if is_tspin and is_perf_clear:
					combo_id = 2

				new_lines += next_points(self.combos_so_far - 1,
										 lines_cleared if lines_cleared != 4 else 0,
										 lines_cleared == 4,
										 is_tspin,
										 is_perf_clear,
										 combo_id == self.last_combo_id)


			nq = [] if len(q) < 2 else deepcopy(q[1:])

			new_node = Tree_node(new_board,
								-1 if len(q) == 0 else q[0],
								held_piece,
								nq,
								new_lines,
								new_combos_so_far,
								combo_id,
								self.ranker,
								is_held)

			self.add_child(([encode_move('hold')] if is_held else []) + moveset, new_node)
Beispiel #3
0
def generate_successor_states(board, piece_type):
	# number of unique rotations per piece
	r = valid_rotations(piece_type)

	# store all possible positions in a queue
	pos = Queue()
	# 3D memo for later ;)
	memo = [[[0 for z in range(r)] for y in range(board.get_height())] for x in range(board.get_width())]

	# for each unique rotation
	for rotation in range(r):
		# construct a temporary piece
		temp_piece = Block(piece_type)
		temp_piece.set_rotation(board, rotation)


		# get the next offset after rotating
		sx = temp_piece.get_offset()[0]

		# for each horizontal position
		for x in range(board.get_width() - temp_piece.get_width() + 1):

			# shift the piece horizontally
			temp_piece.set_offset(x, 0)
			if temp_piece.collides(board):
				continue

			# drop
			temp_piece.drop(board)

			# get final position
			tx, ty = temp_piece.get_offset()

			# memoize
			memo[tx][ty][rotation] = 1

			#print(str(tx) + ", " + str(ty) + ", " + str(rotation))

			# encode moves
			moves = [encode_move('crot') for i in range(rotation)] + [encode_move('left') if x - sx < 0 else encode_move('right') for i in range(abs(x-sx))] + [encode_move('drop')]

			# enqueue
			pos.put((tx, ty, rotation, moves))

	# the final set to return
	children = []

	# while the queue still contains positions
	while not pos.empty():

		child = pos.get()

		# add to final bag
		children.append(child)

		x, y, rot, moves = child

		# make a block and put it into the correct place
		test_piece = Block(piece_type)
		test_piece.execute_moves(moves, board)

		o_off_x, o_off_y = test_piece.get_offset()

		# generate partial movements from this position, i.e. left, right, and all rotations
		# stored in tuples like so (dx, dy, nr)
		next_positions = [(1, 0, rot), (-1, 0, rot)] + [(0,0,i) for i in range(r)]

		# for each partial movement
		for npos in next_positions:
			# quick access variables
			dx, dy, nr = npos

			# rotate the piece for the new rotation, if possibe, else its invalid so skip
			if not test_piece.set_rotation(board, nr):
				continue

			offset = test_piece.get_offset()

			# translate the piece right or left or skip if invalid
			if (dx > 0 and not test_piece.r_translate(board)) or (dx < 0 and not test_piece.l_translate(board)):
				continue

			# apply gravity
			down = test_piece.drop(board)

			# get updated locations
			nx, ny = test_piece.get_offset()

			# check that the move was not already encoded
			if memo[nx][ny][nr] == 1:
				test_piece.dirty_reset_position(o_off_x, o_off_y, rot)
				continue

			# now encode additional movements
			# copy moves and convert drops to down movements because this is more meticulous

			nmoves = deepcopy(moves)

			# convert drops to down moves
			l = len(moves) - 1
			if moves[l] == encode_move('drop'):
				nmoves = nmoves[:l] + [encode_move('down') for i in range(y)]

			# generate additional horizontal movements
			if dx != 0:
				nmoves.append(encode_move('left') if dx == -1 else encode_move('right'))

			# generate rotation movements
			dr = nr - rot
			#print("rotations:",dr)
			if rot == 3 and nr == 0:
				nmoves += [encode_move('crot')]
			elif dr != 0:
				nmoves += [encode_move('crot') if dr > 0 else encode_move('ccrot') for i in range(abs(dr))]

			# generate additional down movements
			nmoves += [encode_move('down') for i in range(down)]

			# enqueue
			pos.put((nx, ny, nr, nmoves))

			# mark this new space as visited, too
			memo[nx][ny][nr] = 1

			# undo moves
			test_piece.dirty_reset_position(o_off_x, o_off_y, rot)

	return children