hlockey 0 → 2

Sign up to get free protection for your applications and to get access to all the features.
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
-