Example #1
0
def yellow_corners(state_str):
    side_faces = ["F", "R", "B", "L"]
    aim_corners = [{"D", side_faces[i], side_faces[(i + 1) % 4]}
                   for i in range(4)]
    corners = []
    for f in side_faces:
        n = get_normal(f)
        m = np.cross(Y, n)
        pos = -Y + n + m
        corners.append({
            get_color_from_state_str(state_str, pos, -Y),
            get_color_from_state_str(state_str, pos, n),
            get_color_from_state_str(state_str, pos, m)
        })
    is_rightly_positioned = [c == cc for c, cc in zip(aim_corners, corners)]
    if sum(is_rightly_positioned) == 1:
        i = is_rightly_positioned.index(True)  # Belgium
        # print("One belgium found", i)
        to_right = aim_corners[(i + 1) % 4] == corners[(i + 3) % 4]
        # print(f"{to_right=}")
        moves = BELGIUM if not to_right else flip_left_right(BELGIUM)
        return rotate_moves_about_y(moves,
                                    get_normal(side_faces[(i + to_right) % 4]))
    # print("Not belgium found")
    return BELGIUM
Example #2
0
def white_cross(state_str):
    # Start with 2nd crown edges
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 0, z])
            cols = [
                get_color_from_state_str(state_str, pos, x * X),
                get_color_from_state_str(state_str, pos, z * Z)
            ]
            if "U" in cols:
                # print("2nd crown")
                i = [c != "U" for c in cols].index(True)
                col = cols[i]
                n = [x * X, z * Z][i]
                v = get_normal(col)
                # print(n, v)
                u = [x * X, z * Z][1 - i]

                m1, m3 = _get_up_turn(n, v)

                m2 = get_face_for_normal(n)
                if np.cross(n, u)[1] > 0:
                    m2 += "'"
                # print(m1, m2, m3)

                return m1 + [m2] + m3

    # Then down edges
    for x, z, n in [(-1, 0, -X), (1, 0, X), (0, -1, -Z), (0, 1, Z)]:
        pos = np.array([x, -1, z])
        c_side = get_color_from_state_str(state_str, pos, n)
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if c_down == "U":
            # print("Down - down")
            m1, m3 = _get_up_turn(get_normal(c_side), n)
            m2 = get_face_for_normal(n) + "2"
            # print(m1, m2, m3)
            return m1 + [m2] + m3
        elif c_side == "U":
            # print("Down - side")
            m1, m3 = _get_up_turn(get_normal(c_side), n)
            m = get_face_for_normal(n)
            mm = get_face_for_normal(np.cross(n, Y))
            m2 = [m, "U", mm, "U'"]

            return m1 + m2 + m3

    # Then up edges (if misplaced)
    for x, z, n in [(-1, 0, -X), (1, 0, X), (0, -1, -Z), (0, 1, Z)]:
        pos = np.array([x, 1, z])
        # print(pos, get_color_from_state_str(state_str, pos, n))
        if get_color_from_state_str(state_str, pos,
                                    n) != get_face_for_normal(n):
            # print("Misplaced", pos, n)
            return [get_face_for_normal(n)]  # Simply get it out

    raise ValueError("No move found, it cross done?")
Example #3
0
def white_corners(state_str):
    # Down corners
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, -1, z])
            csx = get_color_from_state_str(state_str, pos, x * X)
            csz = get_color_from_state_str(state_str, pos, z * Z)
            c_down = get_color_from_state_str(state_str, pos, -Y)
            if csx == "U" or csz == "U":
                # White on side
                # print("Down - side", csx, csz, c_down)
                n = x * X if csx == "U" else z * Z
                v = z * Z if csx == "U" else x * X
                col = csz if csx == "U" else csx
                m1, m3 = _get_up_turn(get_normal(col), v)
                to_right = np.cross(v, n)[1] > 0
                m2 = [get_face_for_normal(n), "D"]
                if to_right:
                    m2[0] += "'"
                    m2[1] += "'"
                m2.append(neg_move(m2[0]))
                return m1 + m2 + m3
            elif c_down == "U":
                # White down -> just move it on side
                csx = get_color_from_state_str(state_str, pos, x * X)
                csz = get_color_from_state_str(state_str, pos, z * Z)
                # print("Down - down", csx, csz)
                m1, m3 = _get_up_turn(get_normal(csx),
                                      z * Z)  # Rotate around x
                f = get_face_for_normal(x * X)
                m2 = [f, "D'", neg_move(f)]
                if x * z > 0:
                    m2 = [neg_move(m) for m in m2]
                # print(m1 + m2 + m3)
                return m1 + m2 + m3
    # Up corners -> move it down
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 1, z])
            cu = get_color_from_state_str(state_str, pos, Y)
            csx = get_color_from_state_str(state_str, pos, x * X)
            csz = get_color_from_state_str(state_str, pos, z * Z)
            if cu != "U" or csx != get_face_for_normal(
                    x * X) or csz != get_face_for_normal(z * Z):
                # print("Corner wrongly oriented")
                n = x * X if csx == "U" else z * Z
                v = z * Z if csx == "U" else x * X
                m2 = [
                    get_face_for_normal(n), "D",
                    neg_move(get_face_for_normal(n))
                ]
                to_right = np.cross(v, n)[1] > 0
                if to_right:
                    m2 = [neg_move(m) for m in m2]
                return m2
    raise ValueError("No move found: is white face finished?")
Example #4
0
def second_crown(state_str):
    for x, z, n in [(-1, 0, -X), (1, 0, X), (0, -1, -Z), (0, 1, Z)]:
        pos = np.array([x, -1, z])
        c_side = get_color_from_state_str(state_str, pos, n)
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if "D" not in [c_side, c_down]:  # Down edges
            # print("Down edge", c_down, c_side)
            # Move in front of c_side color
            theta = angle(n, get_normal(c_side), ignore_axis=1)
            theta = (np.round(theta / np.pi * 2) * 90) % 360
            m1 = []
            if theta == 90:
                m1 = ["D'"]
            elif theta == 180:
                m1 = ["D2"]
            if theta == 270:
                m1 = ["D"]
            # is_right if c_down is to its right
            to_left = np.cross(get_normal(c_side), get_normal(c_down))[1] > 0
            moves = BASE_SECOND_CROWN_MOVE
            if not to_left:
                # print("to_right")
                moves = flip_left_right(moves)
            moves = rotate_moves_about_y(moves, get_normal(c_side))
            return m1 + moves
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 0, z])
            cs1 = get_color_from_state_str(state_str, pos, x * X)
            cs2 = get_color_from_state_str(state_str, pos, z * Z)
            if cs1 != get_face_for_normal(x * X) or cs2 != get_face_for_normal(
                    z * Z):  # Wrong place / orientation
                # print("Edge misplaced", cs1, cs2, x, z)
                if x * z == -1:
                    rotate_about = x * X
                else:
                    rotate_about = z * Z
                moves = rotate_moves_about_y(BASE_SECOND_CROWN_MOVE,
                                             rotate_about)
                return moves
    raise ValueError("No edge for second crown, is second crown done?")
Example #5
0
def test_get_normal():
    assert np.array_equal(get_normal("F"), Z)
    assert np.array_equal(get_normal("B"), -Z)
    assert np.array_equal(get_normal("R"), X)
    assert np.array_equal(get_normal("L"), -X)
    assert np.array_equal(get_normal("U"), Y)
    assert np.array_equal(get_normal("D"), -Y)
Example #6
0
def is_yellow_corners_positioned(state_str):
    side_faces = ["F", "R", "B", "L"]
    for i, f in enumerate(side_faces):
        n = get_normal(f)
        m = np.cross(Y, n)
        pos = -Y + n + m
        corner = {
            get_color_from_state_str(state_str, pos, -Y),
            get_color_from_state_str(state_str, pos, n),
            get_color_from_state_str(state_str, pos, m)
        }
        aim_corner = {"D", side_faces[i], side_faces[(i + 1) % 4]}
        if aim_corner != corner:
            return False
    return True
Example #7
0
    def _animate(self, dt):
        # Needs to be called for each frame to run animations
        if self._animation.empty():
            return
        anim = self._animation.peek()  # Get current face animation
        if anim.current_angle == 0:  # If first frame
            cube_ids = get_cube_ids_on_face(anim.face)
            anim.cubes = self.cubes[cube_ids]
            self.state.move(anim.move)

        speed_deg = dt * anim.DEG_PER_SEC / 1000
        if anim.current_angle >= anim.target_angle - speed_deg:
            self._finish_animation()
            return

        speed_rad = np.radians(speed_deg)
        delta = -speed_rad if not anim.reverse else speed_rad
        rot_vec = delta * get_normal(anim.face)
        rot = Rotation.from_rotvec(rot_vec)
        for cube in anim.cubes:
            cube.rotate(rot)
        anim.current_angle += speed_deg
Example #8
0
def generate_cubes_from_state_str(state_str, check=False):
    if check:
        try:
            kociemba.solve(state_str)
        except ValueError as e:
            raise ValueError(f"Invalid state string {state_str}")

    base = np.eye(3)
    cubes = [None] * 26
    i = 0
    for x in (-1, 0, 1):
        for y in (-1, 0, 1):
            for z in (-1, 0, 1):
                if x == y == z == 0:  # Skip center cube
                    continue
                pos = np.array([x, y, z])

                colors = [False] * 6
                basis = [None] * 3
                for axis in np.where(pos != 0)[0]:
                    color = get_color_from_state_str(state_str, pos,
                                                     pos[axis] * base[axis])
                    norm = get_normal(color)
                    basis[axis] = norm * pos[axis]
                    colors[FACE_ORDER.index(color)] = True

                rot = get_rot_from_basis(basis)
                original_pos = rot.apply(pos)
                ox, oy, oz = original_pos
                id = 9 * (ox + 1) + 3 * (oy + 1) + (oz + 1)
                index = 9 * (x + 1) + 3 * (y + 1) + (z + 1)
                if index > 13:
                    index = index - 1
                if id > 13:
                    id = id - 1
                cube = Cube(initial_rotation=rot.inv(), colors=colors, id=id)
                cubes[index] = cube
                i += 1
    return np.array(cubes)
Example #9
0
 def get_color_on_face(self, face):
     normal = get_normal(face)
     from_normal = self.rotation.inv().apply(normal)
     return get_face_for_normal(from_normal)