l3lab/ntp-mathlib huggingface dataset:
theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α := by rw [nim_def]; 

Proof state:
o : Ordinal.{u_1}
⊢ LeftMoves
      (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) =
    (Quotient.out o).α

Next tactic:
rfl
theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by 

Proof state:
o : Ordinal.{u_1}
⊢ RightMoves (nim o) = (Quotient.out o).α

Next tactic:
rw [nim_def]
theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by rw [nim_def]; 

Proof state:
o : Ordinal.{u_1}
⊢ RightMoves
      (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) =
    (Quotient.out o).α

Next tactic:
rfl
theorem moveLeft_nim_hEq (o : Ordinal) :
    have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance
    HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by 

Proof state:
o : Ordinal.{u_1}
⊢ let_fun this := (_ : IsWellOrder (Quotient.out o).α fun x x_1 => x < x_1);
  HEq (moveLeft (nim o)) fun i => nim (typein (fun x x_1 => x < x_1) i)

Next tactic:
rw [nim_def]
theorem moveLeft_nim_hEq (o : Ordinal) :
    have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance
    HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; 

Proof state:
o : Ordinal.{u_1}
⊢ let_fun this := (_ : IsWellOrder (Quotient.out o).α fun x x_1 => x < x_1);
  HEq
    (moveLeft
      (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)))
    fun i => nim (typein (fun x x_1 => x < x_1) i)

Next tactic:
rfl
theorem moveRight_nim_hEq (o : Ordinal) :
    have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance
    HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by 

Proof state:
o : Ordinal.{u_1}
⊢ let_fun this := (_ : IsWellOrder (Quotient.out o).α fun x x_1 => x < x_1);
  HEq (moveRight (nim o)) fun i => nim (typein (fun x x_1 => x < x_1) i)

Next tactic:
rw [nim_def]
theorem moveRight_nim_hEq (o : Ordinal) :
    have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance
    HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; 

Proof state:
o : Ordinal.{u_1}
⊢ let_fun this := (_ : IsWellOrder (Quotient.out o).α fun x x_1 => x < x_1);
  HEq
    (moveRight
      (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)))
    fun i => nim (typein (fun x x_1 => x < x_1) i)

Next tactic:
rfl
theorem moveLeft_nim {o : Ordinal} (i) : (nim o).moveLeft (toLeftMovesNim i) = nim i := by 

Proof state:
o : Ordinal.{u_1}
i : ↑(Set.Iio o)
⊢ moveLeft (nim o) (toLeftMovesNim i) = nim ↑i

Next tactic:
simp
theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i) = nim i := by 

Proof state:
o : Ordinal.{u_1}
i : ↑(Set.Iio o)
⊢ moveRight (nim o) (toRightMovesNim i) = nim ↑i

Next tactic:
simp
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort*} (i : (nim o).LeftMoves)
    (H : ∀ a (H : a < o), P <| toLeftMovesNim ⟨a, H⟩) : P i := by
  

Proof state:
o : Ordinal.{?u.16604}
P : LeftMoves (nim o) → Sort u_1
i : LeftMoves (nim o)
H : (a : Ordinal.{?u.16604}) → (H : a < o) → P (toLeftMovesNim { val := a, property := H })
⊢ P i

Next tactic:
rw [← toLeftMovesNim.apply_symm_apply i]
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort*} (i : (nim o).LeftMoves)
    (H : ∀ a (H : a < o), P <| toLeftMovesNim ⟨a, H⟩) : P i := by
  rw [← toLeftMovesNim.apply_symm_apply i]; 

Proof state:
o : Ordinal.{?u.16604}
P : LeftMoves (nim o) → Sort u_1
i : LeftMoves (nim o)
H : (a : Ordinal.{?u.16604}) → (H : a < o) → P (toLeftMovesNim { val := a, property := H })
⊢ P (toLeftMovesNim (toLeftMovesNim.symm i))

Next tactic:
apply H
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort*} (i : (nim o).RightMoves)
    (H : ∀ a (H : a < o), P <| toRightMovesNim ⟨a, H⟩) : P i := by
  

Proof state:
o : Ordinal.{?u.17019}
P : RightMoves (nim o) → Sort u_1
i : RightMoves (nim o)
H : (a : Ordinal.{?u.17019}) → (H : a < o) → P (toRightMovesNim { val := a, property := H })
⊢ P i

Next tactic:
rw [← toRightMovesNim.apply_symm_apply i]
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort*} (i : (nim o).RightMoves)
    (H : ∀ a (H : a < o), P <| toRightMovesNim ⟨a, H⟩) : P i := by
  rw [← toRightMovesNim.apply_symm_apply i]; 

Proof state:
o : Ordinal.{?u.17019}
P : RightMoves (nim o) → Sort u_1
i : RightMoves (nim o)
H : (a : Ordinal.{?u.17019}) → (H : a < o) → P (toRightMovesNim { val := a, property := H })
⊢ P (toRightMovesNim (toRightMovesNim.symm i))

Next tactic:
apply H
instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by
  

Proof state:
⊢ IsEmpty (LeftMoves (nim 0))

Next tactic:
rw [nim_def]
instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by
  rw [nim_def]
  

Proof state:
⊢ IsEmpty
    (LeftMoves
      (mk (Quotient.out 0).α (Quotient.out 0).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)))

Next tactic:
exact Ordinal.isEmpty_out_zero
instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by
  

Proof state:
⊢ IsEmpty (RightMoves (nim 0))

Next tactic:
rw [nim_def]
instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by
  rw [nim_def]
  

Proof state:
⊢ IsEmpty
    (RightMoves
      (mk (Quotient.out 0).α (Quotient.out 0).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)))

Next tactic:
exact Ordinal.isEmpty_out_zero
@[simp]
theorem toLeftMovesNim_one_symm (i) :
    (@toLeftMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by
  

Proof state:
i : LeftMoves (nim 1)
⊢ toLeftMovesNim.symm i = { val := 0, property := (_ : 0 ∈ Set.Iio 1) }

Next tactic:
simp [eq_iff_true_of_subsingleton]
@[simp]
theorem toRightMovesNim_one_symm (i) :
    (@toRightMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by
  

Proof state:
i : RightMoves (nim 1)
⊢ toRightMovesNim.symm i = { val := 0, property := (_ : 0 ∈ Set.Iio 1) }

Next tactic:
simp [eq_iff_true_of_subsingleton]
theorem nim_one_moveLeft (x) : (nim 1).moveLeft x = nim 0 := by 

Proof state:
x : LeftMoves (nim 1)
⊢ moveLeft (nim 1) x = nim 0

Next tactic:
simp
theorem nim_one_moveRight (x) : (nim 1).moveRight x = nim 0 := by 

Proof state:
x : RightMoves (nim 1)
⊢ moveRight (nim 1) x = nim 0

Next tactic:
simp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  

Proof state:
⊢ nim 1 ≡r star

Next tactic:
rw [nim_def]
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  

Proof state:
⊢ (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂)) ≡r
    star

Next tactic:
refine' ⟨_, _, fun i => _, fun j => _⟩
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  

Proof state:
case refine'_1
⊢ LeftMoves
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) ≃
    LeftMoves star
case refine'_2
⊢ RightMoves
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) ≃
    RightMoves star
case refine'_3
i :
  LeftMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveLeft
      (mk (Quotient.out 1).α (Quotient.out 1).α (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 ≡r
    moveLeft star (?refine'_1 i)
case refine'_4
j :
  RightMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveRight
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂))
      j ≡r
    moveRight star (?refine'_2 j)

Next tactic:
any_goals dsimp; apply Equiv.equivOfUnique
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals 

Proof state:
case refine'_1
⊢ LeftMoves
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) ≃
    LeftMoves star

Next tactic:
dsimp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; 

Proof state:
case refine'_1
⊢ (Quotient.out 1).α ≃ PUnit.{?u.23865 + 1}

Next tactic:
apply Equiv.equivOfUnique
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals 

Proof state:
case refine'_2
⊢ RightMoves
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) ≃
    RightMoves star

Next tactic:
dsimp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; 

Proof state:
case refine'_2
⊢ (Quotient.out 1).α ≃ PUnit.{?u.23865 + 1}

Next tactic:
apply Equiv.equivOfUnique
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals 

Proof state:
case refine'_3
i :
  LeftMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveLeft
      (mk (Quotient.out 1).α (Quotient.out 1).α (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 ≡r
    moveLeft star ((id (Equiv.equivOfUnique (Quotient.out 1).α PUnit.{?u.23865 + 1})) i)

Next tactic:
dsimp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; 

Proof state:
case refine'_3
i :
  LeftMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ nim (typein (fun x x_1 => x < x_1) i) ≡r 0

Next tactic:
apply Equiv.equivOfUnique
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals 

Proof state:
case refine'_4
j :
  RightMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveRight
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂))
      j ≡r
    moveRight star ((id (Equiv.equivOfUnique (Quotient.out 1).α PUnit.{?u.23865 + 1})) j)

Next tactic:
dsimp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; 

Proof state:
case refine'_4
j :
  RightMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ nim (typein (fun x x_1 => x < x_1) j) ≡r 0

Next tactic:
apply Equiv.equivOfUnique
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; apply Equiv.equivOfUnique
  

Proof state:
case refine'_3
i :
  LeftMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveLeft
      (mk (Quotient.out 1).α (Quotient.out 1).α (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 ≡r
    moveLeft star ((id (Equiv.equivOfUnique (Quotient.out 1).α PUnit.{?u.23865 + 1})) i)
case refine'_4
j :
  RightMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveRight
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂))
      j ≡r
    moveRight star ((id (Equiv.equivOfUnique (Quotient.out 1).α PUnit.{?u.23865 + 1})) j)

Next tactic:
all_goals simp; exact nimZeroRelabelling
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; apply Equiv.equivOfUnique
  all_goals 

Proof state:
case refine'_3
i :
  LeftMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveLeft
      (mk (Quotient.out 1).α (Quotient.out 1).α (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 ≡r
    moveLeft star ((id (Equiv.equivOfUnique (Quotient.out 1).α PUnit.{?u.23865 + 1})) i)

Next tactic:
simp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; apply Equiv.equivOfUnique
  all_goals simp; 

Proof state:
case refine'_3
i :
  LeftMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ nim 0 ≡r 0

Next tactic:
exact nimZeroRelabelling
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; apply Equiv.equivOfUnique
  all_goals 

Proof state:
case refine'_4
j :
  RightMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ moveRight
      (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂))
      j ≡r
    moveRight star ((id (Equiv.equivOfUnique (Quotient.out 1).α PUnit.{?u.25119 + 1})) j)

Next tactic:
simp
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
  rw [nim_def]
  refine' ⟨_, _, fun i => _, fun j => _⟩
  any_goals dsimp; apply Equiv.equivOfUnique
  all_goals simp; 

Proof state:
case refine'_4
j :
  RightMoves
    (mk (Quotient.out 1).α (Quotient.out 1).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂))
⊢ nim 0 ≡r 0

Next tactic:
exact nimZeroRelabelling
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
  

Proof state:
o : Ordinal.{u_1}
⊢ birthday (nim o) = o

Next tactic:
induction' o using Ordinal.induction with o IH
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
  induction' o using Ordinal.induction with o IH
  

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, birthday (nim k) = k
⊢ birthday (nim o) = o

Next tactic:
rw [nim_def, birthday_def]
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def, birthday_def]
  

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, birthday (nim k) = k
⊢ max
      (lsub fun i =>
        birthday
          (moveLeft
            (mk (Quotient.out o).α (Quotient.out o).α (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))
      (lsub fun i =>
        birthday
          (moveRight
            (mk (Quotient.out o).α (Quotient.out o).α (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)) =
    o

Next tactic:
dsimp
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def, birthday_def]
  dsimp
  

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, birthday (nim k) = k
⊢ max (lsub fun i => birthday (nim (typein (fun x x_1 => x < x_1) i)))
      (lsub fun i => birthday (nim (typein (fun x x_1 => x < x_1) i))) =
    o

Next tactic:
rw [max_eq_right le_rfl]
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def, birthday_def]
  dsimp
  rw [max_eq_right le_rfl]
  

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, birthday (nim k) = k
⊢ (lsub fun i => birthday (nim (typein (fun x x_1 => x < x_1) i))) = o

Next tactic:
convert lsub_typein o with i
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def, birthday_def]
  dsimp
  rw [max_eq_right le_rfl]
  convert lsub_typein o with i
  

Proof state:
case h.e'_2.h.e'_2.h
o : Ordinal.{u_1}
IH : ∀ k < o, birthday (nim k) = k
i : (Quotient.out o).α
⊢ birthday (nim (typein (fun x x_1 => x < x_1) i)) = typein (fun x x_1 => x < x_1) i

Next tactic:
exact IH _ (typein_lt_self i)
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  

Proof state:
o : Ordinal.{u_1}
⊢ -nim o = nim o

Next tactic:
induction' o using Ordinal.induction with o IH
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  induction' o using Ordinal.induction with o IH
  

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, -nim k = nim k
⊢ -nim o = nim o

Next tactic:
rw [nim_def]
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def]; 

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, -nim k = nim k
⊢ (-mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂)) =
    mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂)

Next tactic:
dsimp
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def]; dsimp; 

Proof state:
case h
o : Ordinal.{u_1}
IH : ∀ k < o, -nim k = nim k
⊢ (mk (Quotient.out o).α (Quotient.out o).α (fun j => -nim (typein (fun x x_1 => x < x_1) j)) fun i =>
      -nim (typein (fun x x_1 => x < x_1) i)) =
    mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
      nim (typein (fun x x_1 => x < x_1) o₂)

Next tactic:
congr
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def]; dsimp; congr <;> 

Proof state:
case h.e_a
o : Ordinal.{u_1}
IH : ∀ k < o, -nim k = nim k
⊢ (fun j => -nim (typein (fun x x_1 => x < x_1) j)) = fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)

Next tactic:
funext i
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def]; dsimp; congr <;> 

Proof state:
case h.e_a
o : Ordinal.{u_1}
IH : ∀ k < o, -nim k = nim k
⊢ (fun i => -nim (typein (fun x x_1 => x < x_1) i)) = fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)

Next tactic:
funext i
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
  induction' o using Ordinal.induction with o IH
  rw [nim_def]; dsimp; congr <;> funext i <;> 

Proof state:
case h.e_a.h
o : Ordinal.{u_1}
IH : ∀ k < o, -nim k = nim k
i : (Quotient.out o).α
⊢ -nim (typein (fun x x_1 => x < x_1) i) = nim (typein (fun x x_1 => x < x_1) i)

Next tactic:
exact IH _ (Ordinal.typein_lt_self i)
instance nim_impartial (o : Ordinal) : Impartial (nim o) := by
  

Proof state:
o : Ordinal.{?u.34699}
⊢ Impartial (nim o)

Next tactic:
induction' o using Ordinal.induction with o IH
instance nim_impartial (o : Ordinal) : Impartial (nim o) := by
  induction' o using Ordinal.induction with o IH
  

Proof state:
case h
o : Ordinal.{?u.34717}
IH : ∀ k < o, Impartial (nim k)
⊢ Impartial (nim o)

Next tactic:
rw [impartial_def, neg_nim]
instance nim_impartial (o : Ordinal) : Impartial (nim o) := by
  induction' o using Ordinal.induction with o IH
  rw [impartial_def, neg_nim]
  

Proof state:
case h
o : Ordinal.{?u.34717}
IH : ∀ k < o, Impartial (nim k)
⊢ nim o ≈ nim o ∧
    (∀ (i : LeftMoves (nim o)), Impartial (moveLeft (nim o) i)) ∧
      ∀ (j : RightMoves (nim o)), Impartial (moveRight (nim o) j)

Next tactic:
refine' ⟨equiv_rfl, fun i => _, fun i => _⟩
instance nim_impartial (o : Ordinal) : Impartial (nim o) := by
  induction' o using Ordinal.induction with o IH
  rw [impartial_def, neg_nim]
  refine' ⟨equiv_rfl, fun i => _, fun i => _⟩ <;> 

Proof state:
case h.refine'_1
o : Ordinal.{?u.34717}
IH : ∀ k < o, Impartial (nim k)
i : LeftMoves (nim o)
⊢ Impartial (moveLeft (nim o) i)

Next tactic:
simpa using IH _ (typein_lt_self _)
instance nim_impartial (o : Ordinal) : Impartial (nim o) := by
  induction' o using Ordinal.induction with o IH
  rw [impartial_def, neg_nim]
  refine' ⟨equiv_rfl, fun i => _, fun i => _⟩ <;> 

Proof state:
case h.refine'_2
o : Ordinal.{?u.35327}
IH : ∀ k < o, Impartial (nim k)
i : RightMoves (nim o)
⊢ Impartial (moveRight (nim o) i)

Next tactic:
simpa using IH _ (typein_lt_self _)
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 := by
  

Proof state:
o : Ordinal.{u_1}
ho : o ≠ 0
⊢ nim o ‖ 0

Next tactic:
rw [Impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 := by
  rw [Impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
  

Proof state:
o : Ordinal.{u_1}
ho : o ≠ 0
⊢ ∃ j,
    moveRight
        (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
          nim (typein (fun x x_1 => x < x_1) o₂))
        j ≤
      0

Next tactic:
rw [← Ordinal.pos_iff_ne_zero] at ho
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 := by
  rw [Impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
  rw [← Ordinal.pos_iff_ne_zero] at ho
  

Proof state:
o : Ordinal.{u_1}
ho : 0 < o
⊢ ∃ j,
    moveRight
        (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
          nim (typein (fun x x_1 => x < x_1) o₂))
        j ≤
      0

Next tactic:
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 := by
  rw [Impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
  rw [← Ordinal.pos_iff_ne_zero] at ho
  exact ⟨(Ordinal.principalSegOut ho).top, by 

Proof state:
o : Ordinal.{u_1}
ho : 0 < o
⊢ moveRight
      (mk (Quotient.out o).α (Quotient.out o).α (fun o₂ => nim (typein (fun x x_1 => x < x_1) o₂)) fun o₂ =>
        nim (typein (fun x x_1 => x < x_1) o₂))
      (principalSegOut ho).top ≤
    0

Next tactic:
simp
@[simp]
theorem nim_add_equiv_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:
constructor