Combinatorial (pre-)games. #
THIS FILE IS SYNCHRONIZED WITH MATHLIB4. Any changes to this file require a corresponding PR to mathlib4.
The basic theory of combinatorial games, following Conway's book On Numbers and Games
. We
construct "pregames", define an ordering and arithmetic operations on them, then show that the
operations descend to "games", defined via the equivalence relation p ≈ q ↔ p ≤ q ∧ q ≤ p
.
The surreal numbers will be built as a quotient of a subtype of pregames.
A pregame (pgame
below) is axiomatised via an inductive type, whose sole constructor takes two
types (thought of as indexing the possible moves for the players Left and Right), and a pair of
functions out of these types to pgame
(thought of as describing the resulting game after making a
move).
Combinatorial games themselves, as a quotient of pregames, are constructed in game.lean
.
Conway induction #
By construction, the induction principle for pregames is exactly "Conway induction". That is, to
prove some predicate pgame → Prop
holds for all pregames, it suffices to prove that for every
pregame g
, if the predicate holds for every game resulting from making a move, then it also holds
for g
.
While it is often convenient to work "by induction" on pregames, in some situations this becomes
awkward, so we also define accessor functions pgame.left_moves
, pgame.right_moves
,
pgame.move_left
and pgame.move_right
. There is a relation pgame.subsequent p q
, saying that
p
can be reached by playing some non-empty sequence of moves starting from q
, an instance
well_founded subsequent
, and a local tactic pgame_wf_tac
which is helpful for discharging proof
obligations in inductive proofs relying on this relation.
Order properties #
Pregames have both a ≤
and a <
relation, satisfying the usual properties of a preorder
. The
relation 0 < x
means that x
can always be won by Left, while 0 ≤ x
means that x
can be won
by Left as the second player.
It turns out to be quite convenient to define various relations on top of these. We define the "less
or fuzzy" relation x ⧏ y
as ¬ y ≤ x
, the equivalence relation x ≈ y
as x ≤ y ∧ y ≤ x
, and
the fuzzy relation x ‖ y
as x ⧏ y ∧ y ⧏ x
. If 0 ⧏ x
, then x
can be won by Left as the
first player. If x ≈ 0
, then x
can be won by the second player. If x ‖ 0
, then x
can be won
by the first player.
Statements like zero_le_lf
, zero_lf_le
, etc. unfold these definitions. The theorems le_def
and
lf_def
give a recursive characterisation of each relation in terms of themselves two moves later.
The theorems zero_le
, zero_lf
, etc. also take into account that 0
has no moves.
Later, games will be defined as the quotient by the ≈
relation; that is to say, the
antisymmetrization
of pgame
.
Algebraic structures #
We next turn to defining the operations necessary to make games into a commutative additive group. Addition is defined for $x = \{xL | xR\}$ and $y = \{yL | yR\}$ by $x + y = \{xL + y, x + yL | xR + y, x + yR\}$. Negation is defined by $\{xL | xR\} = \{-xR | -xL\}$.
The order structures interact in the expected way with addition, so we have
theorem le_iff_sub_nonneg {x y : pgame} : x ≤ y ↔ 0 ≤ y - x := sorry
theorem lt_iff_sub_pos {x y : pgame} : x < y ↔ 0 < y - x := sorry
We show that these operations respect the equivalence relation, and hence descend to games. At the
level of games, these operations satisfy all the laws of a commutative group. To prove the necessary
equivalence relations at the level of pregames, we introduce the notion of a relabelling
of a
game, and show, for example, that there is a relabelling between x + (y + z)
and (x + y) + z
.
Future work #
- The theory of dominated and reversible positions, and unique normal form for short games.
- Analysis of basic domineering positions.
- Hex.
- Temperature.
- The development of surreal numbers, based on this development of combinatorial games, is still quite incomplete.
References #
The material here is all drawn from
An interested reader may like to formalise some of the material from
- Andreas Blass, A game semantics for linear logic
- [André Joyal, Remarques sur la théorie des jeux à deux personnes][joyal1997]
Pre-game moves #
The type of pre-games, before we have quotiented
by equivalence (pgame.setoid
). In ZFC, a combinatorial game is constructed from
two sets of combinatorial games that have been constructed at an earlier
stage. To do this in type theory, we say that a pre-game is built
inductively from two families of pre-games indexed over any type
in Type u. The resulting type pgame.{u}
lives in Type (u+1)
,
reflecting that it is a proper class in ZFC.
Instances for pgame
- pgame.has_sizeof_inst
- pgame.subsequent.is_trans
- pgame.has_well_founded
- pgame.has_zero
- pgame.inhabited
- pgame.has_one
- pgame.has_le
- pgame.preorder
- pgame.lf.is_irrefl
- pgame.equiv.is_equiv
- pgame.fuzzy.is_symm
- pgame.fuzzy.is_irrefl
- pgame.has_neg
- pgame.has_involutive_neg
- pgame.neg_zero_class
- pgame.has_add
- pgame.has_nat_cast
- pgame.has_sub
- pgame.covariant_class_swap_add_le
- pgame.covariant_class_add_le
- pgame.covariant_class_swap_add_lt
- pgame.covariant_class_add_lt
- pgame.zero_le_one_class
- pgame.setoid
- pgame.has_mul
- pgame.has_inv
- pgame.has_div
The indexing type for allowable moves by Left.
Equations
- (pgame.mk l _x _x_1 _x_2).left_moves = l
Instances for pgame.left_moves
- pgame.is_empty_zero_left_moves
- pgame.unique_one_left_moves
- pgame.lower_bound_left_moves_empty
- pgame.is_empty_left_moves_add
- pgame.unique_star_left_moves
- pgame.is_empty_mul_zero_left_moves
- pgame.is_empty_zero_mul_left_moves
- ordinal.is_empty_zero_to_pgame_left_moves
- ordinal.unique_one_to_pgame_left_moves
- pgame.unique_pow_half_left_moves
- pgame.is_empty_nim_zero_left_moves
- pgame.unique_nim_one_left_moves
- pgame.fintype_left_moves
- pgame.fintype_left_moves_of_state_aux
The indexing type for allowable moves by Right.
Equations
- (pgame.mk _x r _x_1 _x_2).right_moves = r
Instances for pgame.right_moves
- pgame.is_empty_zero_right_moves
- pgame.is_empty_one_right_moves
- pgame.upper_bound_right_moves_empty
- pgame.is_empty_right_moves_add
- pgame.is_empty_nat_right_moves
- pgame.unique_star_right_moves
- pgame.is_empty_mul_zero_right_moves
- pgame.is_empty_zero_mul_right_moves
- ordinal.is_empty_to_pgame_right_moves
- pgame.is_empty_pow_half_zero_right_moves
- pgame.unique_pow_half_succ_right_moves
- pgame.is_empty_nim_zero_right_moves
- pgame.unique_nim_one_right_moves
- pgame.fintype_right_moves
- pgame.fintype_right_moves_of_state_aux
The new game after Left makes an allowed move.
Instances for pgame.move_left
The new game after Right makes an allowed move.
Equations
- (pgame.mk _x r _x_1 R).move_right = R
Instances for pgame.move_right
Construct a pre-game from list of pre-games describing the available moves for Left and Right.
Equations
Instances for pgame.of_lists
Converts a number into a left move for of_lists
.
Equations
- pgame.to_of_lists_left_moves = ((equiv.cast pgame.to_of_lists_left_moves._proof_1).trans equiv.ulift).symm
Converts a number into a right move for of_lists
.
Equations
- pgame.to_of_lists_right_moves = ((equiv.cast pgame.to_of_lists_right_moves._proof_1).trans equiv.ulift).symm
A variant of pgame.rec_on
expressed in terms of pgame.move_left
and pgame.move_right
.
Both this and pgame.rec_on
describe Conway induction on games.
- move_left : ∀ {x : pgame} (i : x.left_moves), (x.move_left i).is_option x
- move_right : ∀ {x : pgame} (i : x.right_moves), (x.move_right i).is_option x
is_option x y
means that x
is either a left or right option for y
.
subsequent x y
says that x
can be obtained by playing some nonempty sequence of moves from
y
. It is the transitive closure of is_option
.
Equations
Instances for pgame.subsequent
Equations
Basic pre-games #
The pre-game zero
is defined by 0 = { | }
.
Equations
Equations
- pgame.inhabited = {default := 0}
The pre-game one
is defined by 1 = { 0 | }
.
Equations
- pgame.has_one = {one := pgame.mk punit pempty (λ (_x : punit), 0) pempty.elim}
Equations
Pre-game order relations #
The less or equal relation on pre-games.
If 0 ≤ x
, then Left can win x
as the second player.
Equations
- pgame.has_le = {le := sym2.game_add.fix pgame.wf_is_option (λ (x y : pgame) (le : Π (a₂ b₂ : pgame), sym2.game_add pgame.is_option ⟦(a₂, b₂)⟧ ⟦(x, y)⟧ → Prop), (∀ (i : x.left_moves), ¬le y (x.move_left i) _) ∧ ∀ (j : y.right_moves), ¬le (y.move_right j) x _)}
The less or fuzzy relation on pre-games.
If 0 ⧏ x
, then Left can win x
as the first player.
Instances for pgame.lf
Definition of x ≤ y
on pre-games, in terms of ⧏
.
The ordering here is chosen so that and.left
refer to moves by Left, and and.right
refer to
moves by Right.
Definition of x ⧏ y
on pre-games, in terms of ≤
.
The ordering here is chosen so that or.inl
refer to moves by Left, and or.inr
refer to
moves by Right.
Alias of pgame.move_left_lf_of_le
.
Alias of pgame.lf_move_right_of_le
.
Equations
- pgame.preorder = {le := has_le.le pgame.has_le, lt := λ (x y : pgame), x ≤ y ∧ x.lf y, le_refl := pgame.preorder._proof_1, le_trans := pgame.preorder._proof_2, lt_iff_le_not_le := pgame.preorder._proof_3}
Alias of pgame.lf_of_le_of_lf
.
Alias of pgame.lf_of_lf_of_le
.
Alias of pgame.lf_of_lt_of_lf
.
Alias of pgame.lf_of_lf_of_lt
.
This special case of pgame.le_of_forall_lf
is useful when dealing with surreals, where <
is
preferred over ⧏
.
The definition of x ≤ y
on pre-games, in terms of ≤
two moves later.
The definition of x ⧏ y
on pre-games, in terms of ⧏
two moves later.
The definition of 0 ≤ x
on pre-games, in terms of 0 ⧏
.
The definition of x ≤ 0
on pre-games, in terms of ⧏ 0
.
The definition of 0 ⧏ x
on pre-games, in terms of 0 ≤
.
The definition of x ⧏ 0
on pre-games, in terms of ≤ 0
.
The definition of 0 ≤ x
on pre-games, in terms of 0 ≤
two moves later.
The definition of x ≤ 0
on pre-games, in terms of ≤ 0
two moves later.
The definition of 0 ⧏ x
on pre-games, in terms of 0 ⧏
two moves later.
The definition of x ⧏ 0
on pre-games, in terms of ⧏ 0
two moves later.
Given a game won by the right player when they play second, provide a response to any move by left.
Equations
Show that the response for right provided by right_response
preserves the right-player-wins
condition.
Given a game won by the left player when they play second, provide a response to any move by right.
Equations
Show that the response for left provided by left_response
preserves the left-player-wins
condition.
An explicit upper bound for a family of pre-games, whose left moves are the union of the left moves of all the pre-games in the family.
Equations
- pgame.upper_bound f = pgame.mk (Σ (i : ι), (f i).left_moves) pempty (λ (x : Σ (i : ι), (f i).left_moves), (f x.fst).move_left x.snd) pempty.elim
An explicit lower bound for a family of pre-games, whose right moves are the union of the right moves of all the pre-games in the family.
Equations
- pgame.lower_bound f = pgame.mk pempty (Σ (i : ι), (f i).right_moves) pempty.elim (λ (x : Σ (i : ι), (f i).right_moves), (f x.fst).move_right x.snd)
The equivalence relation on pre-games. Two pre-games x
, y
are equivalent if x ≤ y
and
y ≤ x
.
If x ≈ 0
, then the second player can always win x
.
Instances for pgame.equiv
The fuzzy, confused, or incomparable relation on pre-games.
If x ‖ 0
, then the first player can always win x
.
Instances for pgame.fuzzy
Relabellings #
- mk : Π {x y : pgame} (L : x.left_moves ≃ y.left_moves) (R : x.right_moves ≃ y.right_moves), (Π (i : x.left_moves), (x.move_left i).relabelling (y.move_left (⇑L i))) → (Π (j : x.right_moves), (x.move_right j).relabelling (y.move_right (⇑R j))) → x.relabelling y
relabelling x y
says that x
and y
are really the same game, just dressed up differently.
Specifically, there is a bijection between the moves for Left in x
and in y
, and similarly
for Right, and under these bijections we inductively have relabelling
s for the consequent games.
Instances for pgame.relabelling
- pgame.relabelling.has_sizeof_inst
- pgame.relabelling.inhabited
- pgame.equiv.has_coe
A constructor for relabellings swapping the equivalences.
Equations
- pgame.relabelling.mk' L R hL hR = pgame.relabelling.mk L.symm R.symm (λ (i : x.left_moves), _.mpr (_.mp (hL (⇑(L.symm) i)))) (λ (j : x.right_moves), _.mpr (_.mp (hR (⇑(R.symm) j))))
The equivalence between left moves of x
and y
given by the relabelling.
Equations
- (pgame.relabelling.mk L R hL hR).left_moves_equiv = L
The equivalence between right moves of x
and y
given by the relabelling.
Equations
- (pgame.relabelling.mk L R hL hR).right_moves_equiv = R
A left move of x
is a relabelling of a left move of y
.
Equations
- (pgame.relabelling.mk L R hL hR).move_left = hL
A left move of y
is a relabelling of a left move of x
.
Equations
- (pgame.relabelling.mk L R hL hR).move_left_symm i = _.mpr (_.mp (hL (⇑(L.symm) i)))
A right move of x
is a relabelling of a right move of y
.
Equations
- (pgame.relabelling.mk L R hL hR).move_right = hR
A right move of y
is a relabelling of a right move of x
.
Equations
- (pgame.relabelling.mk L R hL hR).move_right_symm i = _.mpr (_.mp (hR (⇑(R.symm) i)))
The identity relabelling.
Equations
- pgame.relabelling.refl x = pgame.relabelling.mk (equiv.refl x.left_moves) (equiv.refl x.right_moves) (λ (i : x.left_moves), pgame.relabelling.refl (x.move_left i)) (λ (j : x.right_moves), pgame.relabelling.refl (x.move_right j))
Equations
Flip a relabelling.
Equations
- (pgame.relabelling.mk L R hL hR).symm = pgame.relabelling.mk' L R (λ (i : x.left_moves), (hL i).symm) (λ (j : x.right_moves), (hR j).symm)
A relabelling lets us prove equivalence of games.
Transitivity of relabelling.
Equations
- (pgame.relabelling.mk L₁ R₁ hL₁ hR₁).trans (pgame.relabelling.mk L₂ R₂ hL₂ hR₂) = pgame.relabelling.mk (L₁.trans L₂) (R₁.trans R₂) (λ (i : x.left_moves), (hL₁ i).trans (hL₂ (⇑L₁ i))) (λ (j : x.right_moves), (hR₁ j).trans (hR₂ (⇑R₁ j)))
Any game without left or right moves is a relabelling of 0.
Equations
- pgame.equiv.has_coe = {coe := _}
Replace the types indexing the next moves for Left and Right by equivalent types.
Equations
- pgame.relabel el er = pgame.mk xl' xr' (x.move_left ∘ ⇑el) (x.move_right ∘ ⇑er)
The game obtained by relabelling the next moves is a relabelling of the original game.
Equations
- pgame.relabel_relabelling el er = pgame.relabelling.mk' el er (λ (i : (pgame.relabel el er).left_moves), _.mpr (pgame.relabelling.refl (x.move_left (⇑el i)))) (λ (j : (pgame.relabel el er).right_moves), _.mpr (pgame.relabelling.refl (x.move_right (⇑er j))))
Negation #
Equations
- pgame.has_neg = {neg := pgame.neg}
Equations
- pgame.has_involutive_neg = {neg := has_neg.neg pgame.has_neg, neg_neg := pgame.has_involutive_neg._proof_1}
Equations
- pgame.neg_zero_class = {zero := 0, neg := has_neg.neg pgame.has_neg, neg_zero := pgame.neg_zero_class._proof_1}
Turns a right move for x
into a left move for -x
and vice versa.
Even though these types are the same (not definitionally so), this is the preferred way to convert between them.
Equations
- pgame.to_left_moves_neg = equiv.cast pgame.to_left_moves_neg._proof_1
Turns a left move for x
into a right move for -x
and vice versa.
Even though these types are the same (not definitionally so), this is the preferred way to convert between them.
Equations
- pgame.to_right_moves_neg = equiv.cast pgame.to_right_moves_neg._proof_1
If x
has the same moves as y
, then -x
has the sames moves as -y
.
Equations
- (pgame.relabelling.mk L R hL hR).neg_congr = pgame.relabelling.mk R L (λ (j : (-pgame.mk xl xr xL xR).left_moves), (hR j).neg_congr) (λ (i : (-pgame.mk xl xr xL xR).right_moves), (hL i).neg_congr)
Addition and subtraction #
The sum of x = {xL | xR}
and y = {yL | yR}
is {xL + y, x + yL | xR + y, x + yR}
.
Equations
- pgame.has_add = {add := λ (x y : pgame), pgame.rec (λ (xl xr : Type u) (xL : xl → pgame) (xR : xr → pgame) (IHxl : Π (ᾰ : xl), (λ (x : pgame), pgame → pgame) (xL ᾰ)) (IHxr : Π (ᾰ : xr), (λ (x : pgame), pgame → pgame) (xR ᾰ)) (y : pgame), pgame.rec (λ (yl yr : Type u) (yL : yl → pgame) (yR : yr → pgame) (IHyl : Π (ᾰ : yl), (λ (y : pgame), pgame) (yL ᾰ)) (IHyr : Π (ᾰ : yr), (λ (y : pgame), pgame) (yR ᾰ)), pgame.mk (xl ⊕ yl) (xr ⊕ yr) (sum.rec (λ (i : xl), IHxl i (pgame.mk yl yr yL yR)) IHyl) (sum.rec (λ (i : xr), IHxr i (pgame.mk yl yr yL yR)) IHyr)) y) x y}
The pre-game ((0+1)+⋯)+1
.
Equations
x + 0
has exactly the same moves as x
.
Equations
- (pgame.mk xl xr xL xR).add_zero_relabelling = pgame.relabelling.mk (equiv.sum_empty xl pempty) (equiv.sum_empty xr pempty) (λ (i : (pgame.mk xl xr xL xR + 0).left_moves), sum.cases_on i (λ (i : xl), (xL i).add_zero_relabelling) (λ (i : pempty), pempty.cases_on (λ (i : pempty), ((pgame.mk xl xr xL xR + 0).move_left (sum.inr i)).relabelling ((pgame.mk xl xr xL xR).move_left (⇑(equiv.sum_empty xl pempty) (sum.inr i)))) i)) (λ (j : (pgame.mk xl xr xL xR + 0).right_moves), sum.cases_on j (λ (i : xr), (xR i).add_zero_relabelling) (λ (j : pempty), pempty.cases_on (λ (j : pempty), ((pgame.mk xl xr xL xR + 0).move_right (sum.inr j)).relabelling ((pgame.mk xl xr xL xR).move_right (⇑(equiv.sum_empty xr pempty) (sum.inr j)))) j))
0 + x
has exactly the same moves as x
.
Equations
- (pgame.mk xl xr xL xR).zero_add_relabelling = pgame.relabelling.mk (equiv.empty_sum pempty xl) (equiv.empty_sum pempty xr) (λ (i : (0 + pgame.mk xl xr xL xR).left_moves), sum.cases_on i (λ (i : pempty), pempty.cases_on (λ (i : pempty), ((0 + pgame.mk xl xr xL xR).move_left (sum.inl i)).relabelling ((pgame.mk xl xr xL xR).move_left (⇑(equiv.empty_sum pempty xl) (sum.inl i)))) i) (λ (i : xl), (xL i).zero_add_relabelling)) (λ (j : (0 + pgame.mk xl xr xL xR).right_moves), sum.cases_on j (λ (j : pempty), pempty.cases_on (λ (j : pempty), ((0 + pgame.mk xl xr xL xR).move_right (sum.inl j)).relabelling ((pgame.mk xl xr xL xR).move_right (⇑(equiv.empty_sum pempty xr) (sum.inl j)))) j) (λ (i : xr), (xR i).zero_add_relabelling))
Converts a left move for x
or y
into a left move for x + y
and vice versa.
Even though these types are the same (not definitionally so), this is the preferred way to convert between them.
Equations
- pgame.to_left_moves_add = equiv.cast pgame.to_left_moves_add._proof_1
Converts a right move for x
or y
into a right move for x + y
and vice versa.
Even though these types are the same (not definitionally so), this is the preferred way to convert between them.
Equations
- pgame.to_right_moves_add = equiv.cast pgame.to_right_moves_add._proof_1
If w
has the same moves as x
and y
has the same moves as z
,
then w + y
has the same moves as x + z
.
Equations
- (pgame.relabelling.mk L₁ R₁ hL₁ hR₁).add_congr (pgame.relabelling.mk L₂ R₂ hL₂ hR₂) = let Hwx : (pgame.mk wl wr wL wR).relabelling (pgame.mk xl xr xL xR) := pgame.relabelling.mk L₁ R₁ hL₁ hR₁, Hyz : (pgame.mk yl yr yL yR).relabelling (pgame.mk zl zr zL zR) := pgame.relabelling.mk L₂ R₂ hL₂ hR₂ in pgame.relabelling.mk (L₁.sum_congr L₂) (R₁.sum_congr R₂) (λ (i : (pgame.mk wl wr wL wR + pgame.mk yl yr yL yR).left_moves), sum.cases_on i (λ (i : wl), (hL₁ i).add_congr Hyz) (λ (j : yl), Hwx.add_congr (hL₂ j))) (λ (j : (pgame.mk wl wr wL wR + pgame.mk yl yr yL yR).right_moves), sum.cases_on j (λ (i : wr), (hR₁ i).add_congr Hyz) (λ (j : yr), Hwx.add_congr (hR₂ j)))
If w
has the same moves as x
and y
has the same moves as z
,
then w - y
has the same moves as x - z
.
-(x + y)
has exactly the same moves as -x + -y
.
Equations
- (pgame.mk xl xr xL xR).neg_add_relabelling (pgame.mk yl yr yL yR) = pgame.relabelling.mk (equiv.refl (-(pgame.mk xl xr xL xR + pgame.mk yl yr yL yR)).left_moves) (equiv.refl (-(pgame.mk xl xr xL xR + pgame.mk yl yr yL yR)).right_moves) (λ (j : (-(pgame.mk xl xr xL xR + pgame.mk yl yr yL yR)).left_moves), sum.cases_on j (λ (j : xr), (xR j).neg_add_relabelling (pgame.mk yl yr yL yR)) (λ (j : yr), (pgame.mk xl xr xL xR).neg_add_relabelling (yR j))) (λ (j : (-(pgame.mk xl xr xL xR + pgame.mk yl yr yL yR)).right_moves), sum.cases_on j (λ (j : xl), (xL j).neg_add_relabelling (pgame.mk yl yr yL yR)) (λ (j : yl), (pgame.mk xl xr xL xR).neg_add_relabelling (yL j)))
x + y
has exactly the same moves as y + x
.
Equations
- (pgame.mk xl xr xL xR).add_comm_relabelling (pgame.mk yl yr yL yR) = pgame.relabelling.mk (equiv.sum_comm xl yl) (equiv.sum_comm xr yr) (λ (i : (pgame.mk xl xr xL xR + pgame.mk yl yr yL yR).left_moves), sum.cases_on i (λ (i : xl), id ((xL i).add_comm_relabelling (pgame.mk yl yr yL yR))) (λ (i : yl), id ((pgame.mk xl xr xL xR).add_comm_relabelling (yL i)))) (λ (j : (pgame.mk xl xr xL xR + pgame.mk yl yr yL yR).right_moves), sum.cases_on j (λ (j : xr), id ((xR j).add_comm_relabelling (pgame.mk yl yr yL yR))) (λ (j : yr), id ((pgame.mk xl xr xL xR).add_comm_relabelling (yR j))))
(x + y) + z
has exactly the same moves as x + (y + z)
.
Equations
- (pgame.mk xl xr xL xR).add_assoc_relabelling (pgame.mk yl yr yL yR) (pgame.mk zl zr zL zR) = pgame.relabelling.mk (equiv.sum_assoc xl yl zl) (equiv.sum_assoc xr yr zr) (λ (i : (pgame.mk xl xr xL xR + pgame.mk yl yr yL yR + pgame.mk zl zr zL zR).left_moves), sum.cases_on i (λ (i : xl ⊕ yl), i.cases_on (λ (i : xl), (xL i).add_assoc_relabelling (pgame.mk yl yr yL yR) (pgame.mk zl zr zL zR)) (λ (i : yl), (pgame.mk xl xr xL xR).add_assoc_relabelling (yL i) (pgame.mk zl zr zL zR))) (λ (i : zl), (pgame.mk xl xr xL xR).add_assoc_relabelling (pgame.mk yl yr yL yR) (zL i))) (λ (j : (pgame.mk xl xr xL xR + pgame.mk yl yr yL yR + pgame.mk zl zr zL zR).right_moves), sum.cases_on j (λ (j : xr ⊕ yr), j.cases_on (λ (i : xr), (xR i).add_assoc_relabelling (pgame.mk yl yr yL yR) (pgame.mk zl zr zL zR)) (λ (i : yr), (pgame.mk xl xr xL xR).add_assoc_relabelling (yR i) (pgame.mk zl zr zL zR))) (λ (i : zr), (pgame.mk xl xr xL xR).add_assoc_relabelling (pgame.mk yl yr yL yR) (zR i)))
Special pre-games #
The pre-game star
, which is fuzzy with zero.
Instances for pgame.star
Equations
Equations
Equations
- pgame.zero_le_one_class = {zero_le_one := pgame.zero_le_one_class._proof_1}