l3lab/ntp-mathlib huggingface dataset:
/-- `x * 1` has the same moves as `x`. -/
def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x
  | ⟨xl, xr, xL, xR⟩ => by
    -- Porting note: the next four lines were just `unfold has_one.one,`
    show _ * One.one ≡r _
    unfold One.one
    unfold instOnePGame
    change mk _ _ _ _ * mk _ _ _ _ ≡r _
    -- Porting note: changed `refine'` to `refine`,
    -- otherwise there are typeclass inference failures.
    refine ⟨(Equiv.sumEmpty _ _).trans (Equiv.prodPUnit _),
      (Equiv.emptySum _ _).trans (Equiv.prodPUnit _), ?_, ?_⟩ <;>
    (try rintro (⟨i, ⟨⟩⟩ | ⟨i, ⟨⟩⟩)) <;>
    { (try intro i)
      

Proof state:
case refine_2.inr.mk.unit
xl xr : Type u
xL : xl → PGame
xR : xr → PGame
i : xr
⊢ moveRight (mk xl xr xL xR * mk PUnit.{u + 1} PEmpty.{u + 1} (fun x => 0) PEmpty.elim) (Sum.inr (i, PUnit.unit)) ≡r
    moveRight (mk xl xr xL xR)
      (((Equiv.emptySum (xl × PEmpty.{u + 1}) (xr × PUnit.{u + 1})).trans (Equiv.prodPUnit xr))
        (Sum.inr (i, PUnit.unit)))

Next tactic:
dsimp
/-- `x * 1` has the same moves as `x`. -/
def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x
  | ⟨xl, xr, xL, xR⟩ => by
    -- Porting note: the next four lines were just `unfold has_one.one,`
    show _ * One.one ≡r _
    unfold One.one
    unfold instOnePGame
    change mk _ _ _ _ * mk _ _ _ _ ≡r _
    -- Porting note: changed `refine'` to `refine`,
    -- otherwise there are typeclass inference failures.
    refine ⟨(Equiv.sumEmpty _ _).trans (Equiv.prodPUnit _),
      (Equiv.emptySum _ _).trans (Equiv.prodPUnit _), ?_, ?_⟩ <;>
    (try rintro (⟨i, ⟨⟩⟩ | ⟨i, ⟨⟩⟩)) <;>
    { (try intro i)
      dsimp
      

Proof state:
case refine_2.inr.mk.unit
xl xr : Type u
xL : xl → PGame
xR : xr → PGame
i : xr
⊢ xR i * mk PUnit.{u + 1} PEmpty.{u + 1} (fun x => 0) PEmpty.elim + mk xl xr xL xR * 0 - xR i * 0 ≡r
    xR ((Equiv.emptySum (xl × PEmpty.{u + 1}) (xr × PUnit.{u + 1})) (Sum.inr (i, PUnit.unit))).1

Next tactic:
apply (Relabelling.subCongr (Relabelling.refl _) (mulZeroRelabelling _)).trans
/-- `x * 1` has the same moves as `x`. -/
def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x
  | ⟨xl, xr, xL, xR⟩ => by
    -- Porting note: the next four lines were just `unfold has_one.one,`
    show _ * One.one ≡r _
    unfold One.one
    unfold instOnePGame
    change mk _ _ _ _ * mk _ _ _ _ ≡r _
    -- Porting note: changed `refine'` to `refine`,
    -- otherwise there are typeclass inference failures.
    refine ⟨(Equiv.sumEmpty _ _).trans (Equiv.prodPUnit _),
      (Equiv.emptySum _ _).trans (Equiv.prodPUnit _), ?_, ?_⟩ <;>
    (try rintro (⟨i, ⟨⟩⟩ | ⟨i, ⟨⟩⟩)) <;>
    { (try intro i)
      dsimp
      apply (Relabelling.subCongr (Relabelling.refl _) (mulZeroRelabelling _)).trans
      

Proof state:
case refine_2.inr.mk.unit
xl xr : Type u
xL : xl → PGame
xR : xr → PGame
i : xr
⊢ xR i * mk PUnit.{u + 1} PEmpty.{u + 1} (fun x => 0) PEmpty.elim + mk xl xr xL xR * 0 - 0 ≡r
    xR ((Equiv.emptySum (xl × PEmpty.{u + 1}) (xr × PUnit.{u + 1})) (Sum.inr (i, PUnit.unit))).1

Next tactic:
rw [sub_zero]
/-- `x * 1` has the same moves as `x`. -/
def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x
  | ⟨xl, xr, xL, xR⟩ => by
    -- Porting note: the next four lines were just `unfold has_one.one,`
    show _ * One.one ≡r _
    unfold One.one
    unfold instOnePGame
    change mk _ _ _ _ * mk _ _ _ _ ≡r _
    -- Porting note: changed `refine'` to `refine`,
    -- otherwise there are typeclass inference failures.
    refine ⟨(Equiv.sumEmpty _ _).trans (Equiv.prodPUnit _),
      (Equiv.emptySum _ _).trans (Equiv.prodPUnit _), ?_, ?_⟩ <;>
    (try rintro (⟨i, ⟨⟩⟩ | ⟨i, ⟨⟩⟩)) <;>
    { (try intro i)
      dsimp
      apply (Relabelling.subCongr (Relabelling.refl _) (mulZeroRelabelling _)).trans
      rw [sub_zero]
      

Proof state:
case refine_2.inr.mk.unit
xl xr : Type u
xL : xl → PGame
xR : xr → PGame
i : xr
⊢ xR i * mk PUnit.{u + 1} PEmpty.{u + 1} (fun x => 0) PEmpty.elim + mk xl xr xL xR * 0 + 0 ≡r
    xR ((Equiv.emptySum (xl × PEmpty.{u + 1}) (xr × PUnit.{u + 1})) (Sum.inr (i, PUnit.unit))).1

Next tactic:
exact (addZeroRelabelling _).trans <|
        (((mulOneRelabelling _).addCongr (mulZeroRelabelling _)).trans <| addZeroRelabelling _)
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    

Proof state:
x y z : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
⊢ ⟦mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR⟧ = ⟦mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR)⟧

Next tactic:
let x := mk xl xr xL xR
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    

Proof state:
x✝ y z : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
⊢ ⟦mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR⟧ = ⟦mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR)⟧

Next tactic:
let y := mk yl yr yL yR
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    

Proof state:
x✝ y✝ z : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
⊢ ⟦mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR⟧ = ⟦mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR)⟧

Next tactic:
let z := mk zl zr zL zR
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    

Proof state:
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
⊢ ⟦mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR⟧ = ⟦mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR)⟧

Next tactic:
refine' quot_eq_of_mk'_quot_eq _ _ _ _
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · 

Proof state:
case refine'_1
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
⊢ LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR) ≃
    LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR))

Next tactic:
fconstructor
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · 

Proof state:
case refine'_1.toFun
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
⊢ LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR) →
    LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR))

Next tactic:
rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩)
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          

Proof state:
case refine'_1.toFun.inl.mk.inl.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
snd✝¹ : zl
fst✝ : xl
snd✝ : yl
⊢ LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR))

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          

Proof state:
case refine'_1.toFun.inl.mk.inr.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
snd✝¹ : zl
fst✝ : xr
snd✝ : yr
⊢ LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR))

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          

Proof state:
case refine'_1.toFun.inr.mk.inl.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
snd✝¹ : zr
fst✝ : xl
snd✝ : yr
⊢ LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR))

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          

Proof state:
case refine'_1.toFun.inr.mk.inr.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
snd✝¹ : zr
fst✝ : xr
snd✝ : yl
⊢ LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR))

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · 

Proof state:
case refine'_1.invFun
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
⊢ LeftMoves (mk xl xr xL xR * (mk yl yr yL yR * mk zl zr zL zR)) →
    LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR)

Next tactic:
rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩)
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          

Proof state:
case refine'_1.invFun.inl.mk.inl.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
fst✝¹ : xl
fst✝ : yl
snd✝ : zl
⊢ LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR)

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          

Proof state:
case refine'_1.invFun.inl.mk.inr.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
fst✝¹ : xl
fst✝ : yr
snd✝ : zr
⊢ LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR)

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          

Proof state:
case refine'_1.invFun.inr.mk.inl.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
fst✝¹ : xr
fst✝ : yl
snd✝ : zr
⊢ LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR)

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          

Proof state:
case refine'_1.invFun.inr.mk.inr.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
fst✝¹ : xr
fst✝ : yr
snd✝ : zl
⊢ LeftMoves (mk xl xr xL xR * mk yl yr yL yR * mk zl zr zL zR)

Next tactic:
solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · 

Proof state:
case refine'_1.left_inv
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
⊢ LeftInverse
    (fun a =>
      Sum.casesOn a
        (fun val =>
          Prod.casesOn val fun fst snd =>
            Sum.casesOn snd (fun val => Prod.casesOn val fun fst_1 snd => Sum.inl (Sum.inl (fst, fst_1), snd))
              fun val => Prod.casesOn val fun fst_1 snd => Sum.inr (Sum.inl (fst, fst_1), snd))
        fun val =>
        Prod.casesOn val fun fst snd =>
          Sum.casesOn snd (fun val => Prod.casesOn val fun fst_1 snd => Sum.inr (Sum.inr (fst, fst_1), snd)) fun val =>
            Prod.casesOn val fun fst_1 snd => Sum.inl (Sum.inr (fst, fst_1), snd))
    fun a =>
    Sum.casesOn a
      (fun val =>
        Prod.casesOn val fun fst snd =>
          Sum.casesOn fst (fun val => Prod.casesOn val fun fst snd_1 => Sum.inl (fst, Sum.inl (snd_1, snd))) fun val =>
            Prod.casesOn val fun fst snd_1 => Sum.inr (fst, Sum.inr (snd_1, snd)))
      fun val =>
      Prod.casesOn val fun fst snd =>
        Sum.casesOn fst (fun val => Prod.casesOn val fun fst snd_1 => Sum.inl (fst, Sum.inr (snd_1, snd))) fun val =>
          Prod.casesOn val fun fst snd_1 => Sum.inr (fst, Sum.inl (snd_1, snd))

Next tactic:
rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩)
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;> 

Proof state:
case refine'_1.left_inv.inl.mk.inl.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
snd✝¹ : zl
fst✝ : xl
snd✝ : yl
⊢ (fun a =>
        Sum.casesOn a
          (fun val =>
            Prod.casesOn val fun fst snd =>
              Sum.casesOn snd (fun val => Prod.casesOn val fun fst_1 snd => Sum.inl (Sum.inl (fst, fst_1), snd))
                fun val => Prod.casesOn val fun fst_1 snd => Sum.inr (Sum.inl (fst, fst_1), snd))
          fun val =>
          Prod.casesOn val fun fst snd =>
            Sum.casesOn snd (fun val => Prod.casesOn val fun fst_1 snd => Sum.inr (Sum.inr (fst, fst_1), snd))
              fun val => Prod.casesOn val fun fst_1 snd => Sum.inl (Sum.inr (fst, fst_1), snd))
      ((fun a =>
          Sum.casesOn a
            (fun val =>
              Prod.casesOn val fun fst snd =>
                Sum.casesOn fst (fun val => Prod.casesOn val fun fst snd_1 => Sum.inl (fst, Sum.inl (snd_1, snd)))
                  fun val => Prod.casesOn val fun fst snd_1 => Sum.inr (fst, Sum.inr (snd_1, snd)))
            fun val =>
            Prod.casesOn val fun fst snd =>
              Sum.casesOn fst (fun val => Prod.casesOn val fun fst snd_1 => Sum.inl (fst, Sum.inr (snd_1, snd)))
                fun val => Prod.casesOn val fun fst snd_1 => Sum.inr (fst, Sum.inl (snd_1, snd)))
        (Sum.inl (Sum.inl (fst✝, snd✝), snd✝¹))) =
    Sum.inl (Sum.inl (fst✝, snd✝), snd✝¹)

Next tactic:
rfl
theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * z)⟧ :=
  match x, y, z with
  | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by
    let x := mk xl xr xL xR
    let y := mk yl yr yL yR
    let z := mk zl zr zL zR
    refine' quot_eq_of_mk'_quot_eq _ _ _ _
    · fconstructor
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;>
          -- Porting note: as above, increased the `maxDepth` here by 1.
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩ | ⟨_, ⟨_, _⟩ | ⟨_, _⟩⟩) <;>
          solve_by_elim (config := { maxDepth := 8 }) [Sum.inl, Sum.inr, Prod.mk]
      · rintro (⟨⟨_, _⟩ | ⟨_, _⟩, _⟩ | ⟨⟨_, _⟩ | ⟨_, _⟩, _⟩) <;> 

Proof state:
case refine'_1.left_inv.inl.mk.inr.mk
x✝ y✝ z✝ : PGame
xl xr : Type u_1
xL : xl → PGame
xR : xr → PGame
yl yr : Type u_1
yL : yl → PGame
yR : yr → PGame
zl zr : Type u_1
zL : zl → PGame
zR : zr → PGame
x : PGame := mk xl xr xL xR
y : PGame := mk yl yr yL yR
z : PGame := mk zl zr zL zR
snd✝¹ : zl
fst✝ : xr
snd✝ : yr
⊢ (fun a =>
        Sum.casesOn a
          (fun val =>
            Prod.casesOn val fun fst snd =>
              Sum.casesOn snd (fun val => Prod.casesOn val fun fst_1 snd => Sum.inl (Sum.inl (fst, fst_1), snd))
                fun val => Prod.casesOn val fun fst_1 snd => Sum.inr (Sum.inl (fst, fst_1), snd))
          fun val =>
          Prod.casesOn val fun fst snd =>
            Sum.casesOn snd (fun val => Prod.casesOn val fun fst_1 snd => Sum.inr (Sum.inr (fst, fst_1), snd))
              fun val => Prod.casesOn val fun fst_1 snd => Sum.inl (Sum.inr (fst, fst_1), snd))
      ((fun a =>
          Sum.casesOn a
            (fun val =>
              Prod.casesOn val fun fst snd =>
                Sum.casesOn fst (fun val => Prod.casesOn val fun fst snd_1 => Sum.inl (fst, Sum.inl (snd_1, snd)))
                  fun val => Prod.casesOn val fun fst snd_1 => Sum.inr (fst, Sum.inr (snd_1, snd)))
            fun val =>
            Prod.casesOn val fun fst snd =>
              Sum.casesOn fst (fun val => Prod.casesOn val fun fst snd_1 => Sum.inl (fst, Sum.inr (snd_1, snd)))
                fun val => Prod.casesOn val fun fst snd_1 => Sum.inr (fst, Sum.inl (snd_1, snd)))
        (Sum.inl (Sum.inr (fst✝, snd✝), snd✝¹))) =
    Sum.inl (Sum.inr (fst✝, snd✝), snd✝¹)

Next tactic:
rfl