petli 0.0.2 → 0.0.3
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 +4 -4
- data/Gemfile.lock +3 -4
- data/README.md +10 -10
- data/bin/petli +5 -4
- data/lib/petli/animator.rb +8 -8
- data/lib/petli/pet.rb +6 -8
- data/lib/petli/poop.rb +3 -20
- data/lib/petli/stages/base.rb +76 -0
- data/lib/petli/{rooms → stages}/dice.rb +16 -16
- data/lib/petli/{rooms → stages}/feed.rb +4 -4
- data/lib/petli/stages/guess.rb +51 -0
- data/lib/petli/{rooms → stages}/main.rb +5 -5
- data/lib/petli/stages/play.rb +16 -0
- data/lib/petli/stages.rb +10 -0
- data/lib/petli/version.rb +1 -1
- data/lib/petli.rb +1 -2
- data/lib/tatty/anim.rb +19 -0
- data/lib/{petli → tatty}/db.rb +4 -5
- data/lib/tatty/stage.rb +73 -0
- data/lib/tatty.rb +38 -0
- data/petli.gemspec +0 -1
- metadata +17 -30
- data/lib/petli/hud.rb +0 -44
- data/lib/petli/rooms/guess.rb +0 -51
- data/lib/petli/rooms/play.rb +0 -16
- data/lib/petli/rooms.rb +0 -73
- data/lib/tatty/game.rb +0 -80
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9a8fbb01c6f383d9993c120cb0fd4d2305c82314baf400f4b74bfbee7c1cc81
|
4
|
+
data.tar.gz: 9dff8e3e65d3e93942c4a1fc8589206b740c26e1ac2bb385bf3132a249deb49d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad282f370925d30eb0f04dc1a71a91e3300380b0f4d8b646b4c863d7917c0fb007353190ec35a73a844b67f03d6aff9becf150ea4a1b113a5aa6022ea78cb4aa
|
7
|
+
data.tar.gz: d5b3900600281412ba822dad13604fec9c1578e3621884116d5fe3e2e1b5daf07dca5ad48637877e729da0e73bb9894e8db41573b41edd37e020cc66921ede52
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
petli (0.0.
|
4
|
+
petli (0.0.2)
|
5
5
|
pastel (~> 0.8.0)
|
6
6
|
tty-box (~> 0.7.0)
|
7
7
|
tty-color (~> 0.6.0)
|
8
|
-
tty-config (~> 0.5.0)
|
9
8
|
tty-cursor (~> 0.7.1)
|
10
9
|
tty-platform (~> 0.3.0)
|
11
10
|
tty-reader (~> 0.9.0)
|
@@ -26,7 +25,6 @@ GEM
|
|
26
25
|
strings (~> 0.2.0)
|
27
26
|
tty-cursor (~> 0.7)
|
28
27
|
tty-color (0.6.0)
|
29
|
-
tty-config (0.5.0)
|
30
28
|
tty-cursor (0.7.1)
|
31
29
|
tty-platform (0.3.0)
|
32
30
|
tty-reader (0.9.0)
|
@@ -34,12 +32,13 @@ GEM
|
|
34
32
|
tty-screen (~> 0.8)
|
35
33
|
wisper (~> 2.0)
|
36
34
|
tty-screen (0.8.1)
|
37
|
-
unicode-display_width (2.
|
35
|
+
unicode-display_width (2.1.0)
|
38
36
|
unicode_utils (1.4.0)
|
39
37
|
wisper (2.0.1)
|
40
38
|
|
41
39
|
PLATFORMS
|
42
40
|
arm64-darwin-20
|
41
|
+
x86_64-darwin-20
|
43
42
|
|
44
43
|
DEPENDENCIES
|
45
44
|
petli!
|
data/README.md
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
<p align="center">
|
2
|
+
<h1 align="center">Petli</h1>
|
3
|
+
<p align="center">Virtual Pet in your console. You must feed it, clean up after it, and play with it to keep it happy!</p>
|
4
|
+
<p align="center">
|
5
|
+
<img src="https://media.giphy.com/media/pwtUe2wVhgpQIK5puU/giphy.gif"/>
|
6
|
+
</p>
|
7
|
+
</p>
|
8
|
+
|
9
|
+
---
|
10
10
|
### Usage
|
11
11
|
|
12
|
-
Run `gem install petli` and then run `petli` in your command line
|
12
|
+
Run `gem install petli` and then run `petli` in your command line. Run `petli --help` for more information.
|
13
13
|
|
14
14
|
### Advanced usage
|
15
15
|
|
data/bin/petli
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'petli'
|
3
|
+
require 'tatty'
|
3
4
|
require 'optparse'
|
4
5
|
|
5
6
|
options = {}
|
@@ -12,7 +13,7 @@ OptionParser.new do |opts|
|
|
12
13
|
opts.on("-m", "--medicine", "Feed your pet candy without viewing") {|v| options[:medicine] = v}
|
13
14
|
opts.on("-l", "--clean", "Clean up any 'dirt' without viewing") {|v| options[:clean] = v}
|
14
15
|
opts.on("-p", "--path [PATH]", "path to your pet data (defaults to system config dir)") do |v|
|
15
|
-
$
|
16
|
+
$tattydboverridepath = v
|
16
17
|
end
|
17
18
|
end.parse!
|
18
19
|
|
@@ -20,10 +21,10 @@ pet = Petli::Pet.new
|
|
20
21
|
pet.display # force pet to update first
|
21
22
|
|
22
23
|
if options[:reset]
|
23
|
-
|
24
|
+
Tatty::DB.clear
|
24
25
|
puts "Goodbye. I hope you love your next pet!"
|
25
26
|
elsif options[:status]
|
26
|
-
puts
|
27
|
+
puts Tatty::DB.dump
|
27
28
|
elsif options[:bread]
|
28
29
|
pet.feed!(food: :bread)
|
29
30
|
elsif options[:candy]
|
@@ -33,5 +34,5 @@ elsif options[:medicine]
|
|
33
34
|
elsif options[:clean]
|
34
35
|
pet.clean
|
35
36
|
else
|
36
|
-
Petli::
|
37
|
+
Tatty.run(Petli::Stages::Main, pet: pet)
|
37
38
|
end
|
data/lib/petli/animator.rb
CHANGED
@@ -33,16 +33,16 @@ module Petli
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def step
|
36
|
-
|
36
|
+
add_frame
|
37
37
|
leftarm, rightarm = getit(:arms, 2)
|
38
38
|
lefteye, righteye = getit(:eyes, 2)
|
39
39
|
mouth = getit(:mouth)
|
40
40
|
lefthead, righthead = getit(:head, 2)
|
41
41
|
[leftarm,lefthead,lefteye,mouth,righteye,righthead,rightarm]
|
42
42
|
|
43
|
-
food_peices =
|
43
|
+
food_peices = food.split('')
|
44
44
|
|
45
|
-
ANIMATIONS[
|
45
|
+
ANIMATIONS[action][frame]
|
46
46
|
.sub('a', leftarm.to_s).sub('a', rightarm.to_s)
|
47
47
|
.sub('h', lefthead).sub('h', righthead)
|
48
48
|
.sub('e', lefteye).sub('e', righteye)
|
@@ -93,9 +93,9 @@ module Petli
|
|
93
93
|
private
|
94
94
|
|
95
95
|
def add_frame
|
96
|
-
frame_count = ANIMATIONS[
|
96
|
+
frame_count = ANIMATIONS[action].count
|
97
97
|
@frame += 1
|
98
|
-
if
|
98
|
+
if frame == frame_count
|
99
99
|
@frame = 0
|
100
100
|
@action_stack.shift if @action_stack.count > 0
|
101
101
|
@mood_stack.shift if @mood_stack.count > 0
|
@@ -108,7 +108,7 @@ module Petli
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def food
|
111
|
-
|
111
|
+
data[@food]
|
112
112
|
end
|
113
113
|
|
114
114
|
def frame # to control framerate
|
@@ -116,8 +116,8 @@ module Petli
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def getit(part, vals=1)
|
119
|
-
mood_part =
|
120
|
-
part_frame =
|
119
|
+
mood_part = data[part][mood] || data[part][:default]
|
120
|
+
part_frame = frame % mood_part.count
|
121
121
|
result = mood_part[part_frame]
|
122
122
|
if vals == 2 && result.is_a?(String)
|
123
123
|
[result, result]
|
data/lib/petli/pet.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Petli
|
2
2
|
class Pet
|
3
3
|
include Watch
|
4
|
-
extend DB::Attributes
|
4
|
+
extend Tatty::DB::Attributes
|
5
5
|
|
6
6
|
MOOD_SCALE = [:angry, :annoyed, :normal, :happy, :great]
|
7
7
|
|
@@ -35,17 +35,19 @@ module Petli
|
|
35
35
|
hours_past = hours_since(self.last_meal)
|
36
36
|
self.last_meal = Time.now
|
37
37
|
(0...hours_past).each do |i|
|
38
|
+
next if rand <= 0.3
|
38
39
|
self.health = [1, self.health-1].max
|
39
40
|
self.happiness = [1, self.happiness-1].max
|
40
|
-
self.
|
41
|
+
self.poops << hours_ago(i) if rand <= 0.8 && self.poops.count < Poop::LOCATIONS.count
|
41
42
|
end
|
42
|
-
self.sick = self.poops.filter{|poop| hours_since(poop
|
43
|
+
self.sick = self.poops.filter{|poop| hours_since(poop) > 1 }.count
|
43
44
|
end
|
44
45
|
|
45
46
|
if hours_since(self.last_play) > 1
|
46
47
|
hours_past = hours_since(self.last_play)
|
47
48
|
self.last_play = Time.now
|
48
49
|
(0...hours_past).each do
|
50
|
+
next if rand <= 0.3
|
49
51
|
self.happiness = [1, self.happiness-1].max
|
50
52
|
end
|
51
53
|
end
|
@@ -75,7 +77,7 @@ module Petli
|
|
75
77
|
return self.embarass if ((food == :medicine && self.sick <= 0) || (self.health == 10 && food != :medicine))
|
76
78
|
self.last_meal = Time.now unless food == :medicine
|
77
79
|
@animation.eat(food: food) do
|
78
|
-
self.feed!(food)
|
80
|
+
self.feed!(food: food)
|
79
81
|
end
|
80
82
|
end
|
81
83
|
|
@@ -98,10 +100,6 @@ module Petli
|
|
98
100
|
@animation.action = :stand
|
99
101
|
end
|
100
102
|
|
101
|
-
def poop(hours_ago)
|
102
|
-
self.poops = self.poops + [Poop.new(hours_ago)] if self.poops.count < Poop::LOCATIONS.count
|
103
|
-
end
|
104
|
-
|
105
103
|
def clean
|
106
104
|
self.poops = []
|
107
105
|
end
|
data/lib/petli/poop.rb
CHANGED
@@ -1,26 +1,9 @@
|
|
1
1
|
module Petli
|
2
|
-
class Poop
|
3
|
-
include Watch
|
4
|
-
|
2
|
+
class Poop < Tatty::Anim
|
5
3
|
LOCATIONS = [[1,1], [1,4], [1,7], [11,1], [11,7], [20,1], [20,4], [20,7]]
|
6
4
|
ANIMATION = ["ı ı ı\n༼ᵔ◡ᵔ༽", "ϟ ϟ ϟ\n༼ಠ益ಠ༽"]
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(hrsago)
|
11
|
-
@frame = 0
|
12
|
-
self.hatch = hours_ago(hrsago)
|
13
|
-
end
|
14
|
-
|
15
|
-
def step
|
16
|
-
@frame += 1
|
17
|
-
anim_fram = (@frame/2).ceil
|
18
|
-
@frame = 0 if anim_fram >= ANIMATION.count
|
19
|
-
ANIMATION[anim_fram]
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_json(opts)
|
23
|
-
self.hatch.to_json
|
5
|
+
def initialize()
|
6
|
+
super(ANIMATION)
|
24
7
|
end
|
25
8
|
end
|
26
9
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'pastel'
|
2
|
+
|
3
|
+
module Petli
|
4
|
+
module Stages
|
5
|
+
class Base < Tatty::Stage
|
6
|
+
GAME_WIDTH = 28
|
7
|
+
GAME_HEIGHT = 13
|
8
|
+
|
9
|
+
def initialize(pet:)
|
10
|
+
super()
|
11
|
+
@pet = pet
|
12
|
+
@poop = Poop.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def keypress(event)
|
16
|
+
exit if event.value == "q" || event.value == "\e" || event.value == "x"
|
17
|
+
return if @pet.busy? || @pet.dead?
|
18
|
+
onkey(event)
|
19
|
+
end
|
20
|
+
|
21
|
+
def onkey(event)
|
22
|
+
end
|
23
|
+
|
24
|
+
def actions
|
25
|
+
%w()
|
26
|
+
end
|
27
|
+
|
28
|
+
def action_bar
|
29
|
+
return "" if @pet.dead?
|
30
|
+
p = Pastel.new
|
31
|
+
self.actions.map do |a|
|
32
|
+
key = p.bold("[#{a[0].capitalize}]")
|
33
|
+
"#{key}#{a[1..]}"
|
34
|
+
end.join(" ")
|
35
|
+
end
|
36
|
+
|
37
|
+
def left
|
38
|
+
((screen_width-GAME_WIDTH)/2).round
|
39
|
+
end
|
40
|
+
|
41
|
+
def top
|
42
|
+
((screen_height-GAME_HEIGHT)/2).round
|
43
|
+
end
|
44
|
+
|
45
|
+
def draw
|
46
|
+
p = Pastel.new
|
47
|
+
render_box(
|
48
|
+
title: {
|
49
|
+
top_left: p.bright_white.bold(" Petli "),
|
50
|
+
bottom_right: p.green(" #{@pet.lifetime} days "),
|
51
|
+
},
|
52
|
+
width: GAME_WIDTH,
|
53
|
+
height: GAME_HEIGHT,
|
54
|
+
left: left,
|
55
|
+
top: top,
|
56
|
+
)
|
57
|
+
|
58
|
+
poop = @poop.step
|
59
|
+
@pet.poops.each_with_index do |_, i|
|
60
|
+
x, y = Poop::LOCATIONS[i]
|
61
|
+
render_at(left+1+x, top+1+y, poop)
|
62
|
+
end
|
63
|
+
|
64
|
+
render_at(left+9, top+4, @pet.display)
|
65
|
+
sick = @pet.sick
|
66
|
+
if sick > 0 && !@pet.dead?
|
67
|
+
render_at(left+11-sick, top+4, "[#{'!'*sick}SICK#{'!'*sick}]")
|
68
|
+
end
|
69
|
+
|
70
|
+
render_at(left+1, top+1, "#{p.red("♥")*@pet.health}#{"♡"*(10-@pet.health)} #{"☺"*(10-@pet.happiness)}#{p.green("☻")*@pet.happiness}")
|
71
|
+
render_at(left+1, top+GAME_HEIGHT-2, self.action_bar)
|
72
|
+
render_at(left+GAME_WIDTH-2, top, p.bright_white.bold("[x]"))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Petli
|
2
|
-
module
|
3
|
-
class Dice <
|
2
|
+
module Stages
|
3
|
+
class Dice < Base
|
4
4
|
Symbols = %w(⚀ ⚁ ⚂ ⚃ ⚄ ⚅)
|
5
5
|
|
6
|
-
def initialize(pet)
|
7
|
-
super(pet)
|
6
|
+
def initialize(pet:)
|
7
|
+
super(pet: pet)
|
8
8
|
@value = rand(1..6)
|
9
9
|
@countdown = -1
|
10
10
|
end
|
@@ -14,17 +14,17 @@ module Petli
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def enter
|
17
|
-
pet.play(game: :guess)
|
17
|
+
@pet.play(game: :guess)
|
18
18
|
end
|
19
19
|
|
20
20
|
def leave
|
21
|
-
pet.reset
|
21
|
+
@pet.reset
|
22
22
|
end
|
23
23
|
|
24
24
|
def roll
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def onkey(event)
|
28
28
|
return if event.value != "h" and event.value != "l"
|
29
29
|
@pickedhigher = event.value == "h"
|
30
30
|
@pick = (1..6).to_a.sample
|
@@ -33,19 +33,19 @@ module Petli
|
|
33
33
|
@countdown = 20
|
34
34
|
end
|
35
35
|
|
36
|
-
def draw
|
37
|
-
|
36
|
+
def draw
|
37
|
+
super
|
38
38
|
if @countdown == -1
|
39
|
-
|
40
|
-
|
39
|
+
render_at(left+4, top+6, @value.to_s)
|
40
|
+
render_at(left+23, top+6, Symbols[(0..5).to_a.sample])
|
41
41
|
elsif @countdown == 0
|
42
42
|
@won ? @pet.win : @pet.lose
|
43
|
-
goto(
|
43
|
+
goto(Main, pet: @pet)
|
44
44
|
else
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
render_at(left+4, top+5, "▲") if @pickedhigher
|
46
|
+
render_at(left+4, top+6, @value.to_s)
|
47
|
+
render_at(left+23, top+6, Symbols[@pick-1])
|
48
|
+
render_at(left+4, top+7, "▼") unless @pickedhigher
|
49
49
|
@countdown -= 1
|
50
50
|
end
|
51
51
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Petli
|
2
|
-
module
|
3
|
-
class Feed <
|
2
|
+
module Stages
|
3
|
+
class Feed < Base
|
4
4
|
def actions
|
5
5
|
%w(bread snack med)
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
8
|
+
def onkey(event)
|
9
9
|
if event.value == "b"
|
10
10
|
@pet.feed(food: :bread)
|
11
11
|
elsif event.value == "s"
|
@@ -13,7 +13,7 @@ module Petli
|
|
13
13
|
elsif event.value == "m"
|
14
14
|
@pet.feed(food: :medicine)
|
15
15
|
end
|
16
|
-
goto(
|
16
|
+
goto(Main, pet: @pet)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Petli
|
2
|
+
module Stages
|
3
|
+
class Guess < Base
|
4
|
+
def initialize(pet:)
|
5
|
+
super(pet: pet)
|
6
|
+
@left = true
|
7
|
+
@countdown = -1
|
8
|
+
end
|
9
|
+
|
10
|
+
def actions
|
11
|
+
%w(left right)
|
12
|
+
end
|
13
|
+
|
14
|
+
def enter
|
15
|
+
pet.play(game: :guess)
|
16
|
+
end
|
17
|
+
|
18
|
+
def leave
|
19
|
+
@pet.reset
|
20
|
+
end
|
21
|
+
|
22
|
+
def onkey(event)
|
23
|
+
return if event.value != "l" and event.value != "r"
|
24
|
+
@petpickedleft = rand(1..2) == 1
|
25
|
+
@pickedleft = event.value == "l"
|
26
|
+
(@petpickedleft == @pickedleft) ? @pet.celebrate : @pet.embarass
|
27
|
+
@countdown = 20
|
28
|
+
end
|
29
|
+
|
30
|
+
def draw
|
31
|
+
super
|
32
|
+
if @countdown == -1
|
33
|
+
render_at(left+4, top+5, "☟") if @left
|
34
|
+
render_at(left+23, top+5, "☟") unless @left
|
35
|
+
render_at(left+4, top+6, "▒") if @left
|
36
|
+
render_at(left+23, top+6, "▒") unless @left
|
37
|
+
@left = !@left
|
38
|
+
elsif @countdown == 0
|
39
|
+
(@petpickedleft == @pickedleft) ? @pet.win : @pet.lose
|
40
|
+
goto(Main, pet: @pet)
|
41
|
+
else
|
42
|
+
render_at(left+4, top+5, "☟") if @pickedleft
|
43
|
+
render_at(left+23, top+5, "☟") unless @pickedleft
|
44
|
+
render_at(left+4, top+6, "▒") if @petpickedleft
|
45
|
+
render_at(left+23, top+6, "▒") unless @petpickedleft
|
46
|
+
@countdown -= 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module Petli
|
2
|
-
module
|
3
|
-
class Main <
|
2
|
+
module Stages
|
3
|
+
class Main < Base
|
4
4
|
def actions
|
5
5
|
acts = %w(play feed)
|
6
6
|
acts << "clean" if @pet.poops.count > 0
|
7
7
|
acts
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
return goto(
|
10
|
+
def onkey(event)
|
11
|
+
return goto(Feed, pet: @pet) if event.value == "f"
|
12
12
|
return @pet.clean if event.value == "c"
|
13
|
-
return goto(
|
13
|
+
return goto(Play, pet: @pet) if event.value == "p"
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Petli
|
2
|
+
module Stages
|
3
|
+
class Play < Base
|
4
|
+
def actions
|
5
|
+
%w(guess dice)
|
6
|
+
end
|
7
|
+
|
8
|
+
def onkey(event)
|
9
|
+
return goto(Dice, pet: @pet) if event.value == "d"
|
10
|
+
return goto(Guess, pet: @pet) if event.value == "g"
|
11
|
+
goto(Main, pet: @pet)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
data/lib/petli/stages.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Petli
|
2
|
+
module Stages
|
3
|
+
autoload :Base, "petli/stages/base"
|
4
|
+
autoload :Dice, "petli/stages/dice"
|
5
|
+
autoload :Feed, "petli/stages/feed"
|
6
|
+
autoload :Guess, "petli/stages/guess"
|
7
|
+
autoload :Main, "petli/stages/main"
|
8
|
+
autoload :Play, "petli/stages/play"
|
9
|
+
end
|
10
|
+
end
|
data/lib/petli/version.rb
CHANGED
data/lib/petli.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
module Petli
|
2
2
|
autoload :Animator, "petli/animator"
|
3
|
-
autoload :DB, "petli/db"
|
4
3
|
autoload :HUD, "petli/hud"
|
5
4
|
autoload :Pet, "petli/pet"
|
6
5
|
autoload :Poop, "petli/poop"
|
7
|
-
autoload :
|
6
|
+
autoload :Stages, "petli/Stages"
|
8
7
|
autoload :Watch, "petli/watch"
|
9
8
|
autoload :VERSION, "petli/version"
|
10
9
|
end
|
data/lib/tatty/anim.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Tatty
|
2
|
+
class Anim
|
3
|
+
def initialize(atlas, frame: 0, rate: 2)
|
4
|
+
@atlas = atlas
|
5
|
+
@frame = frame
|
6
|
+
@rate = rate
|
7
|
+
end
|
8
|
+
|
9
|
+
def step
|
10
|
+
@frame += 1
|
11
|
+
@frame = 0 if self.frame >= @atlas.count
|
12
|
+
@atlas[self.frame]
|
13
|
+
end
|
14
|
+
|
15
|
+
def frame
|
16
|
+
(@frame/@rate).ceil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/{petli → tatty}/db.rb
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Tatty
|
2
2
|
require "pstore"
|
3
3
|
require "forwardable"
|
4
4
|
require "tty-platform"
|
@@ -18,9 +18,9 @@ module Petli
|
|
18
18
|
|
19
19
|
attr_reader :db
|
20
20
|
|
21
|
-
def initialize
|
22
|
-
config_path = if !$
|
23
|
-
$
|
21
|
+
def initialize
|
22
|
+
config_path = if !$tattydboverridepath.nil?
|
23
|
+
$tattydboverridepath
|
24
24
|
elsif TTY::Platform.windows?
|
25
25
|
File.join(ENV["APPDATA"], 'petli', 'data.pet')
|
26
26
|
elsif TTY::Platform.linux?
|
@@ -75,4 +75,3 @@ module Petli
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
data/lib/tatty/stage.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Tatty
|
2
|
+
require 'tty-cursor'
|
3
|
+
require 'tty-screen'
|
4
|
+
require 'tty-box'
|
5
|
+
|
6
|
+
class Stage
|
7
|
+
attr_accessor :framerate
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@cursor = TTY::Cursor
|
11
|
+
@framerate = 0.1
|
12
|
+
@buffer = ""
|
13
|
+
end
|
14
|
+
|
15
|
+
def leave
|
16
|
+
end
|
17
|
+
|
18
|
+
def goto(klass, **kargs)
|
19
|
+
::Tatty.goto(klass, **kargs)
|
20
|
+
end
|
21
|
+
|
22
|
+
def screen_size
|
23
|
+
TTY::Screen.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def screen_width
|
27
|
+
TTY::Screen.width
|
28
|
+
end
|
29
|
+
|
30
|
+
def screen_height
|
31
|
+
TTY::Screen.height
|
32
|
+
end
|
33
|
+
|
34
|
+
def move_to(x, y)
|
35
|
+
render @cursor.move_to(x, y)
|
36
|
+
end
|
37
|
+
|
38
|
+
def render(out)
|
39
|
+
@buffer += out
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_at(x, y, out)
|
43
|
+
out.to_s.each_line do |line|
|
44
|
+
render @cursor.move_to(x, y)
|
45
|
+
render line
|
46
|
+
y += 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def draw
|
51
|
+
render "not implemented"
|
52
|
+
end
|
53
|
+
|
54
|
+
def step
|
55
|
+
last_buffer = @buffer
|
56
|
+
@buffer = ""
|
57
|
+
render @cursor.clear_screen
|
58
|
+
move_to(0, 0)
|
59
|
+
self.draw
|
60
|
+
if last_buffer != @buffer
|
61
|
+
print @buffer
|
62
|
+
end
|
63
|
+
sleep(@framerate)
|
64
|
+
end
|
65
|
+
|
66
|
+
def render_box(*content, **kwargs, &block)
|
67
|
+
render @cursor.save
|
68
|
+
move_to(0, 0)
|
69
|
+
render TTY::Box.frame(*content, **kwargs, &block)
|
70
|
+
render @cursor.restore
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/tatty.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Tatty
|
2
|
+
require 'tty-reader'
|
3
|
+
require 'tty-cursor'
|
4
|
+
|
5
|
+
autoload :Anim, "tatty/anim"
|
6
|
+
autoload :DB, "tatty/db"
|
7
|
+
autoload :Stage, "tatty/stage"
|
8
|
+
|
9
|
+
def self.run(klass, **kargs)
|
10
|
+
self.goto(klass, **kargs)
|
11
|
+
@reader = TTY::Reader.new
|
12
|
+
@reader.on(:keypress) do |event|
|
13
|
+
self.stage.keypress(event)
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
TTY::Cursor.invisible do
|
18
|
+
while true
|
19
|
+
@reader.read_keypress(nonblock: true)
|
20
|
+
@stage.step
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue Interrupt => e
|
24
|
+
ensure
|
25
|
+
print TTY::Cursor.clear_screen
|
26
|
+
print TTY::Cursor.move_to(0, 0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.stage
|
31
|
+
@stage
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.goto(klass, **kargs)
|
35
|
+
@stage.leave unless @stage.nil?
|
36
|
+
@stage = klass.new(**kargs)
|
37
|
+
end
|
38
|
+
end
|
data/petli.gemspec
CHANGED
@@ -33,7 +33,6 @@ Gem::Specification.new do |s|
|
|
33
33
|
|
34
34
|
s.add_dependency("pastel", "~> 0.8.0")
|
35
35
|
s.add_dependency("tty-cursor", "~> 0.7.1")
|
36
|
-
s.add_dependency("tty-config", "~> 0.5.0")
|
37
36
|
s.add_dependency("tty-screen", "~> 0.8.1")
|
38
37
|
s.add_dependency("tty-reader", "~> 0.9.0")
|
39
38
|
s.add_dependency("tty-color", "~> 0.6.0")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: petli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Anema
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pastel
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.7.1
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: tty-config
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.5.0
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 0.5.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: tty-screen
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,7 +110,7 @@ dependencies:
|
|
124
110
|
version: 0.3.0
|
125
111
|
description: 'A virtual pet that will live in your command line!
|
126
112
|
|
127
|
-
|
113
|
+
'
|
128
114
|
email:
|
129
115
|
- timanema@gmail.com
|
130
116
|
executables:
|
@@ -143,19 +129,21 @@ files:
|
|
143
129
|
- data/face_ref
|
144
130
|
- lib/petli.rb
|
145
131
|
- lib/petli/animator.rb
|
146
|
-
- lib/petli/db.rb
|
147
|
-
- lib/petli/hud.rb
|
148
132
|
- lib/petli/pet.rb
|
149
133
|
- lib/petli/poop.rb
|
150
|
-
- lib/petli/
|
151
|
-
- lib/petli/
|
152
|
-
- lib/petli/
|
153
|
-
- lib/petli/
|
154
|
-
- lib/petli/
|
155
|
-
- lib/petli/
|
134
|
+
- lib/petli/stages.rb
|
135
|
+
- lib/petli/stages/base.rb
|
136
|
+
- lib/petli/stages/dice.rb
|
137
|
+
- lib/petli/stages/feed.rb
|
138
|
+
- lib/petli/stages/guess.rb
|
139
|
+
- lib/petli/stages/main.rb
|
140
|
+
- lib/petli/stages/play.rb
|
156
141
|
- lib/petli/version.rb
|
157
142
|
- lib/petli/watch.rb
|
158
|
-
- lib/tatty
|
143
|
+
- lib/tatty.rb
|
144
|
+
- lib/tatty/anim.rb
|
145
|
+
- lib/tatty/db.rb
|
146
|
+
- lib/tatty/stage.rb
|
159
147
|
- petli.gemspec
|
160
148
|
homepage: https://github.com/tanema/petli
|
161
149
|
licenses:
|
@@ -182,9 +170,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
170
|
- !ruby/object:Gem::Version
|
183
171
|
version: '0'
|
184
172
|
requirements: []
|
185
|
-
rubygems_version: 3.
|
186
|
-
signing_key:
|
173
|
+
rubygems_version: 3.0.3
|
174
|
+
signing_key:
|
187
175
|
specification_version: 4
|
188
176
|
summary: A little pet in your console
|
189
177
|
test_files: []
|
190
|
-
...
|
data/lib/petli/hud.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require_relative '../tatty/game'
|
2
|
-
require 'pastel'
|
3
|
-
|
4
|
-
module Petli
|
5
|
-
class HUD < Tatty::Game
|
6
|
-
GAME_WIDTH = 28
|
7
|
-
GAME_HEIGHT = 13
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
super()
|
11
|
-
@pet = Pet.new
|
12
|
-
Rooms.enter(@pet)
|
13
|
-
end
|
14
|
-
|
15
|
-
def keypress(event)
|
16
|
-
exit if event.value == "q"
|
17
|
-
return if @pet.busy? || @pet.dead?
|
18
|
-
Rooms.current.keypress(event)
|
19
|
-
end
|
20
|
-
|
21
|
-
def draw
|
22
|
-
h, w = self.screen_size
|
23
|
-
left, top = ((w-GAME_WIDTH)/2).round, ((h-GAME_HEIGHT)/2).round
|
24
|
-
render_box(
|
25
|
-
title: {
|
26
|
-
top_left: Pastel.new.bright_white.bold(" Petli "),
|
27
|
-
bottom_right: Pastel.new.green(" #{@pet.lifetime} days "),
|
28
|
-
},
|
29
|
-
width: GAME_WIDTH,
|
30
|
-
height: GAME_HEIGHT,
|
31
|
-
left: left,
|
32
|
-
top: top,
|
33
|
-
)
|
34
|
-
Rooms.current.draw(self, left, top)
|
35
|
-
render_at(left+1, top+1, status_bar)
|
36
|
-
render_at(left+1, top+GAME_HEIGHT-2, Rooms.current.action_bar)
|
37
|
-
end
|
38
|
-
|
39
|
-
def status_bar
|
40
|
-
p = Pastel.new
|
41
|
-
"#{p.red("♥")*@pet.health}#{"♡"*(10-@pet.health)} #{"☺"*(10-@pet.happiness)}#{p.green("☻")*@pet.happiness}"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/petli/rooms/guess.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module Petli
|
2
|
-
module Rooms
|
3
|
-
class Guess < Room
|
4
|
-
def initialize(pet)
|
5
|
-
super(pet)
|
6
|
-
@left = true
|
7
|
-
@countdown = -1
|
8
|
-
end
|
9
|
-
|
10
|
-
def actions
|
11
|
-
%w(left right)
|
12
|
-
end
|
13
|
-
|
14
|
-
def enter
|
15
|
-
pet.play(game: :guess)
|
16
|
-
end
|
17
|
-
|
18
|
-
def leave
|
19
|
-
pet.reset
|
20
|
-
end
|
21
|
-
|
22
|
-
def keypress(event)
|
23
|
-
return if event.value != "l" and event.value != "r"
|
24
|
-
@petpickedleft = rand(1..2) == 1
|
25
|
-
@pickedleft = event.value == "l"
|
26
|
-
(@petpickedleft == @pickedleft) ? @pet.celebrate : @pet.embarass
|
27
|
-
@countdown = 20
|
28
|
-
end
|
29
|
-
|
30
|
-
def draw(ctx, ox, oy)
|
31
|
-
ctx.render_at(ox+9, oy+4, @pet.display)
|
32
|
-
if @countdown == -1
|
33
|
-
ctx.render_at(ox+4, oy+5, "☟") if @left
|
34
|
-
ctx.render_at(ox+23, oy+5, "☟") unless @left
|
35
|
-
ctx.render_at(ox+4, oy+6, "▒") if @left
|
36
|
-
ctx.render_at(ox+23, oy+6, "▒") unless @left
|
37
|
-
@left = !@left
|
38
|
-
elsif @countdown == 0
|
39
|
-
(@petpickedleft == @pickedleft) ? @pet.win : @pet.lose
|
40
|
-
goto("main")
|
41
|
-
else
|
42
|
-
ctx.render_at(ox+4, oy+5, "☟") if @pickedleft
|
43
|
-
ctx.render_at(ox+23, oy+5, "☟") unless @pickedleft
|
44
|
-
ctx.render_at(ox+4, oy+6, "▒") if @petpickedleft
|
45
|
-
ctx.render_at(ox+23, oy+6, "▒") unless @petpickedleft
|
46
|
-
@countdown -= 1
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
data/lib/petli/rooms/play.rb
DELETED
data/lib/petli/rooms.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
module Petli
|
2
|
-
module Rooms
|
3
|
-
class Room
|
4
|
-
attr_reader :pet
|
5
|
-
|
6
|
-
def initialize(pet)
|
7
|
-
@pet = pet
|
8
|
-
end
|
9
|
-
|
10
|
-
def enter
|
11
|
-
end
|
12
|
-
|
13
|
-
def goto(room_name)
|
14
|
-
klass = ::Petli.const_get("Rooms::#{room_name.capitalize}")
|
15
|
-
self.leave unless klass.nil?
|
16
|
-
::Petli::Rooms.goto(klass)
|
17
|
-
end
|
18
|
-
|
19
|
-
def leave
|
20
|
-
end
|
21
|
-
|
22
|
-
def actions
|
23
|
-
%w()
|
24
|
-
end
|
25
|
-
|
26
|
-
def action_bar
|
27
|
-
return "" if @pet.dead?
|
28
|
-
p = Pastel.new
|
29
|
-
self.actions.map do |a|
|
30
|
-
key = p.bold("[#{a[0].capitalize}]")
|
31
|
-
"#{key}#{a[1..]}"
|
32
|
-
end.join(" ")
|
33
|
-
end
|
34
|
-
|
35
|
-
def keypress(event)
|
36
|
-
end
|
37
|
-
|
38
|
-
def draw(ctx, ox, oy)
|
39
|
-
poops = @pet.poops
|
40
|
-
poops.each_with_index do |poop, i|
|
41
|
-
x, y = Poop::LOCATIONS[i]
|
42
|
-
ctx.render_at(ox+1+x, oy+1+y, poop.step)
|
43
|
-
end
|
44
|
-
@pet.poops = poops
|
45
|
-
ctx.render_at(ox+9, oy+4, @pet.display)
|
46
|
-
sick = @pet.sick
|
47
|
-
if sick > 0 && !@pet.dead?
|
48
|
-
ctx.render_at(ox+11-sick, oy+4, "[#{'!'*sick}SICK#{'!'*sick}]")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
autoload :Main, "petli/rooms/main"
|
54
|
-
autoload :Feed, "petli/rooms/feed"
|
55
|
-
autoload :Play, "petli/rooms/play"
|
56
|
-
autoload :Guess, "petli/rooms/guess"
|
57
|
-
autoload :Dice, "petli/rooms/dice"
|
58
|
-
|
59
|
-
def self.current
|
60
|
-
@room
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.enter(pet)
|
64
|
-
@pet = pet
|
65
|
-
goto(Main)
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.goto(klass)
|
69
|
-
@room = klass.new(@pet)
|
70
|
-
@room.enter
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/lib/tatty/game.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
module Tatty
|
2
|
-
require 'tty-cursor'
|
3
|
-
require 'tty-config'
|
4
|
-
require 'tty-screen'
|
5
|
-
require 'tty-reader'
|
6
|
-
require 'tty-box'
|
7
|
-
|
8
|
-
class Game
|
9
|
-
attr_accessor :framerate, :config
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@config = TTY::Config.new
|
13
|
-
@cursor = TTY::Cursor
|
14
|
-
@reader = TTY::Reader.new
|
15
|
-
@framerate = 0.1
|
16
|
-
@buffer = ""
|
17
|
-
|
18
|
-
@reader.on(:keypress) do |event|
|
19
|
-
self.keypress(event)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def screen_size
|
24
|
-
TTY::Screen.size
|
25
|
-
end
|
26
|
-
|
27
|
-
def move_to(x, y)
|
28
|
-
render @cursor.move_to(x, y)
|
29
|
-
end
|
30
|
-
|
31
|
-
def render(out)
|
32
|
-
@buffer += out
|
33
|
-
end
|
34
|
-
|
35
|
-
def render_at(x, y, out)
|
36
|
-
out.to_s.each_line do |line|
|
37
|
-
render @cursor.move_to(x, y)
|
38
|
-
render line
|
39
|
-
y += 1
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def keypress(event)
|
44
|
-
end
|
45
|
-
|
46
|
-
def draw
|
47
|
-
render "not implemented"
|
48
|
-
end
|
49
|
-
|
50
|
-
def run
|
51
|
-
begin
|
52
|
-
@cursor.invisible do
|
53
|
-
while true
|
54
|
-
@reader.read_keypress(nonblock: true)
|
55
|
-
last_buffer = @buffer
|
56
|
-
@buffer = ""
|
57
|
-
render @cursor.clear_screen
|
58
|
-
move_to(0, 0)
|
59
|
-
self.draw
|
60
|
-
if last_buffer != @buffer
|
61
|
-
print @buffer
|
62
|
-
end
|
63
|
-
sleep(@framerate)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
rescue Interrupt => e
|
67
|
-
ensure
|
68
|
-
print @cursor.clear_screen
|
69
|
-
print @cursor.move_to(0, 0)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def render_box(*content, **kwargs, &block)
|
74
|
-
render @cursor.save
|
75
|
-
move_to(0, 0)
|
76
|
-
render TTY::Box.frame(*content, **kwargs, &block)
|
77
|
-
render @cursor.restore
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|