Class: Mjai::Manue::HoraProbabilityEstimator::Tehais

Inherits:
Object
  • Object
show all
Defined in:
lib/mjai/manue/hora_probability_estimator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scene, remains) ⇒ Tehais

Returns a new instance of Tehais.



41
42
43
44
45
46
47
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 41

def initialize(scene, remains)
  @scene = scene
  @remains = remains
  @shanten_analysis = ShantenAnalysis.new(@remains, @scene.current_shanten, [:normal])
  @progress_prob = get_progress_prob()
  @hora_prob = get_hora_prob()
end

Instance Attribute Details

#hora_probObject (readonly)

Returns the value of attribute hora_prob.



49
50
51
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 49

def hora_prob
  @hora_prob
end

#progress_probObject (readonly)

Returns the value of attribute progress_prob.



49
50
51
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 49

def progress_prob
  @progress_prob
end

Instance Method Details

#get_hora_prob(num_remain_turns = @scene.num_remain_turns) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 51

def get_hora_prob(num_remain_turns = @scene.num_remain_turns)
  return 0.0 if @progress_prob == 0.0
  return 0.0 if num_remain_turns < 0
  shanten = @shanten_analysis.shanten
  hora_prob_on_prog =
      @scene.estimator.get_hora_prob(num_remain_turns - 2, shanten - 1)
  hora_prob_on_no_prog =
      get_hora_prob(num_remain_turns - 2)
  hora_prob = @progress_prob * hora_prob_on_prog +
      (1.0 - @progress_prob) * hora_prob_on_no_prog
  #p [:hora_prob, num_remain_turns, shanten, @progress_prob,
  #    hora_prob, hora_prob_on_prog, hora_prob_on_no_prog]
  return hora_prob
end

#get_pai_prob(pai) ⇒ Object



191
192
193
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 191

def get_pai_prob(pai)
  return (4 - @scene.visible_set[pai]).to_f() / @scene.num_invisible
end

#get_progress_probObject

Probability to decrease >= 1 shanten in 2 turns.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 67

def get_progress_prob()
  
  if @shanten_analysis.shanten > @scene.current_shanten
    return 0.0
  end
  
  #p [:remains, @remains.join(" ")]
  candidates = get_required_pais_candidates()
  
  single_cands = Set.new()
  double_cands = Set.new()
  for pais in candidates
    case pais.size
      when 1
        single_cands.add(pais[0])
      when 2
        double_cands.add(pais)
      else
        raise("should not happen")
    end
  end
  double_cands = double_cands.select() do |pais|
    pais.all?(){ |pai| !single_cands.include?(pai) }
  end
  #p [:single, single_cands.sort().join(" ")]
  #p [:double, double_cands]
  
  # (p, *) or (*, p)
  any_single_prob = single_cands.map(){ |pai| get_pai_prob(pai) }.inject(0.0, :+)
  total_prob = 1.0 - (1.0 - any_single_prob) ** 2
  
  #p [:single_total, total_prob]
  for pai1, pai2 in double_cands
    prob1 = get_pai_prob(pai1)
    #p [:prob, pai1, state]
    prob2 = get_pai_prob(pai2)
    #p [:prob, pai2, state]
    if pai1 == pai2
      # (p1, p1)
      total_prob += prob1 * prob2
    else
      # (p1, p2), (p2, p1)
      total_prob += prob1 * prob2 * 2
    end
  end
  #p [:total_prob, total_prob]
  return total_prob
  
end

#get_required_pais_candidatesObject

Pais required to decrease 1 shanten. Can be multiple pais, but not all multi-pai cases are included.

  • included: 45m for 13m

  • not included: 2m6s for 23m5s



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mjai/manue/hora_probability_estimator.rb', line 121

def get_required_pais_candidates()
  result = Set.new()
  for mentsus in @shanten_analysis.combinations
    for janto_index in [nil] + (0...mentsus.size).to_a()
      t_mentsus = mentsus.dup()
      if janto_index
        next if ![:toitsu, :kotsu].include?(mentsus[janto_index][0])
        t_mentsus.delete_at(janto_index)
      end
      num_required_mentsus = @shanten_analysis.pais.size / 3
      t_shanten =
          -1 +
          (janto_index ? 0 : 1) +
          t_mentsus.
              map(){ |t, ps| 3 - ps.size }.
              sort()[0, num_required_mentsus].
              inject(0, :+)
      #p [:t_shanten, janto_index, t_shanten, @shanten_analysis.shanten]
      next if t_shanten != @shanten_analysis.shanten
      num_groups = t_mentsus.select(){ |t, ps| ps.size >= 2 }.size
      for type, pais in t_mentsus
        rnums_cands = []
        if !janto_index && pais.size == 1
          # 1 -> janto
          rnums_cands.push([0])
        end
        if !janto_index && pais.size == 2 && num_groups > num_required_mentsus
          # 2 -> janto
          case type
            when :ryanpen
              rnums_cands.push([0], [1])
            when :kanta
              rnums_cands.push([0], [2])
          end
        end
        if pais.size == 2
          # 2 -> 3
          case type
            when :ryanpen
              rnums_cands.push([-1], [2])
            when :kanta
              rnums_cands.push([1], [-2, -1], [3, 4])
            when :toitsu
              rnums_cands.push([0], [-2, -1], [-1, 1], [1, 2])
            else
              raise("should not happen")
          end
        end
        if pais.size == 1 && num_groups < num_required_mentsus
          # 1 -> 2
          rnums_cands.push([-2], [-1], [0], [1], [2])
        end
        if pais.size == 1
          # 1 -> 3
          rnums_cands.push([-2, -1], [-1, 1], [1, 2], [0, 0])
        end
        for rnums in rnums_cands
          in_range = rnums.all?() do |rn|
            (rn == 0 || pais[0].type != "t") && (1..9).include?(pais[0].number + rn)
          end
          if in_range
            result.add(rnums.map(){ |rn| Pai.new(pais[0].type, pais[0].number + rn) })
          end
        end
      end
    end
  end
  return result
end