hlockey 4 → 6

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