hlockey 0 → 2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/game.rb DELETED
@@ -1,153 +0,0 @@
1
- require_relative "./messages"
2
-
3
- class Game
4
- attr_reader :stream, :in_progress
5
-
6
- def initialize home, away, prng
7
- @stream = [Messages.StartOfGame(to_s)]
8
- @in_progress = true
9
- @home, @away, @prng = [home, away, prng]
10
- @score = {
11
- :home => 0,
12
- :away => 0
13
- }
14
- @actions = 0
15
- @period = 1
16
- @face_off = true
17
- @team_with_puck = nil
18
- @puckless_team = nil
19
- @puck_holder = nil
20
- @shooting_chance = 0
21
- end
22
-
23
- def to_s
24
- puts "#{home.emoji} #{home.name} vs #{away.name} #{away.emoji}"
25
- end
26
-
27
- def update
28
- return unless @in_progress
29
-
30
- @stream << Messages.StartOfPeriod(@period) if @actions == 0
31
- @actions += 1
32
-
33
- if @face_off
34
- if @puck_holder == nil
35
- # Pass opposite team to who wins the puck to switch_team_with_puck,
36
- # so @team_with_puck & @puckless_team are set to the correct values.
37
- switch_team_with_puck(
38
- action_succeeds?(@home.roster[:center].stats[:offense],
39
- @away.roster[:center].stats[:offense]) ? @away : @home)
40
-
41
- @puck_holder = @team_with_puck.roster[:center]
42
- @stream << Messages.FaceOff(@puck_holder.name)
43
- else
44
- pass
45
- @face_off = false
46
- end
47
- return
48
- end
49
-
50
- case @prng.rand 5 + @shooting_chance
51
- when 0..4
52
- pass
53
- when 5..6 # Check
54
- defender = puckless_non_goalie
55
- @stream << Messages.Hit(@puck_holder.name, defender.name,
56
- try_take_puck(defender), 0, :defense)
57
- else # Shoot
58
- unless @shooting_chance < 5 and
59
- try_block_shot @puckless_team.roster[@prng.rand(2) == 0 ? :ldef : :rdef] or
60
- try_block_shot @puckless_team.roster[:goalie]
61
- @score[@team_with_puck == @home ? :home : :away] += 1
62
-
63
- @stream << Messages.Shoot(shooter,
64
- nil, false,
65
- @home.name, @away.name,
66
- *@score.values)
67
-
68
- @shooting_chance = 0
69
- @face_off = true
70
- @actions = 60 if @period > 3 # Sudden death overtime
71
- end
72
- end
73
-
74
- if @actions == 60
75
- @stream << Messages.EndOfPeriod(@period, @home.name, @away.name, *@score.values)
76
- @actions = 0
77
- @period += 1
78
- if @period > 3 and not(@score[:home] == @score[:away] and @period < 12)
79
- # Game is over
80
- @in_progress = false
81
-
82
- winner, loser = case @score[:home] <=> @score[:away]
83
- when 1
84
- [@home, @away]
85
- when -1
86
- [@away, @home]
87
- else # Tie
88
- @stream << Messages.EndOfGame
89
- @home.losses += 1
90
- @away.losses += 1
91
- return
92
- end
93
-
94
- @stream << Messages.EndOfGame(winner.name)
95
- winner.wins += 1
96
- loser.losses += 1
97
- end
98
- end
99
- end
100
-
101
- private
102
- def action_succeeds? helping_stat, hindering_stat
103
- @prng.rand(10) + helping_stat - hindering_stat > 4
104
- end
105
-
106
- def switch_team_with_puck team_with_puck = @team_with_puck
107
- @team_with_puck, @puckless_team = team_with_puck == @home ?
108
- [@away, @home] : [@home, @away]
109
- @shooting_chance = 0
110
- end
111
-
112
- def pass
113
- sender_name = @puck_holder.name
114
- receiver = puckless_non_goalie(@team_with_puck)
115
- interceptor = puckless_non_goalie
116
-
117
- if not @face_off and try_take_puck interceptor, 2 # Pass intercepted
118
- @stream << Message.Pass(sender_name, receiver.name, interceptor)
119
- return
120
- end
121
-
122
- @stream << Message.Pass(sender_name, receiver.name)
123
- @puck_holder = receiver
124
- @shooting_chance += 1
125
- end
126
-
127
- def try_take_puck player, dis = 0, stat = :agility
128
- return false unless action_succeeds?(player.stats[stat] - dis,
129
- @puck_holder.stats[stat])
130
-
131
- switch_team_with_puck
132
- @puck_holder = player
133
-
134
- true
135
- end
136
-
137
- def try_block_shot blocker
138
- return false unless action_succeeds?(blocker.stats[:defense],
139
- @puck_holder.stats[:offense])
140
-
141
- @shooting_chance += 1
142
- @stream << Message.Shoot(@puck_holder, blocker, try_take_puck(blocker))
143
-
144
- true
145
- end
146
-
147
- def puckless_non_goalie team = @puckless_team
148
- team.roster.values.select do |p|
149
- p != team.roster[:goalie] and p != @puck_holder
150
- end.sample random: @prng
151
- end
152
- end
153
-
data/lib/league.rb DELETED
@@ -1,130 +0,0 @@
1
- require_relative "./game"
2
- require_relative "./team"
3
-
4
- class League
5
- attr_reader :day, :divisions, :games_in_progress, :playoff_teams, :champion_team
6
-
7
- def initialize season, start_time
8
- @day = 0
9
- @divisions = {
10
- "Wet Warm": [
11
- Team.new("Antalya Pirates", "🌊"),
12
- Team.new("Baden Hallucinations", "🍄"),
13
- Team.new("Kópavogur Seals", "🦭"),
14
- Team.new("Lagos Soup", "🥣"),
15
- Team.new("Pica Acid", "🧪")
16
- ],
17
- "Dry Warm": [
18
- Team.new("Dawson City Impostors", "🔪"),
19
- Team.new("Erlangen Ohms", "🇴"),
20
- Team.new("Pompei Eruptions", "🌋"),
21
- Team.new("Rio de Janeiro Directors", "🎦"),
22
- Team.new("Wyrzysk Rockets", "🚀")
23
- ],
24
- "Wet Cool": [
25
- Team.new("Cape Town Transplants", "🌱"),
26
- Team.new("Manbij Fish", "🐠"),
27
- Team.new("Nagqu Paint", "🎨"),
28
- Team.new("Nice Backflippers", "🔄"),
29
- Team.new("Orcadas Base Fog", "🌁")
30
- ],
31
- "Dry Cool": [
32
- Team.new("Baghdad Abacuses", "🧮"),
33
- Team.new("Jakarta Architects", "📐"),
34
- Team.new("Kyoto Payphones", "📳"),
35
- Team.new("Stony Brook Reapers", "💀"),
36
- Team.new("Sydney Thinkers", "🤔")
37
- ]
38
- }
39
- @games_in_progress = []
40
- @games = []
41
- @champion_team = nil
42
- @last_update_time = start_time
43
- @passed_updates = 0
44
- @prng = Random.new 69420 * season
45
- @shuffled_teams = @divisions.values.reduce(:+).shuffle random: @prng
46
- @playoff_teams = nil
47
- @game_in_matchup = 3
48
- end
49
-
50
- def update_state
51
- return if @champion_team
52
-
53
- now = Time.now
54
- five_sec_intervals = (now - @last_update_time).floor / 5
55
-
56
- if five_sec_intervals > 0
57
- five_sec_intervals.times do |i|
58
- if (i + @passed_updates) % 720 == 0
59
- new_games
60
- else
61
- update_games
62
- end
63
-
64
- return if @champion_team
65
- end
66
-
67
- @last_update_time = now
68
- @passed_updates += five_sec_intervals
69
- end
70
- end
71
-
72
- private
73
- def new_games
74
- if @game_in_matchup != (@day > 38 ? 5 : 3)
75
- # New game in matchups
76
- @games.map! do |game| Game.new(game.away, game.home, @prng) end
77
- @game_in_matchup += 1
78
- return
79
- end
80
-
81
- # New matchups
82
- @games.clear
83
- @game_in_matchup = 1
84
- @day += 1
85
-
86
- case @day <=> 39
87
- when -1
88
- (@shuffled_teams.length / 2).times do |i|
89
- pair = [@shuffled_teams[i], @shuffled_teams[-i]]
90
- @games << Game.new(*(@day > 19 ? pair : pair.reverse), @prng)
91
- end
92
-
93
- @shuffled_teams.insert 1, @shuffled_teams.pop
94
- when 0
95
- @playoff_teams = Team.sort_teams(
96
- @divisions.values.map do |teams|
97
- Team.sort_teams(teams).first(2)
98
- end.reduce(:+).map &:copy
99
- )
100
-
101
- new_playoff_matchups
102
- when 1
103
- @playoff_teams = Team.sort_teams(@playoff_teams).first(@playoff_teams.length / 2)
104
-
105
- if @playoff_teams.length == 1
106
- @champion_team = @playoff_teams[0]
107
- return
108
- end
109
-
110
- new_playoff_matchups
111
- end
112
- end
113
-
114
- def update_games
115
- @games_in_progress = @games.select do |game| game.in_progress end
116
- @games_in_progress.each do |game| game.update end
117
- end
118
-
119
- def new_playoff_matchups
120
- @playoff_teams.each do |team|
121
- team.wins = 0
122
- team.losses = 0
123
- end
124
-
125
- (0...@playoff_teams.length).step 2 do |i|
126
- @games << Game.new(*@playoff_teams[i, 2], @prng)
127
- end
128
- end
129
- end
130
-
data/lib/messages.rb DELETED
@@ -1,64 +0,0 @@
1
- class Messages
2
- def initialize event, fields, data
3
- @event = event
4
- data_fields.zip data do |(f, d)|
5
- instance_variable_set "@" + f, d
6
- end
7
- end
8
-
9
- private_class_method :new
10
-
11
- [
12
- [:StartOfGame, :title],
13
- [:EndOfGame, :winning_team],
14
- [:StartOfPeriod, :period],
15
- [:EndOfPeriod, :period, :home, :away, :home_score, :away_score],
16
- [:FaceOff, :winning_player],
17
- [:Hit, :puck_holder, :defender, :puck_taken],
18
- [:Pass, :sender, :receiver, :interceptor],
19
- [:Shoot, :shooter, :blocker, :puck_taken, :home, :away, :home_score, :away_score]
20
- ].each do |event, *fields|
21
- define_method event do |*data|
22
- new event, fields, data
23
- end
24
- end
25
-
26
- def to_s
27
- case @event
28
- when :StartOfGame
29
- @title + "\nHocky!"
30
- when :EndOfGame
31
- "Game over.\n#{@winning_team or "Nobody"} wins!"
32
- when :StartOfPeriod
33
- "Start" + of_period
34
- when :EndOfPeriod
35
- "End" + of_period + score
36
- when :FaceOff
37
- @winning_player + " wins the faceoff!"
38
- when :Hit
39
- "#{@defender} hits #{@puck_holder + takes}!"
40
- when :Pass
41
- "#{@sender} passes to #{@receiver}#{@interceptor ?
42
- "... intercepted by #{@interceptor}!" : "."}"
43
- when :Shoot
44
- "#{@shooter} takes a shot... #{@blocker ?
45
- "#{@blocker} blocks the shot#{takes}!" : "and scores!" + score}"
46
- else
47
- raise "Unknown message"
48
- end
49
- end
50
-
51
- private
52
- def of_period
53
- " of period #{@period}."
54
- end
55
-
56
- def score
57
- "\n#{@home} #{@home_score}, #{@away} #{@away_score}"
58
- end
59
-
60
- def takes
61
- @puck_taken ? " and takes the puck" : ""
62
- end
63
- end
64
-
data/lib/player.rb DELETED
@@ -1,41 +0,0 @@
1
- require_relative "./data/names_markov_chain"
2
-
3
- class Player
4
- attr_reader :name, :stats
5
-
6
- @@prng = Random.new 8010897121101114 # This never changes
7
-
8
- def initialize
9
- @name = random_name + " " + random_name
10
- @stats = [:offense, :defense, :agility].each_with_object Hash.new do |stat, hash|
11
- hash[stat] = @@prng.rand * 5
12
- end
13
- end
14
-
15
- private
16
- def random_name
17
- combination = "__"
18
- next_letter = ""
19
- result = ""
20
-
21
- 10.times do
22
- next_letters = NamesMarkovChain[combination]
23
- break if next_letters.nil?
24
-
25
- cumulative_weights = []
26
- next_letters.values.each do |v|
27
- cumulative_weights << v + (cumulative_weights.last or 0)
28
- end
29
- rand_num = @@prng.rand cumulative_weights.last
30
-
31
- next_letter = next_letters.keys[cumulative_weights.index do |n| rand_num < n end]
32
- break if next_letter == "_"
33
-
34
- result += next_letter
35
- combination = combination[1] + next_letter
36
- end
37
-
38
- result
39
- end
40
- end
41
-
data/lib/team.rb DELETED
@@ -1,46 +0,0 @@
1
- require_relative "./player"
2
-
3
- class Team
4
- attr_accessor :wins, :losses
5
- attr_reader :name, :emoji, :roster
6
-
7
- def initialize name, emoji, roster_idxs = {:lwing => 0,
8
- :center => 1,
9
- :rwing => 2,
10
- :ldef => 3,
11
- :goalie => 4,
12
- :rdef => 5}
13
- @wins = 0
14
- @losses = 0
15
- @name, @emoji = [name, emoji]
16
- @roster = {}
17
- players = []
18
- 6.times do players << Player.new end
19
- roster_idxs.each do |pos, i|
20
- @roster[pos] = players[i]
21
- end
22
- end
23
-
24
- def to_s
25
- "#{@emoji} #{@name}"
26
- end
27
-
28
- def print_win_loss
29
- puts " #{to_s.ljust 26} #{@wins}-#{@losses}"
30
- end
31
-
32
- def print_roster
33
- puts to_s
34
- @roster.each do |pos, player|
35
- puts " #{pos.to_s.ljust 6}: #{player.name}"
36
- player.stats.each do |stat, value|
37
- puts " #{stat}: #{value.round 1}"
38
- end
39
- end
40
- end
41
-
42
- def self.sort_teams teams
43
- teams.sort do |a, b| a.wins - a.losses <=> b.wins - b.losses end
44
- end
45
- end
46
-