petli 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +4 -1
- data/bin/anim +29 -0
- data/bin/bootstrap.rb +3 -0
- data/bin/console +1 -1
- data/bin/petli +1 -2
- data/data/adult/001_diddly.txtanim +91 -0
- data/data/adult/002_kirby.txtanim +91 -0
- data/data/adult/003_tama.txtanim +85 -0
- data/data/adult/004_big.txtanim +62 -0
- data/data/adult/005_angel.txtanim +91 -0
- data/data/death.txtanim +9 -0
- data/data/hatch.txtanim +8 -0
- data/data/infant/001_baby.txtanim +80 -0
- data/data/poop.txtanim +6 -0
- data/data/sleep.txtanim +16 -0
- data/data/teen/001_baloop.txtanim +91 -0
- data/data/teen/002_roboty.txtanim +91 -0
- data/lib/petli/pet/animation.rb +94 -0
- data/lib/petli/pet/death.rb +21 -0
- data/lib/petli/pet/food.rb +42 -0
- data/lib/petli/pet/happy.rb +34 -0
- data/lib/petli/pet.rb +18 -116
- data/lib/petli/stages/base.rb +31 -12
- data/lib/petli/stages/dice.rb +1 -1
- data/lib/petli/stages/guess.rb +1 -1
- data/lib/petli/stages/main.rb +4 -1
- data/lib/petli/version.rb +1 -1
- data/lib/petli/watch.rb +5 -0
- data/lib/petli.rb +9 -4
- data/lib/tatty/anim.rb +48 -6
- data/lib/tatty/atlas.rb +74 -0
- data/lib/tatty/stage.rb +3 -0
- data/lib/tatty.rb +1 -0
- data/petli.gemspec +1 -1
- metadata +26 -10
- data/data/character.json +0 -40
- data/data/face_ref +0 -73
- data/lib/petli/animator.rb +0 -137
- data/lib/petli/poop.rb +0 -9
data/data/sleep.txtanim
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
width: 11
|
2
|
+
height: 4
|
3
|
+
loop: true
|
4
|
+
name: sleep
|
5
|
+
---
|
6
|
+
| | z |
|
7
|
+
| z | |
|
8
|
+
‿ z | ‿ ‿ | ‿ ‿ |
|
9
|
+
‾ | ° | ‾ |
|
10
|
+
---
|
11
|
+
name: blink
|
12
|
+
---
|
13
|
+
| | | | | | | |
|
14
|
+
| | | | | | | |
|
15
|
+
. . | _ _ | . . | _ _ | . . | . . | . . | . . |
|
16
|
+
‾ | ‾ | ‾ | ‾ | ‾ | ‾ | ‾ | ‾ |
|
@@ -0,0 +1,91 @@
|
|
1
|
+
width: 11
|
2
|
+
height: 4
|
3
|
+
loop: true
|
4
|
+
name: walk_great
|
5
|
+
---
|
6
|
+
| | | |
|
7
|
+
|ᕦ(O ‿ O )ᕡ | |ᕦ( O ‿ O)ᕡ |
|
8
|
+
ᕠ(^ ▽ ^)ᕤ | |ᕠ(^ ▽ ^)ᕤ | |
|
9
|
+
| | | |
|
10
|
+
---
|
11
|
+
name: walk_happy
|
12
|
+
---
|
13
|
+
| | | |
|
14
|
+
| | | |
|
15
|
+
ᕠ(O o O)ᕤ |ᕦ(o _ o )ᕡ |ᕠ(O o O)ᕤ |ᕦ( o _ o)ᕡ |
|
16
|
+
| | | |
|
17
|
+
---
|
18
|
+
name: walk_normal
|
19
|
+
---
|
20
|
+
| | | |
|
21
|
+
| | | |
|
22
|
+
ᕠ(O . O)ᕤ |ᕦ(O _ O )ᕡ |ᕠ(O . O)ᕤ |ᕦ( O _ O)ᕡ |
|
23
|
+
| | | |
|
24
|
+
---
|
25
|
+
name: walk_annoyed
|
26
|
+
---
|
27
|
+
| | | |
|
28
|
+
| | | |
|
29
|
+
ᕠ(⊜ _ ⊜)ᕤ |ᕦ(ಠ - ಠ )ᕡ |ᕠ(⊜ _ ⊜)ᕤ |ᕦ( ಠ - ಠ)ᕡ |
|
30
|
+
| | | |
|
31
|
+
---
|
32
|
+
name: walk_angry
|
33
|
+
---
|
34
|
+
| | | |
|
35
|
+
| | | |
|
36
|
+
ᕠ(ಠ 益 ಠ)ᕤ |ᕦ(ಠ ෴ ಠ )ᕡ |ᕠ(ಠ 益 ಠ)ᕤ |ᕦ( ಠ ෴ ಠ)ᕡ |
|
37
|
+
| | | |
|
38
|
+
---
|
39
|
+
name: walk_sick
|
40
|
+
---
|
41
|
+
| | | |
|
42
|
+
| | | |
|
43
|
+
_(ළ - ළ)_ |~(ತ . ತ )~ |_(ළ - ළ)_ |~( ತ . ತ)~ |
|
44
|
+
| | | |
|
45
|
+
---
|
46
|
+
name: stand
|
47
|
+
---
|
48
|
+
| |
|
49
|
+
| |
|
50
|
+
ᕠ(O . O)ᕤ | ᕦ(O _ O)ᕡ |
|
51
|
+
| |
|
52
|
+
---
|
53
|
+
name: celebrate
|
54
|
+
loop_for: 3
|
55
|
+
---
|
56
|
+
| |
|
57
|
+
| |
|
58
|
+
ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ |
|
59
|
+
| |
|
60
|
+
---
|
61
|
+
name: embarass
|
62
|
+
loop_for: 3
|
63
|
+
---
|
64
|
+
| |
|
65
|
+
| |
|
66
|
+
ᕠ(ಥ ◠ ಥ)ᕤ | ᕦ(ಥ - ಥ)ᕡ |
|
67
|
+
| |
|
68
|
+
---
|
69
|
+
name: eat_bread
|
70
|
+
loop: false
|
71
|
+
---
|
72
|
+
| | | | | | | | | | | | | |
|
73
|
+
| | | | | | | | | | | | | |
|
74
|
+
ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ |
|
75
|
+
ʕ=ʔ | ʕ=ʔ | ʕ=ʔ | ʕ=ʔ | ʕ=ʔ | =ʔ | =ʔ | ʔ | ʔ | | | | | |
|
76
|
+
---
|
77
|
+
name: eat_candy
|
78
|
+
loop: false
|
79
|
+
---
|
80
|
+
| | | | | | | | | | | | | |
|
81
|
+
| | | | | | | | | | | | | |
|
82
|
+
ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ |
|
83
|
+
▷☯◁ | ▷☯◁ | ▷☯◁ | ▷☯◁ | ▷☯◁ | ☯◁ | ☯◁ | ◁ | ◁ | | | | | |
|
84
|
+
---
|
85
|
+
name: eat_medicine
|
86
|
+
loop: false
|
87
|
+
---
|
88
|
+
| | | | | | | | | | | | | |
|
89
|
+
| | | | | | | | | | | | | |
|
90
|
+
ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | \(O ▽ O)/ | _(ᗒ ‿ ᗕ)_ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ | ᕠ(☯ ᴥ ☯)ᕤ | ᕦ(✧ O ✧)ᕡ |
|
91
|
+
◖◻◗ | ◖◻◗ | ◖◻◗ | ◖◻◗ | ◖◻◗ | ◻◗ | ◻◗ | ◗ | ◗ | | | | | |
|
@@ -0,0 +1,91 @@
|
|
1
|
+
width: 11
|
2
|
+
height: 4
|
3
|
+
loop: true
|
4
|
+
name: walk_great
|
5
|
+
---
|
6
|
+
| | | |
|
7
|
+
|_[▢ ‿ ▢ ]_ | |_[ ▢ ‿ ▢]_ |
|
8
|
+
\[‾ ▽ ‾]/ | |\[‾ ▽ ‾]/ | |
|
9
|
+
| | | |
|
10
|
+
---
|
11
|
+
name: walk_happy
|
12
|
+
---
|
13
|
+
| | | |
|
14
|
+
| | | |
|
15
|
+
\[▢ ▫ ▢]/ |_[▢ _ ▢ ]_ |\[▢ ▫ ▢]/ |_[ ▢ _ ▢]_ |
|
16
|
+
| | | |
|
17
|
+
---
|
18
|
+
name: walk_normal
|
19
|
+
---
|
20
|
+
| | | |
|
21
|
+
| | | |
|
22
|
+
\[□ . □]/ |_[□ _ □ ]_ |\[□ . □]/ |_[ □ _ □]_ |
|
23
|
+
| | | |
|
24
|
+
---
|
25
|
+
name: walk_annoyed
|
26
|
+
---
|
27
|
+
| | | |
|
28
|
+
| | | |
|
29
|
+
\[⟥ _ ⟤]/ |_[⟥ - ⟤ ]_ |\[⟥ _ ⟤]/ |_[ ⟥ - ⟤]_ |
|
30
|
+
| | | |
|
31
|
+
---
|
32
|
+
name: walk_angry
|
33
|
+
---
|
34
|
+
| | | |
|
35
|
+
| | | |
|
36
|
+
\[⧅ ~ ⧅]/ |_[◫ ෴ ◫ ]_ |\[⧅ ~ ⧅]/ |_[ ◫ ෴ ◫]_ |
|
37
|
+
| | | |
|
38
|
+
---
|
39
|
+
name: walk_sick
|
40
|
+
---
|
41
|
+
| | | |
|
42
|
+
| | | |
|
43
|
+
_[▫ - ▫]_ |~[▪ . ▪ ]~ |_[▫ - ▫]_ |~[ ▪ . ▪]~ |
|
44
|
+
| | | |
|
45
|
+
---
|
46
|
+
name: stand
|
47
|
+
---
|
48
|
+
| |
|
49
|
+
| |
|
50
|
+
\[▢ ▫ ▢]/ | _[▢ _ ▢]_ |
|
51
|
+
| |
|
52
|
+
---
|
53
|
+
name: celebrate
|
54
|
+
loop_for: 3
|
55
|
+
---
|
56
|
+
| |
|
57
|
+
| |
|
58
|
+
\[⛋ - ⛋]/ | _[◰ ▢ ◰]_ |
|
59
|
+
| |
|
60
|
+
---
|
61
|
+
name: embarass
|
62
|
+
loop_for: 3
|
63
|
+
---
|
64
|
+
| |
|
65
|
+
| |
|
66
|
+
\[ಥ ◠ ಥ]/ | _[ಥ - ಥ]_ |
|
67
|
+
| |
|
68
|
+
---
|
69
|
+
name: eat_bread
|
70
|
+
loop: false
|
71
|
+
---
|
72
|
+
| | | | | | | | | | | | | |
|
73
|
+
| | | | | | | | | | | | | |
|
74
|
+
\[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ |
|
75
|
+
ʕ=ʔ | ʕ=ʔ | ʕ=ʔ | ʕ=ʔ | ʕ=ʔ | =ʔ | =ʔ | ʔ | ʔ | | | | | |
|
76
|
+
---
|
77
|
+
name: eat_candy
|
78
|
+
loop: false
|
79
|
+
---
|
80
|
+
| | | | | | | | | | | | | |
|
81
|
+
| | | | | | | | | | | | | |
|
82
|
+
\[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ |
|
83
|
+
▷☯◁ | ▷☯◁ | ▷☯◁ | ▷☯◁ | ▷☯◁ | ☯◁ | ☯◁ | ◁ | ◁ | | | | | |
|
84
|
+
---
|
85
|
+
name: eat_medicine
|
86
|
+
loop: false
|
87
|
+
---
|
88
|
+
| | | | | | | | | | | | | |
|
89
|
+
| | | | | | | | | | | | | |
|
90
|
+
\[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[▫ □ ▫]/ | _[ᗒ ‿ ᗕ]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ | \[⛋ - ⛋]/ | _[◰ ▢ ◰]_ |
|
91
|
+
◖◻◗ | ◖◻◗ | ◖◻◗ | ◖◻◗ | ◖◻◗ | ◻◗ | ◻◗ | ◗ | ◗ | | | | | |
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Petli
|
2
|
+
class Pet
|
3
|
+
module Animation
|
4
|
+
extend Tatty::DB::Attributes
|
5
|
+
db_attr :phase, default: :infant
|
6
|
+
db_attr :phase_select, default: 0
|
7
|
+
db_attr :lights_out, default: false
|
8
|
+
|
9
|
+
def setup_animation
|
10
|
+
hatch if (Time.now - self.birth) < 10
|
11
|
+
end
|
12
|
+
|
13
|
+
def update_animation
|
14
|
+
reset if animation.step && !animation.loop
|
15
|
+
if phase == :infant && hours_since(birth) > 1
|
16
|
+
self.phase = :teen
|
17
|
+
self.phase_select = rand(0...avail_animations[phase].count)
|
18
|
+
elsif phase == :teen && days_since(birth) > 1
|
19
|
+
self.phase = :adult
|
20
|
+
self.phase_select = rand(0...avail_animations[phase].count)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset
|
25
|
+
@doing = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def busy?
|
29
|
+
!@doing.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
def celebrate
|
33
|
+
react(:celebrate)
|
34
|
+
end
|
35
|
+
|
36
|
+
def embarass
|
37
|
+
react(:embarass)
|
38
|
+
end
|
39
|
+
|
40
|
+
def hatch
|
41
|
+
@doing = avail_animations[:hatch]
|
42
|
+
end
|
43
|
+
|
44
|
+
def light_switch
|
45
|
+
self.lights_out = !lights_out
|
46
|
+
self.happiness = [1, self.happiness-1].max if self.lights_out && !sleeping?
|
47
|
+
end
|
48
|
+
|
49
|
+
def sleeping?
|
50
|
+
hour = Time.now.hour
|
51
|
+
hour >= 16 || hour <= 8
|
52
|
+
end
|
53
|
+
|
54
|
+
def react(action)
|
55
|
+
anim = atlas[action]
|
56
|
+
anim.reset
|
57
|
+
@doing = anim
|
58
|
+
end
|
59
|
+
|
60
|
+
def animation
|
61
|
+
if self.dead?
|
62
|
+
avail_animations[:death]
|
63
|
+
elsif !@doing.nil?
|
64
|
+
@doing
|
65
|
+
elsif self.lights_out
|
66
|
+
if sleeping?
|
67
|
+
avail_animations[:sleep][:sleep]
|
68
|
+
else
|
69
|
+
avail_animations[:sleep][:blink]
|
70
|
+
end
|
71
|
+
elsif self.sick > 0
|
72
|
+
atlas[:walk_sick]
|
73
|
+
else
|
74
|
+
atlas["walk_#{self.mood}"]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def atlas
|
79
|
+
avail_animations[phase][phase_select]
|
80
|
+
end
|
81
|
+
|
82
|
+
def avail_animations
|
83
|
+
@avail_animations ||= {
|
84
|
+
hatch: Tatty::Anim.from_atlas(Petli.data_path('hatch.txtanim')),
|
85
|
+
infant: Dir[Petli.data_path('infant',"*.txtanim")].map {|p| Tatty::Atlas.new(p) },
|
86
|
+
teen: Dir[Petli.data_path('teen',"*.txtanim")].map {|p| Tatty::Atlas.new(p) },
|
87
|
+
adult: Dir[Petli.data_path('adult',"*.txtanim")].map {|p| Tatty::Atlas.new(p) },
|
88
|
+
death: Tatty::Anim.from_atlas(Petli.data_path('death.txtanim')),
|
89
|
+
sleep: Tatty::Atlas.new(Petli.data_path('sleep.txtanim')),
|
90
|
+
}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Petli
|
2
|
+
class Pet
|
3
|
+
module Death
|
4
|
+
extend Tatty::DB::Attributes
|
5
|
+
db_attr :birth, default: Time.now, readonly: true
|
6
|
+
db_attr :died_at
|
7
|
+
|
8
|
+
def check_if_dead
|
9
|
+
not_happy = self.happiness <= 1
|
10
|
+
not_healthy = self.health <= 1
|
11
|
+
is_sick = self.sick > 2
|
12
|
+
too_much_time = days_since(self.last_meal) >= 1
|
13
|
+
self.died_at = Time.now if not_happy && not_healthy && (is_sick || too_much_time)
|
14
|
+
end
|
15
|
+
|
16
|
+
def dead?
|
17
|
+
!self.died_at.nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Petli
|
2
|
+
class Pet
|
3
|
+
module Food
|
4
|
+
extend Tatty::DB::Attributes
|
5
|
+
|
6
|
+
POOP_LOCATIONS = [[1,1], [1,4], [1,7], [11,1], [11,7], [20,1], [20,4], [20,7]]
|
7
|
+
|
8
|
+
db_attr :health, default: 5
|
9
|
+
db_attr :last_meal, default: Time.now
|
10
|
+
db_attr :sick, default: 0
|
11
|
+
db_attr :poops, default: []
|
12
|
+
|
13
|
+
def update_hunger
|
14
|
+
for_hours_since(last_meal) do |i, hr_ago|
|
15
|
+
self.last_meal = Time.now
|
16
|
+
next if rand <= 0.3
|
17
|
+
self.health = [1, self.health-1].max
|
18
|
+
self.happiness = [1, self.happiness-1].max
|
19
|
+
self.poops << hr_ago if rand <= 0.8 && self.poops.count < POOP_LOCATIONS.count
|
20
|
+
self.sick = self.poops.filter{|poop| hours_since(poop) > 1 }.count
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def feed(food: :bread)
|
25
|
+
return self.embarass if ((food == :medicine && self.sick <= 0) || (self.health == 10 && food != :medicine))
|
26
|
+
self.last_meal = Time.now unless food == :medicine
|
27
|
+
react("eat_#{food}")
|
28
|
+
self.feed!(food: food)
|
29
|
+
end
|
30
|
+
|
31
|
+
def feed!(food: :bread)
|
32
|
+
self.health = [10, self.health+2].min unless food == :medicine
|
33
|
+
self.happiness = [10, self.happiness+2].min if food == :candy
|
34
|
+
self.sick = [0, self.sick - 1].max if food == :medicine
|
35
|
+
end
|
36
|
+
|
37
|
+
def clean
|
38
|
+
self.poops = []
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Petli
|
2
|
+
class Pet
|
3
|
+
module Happy
|
4
|
+
extend Tatty::DB::Attributes
|
5
|
+
MOOD_SCALE = %i(angry annoyed normal happy great)
|
6
|
+
|
7
|
+
db_attr :mood, default: :normal
|
8
|
+
db_attr :last_play, default: Time.now
|
9
|
+
db_attr :happiness, default: 5
|
10
|
+
|
11
|
+
def update_happiness
|
12
|
+
for_hours_since(last_play) do |i|
|
13
|
+
self.last_play = Time.now
|
14
|
+
next if rand <= 0.3
|
15
|
+
self.happiness = [[1, self.happiness-1].max, self.health <= 3 ? 5 : 10].min
|
16
|
+
end
|
17
|
+
self.mood = MOOD_SCALE[((self.happiness.to_f/10.0)*(MOOD_SCALE.count - 1)).floor]
|
18
|
+
end
|
19
|
+
|
20
|
+
def play(game: :dice)
|
21
|
+
self.last_play = Time.now
|
22
|
+
react(:stand)
|
23
|
+
end
|
24
|
+
|
25
|
+
def win
|
26
|
+
self.happiness = [10, self.happiness+1].min
|
27
|
+
end
|
28
|
+
|
29
|
+
def lose
|
30
|
+
# todo I dont really want it to become more unhappy if they lose
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/petli/pet.rb
CHANGED
@@ -1,131 +1,33 @@
|
|
1
1
|
module Petli
|
2
2
|
class Pet
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
autoload :Food, "petli/pet/food"
|
4
|
+
autoload :Happy, "petli/pet/happy"
|
5
|
+
autoload :Death, "petli/pet/death"
|
6
|
+
autoload :Animation, "petli/pet/animation"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
db_attr :last_play, default: Time.now
|
15
|
-
db_attr :last_meal, default: Time.now
|
16
|
-
db_attr :poops, default: []
|
8
|
+
extend Tatty::DB::Attributes
|
9
|
+
include Animation
|
10
|
+
include Death
|
11
|
+
include Food
|
12
|
+
include Happy
|
13
|
+
include Watch
|
17
14
|
|
18
15
|
def initialize
|
19
16
|
super()
|
20
|
-
|
21
|
-
hatching: (Time.now - self.birth) < 10,
|
22
|
-
mood: self.mood,
|
23
|
-
action: self.died_at.nil? ? :walk : :death
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
def reset
|
28
|
-
@animation.action = :walk
|
17
|
+
setup_animation
|
29
18
|
end
|
30
19
|
|
31
20
|
def display
|
32
|
-
return
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
next if rand <= 0.3
|
39
|
-
self.health = [1, self.health-1].max
|
40
|
-
self.happiness = [1, self.happiness-1].max
|
41
|
-
self.poops << hours_ago(i) if rand <= 0.8 && self.poops.count < Poop::LOCATIONS.count
|
42
|
-
end
|
43
|
-
self.sick = self.poops.filter{|poop| hours_since(poop) > 1 }.count
|
44
|
-
end
|
45
|
-
|
46
|
-
if hours_since(self.last_play) > 1
|
47
|
-
hours_past = hours_since(self.last_play)
|
48
|
-
self.last_play = Time.now
|
49
|
-
(0...hours_past).each do
|
50
|
-
next if rand <= 0.3
|
51
|
-
self.happiness = [1, self.happiness-1].max
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
self.happiness = [self.happiness, 5].min if self.health <= 3
|
56
|
-
self.mood = MOOD_SCALE[((self.happiness.to_f/10.0)*(MOOD_SCALE.count - 1)).floor ]
|
57
|
-
|
58
|
-
self.check_if_dead
|
59
|
-
|
60
|
-
@animation.mood = self.sick > 0 ? :sick : self.mood
|
61
|
-
@animation.step
|
62
|
-
end
|
63
|
-
|
64
|
-
def check_if_dead
|
65
|
-
not_happy = self.happiness <= 1
|
66
|
-
not_healthy = self.health <= 1
|
67
|
-
is_sick = self.sick > 2
|
68
|
-
too_much_time = days_since(self.last_meal) >= 1
|
69
|
-
|
70
|
-
if not_happy && not_healthy && (is_sick || too_much_time)
|
71
|
-
self.died_at = Time.now
|
72
|
-
@animation.action = :death
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def feed(food: :bread)
|
77
|
-
return self.embarass if ((food == :medicine && self.sick <= 0) || (self.health == 10 && food != :medicine))
|
78
|
-
self.last_meal = Time.now unless food == :medicine
|
79
|
-
@animation.eat(food: food) do
|
80
|
-
self.feed!(food: food)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def feed!(food: :bread)
|
85
|
-
self.health = [10, self.health+1].min unless food == :medicine
|
86
|
-
self.happiness = [10, self.happiness+1].min if food == :candy
|
87
|
-
self.sick = [0, self.sick - 1].max if food == :medicine
|
88
|
-
end
|
89
|
-
|
90
|
-
def win
|
91
|
-
self.happiness = [10, self.happiness+1].min
|
92
|
-
end
|
93
|
-
|
94
|
-
def lose
|
95
|
-
# todo I dont really want it to become more unhappy if they lose
|
96
|
-
end
|
97
|
-
|
98
|
-
def play(game: :dice)
|
99
|
-
self.last_play = Time.now
|
100
|
-
@animation.action = :stand
|
101
|
-
end
|
102
|
-
|
103
|
-
def clean
|
104
|
-
self.poops = []
|
105
|
-
end
|
106
|
-
|
107
|
-
def busy?
|
108
|
-
@animation.busy?
|
109
|
-
end
|
110
|
-
|
111
|
-
def dead?
|
112
|
-
@animation.action == :death
|
113
|
-
end
|
114
|
-
|
115
|
-
def celebrate
|
116
|
-
@animation.celebrate
|
117
|
-
end
|
118
|
-
|
119
|
-
def embarass
|
120
|
-
@animation.embarass
|
21
|
+
return animation.next if self.dead?
|
22
|
+
update_hunger
|
23
|
+
update_happiness
|
24
|
+
check_if_dead
|
25
|
+
update_animation
|
26
|
+
animation.display
|
121
27
|
end
|
122
28
|
|
123
29
|
def lifetime
|
124
|
-
|
125
|
-
days_since(self.birth).to_i
|
126
|
-
else
|
127
|
-
days_since(self.birth, self.died_at).to_i
|
128
|
-
end
|
30
|
+
(self.died_at.nil? ? days_since(self.birth) : days_since(self.birth, self.died_at)).to_i
|
129
31
|
end
|
130
32
|
end
|
131
33
|
end
|
data/lib/petli/stages/base.rb
CHANGED
@@ -9,29 +9,48 @@ module Petli
|
|
9
9
|
def initialize(pet:)
|
10
10
|
super()
|
11
11
|
@pet = pet
|
12
|
-
@poop =
|
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
17
|
exit if event.value == "q" || event.value == "\e" || event.value == "x"
|
17
18
|
return if @pet.busy? || @pet.dead?
|
19
|
+
@page -= 1 if event.key.name == :left && @page > 0
|
20
|
+
@page += 1 if event.key.name == :right && @page < action_pages.count - 1
|
18
21
|
onkey(event)
|
19
22
|
end
|
20
23
|
|
21
|
-
def onkey(event)
|
22
|
-
end
|
23
|
-
|
24
24
|
def actions
|
25
25
|
%w()
|
26
26
|
end
|
27
27
|
|
28
|
+
def action_pages
|
29
|
+
pages = []
|
30
|
+
current_page = []
|
31
|
+
fmt_actions = self.actions.map{|a| "[#{a[0].capitalize}]#{a[1..]}"}
|
32
|
+
fmt_actions.each do |action|
|
33
|
+
len = (current_page + [action]).join(" ").length
|
34
|
+
if len >= GAME_WIDTH-2
|
35
|
+
pages << [current_page, current_page.join(" ").length]
|
36
|
+
current_page = [action]
|
37
|
+
else
|
38
|
+
current_page << action
|
39
|
+
end
|
40
|
+
end
|
41
|
+
pages + [[current_page, current_page.join(" ").length]]
|
42
|
+
end
|
43
|
+
|
28
44
|
def action_bar
|
29
|
-
return "" if @pet.dead?
|
45
|
+
return "" if @pet.dead? || @pet.busy?
|
46
|
+
pages = action_pages
|
30
47
|
p = Pastel.new
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
48
|
+
page, page_len = pages[@page]
|
49
|
+
bar = p.bold(@page > 0 ? "◀" : "◁")
|
50
|
+
bar += page.map {|a| "#{p.bold(a[0..2])}#{a[3..]}"}.join(" ")
|
51
|
+
bar += (' ' * (GAME_WIDTH-page_len-4))
|
52
|
+
bar += p.bold(pages.count > 1 && @page < pages.count - 1 ? "▶" : "▷")
|
53
|
+
bar
|
35
54
|
end
|
36
55
|
|
37
56
|
def left
|
@@ -55,9 +74,9 @@ module Petli
|
|
55
74
|
top: top,
|
56
75
|
)
|
57
76
|
|
58
|
-
poop = @poop.
|
77
|
+
poop = @poop.next
|
59
78
|
@pet.poops.each_with_index do |_, i|
|
60
|
-
x, y =
|
79
|
+
x, y = Pet::POOP_LOCATIONS[i]
|
61
80
|
render_at(left+1+x, top+1+y, poop)
|
62
81
|
end
|
63
82
|
|
@@ -67,7 +86,7 @@ module Petli
|
|
67
86
|
render_at(left+11-sick, top+4, "[#{'!'*sick}SICK#{'!'*sick}]")
|
68
87
|
end
|
69
88
|
|
70
|
-
render_at(left+1, top+1, "#{p.red("♥")*@pet.health}#{"♡"*(10-@pet.health)}
|
89
|
+
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
90
|
render_at(left+1, top+GAME_HEIGHT-2, self.action_bar)
|
72
91
|
render_at(left+GAME_WIDTH-2, top, p.bright_white.bold("[x]"))
|
73
92
|
end
|
data/lib/petli/stages/dice.rb
CHANGED
data/lib/petli/stages/guess.rb
CHANGED
data/lib/petli/stages/main.rb
CHANGED
@@ -2,12 +2,15 @@ module Petli
|
|
2
2
|
module Stages
|
3
3
|
class Main < Base
|
4
4
|
def actions
|
5
|
-
|
5
|
+
return %w(light) if @pet.lights_out
|
6
|
+
acts = %w(play feed light)
|
6
7
|
acts << "clean" if @pet.poops.count > 0
|
7
8
|
acts
|
8
9
|
end
|
9
10
|
|
10
11
|
def onkey(event)
|
12
|
+
return @pet.light_switch if event.value == "l"
|
13
|
+
return if @pet.lights_out
|
11
14
|
return goto(Feed, pet: @pet) if event.value == "f"
|
12
15
|
return @pet.clean if event.value == "c"
|
13
16
|
return goto(Play, pet: @pet) if event.value == "p"
|
data/lib/petli/version.rb
CHANGED
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
|