spy_alley_application 0.3.0

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 (148) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +92 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +39 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/lib/spy_alley_application.rb +6 -0
  13. data/lib/spy_alley_application/actions/buy_equipment.rb +31 -0
  14. data/lib/spy_alley_application/actions/choose_new_spy_identity.rb +26 -0
  15. data/lib/spy_alley_application/actions/choose_space_to_move.rb +21 -0
  16. data/lib/spy_alley_application/actions/confiscate_materials.rb +58 -0
  17. data/lib/spy_alley_application/actions/generate_new_game.rb +70 -0
  18. data/lib/spy_alley_application/actions/make_accusation.rb +40 -0
  19. data/lib/spy_alley_application/actions/pass.rb +21 -0
  20. data/lib/spy_alley_application/actions/roll_die.rb +25 -0
  21. data/lib/spy_alley_application/actions/use_move_card.rb +28 -0
  22. data/lib/spy_alley_application/execute_action.rb +20 -0
  23. data/lib/spy_alley_application/injection_container.rb +596 -0
  24. data/lib/spy_alley_application/models/acquisition_method/by_confiscation.rb +22 -0
  25. data/lib/spy_alley_application/models/acquisition_method/by_free_gift.rb +20 -0
  26. data/lib/spy_alley_application/models/acquisition_method/by_passing_start.rb +20 -0
  27. data/lib/spy_alley_application/models/acquisition_method/by_purchase.rb +21 -0
  28. data/lib/spy_alley_application/models/acquisition_method/by_selling_top_secret_information.rb +21 -0
  29. data/lib/spy_alley_application/models/board_spaces/black_market.rb +24 -0
  30. data/lib/spy_alley_application/models/board_spaces/border_crossing.rb +24 -0
  31. data/lib/spy_alley_application/models/board_spaces/buy_equipment.rb +26 -0
  32. data/lib/spy_alley_application/models/board_spaces/buy_password.rb +26 -0
  33. data/lib/spy_alley_application/models/board_spaces/confiscate_materials.rb +24 -0
  34. data/lib/spy_alley_application/models/board_spaces/draw_free_gift.rb +24 -0
  35. data/lib/spy_alley_application/models/board_spaces/draw_move_card.rb +24 -0
  36. data/lib/spy_alley_application/models/board_spaces/embassy.rb +26 -0
  37. data/lib/spy_alley_application/models/board_spaces/move_back.rb +25 -0
  38. data/lib/spy_alley_application/models/board_spaces/sold_top_secret_information.rb +27 -0
  39. data/lib/spy_alley_application/models/board_spaces/spy_alley_entrance.rb +38 -0
  40. data/lib/spy_alley_application/models/board_spaces/spy_eliminator.rb +24 -0
  41. data/lib/spy_alley_application/models/board_spaces/start.rb +36 -0
  42. data/lib/spy_alley_application/models/board_spaces/take_another_turn.rb +24 -0
  43. data/lib/spy_alley_application/models/equipment.rb +42 -0
  44. data/lib/spy_alley_application/models/game_board.rb +23 -0
  45. data/lib/spy_alley_application/models/game_board/black_market_option_state.rb +59 -0
  46. data/lib/spy_alley_application/models/game_board/buy_equipment_option_state.rb +52 -0
  47. data/lib/spy_alley_application/models/game_board/buy_password_option_state.rb +39 -0
  48. data/lib/spy_alley_application/models/game_board/confiscate_materials_option_state.rb +68 -0
  49. data/lib/spy_alley_application/models/game_board/eliminate_player.rb +91 -0
  50. data/lib/spy_alley_application/models/game_board/embassy_victory.rb +23 -0
  51. data/lib/spy_alley_application/models/game_board/equipment_bought.rb +42 -0
  52. data/lib/spy_alley_application/models/game_board/equipment_confiscated.rb +67 -0
  53. data/lib/spy_alley_application/models/game_board/free_gift_drawn.rb +39 -0
  54. data/lib/spy_alley_application/models/game_board/money_gained_or_lost.rb +22 -0
  55. data/lib/spy_alley_application/models/game_board/move_card_drawn.rb +31 -0
  56. data/lib/spy_alley_application/models/game_board/move_card_used.rb +30 -0
  57. data/lib/spy_alley_application/models/game_board/move_options.rb +23 -0
  58. data/lib/spy_alley_application/models/game_board/new_spy_identity_chosen.rb +37 -0
  59. data/lib/spy_alley_application/models/game_board/next_game_state.rb +70 -0
  60. data/lib/spy_alley_application/models/game_board/player_moved.rb +24 -0
  61. data/lib/spy_alley_application/models/game_board/spy_eliminator_options.rb +41 -0
  62. data/lib/spy_alley_application/models/game_state/buy_equipment.rb +26 -0
  63. data/lib/spy_alley_application/models/game_state/choose_new_spy_identity.rb +29 -0
  64. data/lib/spy_alley_application/models/game_state/confiscate_materials.rb +29 -0
  65. data/lib/spy_alley_application/models/game_state/game_over.rb +27 -0
  66. data/lib/spy_alley_application/models/game_state/move_option.rb +25 -0
  67. data/lib/spy_alley_application/models/game_state/spy_eliminator.rb +25 -0
  68. data/lib/spy_alley_application/models/game_state/start_of_turn.rb +23 -0
  69. data/lib/spy_alley_application/models/game_state/victory_reason/by_elimination.rb +22 -0
  70. data/lib/spy_alley_application/models/game_state/victory_reason/by_embassy.rb +22 -0
  71. data/lib/spy_alley_application/models/move_card.rb +26 -0
  72. data/lib/spy_alley_application/models/player.rb +37 -0
  73. data/lib/spy_alley_application/models/sell_top_secret_information.rb +24 -0
  74. data/lib/spy_alley_application/models/validator/buying_equipment.rb +35 -0
  75. data/lib/spy_alley_application/models/validator/choosing_new_spy_identity.rb +33 -0
  76. data/lib/spy_alley_application/models/validator/confiscating_materials.rb +50 -0
  77. data/lib/spy_alley_application/models/validator/making_accusation.rb +31 -0
  78. data/lib/spy_alley_application/models/validator/moving.rb +30 -0
  79. data/lib/spy_alley_application/models/validator/passing.rb +24 -0
  80. data/lib/spy_alley_application/models/validator/rolling_die.rb +29 -0
  81. data/lib/spy_alley_application/models/validator/using_move_card.rb +31 -0
  82. data/lib/spy_alley_application/models/wild_card.rb +25 -0
  83. data/lib/spy_alley_application/new_game.rb +18 -0
  84. data/lib/spy_alley_application/new_game/assign_seats.rb +21 -0
  85. data/lib/spy_alley_application/new_game/assign_spy_identities.rb +24 -0
  86. data/lib/spy_alley_application/results/nodes/buy_equipment_option_node.rb +23 -0
  87. data/lib/spy_alley_application/results/nodes/choose_new_spy_identity_option_node.rb +23 -0
  88. data/lib/spy_alley_application/results/nodes/confiscate_materials_option_node.rb +22 -0
  89. data/lib/spy_alley_application/results/nodes/die_rolled_node.rb +21 -0
  90. data/lib/spy_alley_application/results/nodes/eliminated_player_node.rb +22 -0
  91. data/lib/spy_alley_application/results/nodes/equipment_gained_node.rb +28 -0
  92. data/lib/spy_alley_application/results/nodes/game_over_node.rb +24 -0
  93. data/lib/spy_alley_application/results/nodes/make_accusation_option_node.rb +20 -0
  94. data/lib/spy_alley_application/results/nodes/money_gained_node.rb +25 -0
  95. data/lib/spy_alley_application/results/nodes/money_lost_node.rb +21 -0
  96. data/lib/spy_alley_application/results/nodes/move_back_node.rb +21 -0
  97. data/lib/spy_alley_application/results/nodes/move_card_drawn_node.rb +22 -0
  98. data/lib/spy_alley_application/results/nodes/move_card_used_node.rb +22 -0
  99. data/lib/spy_alley_application/results/nodes/move_option_node.rb +20 -0
  100. data/lib/spy_alley_application/results/nodes/new_spy_identity_chosen_node.rb +21 -0
  101. data/lib/spy_alley_application/results/nodes/next_player_node.rb +20 -0
  102. data/lib/spy_alley_application/results/nodes/pass_option_node.rb +16 -0
  103. data/lib/spy_alley_application/results/nodes/player_movement_node.rb +21 -0
  104. data/lib/spy_alley_application/results/nodes/player_passed_node.rb +19 -0
  105. data/lib/spy_alley_application/results/nodes/reached_embassy_with_all_equipment_node.rb +20 -0
  106. data/lib/spy_alley_application/results/nodes/result_game_board_node.rb +21 -0
  107. data/lib/spy_alley_application/results/nodes/roll_die_option_node.rb +16 -0
  108. data/lib/spy_alley_application/results/nodes/use_move_card_option_node.rb +20 -0
  109. data/lib/spy_alley_application/results/nodes/wild_card_gained_node.rb +27 -0
  110. data/lib/spy_alley_application/results/process_buy_equipment_options.rb +25 -0
  111. data/lib/spy_alley_application/results/process_eliminating_player.rb +36 -0
  112. data/lib/spy_alley_application/results/process_landing_on_space.rb +232 -0
  113. data/lib/spy_alley_application/results/process_move_options.rb +65 -0
  114. data/lib/spy_alley_application/results/process_next_turn_options.rb +87 -0
  115. data/lib/spy_alley_application/results/process_passing_spaces.rb +68 -0
  116. data/lib/spy_alley_application/results/process_proceeding_to_next_state.rb +23 -0
  117. data/lib/spy_alley_application/types/array_of_equipment.rb +7 -0
  118. data/lib/spy_alley_application/types/array_of_free_gifts.rb +7 -0
  119. data/lib/spy_alley_application/types/array_of_move_cards.rb +6 -0
  120. data/lib/spy_alley_application/types/array_of_players.rb +6 -0
  121. data/lib/spy_alley_application/types/board_space.rb +4 -0
  122. data/lib/spy_alley_application/types/coercible_integer_one_to_six.rb +9 -0
  123. data/lib/spy_alley_application/types/equipment.rb +32 -0
  124. data/lib/spy_alley_application/types/equipment_type.rb +9 -0
  125. data/lib/spy_alley_application/types/free_gift.rb +22 -0
  126. data/lib/spy_alley_application/types/game_board.rb +52 -0
  127. data/lib/spy_alley_application/types/game_state.rb +19 -0
  128. data/lib/spy_alley_application/types/move_card.rb +21 -0
  129. data/lib/spy_alley_application/types/nationality.rb +5 -0
  130. data/lib/spy_alley_application/types/player.rb +123 -0
  131. data/lib/spy_alley_application/types/validation_builder.rb +21 -0
  132. data/lib/spy_alley_application/types/validator/non_admin.rb +21 -0
  133. data/lib/spy_alley_application/types/wild_card.rb +14 -0
  134. data/lib/spy_alley_application/validator/builder.rb +119 -0
  135. data/lib/spy_alley_application/validator/buy_equipment.rb +39 -0
  136. data/lib/spy_alley_application/validator/choose_new_spy_identity.rb +24 -0
  137. data/lib/spy_alley_application/validator/confiscate_materials.rb +22 -0
  138. data/lib/spy_alley_application/validator/confiscate_materials/full_validator.rb +39 -0
  139. data/lib/spy_alley_application/validator/confiscate_materials/validate_target_player_id.rb +24 -0
  140. data/lib/spy_alley_application/validator/make_accusation.rb +24 -0
  141. data/lib/spy_alley_application/validator/move.rb +24 -0
  142. data/lib/spy_alley_application/validator/new_game.rb +35 -0
  143. data/lib/spy_alley_application/validator/new_game_builder.rb +32 -0
  144. data/lib/spy_alley_application/validator/no_options.rb +7 -0
  145. data/lib/spy_alley_application/validator/use_move_card.rb +23 -0
  146. data/lib/spy_alley_application/version.rb +3 -0
  147. data/spy_alley_application.gemspec +40 -0
  148. metadata +343 -0
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-initializer'
4
+
5
+ module SpyAlleyApplication
6
+ module Results
7
+ class ProcessMoveOptions
8
+ include Dry::Initializer.define -> do
9
+ option :move_options, type: ::Types::Callable, reader: :private
10
+ option :process_landing_on_space, type: ::Types::Callable, reader: :private
11
+ option :process_next_turn_options, type: ::Types::Callable, reader: :private
12
+ end
13
+
14
+ def call(game_board:, change_orders:, board_space:, spaces_remaining:)
15
+ space_id_list = [board_space.branch_space, board_space.next_space]
16
+ .map{|space| space_id(space, game_board, spaces_remaining - 1)}
17
+ .reject(&:nil?)
18
+ .freeze
19
+
20
+ if space_id_list.length.eql?(1)
21
+ process_landing_on_space.(
22
+ game_board: game_board,
23
+ change_orders: change_orders,
24
+ space_id: space_id_list.first)
25
+ else
26
+ game_board = move_options.(game_board: game_board, options: space_id_list)
27
+ process_next_turn_options.(game_board: game_board, change_orders: change_orders)
28
+ end
29
+ end
30
+
31
+ # player cannot land on border crossing if cannot pay the toll ($5) to cross the border
32
+ def handle_border_crossing(space, game_board:)
33
+ if game_board.current_player.money < 5
34
+ nil
35
+ else
36
+ space.id
37
+ end
38
+ end
39
+
40
+ # no other such restriction from landing on any other space on the board
41
+ def handle_embassy(space, game_board:)
42
+ space.id
43
+ end
44
+ alias_method :handle_move_back, :handle_embassy
45
+ alias_method :handle_buy_password, :handle_embassy
46
+ alias_method :handle_buy_equipment, :handle_embassy
47
+ alias_method :handle_draw_move_card, :handle_embassy
48
+ alias_method :handle_sold_top_secret_information, :handle_embassy
49
+ alias_method :handle_spy_eliminator, :handle_embassy
50
+ alias_method :handle_confiscate_materials, :handle_embassy
51
+ alias_method :handle_take_another_turn, :handle_embassy
52
+ alias_method :handle_draw_free_gift, :handle_embassy
53
+ alias_method :handle_start, :handle_embassy
54
+ alias_method :handle_black_market, :handle_embassy
55
+ alias_method :handle_spy_alley_entrance, :handle_embassy
56
+
57
+ private
58
+ def space_id(space, game_board, spaces_remaining)
59
+ spaces_remaining.times{space = space.next_space}
60
+ space.accept(self, game_board: game_board)
61
+ end
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-initializer'
4
+
5
+ module SpyAlleyApplication
6
+ module Results
7
+ class ProcessNextTurnOptions
8
+ include Dry::Initializer.define -> do
9
+ option :get_buy_equipment_option_node, type: ::Types::Callable, reader: :private
10
+ option :get_choose_new_spy_identity_option_node, type: ::Types::Callable, reader: :private
11
+ option :get_confiscate_materials_option_node, type: ::Types::Callable, reader: :private
12
+ option :get_make_accusation_option_node, type: ::Types::Callable, reader: :private
13
+ option :get_move_option_node, type: ::Types::Callable, reader: :private
14
+ option :get_next_player_node, type: ::Types::Callable, reader: :private
15
+ option :get_pass_option_node, type: ::Types::Callable, reader: :private
16
+ option :get_roll_die_option_node, type: ::Types::Callable, reader: :private
17
+ option :get_use_move_card_option_node, type: ::Types::Callable, reader: :private
18
+ end
19
+ def call(game_board:, change_orders:, **args)
20
+ game_board.game_state.accept(self, game_board: game_board, change_orders: change_orders)
21
+ end
22
+
23
+ def handle_buy_equipment(game_state, game_board:, change_orders:)
24
+ next_player = game_board.current_player
25
+ change_orders.push(get_next_player_node.(player_id: next_player.id))
26
+ .push(get_buy_equipment_option_node.(
27
+ options: game_state.options,
28
+ limit: game_state.limit))
29
+ .push(get_pass_option_node.())
30
+ end
31
+
32
+ def handle_choose_new_spy_identity(game_state, game_board:, change_orders:)
33
+ next_player = game_board.current_player
34
+ change_orders.push(get_next_player_node.(player_id: next_player.id))
35
+ .push(get_choose_new_spy_identity_option_node.(options: game_state.options))
36
+ end
37
+
38
+ def handle_confiscate_materials(game_state, game_board:, change_orders:)
39
+ next_player = game_board.current_player
40
+ game_state.targets.each do |t|
41
+ change_orders = change_orders.push(get_confiscate_materials_option_node.(
42
+ target_player_id: game_board.players.find{|p| p.seat.eql?(t.seat)}.id,
43
+ targetable_equipment: t.equipment))
44
+ end
45
+ change_orders.push(get_pass_option_node.())
46
+ end
47
+
48
+ def handle_game_over(game_state, game_board:, change_orders:)
49
+ change_orders
50
+ end
51
+
52
+ def handle_move_option(game_state, game_board:, change_orders:)
53
+ next_player = game_board.current_player
54
+ change_orders.push(get_next_player_node.(player_id: next_player.id))
55
+ .push(get_move_option_node.(options: game_state.options))
56
+ end
57
+
58
+ def handle_spy_eliminator(game_state, game_board:, change_orders:)
59
+ next_player = game_board.current_player
60
+ target_ids = game_board.players
61
+ .select{|p| game_state.targetable_seats.include?(p.seat)}
62
+ .map(&:id)
63
+ .sort
64
+ change_orders.push(get_next_player_node.(player_id: next_player.id))
65
+ .push(get_make_accusation_option_node.(player_id_list: target_ids))
66
+ .push(get_pass_option_node.())
67
+ end
68
+
69
+ def handle_start_of_turn(game_state, game_board:, change_orders:)
70
+ next_player = game_board.current_player
71
+ move_cards = next_player.move_cards.map(&:value).sort.uniq
72
+ target_ids = game_board.players.reject{|p| p.id.eql?(next_player.id)}.map(&:id).sort
73
+
74
+ change_orders = change_orders.push(get_next_player_node.(player_id: next_player.id))
75
+ .push(get_roll_die_option_node.())
76
+ .push(get_make_accusation_option_node.(player_id_list: target_ids))
77
+
78
+ if !move_cards.empty?
79
+ change_orders = change_orders.push(get_use_move_card_option_node.(card_list:move_cards))
80
+ end
81
+
82
+ change_orders
83
+ end
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,68 @@
1
+ require 'dry-initializer'
2
+ require 'spy_alley_application/models/game_state/buy_equipment'
3
+
4
+ module SpyAlleyApplication
5
+ module Results
6
+ class ProcessPassingSpaces
7
+ include Dry::Initializer.define -> do
8
+ option :get_money_gained_node, type: ::Types::Callable, reader: :private
9
+ option :money_gained_or_lost, type: ::Types::Callable, reader: :private
10
+ option :process_landing_on_space, type: ::Types::Callable, reader: :private
11
+ option :process_move_options, type: ::Types::Callable, reader: :private
12
+ end
13
+
14
+ def call(game_board:, change_orders:, board_space:, spaces_remaining:)
15
+ board_space = board_space.next_space
16
+ if spaces_remaining.eql?(1)
17
+ process_landing_on_space.(
18
+ game_board: game_board,
19
+ change_orders: change_orders,
20
+ space_id: board_space.id)
21
+ else
22
+ board_space.accept(self,
23
+ game_board: game_board,
24
+ change_orders: change_orders,
25
+ spaces_remaining: spaces_remaining)
26
+ end
27
+ end
28
+
29
+ def handle_start(board_space, game_board:, change_orders:, spaces_remaining:)
30
+ call(game_board: money_gained_or_lost.(game_board: game_board, money_adjustment: 15),
31
+ board_space: board_space,
32
+ spaces_remaining: spaces_remaining - 1,
33
+ change_orders: change_orders.push(get_money_gained_node.(
34
+ player_id: game_board.players.find{|p| p.seat.eql?(game_board.game_state.seat)}.id,
35
+ money_gained: 15,
36
+ reason: {name: 'by_passing_start'})))
37
+ end
38
+
39
+ def handle_spy_alley_entrance(board_space, game_board:, change_orders:, spaces_remaining:)
40
+ process_move_options.(
41
+ game_board: game_board,
42
+ change_orders: change_orders,
43
+ board_space: board_space,
44
+ spaces_remaining: spaces_remaining - 1)
45
+ end
46
+
47
+ def handle_buy_password(board_space, game_board:, change_orders:, spaces_remaining:)
48
+ # no special action, go to the next space
49
+ call(game_board: game_board,
50
+ change_orders: change_orders,
51
+ board_space: board_space,
52
+ spaces_remaining: spaces_remaining - 1)
53
+ end
54
+ alias_method :handle_buy_equipment, :handle_buy_password
55
+ alias_method :handle_black_market, :handle_buy_password
56
+ alias_method :handle_border_crossing, :handle_buy_password
57
+ alias_method :handle_confiscate_materials, :handle_buy_password
58
+ alias_method :handle_draw_free_gift, :handle_buy_password
59
+ alias_method :handle_draw_move_card, :handle_buy_password
60
+ alias_method :handle_embassy, :handle_buy_password
61
+ alias_method :handle_move_back, :handle_buy_password
62
+ alias_method :handle_sold_top_secret_information, :handle_buy_password
63
+ alias_method :handle_spy_eliminator, :handle_buy_password
64
+ alias_method :handle_take_another_turn, :handle_buy_password
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,23 @@
1
+ # require 'dry-initializer'
2
+
3
+ module SpyAlleyApplication
4
+ module Results
5
+ class ProcessProceedingToNextState
6
+ include Dry::Initializer.define -> do
7
+ option :get_result_game_board_node, type: ::Types::Callable, reader: :private
8
+ option :next_game_state, type: ::Types::Callable, reader: :private
9
+ option :process_next_turn_options, type: ::Types::Callable, reader: :private
10
+ end
11
+
12
+ def call(game_board:, change_orders:, target_player_id: nil, **args)
13
+ game_board = next_game_state.(
14
+ game_board: game_board,
15
+ target_player_id: target_player_id)
16
+ process_next_turn_options.(
17
+ game_board: game_board,
18
+ change_orders: change_orders.push(get_result_game_board_node.(game_board: game_board)))
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spy_alley_application/types/equipment'
4
+
5
+ SpyAlleyApplication::Types::ArrayOfEquipment =
6
+ Types::Array::of(SpyAlleyApplication::Types::Equipment)
7
+
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spy_alley_application/types/free_gift'
4
+
5
+ SpyAlleyApplication::Types::ArrayOfFreeGifts =
6
+ Types::Array::of(SpyAlleyApplication::Types::FreeGift)
7
+
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spy_alley_application/types/move_card'
4
+
5
+ SpyAlleyApplication::Types::ArrayOfMoveCards =
6
+ ::Types::Array::of(SpyAlleyApplication::Types::MoveCard)
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spy_alley_application/models/player'
4
+
5
+ SpyAlleyApplication::Types::ArrayOfPlayers =
6
+ Types::Array::of(SpyAlleyApplication::Models::Player)
@@ -0,0 +1,4 @@
1
+ # frozen string literal: true
2
+
3
+ SpyAlleyApplication::Types::BoardSpace =
4
+ ::Types.Interface(:id, :next_space, :accept, :in_spy_alley?)
@@ -0,0 +1,9 @@
1
+ # frozen string literal: true
2
+
3
+ module SpyAlleyApplication
4
+ module Types
5
+ end
6
+ end
7
+
8
+ SpyAlleyApplication::Types::CoercibleIntegerOneToSix =
9
+ ::Types::Coercible::Integer.constrained(included_in: (1..6))
@@ -0,0 +1,32 @@
1
+ # frozen string_literal: true
2
+
3
+ require 'dry-types'
4
+ require 'spy_alley_application/models/equipment'
5
+ require 'spy_alley_application/types/equipment_type'
6
+ require 'spy_alley_application/types/nationality'
7
+
8
+ get_equipment = Hash.new do |h, k|
9
+ nationality, type = k.split(' ')
10
+ h[k] = SpyAlleyApplication::Models::Equipment::new(nationality: nationality, type: type)
11
+ end
12
+
13
+ i = Class.new do
14
+ def initialize(get_equipment)
15
+ @get_equipment = get_equipment
16
+ end
17
+
18
+ def call(equipment)
19
+ if !equipment.to_s.count(' ').eql?(1) || !equipment.to_s.split(' ').count.eql?(2)
20
+ raise Dry::Types::ConstraintError::new(
21
+ 'Equipment string is ill formed', equipment.to_s)
22
+ end
23
+ nationality, type = equipment.to_s.split(' ')
24
+ SpyAlleyApplication::Types::Nationality.call(nationality)
25
+ SpyAlleyApplication::Types::EquipmentType.call(type)
26
+ @get_equipment[equipment.to_s]
27
+ end
28
+ end.new(get_equipment)
29
+
30
+ SpyAlleyApplication::Types::Equipment =
31
+ Types::Constructor(SpyAlleyApplication::Models::Equipment){|value| i.call(value)}
32
+
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SpyAlleyApplication
4
+ module Types
5
+ end
6
+ end
7
+
8
+ SpyAlleyApplication::Types::EquipmentType =
9
+ ::Types::String::enum('password', 'disguise', 'codebook', 'key')
@@ -0,0 +1,22 @@
1
+ # frozen string_literal: true
2
+
3
+ require 'spy_alley_application/types/equipment'
4
+ require 'spy_alley_application/models/wild_card'
5
+
6
+ cached_wild_card = SpyAlleyApplication::Models::WildCard::new
7
+
8
+ i = Class.new do
9
+ def initialize(cached_wild_card)
10
+ @cached_wild_card = cached_wild_card
11
+ end
12
+
13
+ def call(free_gift)
14
+ result = nil
15
+ if free_gift.to_s.eql?('wild card')
16
+ result = @cached_wild_card
17
+ end
18
+ result || SpyAlleyApplication::Types::Equipment.call(free_gift)
19
+ end
20
+ end.new(cached_wild_card)
21
+
22
+ SpyAlleyApplication::Types::FreeGift = Types::Constructor(Class){|value| i.call(value)}
@@ -0,0 +1,52 @@
1
+ # frozen string_literal: true
2
+
3
+ require 'dry-types'
4
+ require 'spy_alley_application/models/game_board'
5
+ require 'spy_alley_application/types/player'
6
+
7
+ i = Class.new do
8
+ def call(game_board)
9
+ game_board[:players] = game_board[:players]&.map do |player|
10
+ SpyAlleyApplication::Types::Player.call(player.to_h)
11
+ end
12
+ game_board = SpyAlleyApplication::Models::GameBoard.call(game_board)
13
+ players = game_board.players
14
+ all_players_have_different_ids_seats_and_spy_identities(players)
15
+ verify_current_seat_is_valid(players, game_board.game_state.seat)
16
+ game_board
17
+ end
18
+
19
+ def all_players_have_different_ids_seats_and_spy_identities(players)
20
+ id_list = []
21
+ seat_list = []
22
+ spy_list = []
23
+ players.each do |player|
24
+ if id_list.include?(player.id)
25
+ raise Dry::Types::ConstraintError::new(
26
+ 'All players have distinct ids', players.map(&:id))
27
+ end
28
+ if seat_list.include?(player.seat)
29
+ raise Dry::Types::ConstraintError::new(
30
+ 'All players have distinct seats', players.map(&:seat))
31
+ end
32
+ if spy_list.include?(player.spy_identity)
33
+ raise Dry::Types::ConstraintError::new(
34
+ 'All players have distinct spy_identities', players.map(&:spy_identity))
35
+ end
36
+ id_list.push player.id
37
+ seat_list.push player.seat
38
+ spy_list.push player.spy_identity
39
+ end
40
+ end
41
+
42
+ def verify_current_seat_is_valid(players, seat)
43
+ seat_list = players.map(&:seat)
44
+ if !seat_list.include?(seat)
45
+ raise Dry::Types::ConstraintError::new(
46
+ "The seat whose turn it is not in the player list (#{seat_list})", seat)
47
+ end
48
+ end
49
+ end.new
50
+
51
+ SpyAlleyApplication::Types::GameBoard = Types::Constructor(Class){|value| i.call(value)}
52
+
@@ -0,0 +1,19 @@
1
+ # frozen string literal: true
2
+
3
+ require 'spy_alley_application/models/game_state/buy_equipment'
4
+ require 'spy_alley_application/models/game_state/choose_new_spy_identity'
5
+ require 'spy_alley_application/models/game_state/confiscate_materials'
6
+ require 'spy_alley_application/models/game_state/game_over'
7
+ require 'spy_alley_application/models/game_state/move_option'
8
+ require 'spy_alley_application/models/game_state/spy_eliminator'
9
+ require 'spy_alley_application/models/game_state/start_of_turn'
10
+
11
+ SpyAlleyApplication::Types::GameState =
12
+ SpyAlleyApplication::Models::GameState::BuyEquipment |
13
+ SpyAlleyApplication::Models::GameState::ChooseNewSpyIdentity |
14
+ SpyAlleyApplication::Models::GameState::ConfiscateMaterials |
15
+ SpyAlleyApplication::Models::GameState::GameOver |
16
+ SpyAlleyApplication::Models::GameState::MoveOption |
17
+ SpyAlleyApplication::Models::GameState::SpyEliminator |
18
+ SpyAlleyApplication::Models::GameState::StartOfTurn
19
+
@@ -0,0 +1,21 @@
1
+ # frozen string_literal: true
2
+
3
+ require 'dry-types'
4
+ require 'spy_alley_application/models/move_card'
5
+ require 'spy_alley_application/types/coercible_integer_one_to_six'
6
+
7
+ get_move_card = Hash.new{|h, k| h[k] = SpyAlleyApplication::Models::MoveCard::new(value: k)}
8
+
9
+ i = Class.new do
10
+ def initialize(get_move_card)
11
+ @get_move_card = get_move_card
12
+ end
13
+
14
+ def call(value)
15
+ value = SpyAlleyApplication::Types::CoercibleIntegerOneToSix.call(value)
16
+ @get_move_card[value]
17
+ end
18
+ end.new(get_move_card)
19
+
20
+ SpyAlleyApplication::Types::MoveCard = ::Types::Constructor(Class){|value| i.call(value)}
21
+