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