Theory Simple_Game

subsection ‹Simple Games›

theory Simple_Game
imports
  Main
begin

text ‹Simple games are games where player0 wins all infinite plays.›
locale simple_game =
fixes
  game_move :: 's  's  bool ("_ ⟼♡ _" [70, 70] 80) and
  player0_position :: 's  bool
begin

abbreviation player1_position :: 's  bool
  where player1_position s  ¬ player0_position s

―‹Plays (to be precise: play prefixes) are lists.
  We model them with the most recent move at the beginning.
  (For our purpose it's enough to consider finite plays.)›
type_synonym ('s2) play = 's2 list
type_synonym ('s2) strategy = 's2 play  's2
type_synonym ('s2) posstrategy = 's2  's2

definition strategy_from_positional :: 's posstrategy  's strategy where
  strategy_from_positional pf = (λ play. pf (hd play))

inductive_set plays :: 's  's play set 
  for initial :: 's where
  [initial]  plays initial |
  p#play  plays initial  p ⟼♡ p'  p'#p#play  plays initial

definition play_continuation :: 's play  's play  bool
  where play_continuation p1 p2  (drop (length p2 - length p1) p2) = p1

―‹Plays for a given player 0 strategy›
inductive_set plays_for_0strategy :: 's strategy  's  's play set
  for f initial where
  init: [initial]  plays_for_0strategy f initial |
  p0move:
    n0#play  plays_for_0strategy f initial  player0_position n0  n0 ⟼♡ f (n0#play)
     (f (n0#play))#n0#play  plays_for_0strategy f initial |
  p1move:
    n1#play  plays_for_0strategy f initial  player1_position n1  n1 ⟼♡ n1'
     n1'#n1#play  plays_for_0strategy f initial

lemma strategy0_step:
  assumes
    n0 # n1 # rest  plays_for_0strategy f initial
    player0_position n1
  shows
    f (n1 # rest) = n0
  using assms
  by (induct rule: plays_for_0strategy.cases, auto)

―‹Plays for a given player 1 strategy›
inductive_set plays_for_1strategy :: 's strategy  's  's play set
  for f initial where
  init: [initial]  plays_for_1strategy f initial |
  p0move:
    n0#play  plays_for_1strategy f initial  player0_position n0  n0 ⟼♡ n0'
     n0'#n0#play  plays_for_1strategy f initial |
  p1move:
    n1#play  plays_for_1strategy f initial  player1_position n1  n1 ⟼♡ f (n1#play)
     (f (n1#play))#n1#play  plays_for_1strategy f initial

definition positional_strategy :: 's strategy  bool where
  positional_strategy f  r1 r2 n. f (n # r1) = f (n # r2)

text ‹A strategy is sound if it only decides on enabled transitions.›
definition sound_0strategy :: 's strategy  's  bool where
  sound_0strategy f initial 
     n0 play .
      n0#play  plays_for_0strategy f initial 
      player0_position n0  n0 ⟼♡ f (n0#play)

definition sound_1strategy :: 's strategy  's  bool where
  sound_1strategy f initial 
     n1 play .
      n1#play  plays_for_1strategy f initial 
      player1_position n1  n1 ⟼♡ f (n1#play)

lemma strategy0_plays_subset:
  assumes play  plays_for_0strategy f initial
  shows play  plays initial
  using assms by (induct rule: plays_for_0strategy.induct, auto simp add: plays.intros)
lemma strategy1_plays_subset:
  assumes play  plays_for_1strategy f initial
  shows play  plays initial
  using assms by (induct rule: plays_for_1strategy.induct, auto simp add: plays.intros)

lemma no_empty_plays:
  assumes []  plays initial
  shows False 
  using assms plays.cases by blast

text ‹Player1 wins a play if the play has reached a deadlock where it's player0's turn›

definition player1_wins_immediately :: 's play  bool where
  player1_wins_immediately play  player0_position (hd play)  ( p' . (hd play) ⟼♡ p')

definition player0_winning_strategy :: 's strategy  's  bool where
  player0_winning_strategy f initial  ( play  plays_for_0strategy f initial.
    ¬ player1_wins_immediately play)

definition player0_wins :: 's  bool where
  player0_wins s  ( f . player0_winning_strategy f s  sound_0strategy f s)

lemma stuck_player0_win:
  assumes player1_position initial ( p' . initial ⟼♡ p')
  shows player0_wins initial
proof -
  have pl. pl  plays initial  pl = [initial]
  proof -
    fix pl
    assume pl  plays initial
    thus pl = [initial] using assms(2) by (induct, auto)
  qed
  thus ?thesis using assms(1)
    by (metis list.sel(1) player0_winning_strategy_def player0_wins_def player1_wins_immediately_def
        sound_0strategy_def strategy0_plays_subset)
qed

definition player0_wins_immediately :: 's play  bool where
  player0_wins_immediately play  player1_position (hd play)  ( p' . (hd play) ⟼♡ p')

end
end