hlockey 4 → 6

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/data/election.json +20 -0
  3. data/data/information.json +5 -0
  4. data/data/league.json +1984 -0
  5. data/data/links.json +5 -0
  6. data/data/previous_election_results.json +98 -0
  7. data/lib/hlockey/actions.rb +22 -0
  8. data/lib/hlockey/constants.rb +6 -0
  9. data/lib/hlockey/data.rb +6 -5
  10. data/lib/hlockey/game/fight.rb +35 -20
  11. data/lib/hlockey/game/weather/audacity.rb +20 -0
  12. data/lib/hlockey/game/weather/chicken.rb +57 -0
  13. data/lib/hlockey/game/weather/incline.rb +43 -0
  14. data/lib/hlockey/game/weather/stars.rb +23 -0
  15. data/lib/hlockey/game/weather/sunset.rb +23 -0
  16. data/lib/hlockey/game/weather/waves.rb +33 -0
  17. data/lib/hlockey/game/weather/weatherable.rb +63 -0
  18. data/lib/hlockey/game/weather.rb +17 -0
  19. data/lib/hlockey/game.rb +123 -89
  20. data/lib/hlockey/league.rb +68 -76
  21. data/lib/hlockey/message.rb +62 -62
  22. data/lib/hlockey/mod/fencebuilder.rb +16 -0
  23. data/lib/hlockey/mod/fencedestroyer.rb +16 -0
  24. data/lib/hlockey/mod/handholding.rb +55 -0
  25. data/lib/hlockey/mod/immaterial.rb +26 -0
  26. data/lib/hlockey/mod/locked.rb +22 -0
  27. data/lib/hlockey/mod/moddable.rb +49 -0
  28. data/lib/hlockey/mod/nonconfrontational.rb +17 -0
  29. data/lib/hlockey/mod/powernapper.rb +46 -0
  30. data/lib/hlockey/mod/punchy.rb +17 -0
  31. data/lib/hlockey/mod.rb +25 -0
  32. data/lib/hlockey/selfdescribable.rb +9 -0
  33. data/lib/hlockey/team/player.rb +58 -0
  34. data/lib/hlockey/team/stadium.rb +52 -0
  35. data/lib/hlockey/team.rb +66 -25
  36. data/lib/hlockey/utils.rb +10 -2
  37. data/lib/hlockey/version.rb +1 -1
  38. metadata +37 -19
  39. data/data/election.yaml +0 -21
  40. data/data/external/names.txt +0 -19948
  41. data/data/information.yaml +0 -24
  42. data/data/league.yaml +0 -1526
  43. data/data/links.yaml +0 -3
  44. data/data/previous_election_results.yaml +0 -59
  45. data/lib/hlockey/game/actions.rb +0 -27
  46. data/lib/hlockey/player.rb +0 -73
  47. data/lib/hlockey/weather.rb +0 -168
data/data/links.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "Website": "https://hlockey.gay",
3
+ "Source Code": "https://codeberg.org/LavenderPerry/hlockey",
4
+ "Discord": "https://discord.gg/2N8VN8Q69E"
5
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "vote_amt": 159,
3
+ "categories": {
4
+ "Bribery (49 votes)": {
5
+ "Winning bribe": {
6
+ "winner": "Mods Help (23 votes)"
7
+ }
8
+ },
9
+ "Treasure (83 votes)": {
10
+ "Dave": {
11
+ "winner": "Pica Acid (2 votes / 21 total)",
12
+ "most_votes": "Sydney Thinkers (6 votes)"
13
+ },
14
+ "Nice": {
15
+ "winner": "Nice Backflippers (2 votes / 15 total)",
16
+ "most_votes": "Dawson City Impostors (7 votes)"
17
+ },
18
+ "Vengabus": {
19
+ "winner": "Antalya Pirates (2 votes / 22 total)",
20
+ "most_votes": "Stony Brook Reapers (11 votes)"
21
+ },
22
+ "Unvengabus": {
23
+ "winner": "Rio de Janeiro Directors (Dry Warm) (0 votes / 0 total)"
24
+ },
25
+ "Shared Training": {
26
+ "winner": "Pompei Eruptions (Dry Warm) (4 votes / 16 total)"
27
+ },
28
+ "Theft": {
29
+ "winner": "Sydney Thinkers (8 votes / 9 total)"
30
+ },
31
+ "Hidden Treasure - Evolve": {
32
+ "winner": "Baden Hallucinations (0 votes / 0 total)"
33
+ }
34
+ },
35
+ "Coaching (27 votes)": {
36
+ "Antalya Pirates": {
37
+ "winner": "Draft (1 vote / 1 total)"
38
+ },
39
+ "Baden Hallucinations": {
40
+ "winner": "Draft (0 votes / 0 total)"
41
+ },
42
+ "Kópavogur Seals": {
43
+ "winner": "Big Gamble (0 votes / 0 total)"
44
+ },
45
+ "Lagos Soup": {
46
+ "winner": "Small Gamble (0 votes / 0 total)"
47
+ },
48
+ "Pica Acid": {
49
+ "winner": "Please Block Shots (2 votes / 2 total)"
50
+ },
51
+ "Dawson City Impostors": {
52
+ "winner": "Draft (4 votes / 4 total)"
53
+ },
54
+ "Erlangen Ohms": {
55
+ "winner": "Please Win Faceoffs (1 vote / 2 total)"
56
+ },
57
+ "Pompei Eruptions": {
58
+ "winner": "Please Win Faceoffs (0 votes / 0 total)"
59
+ },
60
+ "Rio de Janeiro Directors": {
61
+ "winner": "Please Win Faceoffs (1 vote / 1 total)"
62
+ },
63
+ "Wyrzysk Rockets": {
64
+ "winner": "Big Gamble (0 votes / 0 total)"
65
+ },
66
+ "Cape Town Transplants": {
67
+ "winner": "Draft (1 vote / 2 total)"
68
+ },
69
+ "Manbij Fish": {
70
+ "winner": "Draft (1 vote / 1 total)"
71
+ },
72
+ "Nagqu Paint": {
73
+ "winner": "Draft (1 vote / 1 total)"
74
+ },
75
+ "Nice Backflippers": {
76
+ "winner": "Draft (1 vote / 1 total)"
77
+ },
78
+ "Orcadas Base Fog": {
79
+ "winner": "Draft (2 votes / 2 total)"
80
+ },
81
+ "Baghdad Abacuses": {
82
+ "winner": "Clock Unwise (0 votes / 0 total)"
83
+ },
84
+ "Jakarta Architects": {
85
+ "winner": "Clock Wise (0 votes / 0 total)"
86
+ },
87
+ "Kyoto Payphones": {
88
+ "winner": "Small Gamble (1 vote / 2 total)"
89
+ },
90
+ "Stony Brook Reapers": {
91
+ "winner": "Please Win Faceoffs (1 vote / 1 total)"
92
+ },
93
+ "Sydney Thinkers": {
94
+ "winner": "Clock Wise (7 votes / 7 total)"
95
+ }
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,22 @@
1
+ require("hlockey/constants")
2
+
3
+ module Hlockey
4
+ ##
5
+ # For classes that deal with actions within a Hlockey game.
6
+ module Actions
7
+ private
8
+
9
+ # For an event that should happen randomly about a certain amount of times per game,
10
+ # returns if the event should happen or not. Should be called once per action.
11
+ # @param times [Integer] the approximate amount of times the event should occur
12
+ # @return [Boolean] if the event should occur
13
+ def random_event_occurs?(times = 1, prng: @prng) =
14
+ prng.rand(NON_OT_ACTIONS / times).zero?
15
+
16
+ # @param succeed_boost [Numeric] increases chance of action succeeding
17
+ # @param fail_boost [Numeric] decreases chance of action succeeding
18
+ # @return [Boolean] if the action succeeded
19
+ def action_succeeds?(succeed_boost, fail_boost, prng: @prng) =
20
+ prng.rand(20) + (succeed_boost - fail_boost) > 9
21
+ end
22
+ end
@@ -1,4 +1,10 @@
1
1
  module Hlockey
2
2
  UPDATE_FREQUENCY_SECONDS = 5
3
3
  UPDATES_PER_HOUR = 3600 / UPDATE_FREQUENCY_SECONDS
4
+
5
+ ACTIONS_PER_PERIOD = 60
6
+ NON_OT_PERIODS = 3
7
+ NON_OT_ACTIONS = ACTIONS_PER_PERIOD * NON_OT_PERIODS
8
+ TOTAL_ACTIONS = UPDATES_PER_HOUR - ACTIONS_PER_PERIOD
9
+ TOTAL_PERIODS = TOTAL_ACTIONS / ACTIONS_PER_PERIOD
4
10
  end
data/lib/hlockey/data.rb CHANGED
@@ -1,5 +1,4 @@
1
- require("hlockey/team") # Class stored in league data
2
- require("yaml")
1
+ require("json")
3
2
 
4
3
  module Hlockey
5
4
  ##
@@ -8,9 +7,11 @@ module Hlockey
8
7
  class << self
9
8
  data_dir = File.expand_path("../../data", __dir__)
10
9
 
11
- Dir.glob("*.yaml", base: data_dir).each do |data_file|
12
- category = File.basename(data_file, ".yaml")
13
- define_method(category) { YAML.unsafe_load_file("#{data_dir}/#{data_file}") }
10
+ Dir.glob("*.json", base: data_dir).each do |data_file|
11
+ # @return [Hash] loaded data
12
+ define_method(File.basename(data_file, ".json")) do
13
+ JSON.parse(File.read("#{data_dir}/#{data_file}"), symbolize_names: true)
14
+ end
14
15
  end
15
16
  end
16
17
  end
@@ -1,4 +1,4 @@
1
- require("hlockey/game/actions")
1
+ require("hlockey/actions")
2
2
  require("hlockey/message")
3
3
 
4
4
  module Hlockey
@@ -11,18 +11,26 @@ module Hlockey
11
11
  # @return [Hash<Symbol => Array<Player>>] the players in the fight
12
12
  attr_reader(:players)
13
13
 
14
+ # @return [Hash<Symbol => Integer>] the amount of successful punches for each team
15
+ attr_reader(:score)
16
+
14
17
  # @param game [Game] the game the fight is a part of
15
- def initialize(game)
18
+ def initialize(game, starting_player = nil)
16
19
  @home = game.home
17
20
  @away = game.away
18
21
  @prng = game.prng
19
22
  @actions = 0
20
- @players = {
21
- home: [@home.roster.values.sample(random: @prng)],
22
- away: [@away.roster.values.sample(random: @prng)]
23
- }
23
+ @players = { home: [], away: [] }
24
+ @players.each_key do |team|
25
+ add_player(if send(team).roster.value?(starting_player)
26
+ starting_player
27
+ else
28
+ get_joining_player(team)
29
+ end,
30
+ team)
31
+ end
32
+
24
33
  @score = { home: 0, away: 0 }
25
- @in_progress = true
26
34
  end
27
35
 
28
36
  # @return [Message] the message to add to the game stream
@@ -42,18 +50,18 @@ module Hlockey
42
50
  return attack if player_joining.nil?
43
51
  end
44
52
 
45
- @players[team_joining] << player_joining
46
-
47
- Message.PlayerJoinedFight(send(team_joining), player_joining)
53
+ add_player(player_joining, team_joining)
48
54
  else # fight ends
49
- @in_progress = false
50
-
51
55
  Message.FightEnded
52
56
  end
53
57
  end
54
58
 
55
59
  private
56
60
 
61
+ # private readers so #send works
62
+ # @return [Team] a team in the fight
63
+ attr_reader(:home, :away)
64
+
57
65
  # @return [Message] returned by #next_action for same purpose
58
66
  def attack
59
67
  attacking_team = rand_team
@@ -71,21 +79,28 @@ module Hlockey
71
79
  end
72
80
 
73
81
  # @param team [:home, :away]
74
- # @return [Player, nil]
75
- def get_joining_player(team)
82
+ # @return [Team::Player, nil]
83
+ def get_joining_player(team) =
76
84
  (send(team).roster.values - @players[team]).sample(random: @prng)
85
+
86
+ # @param player [Team::Player]
87
+ # @param team [:home, :away]
88
+ # @return [Message] the join message
89
+ def add_player(player, team)
90
+ mods_res = player.mods_do(:on_join_fight)
91
+ player = mods_res if mods_res
92
+
93
+ @players[team] << player
94
+
95
+ Message.PlayerJoinedFight(player)
77
96
  end
78
97
 
79
98
  # @return [:home, :away] randomly selected based on amount of players in fight
80
- def rand_team
81
- rand_is_home? ? :home : :away
82
- end
99
+ def rand_team = rand_is_home? ? :home : :away
83
100
 
84
101
  # @param team [:home, :away]
85
102
  # @return [:home, :away] :away if `team` is :home, :home if `team` is :away
86
- def opposite(team)
87
- team == :home ? :away : :home
88
- end
103
+ def opposite(team) = team == :home ? :away : :home
89
104
 
90
105
  # @return [Boolean] if randomly selected team is home team
91
106
  def rand_is_home?
@@ -0,0 +1,20 @@
1
+ require("hlockey/game/weather/weatherable")
2
+ require("hlockey/actions")
3
+
4
+ module Hlockey
5
+ class Game
6
+ module Weather
7
+ ##
8
+ # Audacity weather
9
+ # Causes players to take shots regardless of the state of the game
10
+ class Audacity
11
+ include(Weatherable)
12
+ include(Actions)
13
+
14
+ def on_action
15
+ @game.send(:shoot, audacity: true) if random_event_occurs?(10)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,57 @@
1
+ require("hlockey/game/weather/weatherable")
2
+ require("hlockey/actions")
3
+ require("hlockey/message")
4
+
5
+ module Hlockey
6
+ class Game
7
+ module Weather
8
+ ##
9
+ # Chicken weather
10
+ # Swaps a random roster player with a random shadow player for the rest of the game
11
+ class Chicken
12
+ include(Weatherable)
13
+ include(Actions)
14
+
15
+ def on_game_start
16
+ @chickened_out = { home: {}, away: {} }
17
+ end
18
+
19
+ def on_action
20
+ return unless random_event_occurs?(5)
21
+
22
+ team = rand_team
23
+ pos, shadows_idx = get_swap(team)
24
+ if pos.nil? || shadows_idx.nil?
25
+ team = team == :home ? :away : :home
26
+ pos, shadows_idx = get_swap(team)
27
+ return if pos.nil? || shadows_idx.nil?
28
+ end
29
+
30
+ @chickened_out[team][pos] = shadows_idx
31
+
32
+ @game.stream << Message.ChickenedOut(*swap(team, pos, shadows_idx))
33
+ end
34
+
35
+ def on_game_end
36
+ @chickened_out.each do |team, swaps|
37
+ swaps.each { |pos, shadows_idx| swap(team, pos, shadows_idx) }
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ # @param team_sym [:home, :away]
44
+ # @return [Array<Symbol, Integer>]
45
+ def get_swap(team_sym)
46
+ team = @game.send(team_sym)
47
+
48
+ [
49
+ (team.roster.keys - @chickened_out[team_sym].keys).sample(random: @prng),
50
+ (team.shadows.each_index.to_a - @chickened_out[team_sym].values)
51
+ .sample(random: @prng)
52
+ ]
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ require("hlockey/game/weather/weatherable")
2
+ require("hlockey/message")
3
+
4
+ module Hlockey
5
+ class Game
6
+ module Weather
7
+ ##
8
+ # Incline weather
9
+ # Adds a random amount of score to a favored team's goals
10
+ class Incline
11
+ include(Weatherable)
12
+
13
+ def on_game_start
14
+ make_incline
15
+ end
16
+
17
+ def on_goal(scoring_team)
18
+ return unless scoring_team == @favored_team
19
+
20
+ @game.score[scoring_team] += @prng.rand(0.1..0.5)
21
+ make_incline
22
+ end
23
+
24
+ def on_action
25
+ return unless @incline_changed
26
+
27
+ @game.stream << Message.InclineFavors(@game.send(@favored_team))
28
+ @incline_changed = false
29
+ end
30
+
31
+ private
32
+
33
+ def make_incline
34
+ new_favored_team = rand_team
35
+ return if new_favored_team == @favored_team
36
+
37
+ @favored_team = new_favored_team
38
+ @incline_changed = true
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ require("hlockey/game/weather/weatherable")
2
+ require("hlockey/message")
3
+
4
+ module Hlockey
5
+ class Game
6
+ module Weather
7
+ ##
8
+ # Stars weather
9
+ # Gives the losing team +0.5 score at the end of each period
10
+ class Stars
11
+ include(Weatherable)
12
+
13
+ def on_period_end
14
+ return if @game.score[:home] == @game.score[:away]
15
+
16
+ team = @game.score.min_by { |_, v| v }.first
17
+ @game.score[team] += 0.5
18
+ @game.stream << Message.StarsAlign(@game.send(team))
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require("hlockey/game/weather/weatherable")
2
+
3
+ module Hlockey
4
+ class Game
5
+ module Weather
6
+ ##
7
+ # Sunset weather
8
+ # Makes each team's goals worth less the more the team scores
9
+ class Sunset
10
+ include(Weatherable)
11
+
12
+ def on_game_start
13
+ @score_amt = { home: 0, away: 0 }
14
+ end
15
+
16
+ def on_goal(scoring_team)
17
+ @score_amt[scoring_team] += 1
18
+ @game.score[scoring_team] -= @score_amt[scoring_team] * 0.3
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ require("hlockey/game/weather/weatherable")
2
+ require("hlockey/actions")
3
+ require("hlockey/message")
4
+
5
+ module Hlockey
6
+ class Game
7
+ module Weather
8
+ ##
9
+ # Waves weather
10
+ # Swaps a roster player (worst most likely) with a random shadow player permanently
11
+ class Waves
12
+ include(Weatherable)
13
+ include(Actions)
14
+
15
+ def on_action
16
+ return unless random_event_occurs?
17
+
18
+ team_sym = rand_team
19
+ team = @game.send(team_sym)
20
+ @game.stream << Message.WavesWashedAway(
21
+ *swap(team_sym,
22
+ if @prng.rand(5).zero?
23
+ team.roster.keys.sample(random: @prng)
24
+ else
25
+ team.worst_player_pos
26
+ end,
27
+ @prng.rand(team.shadows.length))
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,63 @@
1
+ require("hlockey/constants")
2
+ require("hlockey/selfdescribable")
3
+
4
+ module Hlockey
5
+ class Game
6
+ module Weather
7
+ ##
8
+ # Module with needed methods for weathers, that every weather includes
9
+ # All methods starting with "on" represent game events weathers may respond to
10
+ module Weatherable
11
+ include(SelfDescribable)
12
+
13
+ def initialize(game)
14
+ @game = game
15
+ @home = @game.home
16
+ @away = @game.away
17
+ @prng = @game.prng
18
+ end
19
+
20
+ def on_game_start() end
21
+
22
+ def on_game_end() end
23
+
24
+ def on_period_end() end
25
+
26
+ def on_action() end
27
+
28
+ def on_goal(scoring_team) end
29
+
30
+ private
31
+
32
+ # Swaps a roster player with a shadows player
33
+ # @param team_sym [:home, :away]
34
+ # @param pos [Symbol] position of roster player swapped out
35
+ # @param shadows_idx [Integer] index of shadows player swapped in
36
+ # @return [Array<Team::Player>] the players that were swapped
37
+ def swap(team_sym, pos, shadows_idx)
38
+ team = @game.send(team_sym)
39
+
40
+ prev_player = team.roster[pos]
41
+ next_player = team.shadows[shadows_idx]
42
+ team.roster[pos] = next_player
43
+ team.shadows[shadows_idx] = prev_player
44
+
45
+ unless @game.fight.nil?
46
+ player_array = @game.fight.players[team_sym]
47
+ player_idx = player_array.index(prev_player)
48
+
49
+ player_array[player_idx] = next_player unless player_idx.nil?
50
+ end
51
+
52
+ prev_player.mods_do(:on_swap, false, shadows_idx, pos, @prng)
53
+ next_player.mods_do(:on_swap, true, pos, shadows_idx, @prng)
54
+
55
+ [prev_player, next_player]
56
+ end
57
+
58
+ # @return [:home, :away]
59
+ def rand_team = @prng.rand(2).zero? ? :home : :away
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,17 @@
1
+ require("hlockey/game/weather/audacity")
2
+ require("hlockey/game/weather/chicken")
3
+ require("hlockey/game/weather/incline")
4
+ require("hlockey/game/weather/stars")
5
+ require("hlockey/game/weather/sunset")
6
+ require("hlockey/game/weather/waves")
7
+
8
+ module Hlockey
9
+ class Game
10
+ ##
11
+ # Weathers modify the mechanics of a Game
12
+ module Weather
13
+ # Every weather class
14
+ WEATHERS = [Audacity, Chicken, Incline, Stars, Sunset, Waves].freeze
15
+ end
16
+ end
17
+ end