l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · 

Proof state:
case mp
o₁ o₂ : Ordinal.{u_1}
⊢ nim o₁ + nim o₂ ≈ 0 → o₁ = o₂

Next tactic:
refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    

Proof state:
case mp
o₁ o₂ : Ordinal.{u_1}
hne : o₁ ≠ o₂
⊢ nim o₁ + nim o₂ ‖ 0

Next tactic:
wlog h : o₁ < o₂
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · 

Proof state:
case mp.inr
o₁ o₂ : Ordinal.{u_1}
hne : o₁ ≠ o₂
this : ∀ (o₁ o₂ : Ordinal.{u_1}), o₁ ≠ o₂ → o₁ < o₂ → nim o₁ + nim o₂ ‖ 0
h : ¬o₁ < o₂
⊢ nim o₁ + nim o₂ ‖ 0

Next tactic:
exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
    

Proof state:
o₁ o₂ : Ordinal.{u_1}
hne : o₁ ≠ o₂
h : o₁ < o₂
⊢ nim o₁ + nim o₂ ‖ 0

Next tactic:
rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂]
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
    rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂]
    

Proof state:
o₁ o₂ : Ordinal.{u_1}
hne : o₁ ≠ o₂
h : o₁ < o₂
⊢ ∃ i,
    0 ≤
      moveLeft
        (nim o₁ +
          mk (Quotient.out o₂).α (Quotient.out o₂).α (fun o₂_1 => nim (typein (fun x x_1 => x < x_1) o₂_1)) fun o₂_1 =>
            nim (typein (fun x x_1 => x < x_1) o₂_1))
        i

Next tactic:
refine' ⟨toLeftMovesAdd (Sum.inr _), _⟩
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
    rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂]
    refine' ⟨toLeftMovesAdd (Sum.inr _), _⟩
    · 

Proof state:
case refine'_1
o₁ o₂ : Ordinal.{u_1}
hne : o₁ ≠ o₂
h : o₁ < o₂
⊢ LeftMoves
    (mk (Quotient.out o₂).α (Quotient.out o₂).α (fun o₂_1 => nim (typein (fun x x_1 => x < x_1) o₂_1)) fun o₂_1 =>
      nim (typein (fun x x_1 => x < x_1) o₂_1))

Next tactic:
exact (Ordinal.principalSegOut h).top
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
    rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂]
    refine' ⟨toLeftMovesAdd (Sum.inr _), _⟩
    · exact (Ordinal.principalSegOut h).top
    · -- Porting note: squeezed simp
      

Proof state:
case refine'_2
o₁ o₂ : Ordinal.{u_1}
hne : o₁ ≠ o₂
h : o₁ < o₂
⊢ 0 ≤
    moveLeft
      (nim o₁ +
        mk (Quotient.out o₂).α (Quotient.out o₂).α (fun o₂_1 => nim (typein (fun x x_1 => x < x_1) o₂_1)) fun o₂_1 =>
          nim (typein (fun x x_1 => x < x_1) o₂_1))
      (toLeftMovesAdd (Sum.inr (principalSegOut h).top))

Next tactic:
simpa only [Ordinal.typein_top, Ordinal.type_lt, PGame.add_moveLeft_inr, PGame.moveLeft_mk]
        using (Impartial.add_self (nim o₁)).2
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
    rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂]
    refine' ⟨toLeftMovesAdd (Sum.inr _), _⟩
    · exact (Ordinal.principalSegOut h).top
    · -- Porting note: squeezed simp
      simpa only [Ordinal.typein_top, Ordinal.type_lt, PGame.add_moveLeft_inr, PGame.moveLeft_mk]
        using (Impartial.add_self (nim o₁)).2
  · 

Proof state:
case mpr
o₁ o₂ : Ordinal.{u_1}
⊢ o₁ = o₂ → nim o₁ + nim o₂ ≈ 0

Next tactic:
rintro rfl
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
  constructor
  · refine' not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 _
    wlog h : o₁ < o₂
    · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h))
    rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂]
    refine' ⟨toLeftMovesAdd (Sum.inr _), _⟩
    · exact (Ordinal.principalSegOut h).top
    · -- Porting note: squeezed simp
      simpa only [Ordinal.typein_top, Ordinal.type_lt, PGame.add_moveLeft_inr, PGame.moveLeft_mk]
        using (Impartial.add_self (nim o₁)).2
  · rintro rfl
    

Proof state:
case mpr
o₁ : Ordinal.{u_1}
⊢ nim o₁ + nim o₁ ≈ 0

Next tactic:
exact Impartial.add_self (nim o₁)
@[simp]
theorem nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} : nim o₁ + nim o₂ ‖ 0 ↔ o₁ ≠ o₂ := by
  

Proof state:
o₁ o₂ : Ordinal.{u_1}
⊢ nim o₁ + nim o₂ ‖ 0 ↔ o₁ ≠ o₂

Next tactic:
rw [iff_not_comm, Impartial.not_fuzzy_zero_iff, nim_add_equiv_zero_iff]
@[simp]
theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o₁ = o₂ := by
  

Proof state:
o₁ o₂ : Ordinal.{u_1}
⊢ nim o₁ ≈ nim o₂ ↔ o₁ = o₂

Next tactic:
rw [Impartial.equiv_iff_add_equiv_zero, nim_add_equiv_zero_iff]
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
 game is equivalent to -/
noncomputable def grundyValue : ∀ _ : PGame.{u}, Ordinal.{u}
  | G => Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i)
termination_by grundyValue G => G
decreasing_by 

Proof state:
x✝ : PGame
G : PGame := x✝
i : LeftMoves G
⊢ (invImage (fun a => a) instWellFoundedRelationPGame).1 (moveLeft G i) x✝

Next tactic:
pgame_wf_tac
theorem grundyValue_eq_mex_left (G : PGame) :
    grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) := by 

Proof state:
G : PGame
⊢ grundyValue G = mex fun i => grundyValue (moveLeft G i)

Next tactic:
rw [grundyValue]
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    

Proof state:
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
⊢ x✝ ≈ nim (grundyValue x✝)

Next tactic:
rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    

Proof state:
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
⊢ ∀ (i : LeftMoves (x✝ + nim (grundyValue x✝))), moveLeft (x✝ + nim (grundyValue x✝)) i ‖ 0

Next tactic:
intro i
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    

Proof state:
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
⊢ moveLeft (x✝ + nim (grundyValue x✝)) i ‖ 0

Next tactic:
apply leftMoves_add_cases i
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · 

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
⊢ ∀ (i : LeftMoves x✝), moveLeft (x✝ + nim (grundyValue x✝)) (toLeftMovesAdd (Sum.inl i)) ‖ 0

Next tactic:
intro i₁
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
⊢ moveLeft (x✝ + nim (grundyValue x✝)) (toLeftMovesAdd (Sum.inl i₁)) ‖ 0

Next tactic:
rw [add_moveLeft_inl]
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
⊢ moveLeft x✝ i₁ + nim (grundyValue x✝) ‖ 0

Next tactic:
apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
⊢ nim (grundyValue (moveLeft G i₁)) + nim (grundyValue x✝) ‖ 0

Next tactic:
rw [nim_add_fuzzy_zero_iff]
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
⊢ grundyValue (moveLeft G i₁) ≠ grundyValue x✝

Next tactic:
intro heq
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
heq : grundyValue (moveLeft G i₁) = grundyValue x✝
⊢ False

Next tactic:
rw [eq_comm, grundyValue_eq_mex_left G] at heq
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
heq : (mex fun i => grundyValue (moveLeft G i)) = grundyValue (moveLeft G i₁)
⊢ False

Next tactic:
have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
heq : (mex fun i => grundyValue (moveLeft G i)) = grundyValue (moveLeft G i₁)
h : ∀ (i : LeftMoves G), grundyValue (moveLeft G i) ≠ mex fun i => grundyValue (moveLeft G i)
⊢ False

Next tactic:
rw [heq] at h
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      rw [heq] at h
      

Proof state:
case hl
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₁ : LeftMoves x✝
heq : (mex fun i => grundyValue (moveLeft G i)) = grundyValue (moveLeft G i₁)
h : ∀ (i : LeftMoves G), grundyValue (moveLeft G i) ≠ grundyValue (moveLeft G i₁)
⊢ False

Next tactic:
exact (h i₁).irrefl
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      rw [heq] at h
      exact (h i₁).irrefl
    · 

Proof state:
case hr
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
⊢ ∀ (i : LeftMoves (nim (grundyValue x✝))), moveLeft (x✝ + nim (grundyValue x✝)) (toLeftMovesAdd (Sum.inr i)) ‖ 0

Next tactic:
intro i₂
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      rw [heq] at h
      exact (h i₁).irrefl
    · intro i₂
      

Proof state:
case hr
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₂ : LeftMoves (nim (grundyValue x✝))
⊢ moveLeft (x✝ + nim (grundyValue x✝)) (toLeftMovesAdd (Sum.inr i₂)) ‖ 0

Next tactic:
rw [add_moveLeft_inr, ← Impartial.exists_left_move_equiv_iff_fuzzy_zero]
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      rw [heq] at h
      exact (h i₁).irrefl
    · intro i₂
      rw [add_moveLeft_inr, ← Impartial.exists_left_move_equiv_iff_fuzzy_zero]
      

Proof state:
case hr
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
i₂ : LeftMoves (nim (grundyValue x✝))
⊢ ∃ i, moveLeft (x✝ + moveLeft (nim (grundyValue x✝)) i₂) i ≈ 0

Next tactic:
revert i₂
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      rw [heq] at h
      exact (h i₁).irrefl
    · intro i₂
      rw [add_moveLeft_inr, ← Impartial.exists_left_move_equiv_iff_fuzzy_zero]
      revert i₂
      

Proof state:
case hr
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
⊢ ∀ (i₂ : LeftMoves (nim (grundyValue x✝))), ∃ i, moveLeft (x✝ + moveLeft (nim (grundyValue x✝)) i₂) i ≈ 0

Next tactic:
rw [nim_def]
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
 nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
  | G => by
    rw [Impartial.equiv_iff_add_equiv_zero, ← Impartial.forall_leftMoves_fuzzy_iff_equiv_zero]
    intro i
    apply leftMoves_add_cases i
    · intro i₁
      rw [add_moveLeft_inl]
      apply
        (fuzzy_congr_left (add_congr_left (Equiv.symm (equiv_nim_grundyValue (G.moveLeft i₁))))).1
      rw [nim_add_fuzzy_zero_iff]
      intro heq
      rw [eq_comm, grundyValue_eq_mex_left G] at heq
      -- Porting note: added universe annotation, argument
      have h := Ordinal.ne_mex.{u, u} (fun i ↦ grundyValue (moveLeft G i))
      rw [heq] at h
      exact (h i₁).irrefl
    · intro i₂
      rw [add_moveLeft_inr, ← Impartial.exists_left_move_equiv_iff_fuzzy_zero]
      revert i₂
      rw [nim_def]
      

Proof state:
case hr
x✝ : PGame
inst✝ : Impartial x✝
G : PGame := x✝
i : LeftMoves (x✝ + nim (grundyValue x✝))
⊢ ∀
    (i₂ :
      LeftMoves
        (mk (Quotient.out (grundyValue x✝)).α (Quotient.out (grundyValue x✝)).α
          (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂))),
    ∃ i,
      moveLeft
          (x✝ +
            moveLeft
              (mk (Quotient.out (grundyValue x✝)).α (Quotient.out (grundyValue x✝)).α
                (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂))
              i₂)
          i ≈
        0

Next tactic:
intro i₂