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