Remove debug code
kind_of -> is_a
add Nセット先取
add damage_voice_disable
replace match_count -> win_count_limit
replace _index -> position
replace kachimake_info -> battle_info
replace pon_command -> se_command
refactoring
Menu セルサイズ変更, フレームborderが1ドット狭い→修正
Menu下BGとBTBで背景切り替え
bugfix line_trial + item で item 取るとクリア
add ff_effect
add sound_theme
refactoring
module → concerning
AutoInput -> Sequencer

diff --git a/examples/test_replay.rb b/examples/test_replay.rb
new file mode 100644
index 0000000..87e215f
--- /dev/null
+++ b/examples/test_replay.rb
@@ -0,0 +1,18 @@
+  if $0 == __FILE__
+    $LOAD_PATH << ".."
+    require 'vortex'
+
+    module Mode
+      class SimpleMode2 < ::Mode::MementMode
+        self.mode_name = "Simple"
+        def initialize
+          super
+          add_field Field.create
+          add_player Player.new(field: @fields[0], controller: BaseController.new)
+          assign_pad
+        end
+      end
+    end
+
+    Window.start(Mode::SimpleMode2)
+  end
diff --git a/lib/vortex/base_controller.rb b/lib/vortex/base_controller.rb
index 4d67c96..d1fd3f0 100644
--- a/lib/vortex/base_controller.rb
+++ b/lib/vortex/base_controller.rb
@@ -152,7 +152,7 @@ class FrameSimple < Mode::Base
       def initialize
         super
         add_field Field.create
-        add_player Player.new(field: @field, input: Handler::AutoInput.new(["U"]*(60*3)), controller: BaseController.new)
+        add_player Player.new(field: @field, input: Handler::Sequencer.new(["U"]*(60*3)), controller: BaseController.new)
       end
     end

diff --git a/lib/vortex/custom_menu.rb b/lib/vortex/custom_menu.rb
index 6651b33..b648651 100644
--- a/lib/vortex/custom_menu.rb
+++ b/lib/vortex/custom_menu.rb
@@ -1,3 +1,5 @@
+require "stylet/contrib/menu"
+
 module Vortex
   module CustomMenu
     class Base < Stylet::Menu::Simple
diff --git a/lib/vortex/field.rb b/lib/vortex/field.rb
index 0dff22b..cdea0dd 100644
--- a/lib/vortex/field.rb
+++ b/lib/vortex/field.rb
@@ -15,7 +15,7 @@ def create(width: 10, height: 20 + hidden_lines, **options)
         end
       end

-      attr_accessor :area, :matrix
+      attr_accessor :area, :matrix, :position

       def initialize(width: Piece::Classic.piece_size_max, height: Piece::Classic.piece_size_max, field_str: nil, position: nil)
         # 空のフィールド生成
@@ -374,12 +374,12 @@ def simple_clone
           end
         end

-        # def marshal_load(variables)
-        #   @matrix, @area, @position = variables
-        # end
-        #
         # def marshal_dump
-        #   [@matrix, @area, @position]
+        #   [@matrix, @area, @position, @damage]
+        # end
+        #
+        # def marshal_load(obj)
+        #   @matrix, @area, @position, @damage = obj
         # end
       end

@@ -722,7 +722,7 @@ def stripe_draw
     end

     concerning :Relations do
-      attr_accessor :top_frame, :position
+      attr_accessor :top_frame

       def joined_players
         top_frame.players.find_all{|e|e.field == self}
diff --git a/lib/vortex/handler.rb b/lib/vortex/handler.rb
index 0802849..8666c6c 100644
--- a/lib/vortex/handler.rb
+++ b/lib/vortex/handler.rb
@@ -1,5 +1,6 @@
-require "stylet"
+# require "stylet"
 require_relative "handler/base"
 require_relative "handler/pad"
-require_relative "handler/auto_input"
+require_relative "handler/mini_sequencer"
+require_relative "handler/sequencer"
 require_relative "handler/computer"
diff --git a/lib/vortex/handler/auto_input.rb b/lib/vortex/handler/auto_input.rb
deleted file mode 100644
index 05bc8dd..0000000
--- a/lib/vortex/handler/auto_input.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# -*- coding: utf-8 -*-
-################################################################################
-# 次に入力の違いを考慮したクラスを3つ定義する
-# 1. AutoInput - プログラムとして自動的に動かせる
-# 2. Pad1  - キーボード1P
-# 3. Pad2  - キーボード2P
-################################################################################
-#
-# 表記
-# *    次のブロックが操作可能になるまで待つ
-# A*   次のブロックが操作可能になるまで待つ(Aを押しっぱなしなのでIRSが発動する。IRSが失敗する場合もある)
-# r    右を押す
-# r|   右を押す(壁かブロックに衝突するまで)
-# _    下に衝突するまで待つ
-# d_   下を押しながら下に衝突するまで待つ
-# u    上を押す
-# r+   右をずっと押しながら溜めが可能になるまで待つ
-# 5    5フレーム待つ
-# A5   Aを押したまま5フレーム待つ
-# .    何もしない(主にボタンを放すのに使う)
-# A . A  Aボタン押す→Aボタン放す→Aボタンを押す(A A だとAを押しっぱなしとみなす)
-# Ar   Aボタンと右を同時に押す
-#
-
-module Vortex
-  module Handler
-    class AutoInput
-      include Handler::Base
-      #
-      # 引数タイプ
-      #
-      # 1. ["A","B","C"]
-      # 2. "A,B,C"
-      # 3. ["A,B","C"]
-      # 4. "A","B","C"
-      #
-      # 元々 1 だけだった。でも 2,3,4 も取れるようにしてみた。
-      # でも、[""]*3 が [] になってしまってややこしいので廃止
-      #
-      # 変換過程
-      # p inkey                                    #=> ["A , B", "", ["A , B"],"",["A,B"]]
-      # p inkey.flatten.join(",")                  #=> "A , B,,A , B,,A,B"
-      # p inkey.flatten.join(",").split(/\s*,\s*/) #=> ["A", "B", "", "A", "B", "", "A", "B"]
-      #
-      def initialize(inkey)
-        super()
-        # 最後の map は [",,"] => [nil,nil,nil] => ["","",""] となるように nil を "" に変換
-
-        if inkey.is_a? String       # 文字列の場合スペース区切りで分ける
-          str = inkey.gsub(/[;#].*$/, "") # コメント除去
-          str = str.gsub(/\n/, "")
-          str = str.strip
-          @inkey = str.split(/\s+/)
-          # p @inkey
-        else
-          @inkey = inkey.flatten    # Array型の場合はいままでの仕様と変わらない
-        end
-
-        # Stylet.logger.debug "AutoInput: #{@inkey.inspect}"
-
-        @save_key = ""              # 反映するキー文字列("lrudABCD"と属性"*|_+"と待ち時間がごっちゃになっている)
-        @delay_count = 0            # 任意の待ち時間が有効になったときにセットされてデクリメントされる
-      end
-
-      def key_bit_update_all(player = nil)
-        if @delay_count > 0         # 任意の時間待ち
-          @delay_count -= 1
-        elsif @save_key.include?("*") # IRS待ち
-        elsif @save_key.include?("|") # 左右の壁衝突待ち
-        elsif @save_key.include?("_") # 下への衝突待ち
-        elsif @save_key.include?("+") # 溜め待ち
-          if key_power_effective?(player.controller.das_delay)
-            @save_key = ""
-          end
-        else
-          # 何の待ちイベントも発生していないので空にしておく
-          # ここが呼ばれるのは delay_count が終了したときだけかな。
-          @save_key = ""
-        end
-
-        # 待ってない場合のみ次のデータを取得できる
-        if @save_key.empty?
-          if @inkey.empty?
-            throw :exit, :lost_key
-          end
-          @save_key = @inkey.shift
-          if md = @save_key.match(/(\d+)/)   # 数値が指定されていれば時間待ちと見なす
-            @delay_count = md.captures.first.to_i - 1
-          end
-        end
-
-        # 最新データとして反映
-        key_objects.each{|v| v << @save_key}
-      end
-
-      # IRSの直後に呼ばれる。
-      # IRSの成功したかどうかには関係がない。
-      # だからブロックが操作可能になるまで待つというのにも使える。
-      def after_user_irs(*args)
-        if @save_key.include?("*")
-          @save_key = ""
-        end
-      end
-
-      def after_move(piece, dir)
-        if @save_key.include?("|")
-          if dir
-            unless piece.moveable?(dir)
-              @save_key = ""
-            end
-          end
-        end
-        if @save_key.include?("_")
-          unless piece.moveable?(:dir_2)
-            @save_key = ""
-          end
-        end
-      end
-    end
-
-    class RsAutoInput < AutoInput
-      require_relative 'reaction_suppression'
-      include ReactionSuppressionMod
-    end
-  end
-end
diff --git a/lib/vortex/handler/base.rb b/lib/vortex/handler/base.rb
index e9fc239..a3c628c 100644
--- a/lib/vortex/handler/base.rb
+++ b/lib/vortex/handler/base.rb
@@ -35,12 +35,12 @@ def next_frame(*args)

       # コールバックされるメソッドたち
       [
-        :key_bit_update_all,                  # キーの内容を更新して欲しいとき(毎フレーム)
-        :think_first_trigger,     # 次のブロックへの操作が有効になったタイミング
-        :after_user_irs,          # IRS直後(成功したかどうかには関係ない)
-        :power_key_filled,        # 溜めが完了したタイミング
-        :after_move,              # 移動直後
-        :reset                    # デバッグ中にリセットされたとき
+        :key_bit_update_all,    # キーの内容を更新して欲しいとき(毎フレーム)
+        :think_first_trigger,   # 次のブロックへの操作が有効になったタイミング
+        :after_user_irs,        # IRS直後(成功したかどうかには関係ない)
+        :power_key_filled,      # 溜めが完了したタイミング
+        :after_move,            # 移動直後
+        :reset                  # デバッグ中にリセットされたとき
       ].each do |method|
         define_method(method) do |*, &_|
         end
diff --git a/lib/vortex/handler/computer.rb b/lib/vortex/handler/computer.rb
index ba69b26..1f5514e 100644
--- a/lib/vortex/handler/computer.rb
+++ b/lib/vortex/handler/computer.rb
@@ -9,7 +9,7 @@
 module Vortex
   module Handler
     class Computer
-      include Handler::Base
+      include Base
       attr_reader :target

       def initialize
diff --git a/lib/vortex/handler/mini_sequencer.rb b/lib/vortex/handler/mini_sequencer.rb
new file mode 100644
index 0000000..14619a8
--- /dev/null
+++ b/lib/vortex/handler/mini_sequencer.rb
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+module Vortex
+  module Handler
+    class MiniSequencer
+      include Base
+
+      attr_accessor :list, :base_index, :index
+
+      def initialize(list, base_index: 0, index: 0)
+        super()
+        @list = list
+        @base_index = base_index
+        @index = index
+      end
+
+      def key_bit_update_all(*)
+        s = @list[@base_index + @index]
+        unless s
+          throw :exit, :lost_key
+        end
+        if s
+          key_objects.each{|v|v << s}
+        end
+        @index += 1
+      end
+    end
+  end
+end
diff --git a/lib/vortex/handler/pad.rb b/lib/vortex/handler/pad.rb
index 33c611e..ab04008 100644
--- a/lib/vortex/handler/pad.rb
+++ b/lib/vortex/handler/pad.rb
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-

 require_relative "base"
-require_relative "reaction_suppression"
+require_relative "react_suppress"

 module Vortex
   module Handler
@@ -19,7 +19,7 @@ def initialize(*)
         @joystick_index = Window::BaseWindow.active_frame.joys.size.times.to_a
       end

-      def key_bit_update_all(*args)
+      def key_bit_update_all(*)
         super
         Window::BaseWindow.active_frame.joys.values_at(*Array.wrap(@joystick_index)).each do |joy|
           bit_update_by_joy(joy)
@@ -28,10 +28,10 @@ def key_bit_update_all(*args)
     end

     class Pad1
-      include Handler::Base
+      include Base
       include Stylet::Input::StandardKeybordBind
       include JoystickSupport
-      include ReactionSuppressionMod
+      include ReactSuppressMod

       self.handle_name = "PAD-1P"
       self.handle_desc = "キーボード配置1・ジョイスティック1"
@@ -49,10 +49,10 @@ def key_bit_update_all(*)
     end

     class Pad2
-      include Handler::Base
+      include Base
       include Stylet::Input::HjklKeyboardBind
       include JoystickSupport
-      include ReactionSuppressionMod
+      include ReactSuppressMod

       self.handle_name = "PAD-2P"
       self.handle_desc = "キーボード配置2・ジョイスティック2"
diff --git a/lib/vortex/handler/react_suppress.rb b/lib/vortex/handler/react_suppress.rb
new file mode 100644
index 0000000..62ed80c
--- /dev/null
+++ b/lib/vortex/handler/react_suppress.rb
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+#
+# レバー反動抑制機能
+#
+# 使い方
+#
+#   1. R だけに 4 フレーム以下入り、
+#   2. ニュートラル状態を 2 フレーム以下で通過し、
+#   3. 反対の L に入ったとき 1 フレーム間 L を無効にする
+#
+# ・上記説明の中で出てきたパラメータ 4 2 1 は、順番に、
+#   side_frames, center_frames, suppression_frames にユーザーが設定する。
+# ・L→ニュートラル→R の場合も同様である
+#
+# アルゴリズム
+#
+# ・レバーの状態を表す文字列と、その状態を継続した時間を表すカウンタを一つの情報とし、配列に push していく
+# ・配列サイズは2、つまり過去2つまで調べられればよい。
+# ・状態が変化したら最新の状態(カウンタは更新する元の @state)を元に過去2つを調べ
+#   抑制する必要があれば最新の状態の @state を無効にする
+#
+# その他
+#
+# ・最初はHandler::Base の key_counter_update_all した後でこれを呼び to_s 値を元に調べ count を 0 にして無効にしていた。
+#   しかし、それでは「上下が入っていれば左右を無効」する処理の後にこれを実行することになってしまい、
+#   本当のレバー入力を元にチェックしていないことになってしまう。
+#   したがって、key_counter_update_all を呼ぶ前にこの処理を行わなくてはならない。
+#   もちろん to_s で状態を調べて count = 0 で無効ではなく、新たに機能追加した state_to_s で調べて
+#   state = false で無効にしなくてはならない。
+#
+module Vortex
+  module Handler
+    class ReactSuppress
+      def initialize(target, side_frames = 4, center_frames = 2, suppression_frames = 1)
+        target_set(target)
+        set_param(side_frames, center_frames, suppression_frames)
+      end
+
+      def target_set(target)
+        @target = target  # 抑制するInputUnitオブジェクト
+
+        @old = ""         # 最初のレバー状態
+        @history = []     # 状態移行履歴
+        @count = 0        # 状態移行するまでの時間測定用
+        @invoke = 0       # 指定したフレーム分抑制する
+        @target_key = nil # 具体的な抑制対象方向
+      end
+
+      def set_param(side_frames, center_frames, suppression_frames)
+        @side_frames = side_frames               # "r"に入れるフレーム数
+        @center_frames = center_frames           # ニュートラル状態のフレーム数
+        @suppression_frames = suppression_frames # "l"を無効にするフレーム数
+      end
+
+      def do_suppression
+        if @old != @target.axis_state_str         # レバーが前の状態から変化したか?
+          @history << [@old, @count]              # 前の状態と前の状態であった時間を保存
+          @history.shift until @history.size <= 2 # 履歴サイズの調整(2つあれば十分)
+          @old = @target.axis_state_str           # これからの状態を設定
+          @count = 0                              # これからの状態をカウントするために初期化
+          # 履歴情報を元に現在のレバー状態を無効にするべきか調べる
+          check_activity("l", "r", :left) or      # "L" <= "" <= "R" の場合
+            check_activity("r", "l", :right)      # "R" <= "" <= "L" の場合
+        end
+        @count += 1
+
+        # 無効にするのが有効なら時間内だけ無効にする
+        if @invoke >= 1
+          @invoke -= 1
+          @target.axis[@target_key].state = false # instance_eval{@count=0}ではない点に注意。
+        end
+      end
+
+      def check_activity(prev0, prev2, key)
+        state1, count1 = @history[-1]
+        state2, count2 = @history[-2]
+
+        if [
+            @target.axis_state_str == prev0,            # 現在 "L" で
+            state1 == "" && count1 <= @center_frames,  # 1つ前が ""(センター) で制限時間以内で
+            state2 == prev2 && count2 <= @side_frames, # 2つ前が "R" で制限時間以内なら
+          ].all?
+          @invoke = @suppression_frames                    # 抑制発動
+          @target_key = key                                # 抑制するキーの設定
+          true
+        else
+          false
+        end
+      end
+    end
+
+    # 反動抑制機能付きモジュール
+    module ReactSuppressMod
+      attr_reader :rs
+
+      def initialize(*args)
+        super
+        @rs = ReactSuppress.new(self)
+      end
+
+      def key_counter_update_all
+        @rs.do_suppression
+        super
+      end
+    end
+  end
+
+  if $0 == __FILE__
+  end
+end
diff --git a/lib/vortex/handler/reaction_suppression.rb b/lib/vortex/handler/reaction_suppression.rb
deleted file mode 100644
index 2e928ee..0000000
--- a/lib/vortex/handler/reaction_suppression.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# レバー反動抑制機能
-#
-# 使い方
-#
-#   1. R だけに 4 フレーム以下入り、
-#   2. ニュートラル状態を 2 フレーム以下で通過し、
-#   3. 反対の L に入ったとき 1 フレーム間 L を無効にする
-#
-# ・上記説明の中で出てきたパラメータ 4 2 1 は、順番に、
-#   side_frames, center_frames, suppression_frames にユーザーが設定する。
-# ・L→ニュートラル→R の場合も同様である
-#
-# アルゴリズム
-#
-# ・レバーの状態を表す文字列と、その状態を継続した時間を表すカウンタを一つの情報とし、配列に push していく
-# ・配列サイズは2、つまり過去2つまで調べられればよい。
-# ・状態が変化したら最新の状態(カウンタは更新する元の @state)を元に過去2つを調べ
-#   抑制する必要があれば最新の状態の @state を無効にする
-#
-# その他
-#
-# ・最初はHandler::Base の key_counter_update_all した後でこれを呼び to_s 値を元に調べ count を 0 にして無効にしていた。
-#   しかし、それでは「上下が入っていれば左右を無効」する処理の後にこれを実行することになってしまい、
-#   本当のレバー入力を元にチェックしていないことになってしまう。
-#   したがって、key_counter_update_all を呼ぶ前にこの処理を行わなくてはならない。
-#   もちろん to_s で状態を調べて count = 0 で無効ではなく、新たに機能追加した state_to_s で調べて
-#   state = false で無効にしなくてはならない。
-#
-module Vortex
-  module Handler
-    class ReactionSuppression
-      def initialize(target, side_frames = 4, center_frames = 2, suppression_frames = 1)
-        target_set(target)
-        set_param(side_frames, center_frames, suppression_frames)
-      end
-
-      def target_set(target)
-        @target = target  # 抑制するInputUnitオブジェクト
-
-        @old = ""         # 最初のレバー状態
-        @history = []     # 状態移行履歴
-        @count = 0        # 状態移行するまでの時間測定用
-        @invoke = 0       # 指定したフレーム分抑制する
-        @target_key = nil # 具体的な抑制対象方向
-      end
-
-      def set_param(side_frames, center_frames, suppression_frames)
-        @side_frames = side_frames               # "r"に入れるフレーム数
-        @center_frames = center_frames           # ニュートラル状態のフレーム数
-        @suppression_frames = suppression_frames # "l"を無効にするフレーム数
-      end
-
-      def do_suppression
-        if @old != @target.axis_state_str         # レバーが前の状態から変化したか?
-          @history << [@old, @count]              # 前の状態と前の状態であった時間を保存
-          @history.shift until @history.size <= 2 # 履歴サイズの調整(2つあれば十分)
-          @old = @target.axis_state_str           # これからの状態を設定
-          @count = 0                              # これからの状態をカウントするために初期化
-          # 履歴情報を元に現在のレバー状態を無効にするべきか調べる
-          check_activity("l", "r", :left) or      # "L" <= "" <= "R" の場合
-            check_activity("r", "l", :right)      # "R" <= "" <= "L" の場合
-        end
-        @count += 1
-
-        # 無効にするのが有効なら時間内だけ無効にする
-        if @invoke >= 1
-          @invoke -= 1
-          @target.axis[@target_key].state = false # instance_eval{@count=0}ではない点に注意。
-        end
-      end
-
-      def check_activity(prev0, prev2, key)
-        state1, count1 = @history[-1]
-        state2, count2 = @history[-2]
-
-        if [
-            @target.axis_state_str == prev0,            # 現在 "L" で
-            state1 == "" && count1 <= @center_frames,  # 1つ前が ""(センター) で制限時間以内で
-            state2 == prev2 && count2 <= @side_frames, # 2つ前が "R" で制限時間以内なら
-          ].all?
-          @invoke = @suppression_frames                    # 抑制発動
-          @target_key = key                                # 抑制するキーの設定
-          true
-        else
-          false
-        end
-      end
-    end
-
-    # 反動抑制機能付きモジュール
-    module ReactionSuppressionMod
-      attr_reader :rs
-
-      def initialize(*args)
-        super
-        @rs = ReactionSuppression.new(self)
-      end
-
-      def key_counter_update_all
-        @rs.do_suppression
-        super
-      end
-    end
-  end
-
-  if $0 == __FILE__
-  end
-end
diff --git a/lib/vortex/handler/sequencer.rb b/lib/vortex/handler/sequencer.rb
new file mode 100644
index 0000000..f56d35d
--- /dev/null
+++ b/lib/vortex/handler/sequencer.rb
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+################################################################################
+# 次に入力の違いを考慮したクラスを3つ定義する
+# 1. Sequencer - プログラムとして自動的に動かせる
+# 2. Pad1  - キーボード1P
+# 3. Pad2  - キーボード2P
+################################################################################
+#
+# 表記
+# *    次のブロックが操作可能になるまで待つ
+# A*   次のブロックが操作可能になるまで待つ(Aを押しっぱなしなのでIRSが発動する。IRSが失敗する場合もある)
+# r    右を押す
+# r|   右を押す(壁かブロックに衝突するまで)
+# _    下に衝突するまで待つ
+# d_   下を押しながら下に衝突するまで待つ
+# u    上を押す
+# r+   右をずっと押しながら溜めが可能になるまで待つ
+# 5    5フレーム待つ
+# A5   Aを押したまま5フレーム待つ
+# .    何もしない(主にボタンを放すのに使う)
+# A . A  Aボタン押す→Aボタン放す→Aボタンを押す(A A だとAを押しっぱなしとみなす)
+# Ar   Aボタンと右を同時に押す
+#
+
+module Vortex
+  module Handler
+    class Sequencer
+      include Base
+      #
+      # 引数タイプ
+      #
+      # 1. ["A","B","C"]
+      # 2. "A,B,C"
+      # 3. ["A,B","C"]
+      # 4. "A","B","C"
+      #
+      # 元々 1 だけだった。でも 2,3,4 も取れるようにしてみた。
+      # でも、[""]*3 が [] になってしまってややこしいので廃止
+      #
+      # 変換過程
+      # p inkey                                    #=> ["A , B", "", ["A , B"],"",["A,B"]]
+      # p inkey.flatten.join(",")                  #=> "A , B,,A , B,,A,B"
+      # p inkey.flatten.join(",").split(/\s*,\s*/) #=> ["A", "B", "", "A", "B", "", "A", "B"]
+      #
+      def initialize(inkey)
+        super()
+        # 最後の map は [",,"] => [nil,nil,nil] => ["","",""] となるように nil を "" に変換
+
+        if inkey.is_a? String       # 文字列の場合スペース区切りで分ける
+          str = inkey.gsub(/[;#].*$/, "") # コメント除去
+          str = str.gsub(/\n/, "")
+          str = str.strip
+          @inkey = str.split(/\s+/)
+          # p @inkey
+        else
+          @inkey = inkey.flatten    # Array型の場合はいままでの仕様と変わらない
+        end
+
+        # Stylet.logger.debug "Sequencer: #{@inkey.inspect}"
+
+        @save_key = ""              # 反映するキー文字列("lrudABCD"と属性"*|_+"と待ち時間がごっちゃになっている)
+        @delay_count = 0            # 任意の待ち時間が有効になったときにセットされてデクリメントされる
+      end
+
+      def key_bit_update_all(player)
+        if @delay_count > 0         # 任意の時間待ち
+          @delay_count -= 1
+        elsif @save_key.include?("*") # IRS待ち
+        elsif @save_key.include?("|") # 左右の壁衝突待ち
+        elsif @save_key.include?("_") # 下への衝突待ち
+        elsif @save_key.include?("+") # 溜め待ち
+          if key_power_effective?(player.controller.das_delay)
+            @save_key = ""
+          end
+        else
+          # 何の待ちイベントも発生していないので空にしておく
+          # ここが呼ばれるのは delay_count が終了したときだけかな。
+          @save_key = ""
+        end
+
+        # 待ってない場合のみ次のデータを取得できる
+        if @save_key.empty?
+          if @inkey.empty?
+            throw :exit, :lost_key
+          end
+          @save_key = @inkey.shift
+          if md = @save_key.match(/(\d+)/)   # 数値が指定されていれば時間待ちと見なす
+            @delay_count = md.captures.first.to_i - 1
+          end
+        end
+
+        # 最新データとして反映
+        key_objects.each{|v| v << @save_key}
+      end
+
+      # IRSの直後に呼ばれる。
+      # IRSの成功したかどうかには関係がない。
+      # だからブロックが操作可能になるまで待つというのにも使える。
+      def after_user_irs(*args)
+        if @save_key.include?("*")
+          @save_key = ""
+        end
+      end
+
+      def after_move(piece, dir)
+        if @save_key.include?("|")
+          if dir
+            unless piece.moveable?(dir)
+              @save_key = ""
+            end
+          end
+        end
+        if @save_key.include?("_")
+          unless piece.moveable?(:dir_2)
+            @save_key = ""
+          end
+        end
+      end
+    end
+
+    class RsSequencer < Sequencer
+      require_relative "react_suppress"
+      include ReactSuppressMod
+    end
+  end
+end
diff --git a/lib/vortex/mode.rb b/lib/vortex/mode.rb
index 3f97c96..42bd9e1 100644
--- a/lib/vortex/mode.rb
+++ b/lib/vortex/mode.rb
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8; compile-command: "be rsdl test_replay.rb" -*-

 require "observer"
 require "active_support/core_ext/class/attribute"
@@ -27,6 +27,7 @@ def initialize(*)
         @players = []
         @setuped = false
         @state = State.new(:vss_boot)
+        @frame_counter = 0
       end

       def add_player(player)
@@ -49,19 +50,23 @@ def any_setup_once
       end

       def any_setup
-        new_seed = Random.new_seed
         @fields.each.with_index{|e, i|e.position ||= i}
         @players.each.with_index{|e, i|e.position ||= i}
         @players.each{|e|e.top_frame = self}
+        new_seed = Random.new_seed
         @players.each{|e|e.randomizer.random_shuffle(new_seed)}
         @controllers = @players.collect{|e|e.controller}.uniq
       end

       def all_objects_next_frame
-        any_setup_once
+        if @frame_counter == 0
+          any_setup_once
+          @seginfo1 = create_memento
+        end
         @fields.each{|e|e.next_frame}
         @players.each{|e|e.next_frame}
         @controllers.each(&:next_frame_pass)
+        @frame_counter += 1
         nil
       end

@@ -90,11 +95,11 @@ def show_loop(&block)
         end
       end

-      def start(fps = nil, &block)
+      def start # (fps = nil, &block)
         catch(:exit) do
           loop do
             next_frame
-            block.call if block
+            # block.call if block
           end
         end
       end
@@ -195,7 +200,9 @@ def vss_menu_win_count_limit_select
         def vss_menu_charactor_select
           if @state.start?
             @menus = @players.collect do |player|
-              player.charactor_key ||= PuyoFever::Charactor.keys.sample
+              if player.respond_to?(:charactor_key)
+                player.charactor_key ||= PuyoFever::Charactor.keys.sample
+              end
               CustomMenu::CharSelectMenu.new(name: "#{player.position.next}P", :bar => nil, joystick_index: player.position, :input => Handler.default_pad_list[player.position].new).tap do |menu|
                 if player.controller.respond_to?(:charactor_key) && player.charactor
                   menu.elements << {
@@ -308,27 +315,31 @@ def vss_menu_open
             if @music
               Soundman.music_play @music
             end
-            @retry = false
-            @counter_for_close = 10
             @menu = CustomMenu::SeOnlyMenu.new
-            @menu.elements << {:name => "もう1回", :se_command => proc { @retry = true }}
+            @menu.elements << {:name => "もう1回", :se_command => proc { @state.jump_to :vss_retry_process }}
+            @menu.elements << {:name => "リプレイする", :se_command => proc {
+                replay_start
+                @state.jump_to :vss_retry_process
+              }}
+            @menu.elements << {:name => "リプレイ保存", :se_command => proc { save_replay }}
             if !Vortex.config.countdown_close
               @menu.elements << {:name => "やめる",  :se_command => proc {|m| m.force_close }}
             else
+              postponement_counter = 10
               close_process = proc{|m|
                 Soundman.se_obj(:menu_select).play
-                @counter_for_close -= 1
-                if @counter_for_close <= 0
+                postponement_counter -= 1
+                if postponement_counter <= 0
                   m.force_close
                 end
               }
               @menu.elements << {
                 :name => "やめる",
-                :value => proc { @counter_for_close },
+                :value => proc { postponement_counter },
                 :simple_command => close_process,
                 :every_command => proc {|m|
                   if m.root.input.ext_button.btStart.trigger?
-                    @retry = true
+                    @state.jump_to :vss_retry_process
                   end
                   if m.root.close_trigger?
                     # Window::BaseWindow.active_frame.ff_effect = false
@@ -339,9 +350,6 @@ def vss_menu_open
             end
           end
           @menu.update
-          if @retry
-            @state.jump_to :vss_retry_process
-          end
         end

         def vss_retry_process
@@ -377,7 +385,7 @@ def charactor_sample_voice_call(player)
       end
     end

-    module MementControlMethods
+    module Memento
       extend ActiveSupport::Concern

       included do
@@ -402,7 +410,7 @@ def replay_a_to_b(marshal1, marshal2)
           field1, players1 = Marshal.load(marshal1)
           field2, alive_players = Marshal.load(marshal2)
           players1.each.with_index{|e,i|
-            e.input = AutoInput.new(alive_players[i].input.history[e.input.history.size..-1])
+            e.input = MiniSequencer.new(alive_players[i].input.history[e.input.history.size..-1])
           }
           new(field1, players1)
         end
@@ -418,7 +426,7 @@ def initialize(*)
       end

       def create_memento
-        any_setup_once     # FIXME: ここに入れるのどうなんだ
+        any_setup_once
         Marshal.dump([@fields, @players])
       end

@@ -428,6 +436,7 @@ def restore_memento(memento)
       end

       def push_memento
+        Vortex.logger.debug "push_memento"
         @memento_stack.push(create_memento)
       end

@@ -435,103 +444,100 @@ def undo
         restore_memento(@memento_stack.pop)
       end

-      def to_marshal_binary
-        require "etc"
-        Marshal.dump(:seginfo => @seginfo, :seginfo1 => @seginfo1, :seginfo2 => @seginfo2, :time => Time.now, :user => Etc.getlogin)
-      end
-    end
+      # def to_marshal_binary
+      #   require "etc"
+      #   Marshal.dump(:seginfo => @seginfo, :seginfo1 => @seginfo1, :seginfo2 => @seginfo2, :time => Time.now, :user => Etc.getlogin)
+      # end

-    module SegmentAutoSaveHeavyMethods
-      extend ActiveSupport::Concern
-
-      included do
+      def save_replay
       end

-      module self::ClassMethods
-      end
-
-      def next_frame
-        # 1Pのlevelチェックしかしていない点に注意。
-        # 本当は segment_index が上った時だけ処理を行いたい。
-        # 改善の余地あり。
-        super
+      def replay_start
+        histories = @players.collect{|e|e.input.history}.each
+        _fields, _players = Marshal.load(@seginfo1)

-        flash_seginfo
-      end
+        @fields = []
+        @players = []

-      def flash_seginfo
-        # 本当は segment_index が上った時だけ処理を行いたい。
-        @seginfo ||= []
-        @players.each.with_index{|e, i|
-          @seginfo[i] ||= []
-          raise "セグメント情報がありません。" unless e.controller.segment_index
-          if @seginfo[i][e.controller.segment_index].nil?
-            @seginfo[i][e.controller.segment_index] = create_memento
-          end
-        }
-      end
+        _fields.each{|e|add_field e}
+        _players.each{|e|add_player e}

-      def save_direct_info
-        @players.each_index{|i|
-          @seginfo[i] << create_memento
+        @players.each{|player|
+          player.input = Handler::MiniSequencer.new(histories.next)
         }
-      end
-
-      def start(fps=0, &block)
-        flash_seginfo
-
-        @seginfo1 = create_memento   # なくてもよい。
-        ret = super(fps, &block)
-        @seginfo2 = create_memento   # 必要。これも使ってない？

-        # 最後の状態を記録
-        save_direct_info
-
-        ret
-      end
+        any_setup
+        @frame_counter = 0
+      end
+
+      # def next_frame
+      #   # 1Pのlevelチェックしかしていない点に注意。
+      #   # 本当は segment_index が上った時だけ処理を行いたい。
+      #   # 改善の余地あり。
+      #   super
+      #
+      #   flash_seginfo
+      # end
+      #
+      # def flash_seginfo
+      #   # 本当は segment_index が上った時だけ処理を行いたい。
+      #   @seginfo ||= []
+      #   @players.each.with_index{|e, i|
+      #     @seginfo[i] ||= []
+      #     raise "セグメント情報がありません。" unless e.controller.segment_index
+      #     if @seginfo[i][e.controller.segment_index].nil?
+      #       @seginfo[i][e.controller.segment_index] = create_memento
+      #     end
+      #   }
+      # end
+      #
+      # def save_direct_info
+      #   @players.each_index{|i|
+      #     @seginfo[i] << create_memento
+      #   }
+      # end
+
+      # def start ## fps=0, &block)
+      #   # flash_seginfo
+      #
+      #   @seginfo1 = create_memento   # なくてもよい。
+      #   ret = super # (fps, &block)
+      #   @seginfo2 = create_memento   # 必要。これも使ってない？
+      #
+      #   # # 最後の状態を記録
+      #   # save_direct_info
+      #
+      #   ret
+      # end
+
+      # def func1
+      #   history = @players.first.input.history
+      #   @fields, @players = Marshal.load(@seginfo1)
+      #   @players.first.input = Handler::MiniSequencer.new(history)
+      # end
     end

     class Base
       include Core
-      include MementControlMethods
+      include Memento
     end

     class BaseSingle
       include Core
-      include MementControlMethods
+      include Memento
       include VersusContinueMethods
     end

     class BaseVs
       include Core
-      include MementControlMethods
+      include Memento
       include VersusContinueMethods
     end

     # 危険(重い！)
     class MementMode
       include Core
-      include MementControlMethods
-      include SegmentAutoSaveHeavyMethods
+      include Memento
     end
   end
-
-  if $0 == __FILE__
-    $LOAD_PATH << ".."
-    require_relative 'vortex'
-
-    module Mode
-      class SimpleMode2 < ::Mode::MementMode
-        self.mode_name = "Simple"
-        def initialize
-          super
-          add_field Field.create
-          add_player Player.new(field: @fields[0], controller: BaseController.new)
-          assign_pad
-        end
-      end
-    end
-
-    Window.start(Mode::SimpleMode2)
-  end
 end
diff --git a/lib/vortex/mode/versus_test_mode.rb b/lib/vortex/mode/versus_test_mode.rb
index 76d6f2a..9866ee4 100644
--- a/lib/vortex/mode/versus_test_mode.rb
+++ b/lib/vortex/mode/versus_test_mode.rb
@@ -31,7 +31,7 @@ def initialize(params)
           end
           handler = nil
           if !params[:user_play] && pl[:input]
-            handler = Handler::AutoInput.new(pl[:input])
+            handler = Handler::Sequencer.new(pl[:input])
           end
           add_field field
           add_player Player.new(field: field, input: handler, randomizer: randomizer, controller: controller)
diff --git a/lib/vortex/player.rb b/lib/vortex/player.rb
index bcbf79d..4e11909 100644
--- a/lib/vortex/player.rb
+++ b/lib/vortex/player.rb
@@ -123,6 +123,37 @@ def primary?
       def other_players
         players - [self]
       end
+
+      # def marshal_dump
+      #   # [:@field, :@column, :@input, :@randomizer, :@controller, :@piece_class, :@randy, :@state, :@current_piece, :@lock_piece, :@next_pieces, :@dead, :@top_frame, :@position]
+      #   need_vars.collect{|e|instance_variable_get(e)}
+      # end
+      #
+      # def marshal_load(obj)
+      #   need_vars.each.with_index{|e, i|
+      #     instance_variable_set(e, obj[i])
+      #   }
+      # end
+      #
+      # def need_vars
+      #   instance_variables
+      #   # [
+      #   #   :@field,
+      #   #   :@column,
+      #   #   :@input,
+      #   #   :@randomizer,
+      #   #   :@controller,
+      #   #   :@piece_class,
+      #   #   :@randy,
+      #   #   :@state,
+      #   #   :@current_piece,
+      #   #   :@lock_piece,
+      #   #   :@next_pieces,
+      #   #   :@dead,
+      #   #   # :@top_frame,
+      #   #   :@position,
+      #   # ]
+      # end
     end

     def win_process
@@ -133,7 +164,7 @@ def win_process

     def next_frame
       @input.next_frame(self)
-      @state.loop_in { send(@state.state) }
+      @state.loop_in { send @state.state }
       @controller.next_frame_done(self)
     end

diff --git a/lib/vortex/simulator.rb b/lib/vortex/simulator.rb
index c856f74..e33787f 100644
--- a/lib/vortex/simulator.rb
+++ b/lib/vortex/simulator.rb
@@ -56,7 +56,7 @@ def initialize(*)
   end

   class SimulateFrame < Mode::Base
-    include Mode::MementControlMethods
+    include Mode::Memento

     def initialize(params)
       super if defined? super
@@ -67,7 +67,7 @@ def initialize(params)
   end

   class AutoPlayFrame < Mode::Base
-    # include Mode::MementControlMethods ←これを入れるとおかしくなる。
+    # include Mode::Memento ←これを入れるとおかしくなる。
     # params[:controller] の保存に失敗しているのかも
     # SimulateFrame との違いは Handler::Handler だからここが原因か？
     # ↑は関係なかった
@@ -78,7 +78,7 @@ def initialize(params)
       super()
       @simulator_params = params
       add_field Field.create(field_str: params[:field])
-      add_player Player.new(field: @fields[0], input: Handler::AutoInput.new(params[:input]), randomizer: Randomizer::Original.new(params[:randomizer]), controller: Marshal.load(Marshal.dump(params[:controller])))
+      add_player Player.new(field: @fields[0], input: Handler::Sequencer.new(params[:input]), randomizer: Randomizer::Original.new(params[:randomizer]), controller: Marshal.load(Marshal.dump(params[:controller])))
     end
   end

diff --git a/lib/vortex/simulator/t_spin.rb b/lib/vortex/simulator/t_spin.rb
index bdac2fc..127ac2e 100644
--- a/lib/vortex/simulator/t_spin.rb
+++ b/lib/vortex/simulator/t_spin.rb
@@ -154,7 +154,7 @@ def field_data

     frame = Mode::Base.new
     frame.add_field field
-    frame.add_player Player.new(field: field, input: Handler::AutoInput.new(@params[:input]), randomizer: Randomizer::Original.new(@params[:randomizer]), controller: controller)
+    frame.add_player Player.new(field: field, input: Handler::Sequencer.new(@params[:input]), randomizer: Randomizer::Original.new(@params[:randomizer]), controller: controller)

     if false
       ui = UI::Window::SimulateWindow.new(frame)
diff --git a/lib/vortex/simulator/world_rule_piece_controll_optimize.rb b/lib/vortex/simulator/world_rule_piece_controll_optimize.rb
index f99dbad..b45ee01 100644
--- a/lib/vortex/simulator/world_rule_piece_controll_optimize.rb
+++ b/lib/vortex/simulator/world_rule_piece_controll_optimize.rb
@@ -797,7 +797,7 @@ def field_data(piece, operation_key)
     field = Field.new(width: 10, height: 10, field_str: Field.hole_in_piece(piece))
     frame = Mode::Base.new
     frame.add_field field
-    frame.add_player Player.new(field: field, input: Handler::AutoInput.new(operation[:input] + " u_ *"), randomizer: Randomizer::Original.new(piece.color.downcase[0..0]), controller: controller)
+    frame.add_player Player.new(field: field, input: Handler::Sequencer.new(operation[:input] + " u_ *"), randomizer: Randomizer::Original.new(piece.color.downcase[0..0]), controller: controller)
     if false
       ui = UI::Window::SimulateWindow.new(frame)
       ui.title = title
diff --git a/lib/vortex/soundman.rb b/lib/vortex/soundman.rb
index 5bdc3c7..7b9651e 100644
--- a/lib/vortex/soundman.rb
+++ b/lib/vortex/soundman.rb
@@ -57,6 +57,10 @@ def sound_effect_load_all
           end
         end
       end
+
+      def logger
+        Stylet.logger
+      end
     end
   end
 end
diff --git a/lib/vortex/test_replay.rb b/lib/vortex/test_replay.rb
new file mode 100644
index 0000000..a18f306
--- /dev/null
+++ b/lib/vortex/test_replay.rb
@@ -0,0 +1,24 @@
+$LOAD_PATH.unshift ".."
+require "vortex"
+require_relative "mode/standard_mode"
+
+module Vortex
+  module Mode
+    class SimpleMode2 < Mode::BaseSingle
+      self.mode_name = "Simple"
+      def initialize
+        super
+        add_field Field.create
+        add_player Player.new(field: @fields[0], controller: StandardController.new)
+        assign_pad
+      end
+    end
+  end
+
+  instance = Mode::SimpleMode2.new
+  instance.add_observer(Window::Anything.instance)
+  instance.start
+
+  instance.replay_start
+  instance.start
+end
diff --git a/spec/auto_input_spec.rb b/spec/auto_input_spec.rb
deleted file mode 100644
index 3b86069..0000000
--- a/spec/auto_input_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-require "spec_helper"
-
-describe Handler::AutoInput do
-  it "new" do
-    obj = Handler::AutoInput.new(["udlrABCD", "", "ud"])
-
-    obj.next_frame
-    # UDがあるとLRが無効になる
-
-    obj.to_s.should == "udABCD"
-
-    obj.next_frame
-    obj.to_s.should == ""
-
-    obj.next_frame
-    obj.to_s.should == "ud"
-
-    obj.history.should == ["udABCD", "", "ud"]
-  end
-
-  it "new2" do
-    obj = Handler::AutoInput.new("A B C")
-    3.times{obj.next_frame}
-    obj.history.should == ["A", "B", "C"]
-  end
-
-  it "new3" do
-    obj = Handler::AutoInput.new([""] * 3)
-    3.times{obj.next_frame}
-    obj.history.should == ["", "", ""]
-  end
-end
diff --git a/spec/player_spec.rb b/spec/player_spec.rb
index e3398ee..08494fd 100644
--- a/spec/player_spec.rb
+++ b/spec/player_spec.rb
@@ -14,7 +14,7 @@ def initialize(params = {})
 describe Player do
   def frame_at(tm, dim, input, order, params = {})
     field = Field.new(dim)
-    player = Player.new(field: field, input: Handler::AutoInput.new(input), randomizer: Randomizer::Original.new(order), controller: MockController.new(params))
+    player = Player.new(field: field, input: Handler::Sequencer.new(input), randomizer: Randomizer::Original.new(order), controller: MockController.new(params))
     tm.times { player.next_frame }
     player.put_on
     field.to_s(:compact => true)
diff --git a/spec/react_suppress_spec.rb b/spec/react_suppress_spec.rb
new file mode 100644
index 0000000..81bda7a
--- /dev/null
+++ b/spec/react_suppress_spec.rb
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+require "spec_helper"
+
+describe Handler::ReactSuppress do
+  it "反動抑制が効いている" do
+    input  = ["r", "r", "r", "", "", "l", "l", "", "", "r", "r", "r"]
+    output = ["r", "r", "r", "", "",  "", "l", "", "",  "", "r", "r"]
+    obj = Handler::RsSequencer.new(input)
+    obj.rs.set_param(3, 2, 1)
+    input.each{obj.next_frame}
+    obj.history.should == output
+  end
+end
diff --git a/spec/reaction_suppression_spec.rb b/spec/reaction_suppression_spec.rb
deleted file mode 100644
index f606c6e..0000000
--- a/spec/reaction_suppression_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-require "spec_helper"
-
-describe Handler::ReactionSuppression do
-  it "反動抑制が効いている" do
-    input  = ["r", "r", "r", "", "", "l", "l", "", "", "r", "r", "r"]
-    output = ["r", "r", "r", "", "",  "", "l", "", "",  "", "r", "r"]
-    obj = Handler::RsAutoInput.new(input)
-    obj.rs.set_param(3, 2, 1)
-    input.each{obj.next_frame}
-    obj.history.should == output
-  end
-end
diff --git a/spec/sequencer_spec.rb b/spec/sequencer_spec.rb
new file mode 100644
index 0000000..b86173c
--- /dev/null
+++ b/spec/sequencer_spec.rb
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+require "spec_helper"
+
+describe Handler::Sequencer do
+  it "new" do
+    obj = Handler::Sequencer.new(["udlrABCD", "", "ud"])
+
+    obj.next_frame
+    # UDがあるとLRが無効になる
+
+    obj.to_s.should == "udABCD"
+
+    obj.next_frame
+    obj.to_s.should == ""
+
+    obj.next_frame
+    obj.to_s.should == "ud"
+
+    obj.history.should == ["udABCD", "", "ud"]
+  end
+
+  it "new2" do
+    obj = Handler::Sequencer.new("A B C")
+    3.times{obj.next_frame}
+    obj.history.should == ["A", "B", "C"]
+  end
+
+  it "new3" do
+    obj = Handler::Sequencer.new([""] * 3)
+    3.times{obj.next_frame}
+    obj.history.should == ["", "", ""]
+  end
+end
mode replay refactoring