rochambeau 0.0.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.
- checksums.yaml +7 -0
- data/lib/rochambeau.rb +11 -0
- data/lib/rochambeau/cli.rb +70 -0
- data/lib/rochambeau/game_mode.rb +32 -0
- data/lib/rochambeau/option.rb +121 -0
- metadata +46 -0
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,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: []
|