Documentation

LeanPool.MisereGames.Misere.Stride

Misere combinatorial games.

Solved #

@[irreducible]

Intuitively, a position is solved for a given player if they win regardless of the moves they make.

Equations
  • One or more equations did not get rendered due to their size.
Instances For
    theorem MisereGames.GameForm.isSolved_def (p : Player) (g : GameForm) :
    IsSolved p g 0Moves.moves p g (g 0¬Form.IsEnd (-p) g) ∀ (gp : GameForm), Moves.IsOption gp gIsSolved p gp
    theorem MisereGames.GameForm.isSolved_zero_not_mem {p : Player} {g : GameForm} (h_isSolved : IsSolved p g) :
    0Moves.moves p g
    theorem MisereGames.GameForm.isSolved_zero_mem {p : Player} {g : GameForm} (h_isSolved : IsSolved p g) (h_isOption : Moves.IsOption 0 g) :
    theorem MisereGames.GameForm.isSolved_not_isEnd {p : Player} {g : GameForm} (h_isSolved : IsSolved p g) (h_ne_zero : g 0) :
    theorem MisereGames.GameForm.isSolved_of_mem_moves {p : Player} {g g' : GameForm} {q : Player} (h : IsSolved p g) (hm : g' Moves.moves q g) :
    theorem MisereGames.GameForm.isSolved_add {p : Player} {g h : GameForm} (h_isSolved_g : IsSolved p g) (h_isSolved_h : IsSolved p h) :
    IsSolved p (g + h)

    The sum of two solved games is solved.

    Integers #

    Zero is the only game solved for both players

    Strides #

    @[irreducible]

    Stride measures exactly how many moves away each player is from a solved position.

    Stride is not well-defined for all game forms.

    Equations
    Instances For
      @[simp]

      The stride equals zero if the game is solved.

      theorem MisereGames.GameForm.hasStride_isSolved_iff_zero {p : Player} {g : GameForm} {n : } (h_hasStride : HasStride p g n) :
      IsSolved p g n = 0

      A game is solved if its stride equals zero.

      theorem MisereGames.GameForm.hasStride_succ_iff {p : Player} {g : GameForm} {n : } :
      HasStride p g (n + 1) ¬IsSolved p g (∀ g'Moves.moves p g, ∃ (k : ), n k HasStride p g' k) (∃ (g' : GameForm) (_ : g' Moves.moves p g), HasStride p g' n g''Moves.moves p g, ∀ (m : ), HasStride (-p) g'' m∃ (k : ), m k HasStride (-p) g' k) (∀ g'Moves.moves (-p) g, kn + 1, HasStride p g' k) (Moves.moves (-p) g ∃ (g' : GameForm) (_ : g' Moves.moves (-p) g), HasStride p g' (n + 1))
      theorem MisereGames.GameForm.hasStride_succ_support {p : Player} {g : GameForm} {n : } (h : HasStride p g (n + 1)) (g' : GameForm) (hg' : g' Moves.moves p g) :
      ∃ (k : ), n k HasStride p g' k

      If the stride of $G$ is not zero, then every response lowers the stride by at most one.

      theorem MisereGames.GameForm.hasStride_succ_exists_best {p : Player} {g : GameForm} {n : } (h : HasStride p g (n + 1)) :
      ∃ (g' : GameForm) (_ : g' Moves.moves p g), HasStride p g' n g''Moves.moves p g, ∀ (m : ), HasStride (-p) g'' m∃ (k : ), m k HasStride (-p) g' k

      If the stride of $G$ is not zero, then there exist some response to stride lower by one.

      theorem MisereGames.GameForm.hasStride_succ_support_neg {p : Player} {g : GameForm} {n : } (h : HasStride p g (n + 1)) (g' : GameForm) (hg' : g' Moves.moves (-p) g) :
      kn + 1, HasStride p g' k

      If the stride of $G$ is not zero, then every opponent move preserves the stride.

      theorem MisereGames.GameForm.hasStride_succ_exists_preserve_neg {p : Player} {g : GameForm} {n : } (h : HasStride p g (n + 1)) (h_ne : Moves.moves (-p) g ) :
      ∃ (g' : GameForm) (_ : g' Moves.moves (-p) g), HasStride p g' (n + 1)

      Some opponent move preserves stride.

      theorem MisereGames.GameForm.hasStride_unique {p : Player} {g : GameForm} {n k : } (h_n : HasStride p g n) (h_k : HasStride p g k) :
      n = k

      If a game has stride, then the value is unique.

      This is a workaround for not defining stride as a function to option ℕ.

      theorem MisereGames.GameForm.hasStride_mk_iff {p : Player} (n : ) {k : } {g : GameForm} (h_stride : HasStride p g n) :
      HasStride p g k k = n

      Helper for building iff lemmas

      theorem MisereGames.GameForm.hasStride_good_move_neg_stride {p : Player} {g : GameForm} {n r : } (h : HasStride p g (n + 1)) (h_r : HasStride (-p) g r) :
      ∃ (g' : GameForm) (_ : g' Moves.moves p g), HasStride p g' n HasStride (-p) g' r

      The good move preserves (-p)-stride: if HasStride p g (n+1) and HasStride (-p) g r, then the good p-move has (-p)-stride exactly r.

      theorem MisereGames.GameForm.hasStride_of_mem_moves_neg {p : Player} {g g' : GameForm} {n : } (hg : HasStride p g n) (hm : g' Moves.moves (-p) g) :
      kn, HasStride p g' k

      Opponent moves have stride ≤ n.

      theorem MisereGames.GameForm.hasStride_succ_iff' {p : Player} {g : GameForm} {n m : } (h_hasStride_m : HasStride (-p) g m) :
      HasStride p g (n + 1) ¬IsSolved p g (∀ g'Moves.moves p g, ∃ (k : ), n k HasStride p g' k) (∃ (g' : GameForm) (_ : g' Moves.moves p g), HasStride p g' n HasStride (-p) g' m) (∀ g'Moves.moves (-p) g, kn + 1, HasStride p g' k) (Moves.moves (-p) g ∃ (g' : GameForm) (_ : g' Moves.moves (-p) g), HasStride p g' (n + 1))

      A variant of hasStride_succ_iff that simplifies condition B' when we know the (-p)-stride. Instead of requiring the good move to have the max (-p)-stride among all p-moves, we simply require the good move to preserve the (-p)-stride exactly.

      theorem MisereGames.GameForm.hasStride_succ_exists_best' {p : Player} {g : GameForm} {n m : } (h_n : HasStride p g (n + 1)) (h_m : HasStride (-p) g m) :
      ∃ (g' : GameForm) (_ : g' Moves.moves p g), HasStride p g' n HasStride (-p) g' m

      Variant of hasStride_succ_exists_best with known opponent stride

      theorem MisereGames.GameForm.hasStride_of_mem_moves {p : Player} {g g' : GameForm} {n : } (hg : HasStride p g n) (hm : g' Moves.moves p g) :
      ∃ (j : ), n - 1 j HasStride p g' j

      Addition #

      theorem MisereGames.GameForm.hasStride_add {p : Player} {g h : GameForm} {sL_g sL_h sR_g sR_h : } (h_sL_g : HasStride p g sL_g) (h_sL_h : HasStride p h sL_h) (h_sR_g : HasStride (-p) g sR_g) (h_sR_h : HasStride (-p) h sR_h) :
      HasStride p (g + h) (sL_g + sL_h)

      The stride of a sum is the sum of the strides.

      @[simp]

      Integers #

      Outcomes #

      If a game has both strides, then they determine who wins going first.

      If a game has both strides, then they determine the outcome.

      If a game has both strides, then they determine the outcome.

      theorem MisereGames.GameForm.hasStride_isPFree {p : Player} {g : GameForm} {l r : } (h_l : HasStride p g l) (h_r : HasStride (-p) g r) :

      If a game has both strides, then it is $\mathscr{P}$-free.

      A predicate containing games with prescribed Left and Right strides.

      Instances
        theorem MisereGames.GameForm.ClosedUnderAdd.closure_has_stride_aux {R : Type u} [Ruleset R] (p : Player) {g : GameForm} (stride : RPlayer) (hasStride : ∀ (r : R) (p : Player), HasStride p (Ruleset.toGameForm r) (stride r p)) (h_g : Form.ClosedUnderAdd.closure (Ruleset.Forms R) g) :
        ∃ (n : ), HasStride p g n
        theorem MisereGames.GameForm.ClosedUnderAdd.closure_mk_with_strides_aux {A : GameFormProp} (mk_stride_other_zero : ∀ (p : Player) (n : ), ∃ (g : GameForm), A g HasStride p g n HasStride (-p) g 0) (l r : ) :
        theorem MisereGames.GameForm.stride_diff_eq_of_misereEQ {A : GameFormProp} [Strided A] {g h : GameForm} (h_eq : g =m A h) {sL_g sR_g sL_h sR_h : } (h_ng : HasStride Player.left g sL_g) (h_rg : HasStride Player.right g sR_g) (h_nh : HasStride Player.left h sL_h) (h_rh : HasStride Player.right h sR_h) :
        sL_g - sR_g = sL_h - sR_h
        theorem MisereGames.GameForm.misereEQ_of_stride_diff_eq {A : GameFormProp} [Strided A] {g h : GameForm} {sL_g sR_g sL_h sR_h : } (h_ng : HasStride Player.left g sL_g) (h_rg : HasStride Player.right g sR_g) (h_nh : HasStride Player.left h sL_h) (h_rh : HasStride Player.right h sR_h) (h_diff : sL_g - sR_g = sL_h - sR_h) :
        g =m A h
        theorem MisereGames.GameForm.misereEQ_iff_stride_diff_eq {A : GameFormProp} [Strided A] {g h : GameForm} {ng rg nh rh : } (h_ng : HasStride Player.left g ng) (h_rg : HasStride Player.right g rg) (h_nh : HasStride Player.left h nh) (h_rh : HasStride Player.right h rh) :
        g =m A h ng - rg = nh - rh

        The stride difference characterises misère equivalence for strided games.

        theorem MisereGames.GameForm.misereGE_of_stride_diff_le {A : GameFormProp} [Strided A] {g h : GameForm} {sL_g sR_g sL_h sR_h : } (h_sL_g : HasStride Player.left g sL_g) (h_sR_g : HasStride Player.right g sR_g) (h_sL_h : HasStride Player.left h sL_h) (h_sR_h : HasStride Player.right h sR_h) (h_le : sL_g - sR_g sL_h - sR_h) :
        g ≥m A h

        The misère quotient of a strided class is totally ordered. This follows from the fact that the ordering is determined by stride differences.

        noncomputable def MisereGames.GameForm.Strided.strideDiff {A : GameFormProp} [Strided A] (g : GameForm) (hg : A g) :

        The stride difference of a game in a strided class A. This is the left stride minus the right stride, as an integer.

        Equations
        Instances For
          theorem MisereGames.GameForm.strideDiff_eq {A : GameFormProp} [Strided A] {g : GameForm} {hg : A g} {l r : } (hl : HasStride Player.left g l) (hr : HasStride Player.right g r) :
          Strided.strideDiff g hg = l - r

          The stride difference is well-defined regardless of which stride witnesses are used.

          theorem MisereGames.GameForm.Strided.strideDiff_eq_of_misereEQ {A : GameFormProp} [Strided A] {g h : GameForm} (hg : A g) (hh : A h) (heq : g =m A h) :

          Misère equivalent games have the same stride difference.

          The stride difference function on the misère quotient, defined via representative. This is well-defined because misère equivalent games have the same stride difference.

          Equations
          Instances For

            The stride difference function on the quotient is injective.

            The stride difference function on the quotient is surjective: for any integer d, there is a game in A with stride difference d.

            The misère quotient of a strided class is equivalent to the integers. The equivalence sends each equivalence class to its stride difference.

            Equations
            Instances For
              theorem MisereGames.GameForm.stride_diff_le_of_misereGE {A : GameFormProp} [Strided A] {g h : GameForm} (h_ge : g ≥m A h) {ng rg nh rh : } (h_ng : HasStride Player.left g ng) (h_rg : HasStride Player.right g rg) (h_nh : HasStride Player.left h nh) (h_rh : HasStride Player.right h rh) :
              ng - rg nh - rh

              If g ≥m A h then the stride difference of g is that of h. The converse of misereGE_of_stride_diff_le.

              theorem MisereGames.GameForm.misereGE_iff_stride_diff_le {A : GameFormProp} [Strided A] {g h : GameForm} {ng rg nh rh : } (h_ng : HasStride Player.left g ng) (h_rg : HasStride Player.right g rg) (h_nh : HasStride Player.left h nh) (h_rh : HasStride Player.right h rh) :
              g ≥m A h ng - rg nh - rh

              Misère GE is equivalent to stride difference inequality.

              The ordering on the misère quotient corresponds to on stride differences: mk A g hg ≤ mk A h hh iff strideDiff A g hg ≥ strideDiff A h hh.

              The misère quotient ordering via the integer equivalence: a ≤ b iff the image of a under the equivalence is ≥ the image of b. Equivalently, the equivalence is an order-reversing bijection.