hlockey 6 → 7
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.
- checksums.yaml +4 -4
- data/data/election.json +6 -3
- data/data/infinileague.json +189 -0
- data/data/information.json +2 -1
- data/data/league.json +789 -731
- data/data/messages.json +46 -0
- data/data/previous_election_results.json +32 -39
- data/lib/hlockey/game/fight.rb +78 -29
- data/lib/hlockey/game/weather/chicken.rb +2 -1
- data/lib/hlockey/game/weather/incline.rb +2 -1
- data/lib/hlockey/game/weather/stars.rb +1 -1
- data/lib/hlockey/game/weather/sunset.rb +1 -3
- data/lib/hlockey/game/weather/waves.rb +7 -9
- data/lib/hlockey/game/weather/weatherable.rb +4 -4
- data/lib/hlockey/game.rb +156 -115
- data/lib/hlockey/league.rb +47 -27
- data/lib/hlockey/message.rb +23 -151
- data/lib/hlockey/mod/fencebuilder.rb +1 -2
- data/lib/hlockey/mod/fencedestroyer.rb +1 -1
- data/lib/hlockey/mod/handholding.rb +18 -16
- data/lib/hlockey/mod/immaterial.rb +7 -5
- data/lib/hlockey/mod/locked.rb +9 -3
- data/lib/hlockey/mod/moddable.rb +25 -4
- data/lib/hlockey/mod/powernapper.rb +11 -7
- data/lib/hlockey/mod/punchy.rb +6 -2
- data/lib/hlockey/selfdescribable.rb +1 -3
- data/lib/hlockey/team/player.rb +3 -0
- data/lib/hlockey/team.rb +3 -3
- data/lib/hlockey/utils.rb +36 -4
- data/lib/hlockey/version.rb +1 -1
- data/lib/hlockey.rb +15 -0
- metadata +6 -4
data/data/messages.json
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"season_day": "Season %{season} day %{day}",
|
3
|
+
"season_starts": "Season %{season} starts at %{time}.",
|
4
|
+
"season_champion": "Your season %{season} champions are the %{team}!",
|
5
|
+
"season_off": "no games right now. it is the offseason. join the Hlockey Discord for updates.",
|
6
|
+
|
7
|
+
"game_start": "Hocky!",
|
8
|
+
"game_end": "Game over.\n%{winning_team} win!",
|
9
|
+
"game_score": "%{home} %{home_score}, %{away} %{away_score}",
|
10
|
+
"game_period_start": "Start of period %{period}.",
|
11
|
+
"game_period_end": "End of period %{period}.",
|
12
|
+
"game_faceoff": "%{winning_player} wins the faceoff!",
|
13
|
+
"game_pass": "%{sender} passes to %{receiver}.",
|
14
|
+
"game_pass_intercept": "%{sender}'s pass to %{receiver} is intercepted by %{interceptor}!",
|
15
|
+
"game_hit": "%{defender} hits %{puck_holder}.",
|
16
|
+
"game_shot": "%{shooter} takes a shot...",
|
17
|
+
"game_shot_audacious": "%{shooter} takes an audacious shot...",
|
18
|
+
"game_shot_scored": "%{shooter} scores!",
|
19
|
+
"game_shot_blocked": "%{blocker} blocks the shot.",
|
20
|
+
"game_partying": "%{player} is partying!",
|
21
|
+
"game_possession_change": "%{player} takes the puck!\n%{new_puck_team} have possession.",
|
22
|
+
|
23
|
+
"fight_start": "%{home_player} and %{away_player} start fighting!",
|
24
|
+
"fight_player_join": "%{player} from %{team} joins the fight!",
|
25
|
+
"fight_player_withdraw": "%{player} withdraws from the fight!",
|
26
|
+
"fight_attack": "%{player} is going for a punch...",
|
27
|
+
"fight_hit": "The punch lands to hit %{player}!",
|
28
|
+
"fight_block": "%{player} blocks the punch!",
|
29
|
+
"fight_dodge": "%{player} dodges the punch!",
|
30
|
+
"fight_end": "The fight has ended.",
|
31
|
+
"fight_end_morale_gain": "%{team} gains %{num} morale.",
|
32
|
+
"fight_end_morale_loss": "%{team} loses %{num} morale.",
|
33
|
+
|
34
|
+
"weather_chicken_event": "%{prev_player} chickened out!\nReplaced by %{next_player} for the game.",
|
35
|
+
"weather_incline_event": "The incline favors %{team}.",
|
36
|
+
"weather_stars_event": "The stars align for %{team}. They get half a goal.",
|
37
|
+
"weather_waves_event": "%{prev_player} is washed away by the waves...\nReplaced by %{next_player} for the season.",
|
38
|
+
|
39
|
+
"mod_immaterial_event": "%{hitting_player} goes right through %{player}!",
|
40
|
+
"mod_fence_event": "%{player} is a fence%{type}.\n%{player} swaps with %{swap_player} instead.",
|
41
|
+
"mod_handholding_event": "%{player} is holding %{other_player}'s hand.\n%{other_player} follows %{player} by swapping with %{swap_player}.",
|
42
|
+
"mod_locked_event": "%{player} is locked and does not get swapped with %{swap_player}",
|
43
|
+
"mod_powernap_start": "%{player} gets a boost from powernapping!",
|
44
|
+
"mod_powernap_end": "%{player}'s powernap boost has ended.",
|
45
|
+
"mod_punchy_event": "%{player} is looking for a fight..."
|
46
|
+
}
|
@@ -1,35 +1,28 @@
|
|
1
1
|
{
|
2
|
-
"vote_amt":
|
2
|
+
"vote_amt": 91,
|
3
3
|
"categories": {
|
4
|
-
"
|
5
|
-
"Winning bribe": {
|
6
|
-
"winner": "Mods Help (23 votes)"
|
7
|
-
}
|
8
|
-
},
|
9
|
-
"Treasure (83 votes)": {
|
4
|
+
"Treasure (64 votes)": {
|
10
5
|
"Dave": {
|
11
|
-
"winner": "
|
12
|
-
"most_votes": "Sydney Thinkers (6 votes)"
|
6
|
+
"winner": "Cape Town Transplants (2 votes / 7 total)"
|
13
7
|
},
|
14
8
|
"Nice": {
|
15
|
-
"winner": "
|
16
|
-
"most_votes": "Dawson City Impostors (
|
9
|
+
"winner": "Stony Brook Reapers (1 vote / 15 total)",
|
10
|
+
"most_votes": "Dawson City Impostors (9 votes)"
|
17
11
|
},
|
18
12
|
"Vengabus": {
|
19
|
-
"winner": "
|
20
|
-
"most_votes": "
|
21
|
-
},
|
22
|
-
"Unvengabus": {
|
23
|
-
"winner": "Rio de Janeiro Directors (Dry Warm) (0 votes / 0 total)"
|
13
|
+
"winner": "Stony Brook Reapers (1 vote / 11 total)",
|
14
|
+
"most_votes": "Rio de Janeiro Directors (4 votes)"
|
24
15
|
},
|
25
16
|
"Shared Training": {
|
26
|
-
"winner": "Pompei Eruptions (Dry Warm) (
|
17
|
+
"winner": "Pompei Eruptions (Dry Warm) (1 votes / 15 total)",
|
18
|
+
"most_votes": "Kyoto Payphones (3 votes)"
|
27
19
|
},
|
28
20
|
"Theft": {
|
29
|
-
"winner": "
|
21
|
+
"winner": "Baden Hallucinations (1 vote / 14 total)",
|
22
|
+
"most_votes": "Rio de Janeiro Directors (3 votes)"
|
30
23
|
},
|
31
|
-
"
|
32
|
-
"winner": "
|
24
|
+
"Shadow Lock": {
|
25
|
+
"winner": "Nagqu Paint (2 votes / 2 total)"
|
33
26
|
}
|
34
27
|
},
|
35
28
|
"Coaching (27 votes)": {
|
@@ -37,62 +30,62 @@
|
|
37
30
|
"winner": "Draft (1 vote / 1 total)"
|
38
31
|
},
|
39
32
|
"Baden Hallucinations": {
|
40
|
-
"winner": "Draft (
|
33
|
+
"winner": "Draft (2 votes / 2 total)"
|
41
34
|
},
|
42
35
|
"Kópavogur Seals": {
|
43
|
-
"winner": "
|
36
|
+
"winner": "Please Block Shots (0 votes / 0 total)"
|
44
37
|
},
|
45
38
|
"Lagos Soup": {
|
46
39
|
"winner": "Small Gamble (0 votes / 0 total)"
|
47
40
|
},
|
48
41
|
"Pica Acid": {
|
49
|
-
"winner": "
|
42
|
+
"winner": "Big Gamble (0 votes / 0 total)"
|
50
43
|
},
|
51
44
|
"Dawson City Impostors": {
|
52
|
-
"winner": "
|
45
|
+
"winner": "Please Block Shots (2 votes / 5 total)"
|
53
46
|
},
|
54
47
|
"Erlangen Ohms": {
|
55
|
-
"winner": "
|
48
|
+
"winner": "Clock Wise (1 vote / 1 total)"
|
56
49
|
},
|
57
50
|
"Pompei Eruptions": {
|
58
|
-
"winner": "Please Win Faceoffs (
|
51
|
+
"winner": "Please Win Faceoffs (1 vote / 1 total)"
|
59
52
|
},
|
60
53
|
"Rio de Janeiro Directors": {
|
61
|
-
"winner": "Please Win Faceoffs (
|
54
|
+
"winner": "Please Win Faceoffs (3 votes / 3 total)"
|
62
55
|
},
|
63
56
|
"Wyrzysk Rockets": {
|
64
|
-
"winner": "
|
57
|
+
"winner": "Revolution (0 votes / 0 total)"
|
65
58
|
},
|
66
59
|
"Cape Town Transplants": {
|
67
|
-
"winner": "
|
60
|
+
"winner": "Small Gamble (0 votes / 0 total)"
|
68
61
|
},
|
69
62
|
"Manbij Fish": {
|
70
|
-
"winner": "
|
63
|
+
"winner": "Clock Wise (0 votes / 0 total)"
|
71
64
|
},
|
72
65
|
"Nagqu Paint": {
|
73
|
-
"winner": "
|
66
|
+
"winner": "Please Win Faceoffs (1 vote / 1 total)"
|
74
67
|
},
|
75
68
|
"Nice Backflippers": {
|
76
|
-
"winner": "
|
69
|
+
"winner": "Please Block Shots (1 vote / 1 total)"
|
77
70
|
},
|
78
71
|
"Orcadas Base Fog": {
|
79
|
-
"winner": "
|
72
|
+
"winner": "Small Gamble (1 vote / 1 total)"
|
80
73
|
},
|
81
74
|
"Baghdad Abacuses": {
|
82
|
-
"winner": "
|
75
|
+
"winner": "Please Win Faceoffs (0 votes / 0 total)"
|
83
76
|
},
|
84
77
|
"Jakarta Architects": {
|
85
|
-
"winner": "
|
78
|
+
"winner": "Please Win Faceoffs (0 votes / 0 total)"
|
86
79
|
},
|
87
80
|
"Kyoto Payphones": {
|
88
|
-
"winner": "
|
81
|
+
"winner": "Big Gamble (6 votes / 6 total)"
|
89
82
|
},
|
90
83
|
"Stony Brook Reapers": {
|
91
|
-
"winner": "
|
84
|
+
"winner": "Clock Unwise (1 vote / 1 total)"
|
92
85
|
},
|
93
86
|
"Sydney Thinkers": {
|
94
|
-
"winner": "
|
87
|
+
"winner": "Draft (3 votes / 4 total)"
|
95
88
|
}
|
96
89
|
}
|
97
90
|
}
|
98
|
-
}
|
91
|
+
}
|
data/lib/hlockey/game/fight.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require("hlockey/actions")
|
2
2
|
require("hlockey/message")
|
3
|
+
require("hlockey/mod/punchy")
|
3
4
|
|
4
5
|
module Hlockey
|
5
6
|
class Game
|
@@ -8,21 +9,20 @@ module Hlockey
|
|
8
9
|
class Fight
|
9
10
|
include(Actions)
|
10
11
|
|
11
|
-
# @return [Hash<Symbol => Array<Player>>] the players in the fight
|
12
|
+
# @return [Hash<Symbol => Array<Team::Player>>] the players in the fight
|
12
13
|
attr_reader(:players)
|
13
14
|
|
14
15
|
# @return [Hash<Symbol => Integer>] the amount of successful punches for each team
|
15
16
|
attr_reader(:score)
|
16
17
|
|
17
18
|
# @param game [Game] the game the fight is a part of
|
19
|
+
# @param starting_player [Team::Player] the player that started the fight, if any
|
18
20
|
def initialize(game, starting_player = nil)
|
19
|
-
@
|
20
|
-
@away = game.away
|
21
|
-
@prng = game.prng
|
21
|
+
@game = game
|
22
22
|
@actions = 0
|
23
23
|
@players = { home: [], away: [] }
|
24
24
|
@players.each_key do |team|
|
25
|
-
add_player(if send(team).roster.value?(starting_player)
|
25
|
+
add_player(if @game.send(team).roster.value?(starting_player)
|
26
26
|
starting_player
|
27
27
|
else
|
28
28
|
get_joining_player(team)
|
@@ -33,11 +33,19 @@ module Hlockey
|
|
33
33
|
@score = { home: 0, away: 0 }
|
34
34
|
end
|
35
35
|
|
36
|
-
# @return [Message] the message to add to the game stream
|
37
36
|
def next_action
|
38
37
|
@actions += 1
|
39
38
|
|
40
|
-
|
39
|
+
# If fight has a single player on one side who is outnumbered,
|
40
|
+
# there is a chance that player will withdraw, ending the fight.
|
41
|
+
if @players[:home].length == 1
|
42
|
+
return if @players[:away].length > 1 && player_withdraws?(@players[:home].first,
|
43
|
+
:home)
|
44
|
+
elsif @players[:away].length == 1
|
45
|
+
return if player_withdraws?(@players[:away].first, :away)
|
46
|
+
end
|
47
|
+
|
48
|
+
case @game.prng.rand(@actions)
|
41
49
|
when 0..3 # attack
|
42
50
|
attack
|
43
51
|
when 4..7 # player joins
|
@@ -47,52 +55,93 @@ module Hlockey
|
|
47
55
|
if player_joining.nil?
|
48
56
|
team_joining = opposite(team_joining)
|
49
57
|
player_joining = get_joining_player(team_joining)
|
50
|
-
|
58
|
+
if player_joining.nil?
|
59
|
+
attack
|
60
|
+
return
|
61
|
+
end
|
51
62
|
end
|
52
63
|
|
53
64
|
add_player(player_joining, team_joining)
|
54
65
|
else # fight ends
|
55
|
-
Message.
|
66
|
+
@game.stream << Message.new(:fight_end)
|
56
67
|
end
|
57
68
|
end
|
58
69
|
|
59
70
|
private
|
60
71
|
|
61
|
-
# private readers so #send works
|
62
|
-
# @return [Team] a team in the fight
|
63
|
-
attr_reader(:home, :away)
|
64
|
-
|
65
|
-
# @return [Message] returned by #next_action for same purpose
|
66
72
|
def attack
|
67
73
|
attacking_team = rand_team
|
68
74
|
defending_team = opposite(attacking_team)
|
69
75
|
|
70
|
-
attacking_player = @players[attacking_team].sample(random: @prng)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
attacking_player = @players[attacking_team].sample(random: @game.prng)
|
77
|
+
@game.stream << Message.new(:fight_attack, player: attacking_player)
|
78
|
+
|
79
|
+
defending_player = @players[defending_team].sample(random: @game.prng)
|
80
|
+
|
81
|
+
if action_succeeds?(defending_player.stats[:defense],
|
82
|
+
defending_player.stats[:agility],
|
83
|
+
prng: @game.prng)
|
84
|
+
# Try to block the punch
|
85
|
+
if action_succeeds?(defending_player.stats[:defense],
|
86
|
+
attacking_player.stats[:offense],
|
87
|
+
prng: @game.prng)
|
88
|
+
# Punch sucessfully blocked
|
89
|
+
@game.stream << Message.new(:fight_block, player: defending_player)
|
90
|
+
return
|
91
|
+
end
|
92
|
+
# Try to dodge the punch
|
93
|
+
elsif action_succeeds?(defending_player.stats[:agility],
|
94
|
+
attacking_player.stats[:offense],
|
95
|
+
prng: @game.prng)
|
96
|
+
# Punch sucessfully dodged
|
97
|
+
@game.stream << Message.new(:fight_dodge, player: defending_player)
|
98
|
+
return
|
99
|
+
end
|
77
100
|
|
78
|
-
|
101
|
+
# Punch lands
|
102
|
+
@game.stream << Message.new(:fight_hit, player: defending_player)
|
103
|
+
@score[attacking_team] += 1
|
104
|
+
player_withdraws?(defending_player, defending_team)
|
79
105
|
end
|
80
106
|
|
81
107
|
# @param team [:home, :away]
|
82
108
|
# @return [Team::Player, nil]
|
83
109
|
def get_joining_player(team) =
|
84
|
-
(send(team).roster.values - @players[team]).sample(random: @prng)
|
110
|
+
(@game.send(team).roster.values - @players[team]).sample(random: @game.prng)
|
85
111
|
|
86
112
|
# @param player [Team::Player]
|
87
113
|
# @param team [:home, :away]
|
88
|
-
# @return [Message] the join message
|
89
114
|
def add_player(player, team)
|
115
|
+
@game.stream << Message.new(:fight_player_join, player:, team: player.team)
|
116
|
+
|
90
117
|
mods_res = player.mods_do(:on_join_fight)
|
91
|
-
player
|
118
|
+
if mods_res # Mod would return a joining player to replace them
|
119
|
+
@game.stream << Message.new(:fight_player_withdraw, player:)
|
120
|
+
player = mods_res
|
121
|
+
@game.stream << Message.new(:fight_player_join, player:, team: player.team)
|
122
|
+
end
|
92
123
|
|
93
124
|
@players[team] << player
|
125
|
+
end
|
126
|
+
|
127
|
+
# @param player [Team::Player]
|
128
|
+
# @param team [:home, :away]
|
129
|
+
# @return [Boolean] if the player withdrew
|
130
|
+
def player_withdraws?(player, team)
|
131
|
+
return false unless player.mods.none? { _1.is_a?(Mod::Punchy) } &&
|
132
|
+
@game.prng.rand(50).zero?
|
133
|
+
|
134
|
+
# Player withdraws
|
135
|
+
@game.stream << Message.new(:fight_player_withdraw, player:)
|
136
|
+
@players[team].delete(player)
|
137
|
+
|
138
|
+
if @players[team].empty?
|
139
|
+
@game.stream << Message.new(:fight_end)
|
140
|
+
@score[team] = 0
|
141
|
+
@score[opposite(team)] = 10
|
142
|
+
end
|
94
143
|
|
95
|
-
|
144
|
+
true
|
96
145
|
end
|
97
146
|
|
98
147
|
# @return [:home, :away] randomly selected based on amount of players in fight
|
@@ -104,10 +153,10 @@ module Hlockey
|
|
104
153
|
|
105
154
|
# @return [Boolean] if randomly selected team is home team
|
106
155
|
def rand_is_home?
|
107
|
-
home_player_amount = @home.roster.values.length
|
108
|
-
away_player_amount = @away.roster.values.length
|
156
|
+
home_player_amount = @game.home.roster.values.length
|
157
|
+
away_player_amount = @game.away.roster.values.length
|
109
158
|
|
110
|
-
@prng.rand(home_player_amount + away_player_amount) < home_player_amount
|
159
|
+
@game.prng.rand(home_player_amount + away_player_amount) < home_player_amount
|
111
160
|
end
|
112
161
|
end
|
113
162
|
end
|
@@ -24,7 +24,8 @@ module Hlockey
|
|
24
24
|
def on_action
|
25
25
|
return unless @incline_changed
|
26
26
|
|
27
|
-
@game.stream << Message.
|
27
|
+
@game.stream << Message.new(:weather_incline_event,
|
28
|
+
team: @game.send(@favored_team))
|
28
29
|
@incline_changed = false
|
29
30
|
end
|
30
31
|
|
@@ -17,15 +17,13 @@ module Hlockey
|
|
17
17
|
|
18
18
|
team_sym = rand_team
|
19
19
|
team = @game.send(team_sym)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@prng.rand(team.shadows.length))
|
28
|
-
)
|
20
|
+
player_leaving_pos = if @prng.rand(5).zero?
|
21
|
+
team.roster.keys.sample(random: @prng)
|
22
|
+
else
|
23
|
+
team.worst_player_pos
|
24
|
+
end
|
25
|
+
swap_res = swap(team_sym, player_leaving_pos, @prng.rand(team.shadows.length))
|
26
|
+
@game.stream << Message.new(:weather_waves_event, **swap_res)
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
@@ -33,7 +33,7 @@ module Hlockey
|
|
33
33
|
# @param team_sym [:home, :away]
|
34
34
|
# @param pos [Symbol] position of roster player swapped out
|
35
35
|
# @param shadows_idx [Integer] index of shadows player swapped in
|
36
|
-
# @return [
|
36
|
+
# @return [Hash<[:prev_player, :next_player] => Team::Player>] the swapped players
|
37
37
|
def swap(team_sym, pos, shadows_idx)
|
38
38
|
team = @game.send(team_sym)
|
39
39
|
|
@@ -49,10 +49,10 @@ module Hlockey
|
|
49
49
|
player_array[player_idx] = next_player unless player_idx.nil?
|
50
50
|
end
|
51
51
|
|
52
|
-
prev_player.mods_do(:on_swap, false, shadows_idx, pos
|
53
|
-
next_player.mods_do(:on_swap, true, pos, shadows_idx
|
52
|
+
prev_player.mods_do(:on_swap, false, shadows_idx, pos)
|
53
|
+
next_player.mods_do(:on_swap, true, pos, shadows_idx)
|
54
54
|
|
55
|
-
|
55
|
+
{ prev_player:, next_player: }
|
56
56
|
end
|
57
57
|
|
58
58
|
# @return [:home, :away]
|