petli 0.0.3 → 0.0.5

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.
@@ -9,29 +9,54 @@ module Petli
9
9
  def initialize(pet:)
10
10
  super()
11
11
  @pet = pet
12
- @poop = Poop.new
12
+ @poop = Tatty::Anim.from_atlas(Petli.data_path('poop.txtanim'))
13
+ @page = 0
13
14
  end
14
15
 
15
16
  def keypress(event)
16
- exit if event.value == "q" || event.value == "\e" || event.value == "x"
17
+ key = event.value.downcase
18
+ exit if key == "q" || key == "\e" || key == "x"
17
19
  return if @pet.busy? || @pet.dead?
18
- onkey(event)
20
+ @page -= 1 if event.key.name == :left && @page > 0
21
+ @page += 1 if event.key.name == :right && @page < action_pages.count - 1
22
+ keyact = self.actions.keys.find{|k| k[0].to_s.downcase == key}
23
+ if !keyact.nil?
24
+ actions[keyact].call
25
+ elsif !self.actions[:else].nil?
26
+ actions[:else].call
27
+ end
19
28
  end
20
29
 
21
- def onkey(event)
30
+ def actions
31
+ {}
22
32
  end
23
33
 
24
- def actions
25
- %w()
34
+ def action_pages
35
+ pages = []
36
+ current_page = []
37
+ fmt_actions = self.actions.filter{|a,b| a != :else}.keys.map{|a| "[#{a[0].capitalize}]#{a[1..]}"}
38
+ fmt_actions.each do |action|
39
+ len = (current_page + [action]).join(" ").length
40
+ if len >= GAME_WIDTH-2
41
+ pages << [current_page, current_page.join(" ").length]
42
+ current_page = [action]
43
+ else
44
+ current_page << action
45
+ end
46
+ end
47
+ pages + [[current_page, current_page.join(" ").length]]
26
48
  end
27
49
 
28
50
  def action_bar
29
- return "" if @pet.dead?
51
+ return "" if @pet.dead? || @pet.busy?
52
+ pages = action_pages
30
53
  p = Pastel.new
31
- self.actions.map do |a|
32
- key = p.bold("[#{a[0].capitalize}]")
33
- "#{key}#{a[1..]}"
34
- end.join(" ")
54
+ page, page_len = pages[@page]
55
+ bar = p.bold(@page > 0 ? "◀" : "◁")
56
+ bar += page.map {|a| "#{p.bold(a[0..2])}#{a[3..]}"}.join(" ")
57
+ bar += (' ' * (GAME_WIDTH-page_len-4))
58
+ bar += p.bold(pages.count > 1 && @page < pages.count - 1 ? "▶" : "▷")
59
+ bar
35
60
  end
36
61
 
37
62
  def left
@@ -55,9 +80,9 @@ module Petli
55
80
  top: top,
56
81
  )
57
82
 
58
- poop = @poop.step
83
+ poop = @poop.next
59
84
  @pet.poops.each_with_index do |_, i|
60
- x, y = Poop::LOCATIONS[i]
85
+ x, y = Pet::POOP_LOCATIONS[i]
61
86
  render_at(left+1+x, top+1+y, poop)
62
87
  end
63
88
 
@@ -67,7 +92,7 @@ module Petli
67
92
  render_at(left+11-sick, top+4, "[#{'!'*sick}SICK#{'!'*sick}]")
68
93
  end
69
94
 
70
- render_at(left+1, top+1, "#{p.red("♥")*@pet.health}#{"♡"*(10-@pet.health)} #{"☺"*(10-@pet.happiness)}#{p.green("☻")*@pet.happiness}")
95
+ render_at(left+1, top+1, "#{p.red("♥")*@pet.health}#{"♡"*(10-@pet.health)} #{@pet.sick > 0 ? p.red("☠") : "☠"}#{@pet.lights_out ? "☼" : p.yellow("☀")} #{"☺"*(10-@pet.happiness)}#{p.green("☻")*@pet.happiness}")
71
96
  render_at(left+1, top+GAME_HEIGHT-2, self.action_bar)
72
97
  render_at(left+GAME_WIDTH-2, top, p.bright_white.bold("[x]"))
73
98
  end
@@ -10,7 +10,10 @@ module Petli
10
10
  end
11
11
 
12
12
  def actions
13
- %w(higher lower)
13
+ {
14
+ higher: -> {pick("h")},
15
+ lower: -> {pick("l")},
16
+ }
14
17
  end
15
18
 
16
19
  def enter
@@ -24,13 +27,12 @@ module Petli
24
27
  def roll
25
28
  end
26
29
 
27
- def onkey(event)
28
- return if event.value != "h" and event.value != "l"
29
- @pickedhigher = event.value == "h"
30
+ def pick(dir)
30
31
  @pick = (1..6).to_a.sample
31
- @won = (event.value == "h" && @pick > @value) || (event.value == "l" && @pick < @value)
32
+ @pickedhigher = dir == "h"
33
+ @won = (dir == "h" && @pick > @value) || (dir == "l" && @pick < @value)
32
34
  @won ? @pet.celebrate : @pet.embarass
33
- @countdown = 20
35
+ @countdown = 10
34
36
  end
35
37
 
36
38
  def draw
@@ -2,17 +2,17 @@ module Petli
2
2
  module Stages
3
3
  class Feed < Base
4
4
  def actions
5
- %w(bread snack med)
5
+ acts = {
6
+ bread: -> {feed(:bread)},
7
+ snack: -> {feed(:candy)},
8
+ else: -> {goto(Main, pet: @pet)},
9
+ }
10
+ acts[:med] = -> {feed(:medicine)} if @pet.sick?
11
+ acts
6
12
  end
7
13
 
8
- def onkey(event)
9
- if event.value == "b"
10
- @pet.feed(food: :bread)
11
- elsif event.value == "s"
12
- @pet.feed(food: :candy)
13
- elsif event.value == "m"
14
- @pet.feed(food: :medicine)
15
- end
14
+ def feed(food)
15
+ @pet.feed(food: food)
16
16
  goto(Main, pet: @pet)
17
17
  end
18
18
  end
@@ -8,7 +8,10 @@ module Petli
8
8
  end
9
9
 
10
10
  def actions
11
- %w(left right)
11
+ {
12
+ left: -> {pick("l")},
13
+ right: -> {pick("r")},
14
+ }
12
15
  end
13
16
 
14
17
  def enter
@@ -19,12 +22,11 @@ module Petli
19
22
  @pet.reset
20
23
  end
21
24
 
22
- def onkey(event)
23
- return if event.value != "l" and event.value != "r"
25
+ def pick(dir)
24
26
  @petpickedleft = rand(1..2) == 1
25
- @pickedleft = event.value == "l"
27
+ @pickedleft = dir == "l"
26
28
  (@petpickedleft == @pickedleft) ? @pet.celebrate : @pet.embarass
27
- @countdown = 20
29
+ @countdown = 10
28
30
  end
29
31
 
30
32
  def draw
@@ -2,16 +2,15 @@ module Petli
2
2
  module Stages
3
3
  class Main < Base
4
4
  def actions
5
- acts = %w(play feed)
6
- acts << "clean" if @pet.poops.count > 0
5
+ return {light: -> {@pet.light_switch}} if @pet.lights_out
6
+ acts = {
7
+ play: -> {goto(Play, pet: @pet)},
8
+ feed: -> {goto(Feed, pet: @pet)},
9
+ light: -> {@pet.light_switch},
10
+ }
11
+ acts[:clean] = -> {@pet.clean} if @pet.poops.count > 0
7
12
  acts
8
13
  end
9
-
10
- def onkey(event)
11
- return goto(Feed, pet: @pet) if event.value == "f"
12
- return @pet.clean if event.value == "c"
13
- return goto(Play, pet: @pet) if event.value == "p"
14
- end
15
14
  end
16
15
  end
17
16
  end
@@ -2,13 +2,11 @@ module Petli
2
2
  module Stages
3
3
  class Play < Base
4
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)
5
+ {
6
+ guess: -> {goto(Guess, pet: @pet)},
7
+ dice: -> {goto(Dice, pet: @pet)},
8
+ else: -> {goto(Main, pet: @pet)},
9
+ }
12
10
  end
13
11
  end
14
12
  end
data/lib/petli/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Petli
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/petli/watch.rb CHANGED
@@ -15,6 +15,11 @@ module Petli
15
15
  time_elapsed(last, HOURS_DIV)
16
16
  end
17
17
 
18
+ def for_hours_since(last)
19
+ hours_past = hours_since(last)
20
+ (0...hours_past).each { |i| yield(i, hours_ago(i)) } if hours_past > 1
21
+ end
22
+
18
23
  def hours_ago(hrs)
19
24
  Time.now - (hrs * 3600)
20
25
  end
data/lib/petli.rb CHANGED
@@ -1,9 +1,14 @@
1
1
  module Petli
2
- autoload :Animator, "petli/animator"
3
- autoload :HUD, "petli/hud"
4
2
  autoload :Pet, "petli/pet"
5
- autoload :Poop, "petli/poop"
6
3
  autoload :Stages, "petli/Stages"
7
- autoload :Watch, "petli/watch"
8
4
  autoload :VERSION, "petli/version"
5
+ autoload :Watch, "petli/watch"
6
+
7
+ def self.root
8
+ File.expand_path(File.join(__dir__, '..'))
9
+ end
10
+
11
+ def self.data_path(*filepaths)
12
+ File.join(root, 'data', *filepaths)
13
+ end
9
14
  end
data/lib/tatty/anim.rb CHANGED
@@ -1,18 +1,60 @@
1
1
  module Tatty
2
2
  class Anim
3
- def initialize(atlas, frame: 0, rate: 2)
3
+ attr_reader :width, :height, :loop, :rate, :name
4
+
5
+ def self.from_atlas(filepath, name: :default)
6
+ Atlas.new(filepath)[name]
7
+ end
8
+
9
+ def initialize(atlas, width:, height:, **kargs)
4
10
  @atlas = atlas
5
- @frame = frame
6
- @rate = rate
11
+ @rate = kargs[:speed] || 2
12
+ @loop = kargs[:loop] || false
13
+ if kargs[:loop_for].nil?
14
+ @loop_for = -1
15
+ else
16
+ @loop = false
17
+ @loop_for_start = kargs[:loop_for] || -1
18
+ @loop_for = @loop_for_start
19
+ end
20
+ @name = kargs[:name]
21
+ @width = width
22
+ @height = height
23
+ reset
24
+ end
25
+
26
+ def reset
27
+ @frame = 0
28
+ @loop_for = @loop_for_start if @loop_for == 0
7
29
  end
8
30
 
9
31
  def step
10
32
  @frame += 1
11
- @frame = 0 if self.frame >= @atlas.count
12
- @atlas[self.frame]
33
+ if rate_frame >= @atlas.count
34
+ reset if self.loop
35
+ @loop_for -= 1 if @loop_for > 0
36
+ true
37
+ else
38
+ false
39
+ end
40
+ end
41
+
42
+ def display
43
+ @atlas[rate_frame]
44
+ end
45
+
46
+ def next
47
+ step
48
+ display
13
49
  end
14
50
 
15
- def frame
51
+ def loop
52
+ @loop || @loop_for > 0
53
+ end
54
+
55
+ private
56
+
57
+ def rate_frame
16
58
  (@frame/@rate).ceil
17
59
  end
18
60
  end
@@ -0,0 +1,78 @@
1
+ require 'yaml'
2
+
3
+ module Tatty
4
+ class Atlas
5
+ def initialize(filepath)
6
+ @filepath = File.expand_path(filepath)
7
+ @sheet = {}
8
+ parse_data
9
+ end
10
+
11
+ def [](name)
12
+ @sheet[name.to_sym]
13
+ end
14
+
15
+ def names
16
+ @sheet.keys
17
+ end
18
+
19
+ private
20
+
21
+ def parse_data
22
+ chunks = File.read(@filepath).split(/^---.*$/)
23
+ shouldBeYaml = true
24
+ default_config = {name: :default}.merge(parse_yaml(chunks.first))
25
+ default_config.delete(:alias)
26
+ config = {}
27
+ chunks.each do |chunk|
28
+ if shouldBeYaml
29
+ config = default_config.merge(parse_yaml(chunk))
30
+ else
31
+ validate_config(config)
32
+ animation = Anim.new(parse_animation(chunk, config), **config)
33
+ ([config[:name]] + Array(config[:alias])).map(&:to_sym).each do |name|
34
+ @sheet[name] = animation
35
+ end
36
+ end
37
+ shouldBeYaml = !shouldBeYaml
38
+ end
39
+ end
40
+
41
+ def validate_config(config)
42
+ name = config[:name].to_sym
43
+ if name.nil?
44
+ raise "All animations in an atlas need to have a name attribute"
45
+ elsif !@sheet[name].nil?
46
+ raise "Duplicate animation name '#{name}'"
47
+ elsif config[:width].nil? || config[:height].nil?
48
+ raise "Animation '#{name}' does not have a width and/or height attribute"
49
+ end
50
+ end
51
+
52
+ def parse_yaml(chunk)
53
+ YAML.load(chunk).each_with_object({}) { |(k,v), h| h[k.to_sym] = v }
54
+ rescue
55
+ raise "unable to parse chunk #{chunk}"
56
+ end
57
+
58
+ def parse_animation(chunk, config)
59
+ width, height = config[:width], config[:height]
60
+ frames = []
61
+ frame_offset = 0
62
+ chunk.lines.each_slice(height+1).to_a.each do |frame_line|
63
+ frame_line.each do |line|
64
+ i = 0
65
+ while line.length > 1
66
+ frames[frame_offset+i] ||= []
67
+ frames[frame_offset+i] << line.slice!(0, width)
68
+ line.slice!(0, 1) # separator
69
+ i+=1
70
+ end
71
+ end
72
+ frame_offset = frames.count
73
+ end
74
+ frames.map {|f| f.join("\n") }
75
+ end
76
+ end
77
+ end
78
+
data/lib/tatty/stage.rb CHANGED
@@ -19,6 +19,9 @@ module Tatty
19
19
  ::Tatty.goto(klass, **kargs)
20
20
  end
21
21
 
22
+ def keypress(evt)
23
+ end
24
+
22
25
  def screen_size
23
26
  TTY::Screen.size
24
27
  end
data/lib/tatty.rb CHANGED
@@ -3,15 +3,14 @@ module Tatty
3
3
  require 'tty-cursor'
4
4
 
5
5
  autoload :Anim, "tatty/anim"
6
+ autoload :Atlas, "tatty/atlas"
6
7
  autoload :DB, "tatty/db"
7
8
  autoload :Stage, "tatty/stage"
8
9
 
9
10
  def self.run(klass, **kargs)
10
11
  self.goto(klass, **kargs)
11
- @reader = TTY::Reader.new
12
- @reader.on(:keypress) do |event|
13
- self.stage.keypress(event)
14
- end
12
+ @reader = TTY::Reader.new(track_history: false)
13
+ @reader.on(:keypress){|e| self.stage.keypress(e)}
15
14
 
16
15
  begin
17
16
  TTY::Cursor.invisible do
data/petli.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  HERE
25
25
  s.metadata = { "source_code_uri" => "https://github.com/tanema/petli" }
26
26
 
27
- s.files = Dir.glob('{bin/*,lib/**/*,data/*,[A-Z]*}')
27
+ s.files = Dir.glob('{bin/*,lib/**/*,data/**/*,[A-Z]*}')
28
28
  s.bindir = "bin"
29
29
  s.executables = ["petli"]
30
30
  s.require_paths = ['lib']
@@ -33,7 +33,7 @@ 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-screen", "~> 0.8.1")
36
+ s.add_dependency("tty-screen", "~> 0.8.2")
37
37
  s.add_dependency("tty-reader", "~> 0.9.0")
38
38
  s.add_dependency("tty-color", "~> 0.6.0")
39
39
  s.add_dependency("tty-box", "~> 0.7.0")
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: petli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Anema
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-10-13 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: pastel
@@ -44,14 +43,14 @@ dependencies:
44
43
  requirements:
45
44
  - - "~>"
46
45
  - !ruby/object:Gem::Version
47
- version: 0.8.1
46
+ version: 0.8.2
48
47
  type: :runtime
49
48
  prerelease: false
50
49
  version_requirements: !ruby/object:Gem::Requirement
51
50
  requirements:
52
51
  - - "~>"
53
52
  - !ruby/object:Gem::Version
54
- version: 0.8.1
53
+ version: 0.8.2
55
54
  - !ruby/object:Gem::Dependency
56
55
  name: tty-reader
57
56
  requirement: !ruby/object:Gem::Requirement
@@ -110,7 +109,7 @@ dependencies:
110
109
  version: 0.3.0
111
110
  description: 'A virtual pet that will live in your command line!
112
111
 
113
- '
112
+ '
114
113
  email:
115
114
  - timanema@gmail.com
116
115
  executables:
@@ -123,14 +122,28 @@ files:
123
122
  - LICENSE
124
123
  - README.md
125
124
  - Rakefile
125
+ - bin/anim
126
+ - bin/bootstrap.rb
126
127
  - bin/console
127
128
  - bin/petli
128
- - data/character.json
129
- - data/face_ref
129
+ - data/adult/001_diddly.txtanim
130
+ - data/adult/002_kirby.txtanim
131
+ - data/adult/003_tama.txtanim
132
+ - data/adult/004_big.txtanim
133
+ - data/adult/005_angel.txtanim
134
+ - data/death.txtanim
135
+ - data/hatch.txtanim
136
+ - data/infant/001_baby.txtanim
137
+ - data/poop.txtanim
138
+ - data/sleep.txtanim
139
+ - data/teen/001_baloop.txtanim
140
+ - data/teen/002_roboty.txtanim
130
141
  - lib/petli.rb
131
- - lib/petli/animator.rb
132
142
  - lib/petli/pet.rb
133
- - lib/petli/poop.rb
143
+ - lib/petli/pet/animation.rb
144
+ - lib/petli/pet/death.rb
145
+ - lib/petli/pet/food.rb
146
+ - lib/petli/pet/happy.rb
134
147
  - lib/petli/stages.rb
135
148
  - lib/petli/stages/base.rb
136
149
  - lib/petli/stages/dice.rb
@@ -142,6 +155,7 @@ files:
142
155
  - lib/petli/watch.rb
143
156
  - lib/tatty.rb
144
157
  - lib/tatty/anim.rb
158
+ - lib/tatty/atlas.rb
145
159
  - lib/tatty/db.rb
146
160
  - lib/tatty/stage.rb
147
161
  - petli.gemspec
@@ -170,8 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
184
  - !ruby/object:Gem::Version
171
185
  version: '0'
172
186
  requirements: []
173
- rubygems_version: 3.0.3
174
- signing_key:
187
+ rubygems_version: 3.6.7
175
188
  specification_version: 4
176
189
  summary: A little pet in your console
177
190
  test_files: []
191
+ ...
data/data/character.json DELETED
@@ -1,40 +0,0 @@
1
- {
2
- "eyes": {
3
- "default": ["O"],
4
- "mezmerized": ["◉", "✧", "☯"],
5
- "great": ["^", "O"],
6
- "happy": ["O", "o"],
7
- "tired": ["ළ", "ತ"],
8
- "annoyed": ["⊜", "ಠ"],
9
- "angry": ["ಠ"],
10
- "embarassed": ["ಥ"],
11
- "eating": ["O", ["ᗒ", "ᗕ"]],
12
- "sick": [["⨴","⨵"],"ꔸ"]
13
- },
14
- "mouth": {
15
- "default": ["_", "."],
16
- "mezmerized": ["ᴥ", "O"],
17
- "great": ["▽", "‿"],
18
- "happy": ["o", "_"],
19
- "tired": ["-", "."],
20
- "annoyed": ["_", "-"],
21
- "angry": ["益", "෴"],
22
- "embarassed": ["◠", "-"],
23
- "eating": ["▽", "‿"],
24
- "sick": ["▱","﹃"]
25
- },
26
- "arms": {
27
- "default": [["ᕠ", "ᕤ"], ["ᕦ", "ᕡ"]],
28
- "plain": ["_", "~"],
29
- "tired": ["_", "~"],
30
- "embarassed": [["乁","ㄏ"], "_"],
31
- "eating": [["\\", "/"], "_"],
32
- "sick": ["_", "~"]
33
- },
34
- "head": {
35
- "default": [["(", ")"]]
36
- },
37
- "bread": "ʕ=ʔ",
38
- "candy": "▷☯◁",
39
- "medicine": "◖◻◗"
40
- }
data/data/face_ref DELETED
@@ -1,73 +0,0 @@
1
- ☠⚕
2
- (o . o)
3
- (o _ o)
4
- (o _ O)
5
- (O _ O)
6
- (* ^ *)
7
- (O _ o)
8
- (ʘ _ ʘ)
9
- (u _ u)
10
- (^ _ ^)
11
- (ಠ _ ಠ)
12
- (^ o ^)
13
- (◉ ᴥ ◉)
14
- (o O o)
15
- (o - o)
16
- (- _ -)
17
- (T _ T)
18
- (ಥ _ ಥ)
19
- (ಠ 益ಠ)
20
- (ಠ ෴ ಠ)
21
- (ᴗ □ ᴗ)
22
- ☆゚☆゚☆゚☆゚
23
- (o ‿ o)
24
- (ᗒ o ᗕ)
25
- (⇀ - ↼)
26
- (⨴ _ ⨵)
27
- (ꔸ _ ꔸ)
28
- (ළ _ ළ) # tired
29
- (ತ _ ತ)
30
- (⊜ _ ⊜)
31
- (✧ _ ✧)
32
- (☯ _ ☯)
33
-
34
- \(⇀ O ↼)/ ʕ=ʔ
35
- _(O _ O)_ =ʔ
36
- \(⇀ O ↼)/ =ʔ
37
- _(O _ O)_ ʔ
38
- \(⇀ O ↼)/ ʔ
39
- _(O _ O)_
40
- (◉ ᴥ ◉)
41
- (o O o)
42
-
43
- ξꔸ ꔸ)
44
-
45
- ☛(O _ O)☛
46
- ☚(O _ O)☚
47
- 乁(O _ O)ㄏ
48
- _(O _ O)_
49
- ᕠ(O _ O)ᕤ
50
- ᕦ(O _ O)ᕡ
51
- \(O _ O)/
52
- /(O _ O)\
53
-
54
- ߍ೧
55
- ༼ºل͟º༽
56
-
57
- poop friend
58
- ı ┐ ┌ ┌ ı ı ı ┌ ┐ ┐ ı ı
59
- ༼ᵔ◡ᵔ༽ ༼ಠ益ಠ༽ ༼ᵔ◡ᵔ༽ ༼ಠ益ಠ༽
60
-
61
- ⚀ ⚁ ⚂ ⚃ ⚄ ⚅
62
-
63
- _
64
- (O O)
65
- |-|
66
-
67
-
68
-
69
- ┌───┐
70
- │ ☠ │
71
- │ │
72
- ```````
73
-