rochambeau 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0c507e4a422648c5da20a64647fa103c302426fe0d4d891e1d3f9669a60abc2c
4
+ data.tar.gz: 699067dee47107c716c00f539180878f377ee17802ab0d71f211ff51401ffd61
5
+ SHA512:
6
+ metadata.gz: 4198c70160ce838c5ee79a948f7cc0b87fccc9504d483d19f972d476498ae33cf48dc43054ba0bfdda93521a39a7d2fac35a71ecba873375aa6525357c426013
7
+ data.tar.gz: d2d014b7840d76cd97c545bfed97e7b8bad3b6d5a716e96b5de2f08ead56b7b978a85a236ab131fc609de750c368588ae70754d7381c21ba04b51bafa34e9296
data/lib/rochambeau.rb ADDED
@@ -0,0 +1,11 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ class Rochambeau
5
+ extend T::Sig
6
+
7
+ VERSION = '1.9'
8
+
9
+ class InvalidOptionError < StandardError
10
+ end
11
+ end
@@ -0,0 +1,70 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../rochambeau'
5
+ require_relative '../rochambeau/option'
6
+ require_relative '../rochambeau/game_mode'
7
+
8
+ class Rochambeau
9
+ class Cli < Thor
10
+ extend T::Sig
11
+
12
+ desc 'version', 'Display version information.'
13
+ sig { void }
14
+ def version
15
+ puts <<~VERSION
16
+ Rochambeau #{Rochambeau::VERSION}
17
+ GitHub: https://github.com/jigarius/rochambeau
18
+ VERSION
19
+ end
20
+
21
+ desc 'play', 'Play Rock-Paper-Scissors.'
22
+ option 'advanced',
23
+ aliases: ['a'],
24
+ type: :boolean,
25
+ default: false,
26
+ desc: 'Advanced mode contains the options "Lizard" and "Spock".'
27
+ sig { void }
28
+ def play
29
+ system 'clear'
30
+
31
+ game_mode =
32
+ options.advanced ? GameMode::ADVANCED : GameMode::BASIC
33
+
34
+ choice = input_choice(game_mode)
35
+ random = T.cast(game_mode.options.sample, Option)
36
+
37
+ puts '------'
38
+ puts "Bot: #{random}"
39
+ puts "You: #{choice}"
40
+ puts '------'
41
+
42
+ puts Option.explain(choice, random) unless random == choice
43
+
44
+ case choice <=> random
45
+ when 1
46
+ puts 'You won (:'
47
+ when -1
48
+ puts 'Bot won :('
49
+ puts 'Better luck next time.'
50
+ else
51
+ puts 'Match draw.'
52
+ end
53
+ end
54
+
55
+ default_task :play
56
+
57
+ private
58
+
59
+ no_commands do
60
+ def input_choice(game_mode)
61
+ T.cast(game_mode, GameMode)
62
+ puts game_mode.options.map(&:label).join(' · ')
63
+ chosen_initial = ask('Make a choice', {
64
+ limited_to: game_mode.options.map(&:initial)
65
+ })
66
+ Rochambeau::Option.from_initial chosen_initial
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,32 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'option'
5
+
6
+ class Rochambeau
7
+ class GameMode < T::Struct
8
+ extend T::Sig
9
+
10
+ const :options, T::Array[Option]
11
+
12
+ private_class_method :new
13
+
14
+ BASIC = T.let(
15
+ new(
16
+ options: [
17
+ Option::ROCK,
18
+ Option::PAPER,
19
+ Option::SCISSORS,
20
+ ]
21
+ ),
22
+ GameMode
23
+ )
24
+
25
+ ADVANCED = T.let(
26
+ new(
27
+ options: Option::ALL
28
+ ),
29
+ GameMode
30
+ )
31
+ end
32
+ end
@@ -0,0 +1,121 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ class Rochambeau
5
+ class Option
6
+ extend T::Sig
7
+
8
+ sig { returns(String) }
9
+ attr_reader :initial, :name
10
+
11
+ private_class_method :new
12
+
13
+ sig { params(initial: String, name: String).void }
14
+ def initialize(initial, name)
15
+ @initial = initial
16
+ @name = name
17
+ end
18
+
19
+ ROCK = T.let(new('r', 'rock'), Option)
20
+ PAPER = T.let(new('p', 'paper'), Option)
21
+ SCISSORS = T.let(new('s', 'scissors'), Option)
22
+ LIZARD = T.let(new('l', 'lizard'), Option)
23
+ SPOCK = T.let(new('v', 'spock'), Option)
24
+
25
+ ALL = T.let(
26
+ [ROCK, PAPER, SCISSORS, LIZARD, SPOCK],
27
+ T::Array[Option]
28
+ )
29
+
30
+ OUTCOMES = T.let(
31
+ {
32
+ ROCK => {
33
+ ROCK => { result: 0, explanation: nil },
34
+ PAPER => { result: -1, explanation: 'Paper covers rock.' },
35
+ SCISSORS => { result: 1, explanation: 'Rock crushes scissors.' },
36
+ LIZARD => { result: 1, explanation: 'Rock crushes lizard.' },
37
+ SPOCK => { result: -1, explanation: 'Spock vaporizes rock.' }
38
+ },
39
+ PAPER => {
40
+ ROCK => { result: 1, explanation: 'Paper covers rock.' },
41
+ PAPER => { result: 0, explanation: nil },
42
+ SCISSORS => { result: -1, explanation: 'Scissors cut paper.' },
43
+ LIZARD => { result: -1, explanation: 'Lizard eats paper.' },
44
+ SPOCK => { result: 1, explanation: 'Paper disproves Spock.' }
45
+ },
46
+ SCISSORS => {
47
+ ROCK => { result: -1, explanation: 'Rock crushes scissors.' },
48
+ PAPER => { result: 1, explanation: 'Scissors cut paper.' },
49
+ SCISSORS => { result: 0, explanation: nil },
50
+ LIZARD => { result: 1, explanation: 'Scissors decapitate lizard.' },
51
+ SPOCK => { result: -1, explanation: 'Spock smashes scissors.' }
52
+ },
53
+ LIZARD => {
54
+ ROCK => { result: -1, explanation: 'Rock crushes lizard.' },
55
+ PAPER => { result: 1, explanation: 'Lizard eats paper.' },
56
+ SCISSORS => { result: -1, explanation: 'Scissors decapitate lizard.' },
57
+ LIZARD => { result: 0, explanation: nil },
58
+ SPOCK => { result: 1, explanation: 'Lizard poisons Spock.' }
59
+ },
60
+ SPOCK => {
61
+ ROCK => { result: 1, explanation: 'Spock vaporizes rock.' },
62
+ PAPER => { result: -1, explanation: 'Paper disproves Spock.' },
63
+ SCISSORS => { result: 1, explanation: 'Spock smashes scissors.' },
64
+ LIZARD => { result: -1, explanation: 'Lizard poisons Spock.' },
65
+ SPOCK => { result: 0, explanation: nil }
66
+ }
67
+ },
68
+ T::Hash[
69
+ Option,
70
+ T::Hash[
71
+ Option,
72
+ { result: Integer, explanation: T.nilable(String) }
73
+ ]
74
+ ]
75
+ )
76
+ private_constant(:OUTCOMES)
77
+
78
+ sig { params(other: Option).returns(Integer) }
79
+ def <=>(other)
80
+ unless OUTCOMES[self] && T.must(OUTCOMES[self])[other]
81
+ raise StandardError, "Could not compare #{self} with #{other}"
82
+ end
83
+
84
+ T.must(T.must(OUTCOMES[self])[other])[:result]
85
+ end
86
+
87
+ sig { returns(String) }
88
+ def to_s
89
+ @name
90
+ end
91
+
92
+ sig { returns(String) }
93
+ def label
94
+ "#{@name.capitalize} (#{@initial})"
95
+ end
96
+
97
+ class << self
98
+ extend(T::Sig)
99
+
100
+ sig do
101
+ params(option1: Option, option2: Option)
102
+ .returns(T.nilable(String))
103
+ end
104
+ def explain(option1, option2)
105
+ unless OUTCOMES[option1] && T.must(OUTCOMES[option1])[option2]
106
+ raise StandardError, "Unexpected combination: #{option1}, #{option2}"
107
+ end
108
+
109
+ T.must(T.must(OUTCOMES[option1])[option2])[:explanation]
110
+ end
111
+
112
+ sig { params(initial: String).returns(Option) }
113
+ def from_initial(initial)
114
+ result = ALL.detect { |o| o.initial == initial }
115
+ return result if result
116
+
117
+ raise Rochambeau::InvalidOptionError, "Invalid initial '#{initial}'."
118
+ end
119
+ end
120
+ end
121
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rochambeau
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jigar Mehta
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-02-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Command-line edition of the Rock-Paper-Scissors game.
14
+ email: hello@jigarius.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/rochambeau.rb
20
+ - lib/rochambeau/cli.rb
21
+ - lib/rochambeau/game_mode.rb
22
+ - lib/rochambeau/option.rb
23
+ homepage: https://rubygems.org/gems/rochambeau
24
+ licenses:
25
+ - LGPL-2.1
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 2.7.0
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubygems_version: 3.1.4
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: 'Rock, paper, scissors: Command line edition.'
46
+ test_files: []