summaryrefslogtreecommitdiff
path: root/app/models/ptu_pokemon.rb
blob: 6074fcd2e7cd120cdf1125a1bfb93f1fc1df30d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class PtuPokemon < ApplicationRecord
  validates :name, uniqueness: true
  validates :name, :base_hp, :base_atk, :base_def, :base_spatk, :base_spdef, :base_speed, presence: true
  validates :male_chance, inclusion: 0..100, allow_nil: true

  def female_chance
    (100.0 - self.male_chance) if self.male_chance
  end

  def gender_ratio_string
    if self.male_chance
      "Male #{self.male_chance}% / Female #{self.female_chance}%"
    else
      "No gender"
    end
  end

  def random_stat_hash(level: 1)
    nature = PtuNature.find(PtuNature.pluck(:id).sample)
    if self.male_chance
      gender = 1 + rand(100) <= self.male_chance ? "Male" : "Female"
    else
      gender = "No gender"
    end
    hash = {
      name: self.name,
      level: level,
      gender: gender,
      nature: nature.name,
      base_stats: {
        hp: self.base_hp,
        atk: self.base_atk,
        def: self.base_def,
        spatk: self.base_spatk,
        spdef: self.base_spdef,
        speed: self.base_speed,
      },
      stats: {},
    }

    # Adjust base stats for nature
    hash[:base_stats][nature.raises.to_sym] += nature.raises.to_sym == :hp ? 1 : 2
    hash[:base_stats][nature.lowers.to_sym] -= nature.lowers.to_sym == :hp ? 1 : 2
    hash[:base_stats][nature.lowers.to_sym] = [1, hash[:base_stats][nature.lowers.to_sym]].max

    # e.g. [[:speed, 9], [:atk, 8], [:def, 8], [:spatk, 6], [:spdef, 6], [:hp, 5]]
    sorted_base_stats = hash[:base_stats].sort_by { |_, v| -v }

    rank = 1
    # e.g. [1, 2, 2, 4, 4, 6]
    rankings_array = sorted_base_stats.each_with_index.map { |a, i| sorted_base_stats[i - 1][1] == a[1] ? rank : (rank = i + 1) }

    # e.g. {:speed=>1, :atk=>2, :def=>2, :spatk=>4, :spdef=>4, :hp=>6}
    base_stat_rankings = Hash[sorted_base_stats.map { |s| s[0] }.zip(rankings_array)]

    hash[:stats] = hash[:base_stats].deep_dup
    points_to_assign = 10 + level
    points_to_assign.times do
      loop do
        stat = hash[:stats].keys.sample
        higher_base_stats = base_stat_rankings.select { |_, v| v < base_stat_rankings[stat] }.keys
        if higher_base_stats.select { |s| hash[:stats][s] <= (hash[:stats][stat] + 1) }.any?
          next
        else
          hash[:stats][stat] += 1 and break
        end
      end
    end

    hash[:hit_points] = 10 + level + (hash[:stats][:hp] * 3)

    hash
  end
end