bytepet-cli 0.1.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.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # ⚡ bytepet-cli
2
+
3
+ > A terminal pet that lives in your CLI — feed it, play with it, watch it grow.
4
+
5
+ ```
6
+ /\_____/\
7
+ ( ^ ^ )
8
+ ( =^.^= ) Pixel the Cat
9
+ (--m-m----) Level 3 · 45/300 XP
10
+
11
+ ❤️ Health ██████████ 100%
12
+ 🍖 Hunger ███████░░░ 70%
13
+ 😊 Happiness ████████░░ 80%
14
+ ⚡ Energy █████░░░░░ 50%
15
+
16
+ [f] Feed [p] Play [s] Sleep [q] Quit
17
+ ```
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install -g bytepet-cli
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ```bash
28
+ byte
29
+ ```
30
+
31
+ That's it. Your pet remembers you between sessions — stats decay while you're away, so check in often!
32
+
33
+ ## Pets
34
+
35
+ Choose from three pets on first run:
36
+ - 🐱 **Cat** — curious and independent
37
+ - 🐶 **Dog** — loyal and energetic
38
+ - 🐉 **Dragon** — rare and mysterious
39
+
40
+ ## Stats
41
+
42
+ | Stat | Description |
43
+ |------|-------------|
44
+ | ❤️ Health | Drops if hunger or happiness hits 0 |
45
+ | 🍖 Hunger | Decays over time — feed your pet! |
46
+ | 😊 Happiness | Decays over time — play with your pet! |
47
+ | ⚡ Energy | Decays over time — let your pet sleep! |
48
+ | ⭐ XP / Level | Earned through feeding, playing, sleeping |
49
+
50
+ ## Actions
51
+
52
+ | Key | Action | XP |
53
+ |-----|--------|----|
54
+ | `f` | Feed your pet | +10 XP |
55
+ | `p` | Play Rock Paper Scissors | +5–15 XP |
56
+ | `s` | Put your pet to sleep | +5 XP |
57
+ | `q` | Quit | — |
58
+
59
+ ## Moods
60
+
61
+ Your pet's ASCII art changes based on its mood:
62
+ - 😊 **Happy** — all stats healthy
63
+ - 🍖 **Hungry** — hunger below 20%
64
+ - 😴 **Sleepy** — energy below 20%
65
+ - 😢 **Sad** — happiness below 30%
66
+ - 🤒 **Sick** — health below 20%
67
+
68
+ ## Roadmap
69
+
70
+ - v0.1.0 — ✅ Core pet, 3 animals, 5 stats, RPS mini game
71
+ - v0.2.0 — More mini games, pet evolution stages, rare pets
72
+ - v0.3.0 — Pet accessories, backgrounds, seasonal events
73
+ - v1.0.0 — Pro tier: multiple pets, cloud sync, pet sharing
74
+
75
+ ## License
76
+
77
+ UNLICENSED — © 2025 Muhammad Talha Khan
package/bin/byte.js ADDED
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const readline = require('readline');
6
+ const { PETS, getMood, getArt } = require('../lib/pets');
7
+ const { load, save, applyDecay, createPet, addXP } = require('../lib/state');
8
+ const rps = require('../lib/rps');
9
+
10
+ // ── Colors ───────────────────────────────────────────────────────────────────
11
+ const c = {
12
+ reset: '\x1b[0m',
13
+ bold: '\x1b[1m',
14
+ dim: '\x1b[2m',
15
+ red: '\x1b[31m',
16
+ green: '\x1b[32m',
17
+ yellow: '\x1b[33m',
18
+ blue: '\x1b[34m',
19
+ magenta: '\x1b[35m',
20
+ cyan: '\x1b[36m',
21
+ white: '\x1b[37m',
22
+ gray: '\x1b[90m',
23
+ };
24
+
25
+ const paint = (color, text) => `${color}${text}${c.reset}`;
26
+
27
+ // ── Helpers ───────────────────────────────────────────────────────────────────
28
+ function bar(value, max = 100, len = 10) {
29
+ const filled = Math.round((value / max) * len);
30
+ const empty = len - filled;
31
+ const color = value > 60 ? c.green : value > 30 ? c.yellow : c.red;
32
+ return `${color}${'█'.repeat(filled)}${c.gray}${'░'.repeat(empty)}${c.reset}`;
33
+ }
34
+
35
+ function ask(rl, question) {
36
+ return new Promise(res => rl.question(question, ans => res(ans.trim())));
37
+ }
38
+
39
+ function clearScreen() {
40
+ process.stdout.write('\x1Bc');
41
+ }
42
+
43
+ function moodMessage(mood, name) {
44
+ const messages = {
45
+ happy: `${name} is happy and energetic! 😊`,
46
+ hungry: `${name} is hungry... feed me! 🍖`,
47
+ sleepy: `${name} is really tired... 😴`,
48
+ sad: `${name} needs some attention 😢`,
49
+ sick: `${name} is not feeling well 🤒`,
50
+ };
51
+ return messages[mood];
52
+ }
53
+
54
+ // ── First run: pick pet ───────────────────────────────────────────────────────
55
+ async function onboard() {
56
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
57
+
58
+ clearScreen();
59
+ console.log('');
60
+ console.log(paint(c.bold + c.cyan, ' 🥚 Welcome to byte-cli!'));
61
+ console.log(paint(c.gray, ' Your terminal pet is waiting...\n'));
62
+
63
+ console.log(paint(c.bold, ' Choose your pet:\n'));
64
+ console.log(` ${paint(c.cyan, '[1]')} 🐱 Cat`);
65
+ console.log(` ${paint(c.yellow, '[2]')} 🐶 Dog`);
66
+ console.log(` ${paint(c.magenta, '[3]')} 🐉 Dragon`);
67
+ console.log('');
68
+
69
+ let petType = null;
70
+ while (!petType) {
71
+ const choice = await ask(rl, ' Your choice: ');
72
+ if (choice === '1') petType = 'cat';
73
+ else if (choice === '2') petType = 'dog';
74
+ else if (choice === '3') petType = 'dragon';
75
+ else console.log(paint(c.red, ' Please pick 1, 2, or 3.\n'));
76
+ }
77
+
78
+ console.log('');
79
+ const name = await ask(rl, paint(c.bold, ` What will you name your ${PETS[petType].name}?\n `) + '> ');
80
+ rl.close();
81
+
82
+ const petName = name || PETS[petType].name;
83
+ const state = createPet(petName, petType);
84
+ save(state);
85
+
86
+ clearScreen();
87
+ console.log('');
88
+ console.log(paint(c.bold + c.green, ` 🎉 ${petName} the ${PETS[petType].name} has been born!\n`));
89
+ console.log(paint(c.gray, ' Take good care of them. Come back often — they miss you when you\'re away.\n'));
90
+
91
+ await new Promise(res => setTimeout(res, 1500));
92
+ return state;
93
+ }
94
+
95
+ // ── Render main screen ────────────────────────────────────────────────────────
96
+ function renderHome(state) {
97
+ const { name, petType, stats } = state;
98
+ const mood = getMood(stats);
99
+ const art = getArt(petType, stats);
100
+ const xpNeeded = stats.level * 100;
101
+
102
+ clearScreen();
103
+ console.log('');
104
+ console.log(paint(c.bold + c.cyan, ' ⚡ byte-cli\n'));
105
+
106
+ // ASCII art
107
+ art.forEach(line => console.log(paint(c.yellow, ' ' + line)));
108
+ console.log('');
109
+
110
+ // Name + level
111
+ console.log(` ${paint(c.bold, name + ' the ' + PETS[petType].name)} ${paint(c.gray, '·')} ${paint(c.magenta, 'Level ' + stats.level)} ${paint(c.gray, '·')} ${paint(c.dim, stats.xp + '/' + xpNeeded + ' XP')}`);
112
+ console.log('');
113
+
114
+ // Stats
115
+ console.log(` ❤️ Health ${bar(stats.health)} ${paint(c.gray, Math.round(stats.health) + '%')}`);
116
+ console.log(` 🍖 Hunger ${bar(stats.hunger)} ${paint(c.gray, Math.round(stats.hunger) + '%')}`);
117
+ console.log(` 😊 Happiness ${bar(stats.happiness)} ${paint(c.gray, Math.round(stats.happiness) + '%')}`);
118
+ console.log(` ⚡ Energy ${bar(stats.energy)} ${paint(c.gray, Math.round(stats.energy) + '%')}`);
119
+ console.log('');
120
+
121
+ // Mood message
122
+ console.log(` ${paint(c.dim, moodMessage(mood, name))}`);
123
+ console.log('');
124
+
125
+ // Actions
126
+ console.log(paint(c.gray, ' ─────────────────────────────────────────'));
127
+ console.log(` ${paint(c.cyan, '[f]')} Feed ${paint(c.cyan, '[p]')} Play ${paint(c.cyan, '[s]')} Sleep ${paint(c.cyan, '[q]')} Quit`);
128
+ console.log('');
129
+ }
130
+
131
+ // ── Actions ───────────────────────────────────────────────────────────────────
132
+ function feed(state) {
133
+ const s = { ...state, stats: { ...state.stats } };
134
+ const boost = Math.min(100 - s.stats.hunger, 30);
135
+ s.stats.hunger = Math.min(100, s.stats.hunger + 30);
136
+ s.stats.happiness = Math.min(100, s.stats.happiness + 5);
137
+ const { state: newState, leveledUp } = addXP(s, 10);
138
+ return { state: newState, leveledUp, msg: `${paint(c.green, '🍖 Yum!')} Hunger +${boost} XP +10` };
139
+ }
140
+
141
+ function sleep(state) {
142
+ const s = { ...state, stats: { ...state.stats } };
143
+ s.stats.energy = Math.min(100, s.stats.energy + 40);
144
+ s.stats.health = Math.min(100, s.stats.health + 5);
145
+ const { state: newState, leveledUp } = addXP(s, 5);
146
+ return { state: newState, leveledUp, msg: `${paint(c.blue, '💤 Zzz...')} Energy +40 XP +5` };
147
+ }
148
+
149
+ // ── Main loop ─────────────────────────────────────────────────────────────────
150
+ async function main() {
151
+ let state = load();
152
+
153
+ if (!state) {
154
+ state = await onboard();
155
+ } else {
156
+ state = applyDecay(state);
157
+ save(state);
158
+ }
159
+
160
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
161
+ readline.emitKeypressEvents(process.stdin);
162
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
163
+
164
+ let message = '';
165
+ let running = true;
166
+
167
+ renderHome(state);
168
+ if (message) console.log(` ${message}\n`);
169
+
170
+ process.stdin.on('keypress', async (str, key) => {
171
+ if (!running) return;
172
+
173
+ if (key.name === 'q' || (key.ctrl && key.name === 'c')) {
174
+ running = false;
175
+ state.lastSeen = Date.now();
176
+ save(state);
177
+ rl.close();
178
+ clearScreen();
179
+ console.log('');
180
+ console.log(paint(c.cyan, ` 👋 Goodbye! ${state.name} will miss you.\n`));
181
+ process.exit(0);
182
+ }
183
+
184
+ if (key.name === 'f') {
185
+ const result = feed(state);
186
+ state = result.state;
187
+ message = result.msg;
188
+ if (result.leveledUp) message += paint(c.magenta + c.bold, ` 🎉 LEVEL UP! Now level ${state.stats.level}!`);
189
+ save(state);
190
+ renderHome(state);
191
+ console.log(` ${message}\n`);
192
+ }
193
+
194
+ if (key.name === 's') {
195
+ const result = sleep(state);
196
+ state = result.state;
197
+ message = result.msg;
198
+ if (result.leveledUp) message += paint(c.magenta + c.bold, ` 🎉 LEVEL UP! Now level ${state.stats.level}!`);
199
+ save(state);
200
+ renderHome(state);
201
+ console.log(` ${message}\n`);
202
+ }
203
+
204
+ if (key.name === 'p') {
205
+ process.stdin.setRawMode(false);
206
+ rl.close();
207
+ running = false;
208
+
209
+ const result = await rps.play(state.name);
210
+
211
+ // Apply game results to stats
212
+ state.stats.happiness = Math.min(100, state.stats.happiness + result.happinessBoost);
213
+ state.stats.energy = Math.max(0, state.stats.energy - result.energyCost);
214
+ const { state: newState, leveledUp } = addXP(state, result.xpEarned);
215
+ state = newState;
216
+
217
+ if (leveledUp) {
218
+ console.log(paint(c.magenta + c.bold, ` 🎉 LEVEL UP! ${state.name} is now level ${state.stats.level}!\n`));
219
+ await new Promise(res => setTimeout(res, 1500));
220
+ }
221
+
222
+ save(state);
223
+
224
+ // Restart loop
225
+ running = true;
226
+ const newRl = readline.createInterface({ input: process.stdin, output: process.stdout });
227
+ readline.emitKeypressEvents(process.stdin);
228
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
229
+
230
+ renderHome(state);
231
+
232
+ process.stdin.removeAllListeners('keypress');
233
+ process.stdin.on('keypress', async (str, key) => {
234
+ // re-attach same handler by restarting main — simplest approach
235
+ newRl.close();
236
+ process.stdin.setRawMode(false);
237
+ process.stdin.removeAllListeners('keypress');
238
+ main();
239
+ });
240
+ }
241
+ });
242
+ }
243
+
244
+ main().catch(err => {
245
+ console.error('Error:', err.message);
246
+ process.exit(1);
247
+ });
package/lib/pets.js ADDED
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ const PETS = {
4
+ cat: {
5
+ emoji: '🐱',
6
+ name: 'Cat',
7
+ moods: {
8
+ happy: [
9
+ ' /\\_____/\\ ',
10
+ ' ( ^ ^ ) ',
11
+ ' ( =^.^= ) ',
12
+ ' (--m-m----) ',
13
+ ],
14
+ hungry: [
15
+ ' /\\_____/\\ ',
16
+ ' ( - - ) ',
17
+ ' ( =o.o= ) ',
18
+ ' (--m-m----) ',
19
+ ],
20
+ sleepy: [
21
+ ' /\\_____/\\ ',
22
+ ' ( - - ) ',
23
+ ' ( =-.-= ) ',
24
+ ' (--m-m----) ',
25
+ ],
26
+ sad: [
27
+ ' /\\_____/\\ ',
28
+ ' ( T T ) ',
29
+ ' ( =v.v= ) ',
30
+ ' (--m-m----) ',
31
+ ],
32
+ sick: [
33
+ ' /\\_____/\\ ',
34
+ ' ( x x ) ',
35
+ ' ( =@.@= ) ',
36
+ ' (--m-m----) ',
37
+ ],
38
+ },
39
+ },
40
+ dog: {
41
+ emoji: '🐶',
42
+ name: 'Dog',
43
+ moods: {
44
+ happy: [
45
+ ' / \\_/ \\ ',
46
+ ' ( ^ ^ ) ',
47
+ ' ( o.o ) ',
48
+ ' \\ ___/ ',
49
+ ' | | ',
50
+ ],
51
+ hungry: [
52
+ ' / \\_/ \\ ',
53
+ ' ( - - ) ',
54
+ ' ( u.u ) ',
55
+ ' \\ ___/ ',
56
+ ' | | ',
57
+ ],
58
+ sleepy: [
59
+ ' / \\_/ \\ ',
60
+ ' ( - - ) ',
61
+ ' ( -.– ) ',
62
+ ' \\ ___/ ',
63
+ ' | | ',
64
+ ],
65
+ sad: [
66
+ ' / \\_/ \\ ',
67
+ ' ( T T ) ',
68
+ ' ( v.v ) ',
69
+ ' \\ ___/ ',
70
+ ' | | ',
71
+ ],
72
+ sick: [
73
+ ' / \\_/ \\ ',
74
+ ' ( x x ) ',
75
+ ' ( @.@ ) ',
76
+ ' \\ ___/ ',
77
+ ' | | ',
78
+ ],
79
+ },
80
+ },
81
+ dragon: {
82
+ emoji: '🐉',
83
+ name: 'Dragon',
84
+ moods: {
85
+ happy: [
86
+ ' / \\ / \\ ',
87
+ ' ( o \\/ o)',
88
+ ' ( /\\ )',
89
+ ' __\\_/ \\_/__ ',
90
+ '(____________)',
91
+ ],
92
+ hungry: [
93
+ ' / \\ / \\ ',
94
+ ' ( - \\/ -)',
95
+ ' ( /\\ )',
96
+ ' __\\_/ \\_/__ ',
97
+ '(____________)',
98
+ ],
99
+ sleepy: [
100
+ ' / \\ / \\ ',
101
+ ' ( - \\/ -)',
102
+ ' ( -– )',
103
+ ' __\\_/ \\_/__ ',
104
+ '(____________)',
105
+ ],
106
+ sad: [
107
+ ' / \\ / \\ ',
108
+ ' ( T \\/ T)',
109
+ ' ( /\\ )',
110
+ ' __\\_/ \\_/__ ',
111
+ '(____________)',
112
+ ],
113
+ sick: [
114
+ ' / \\ / \\ ',
115
+ ' ( x \\/ x)',
116
+ ' ( @~@ )',
117
+ ' __\\_/ \\_/__ ',
118
+ '(____________)',
119
+ ],
120
+ },
121
+ },
122
+ };
123
+
124
+ function getMood(stats) {
125
+ if (stats.health < 20) return 'sick';
126
+ if (stats.hunger < 20) return 'hungry';
127
+ if (stats.energy < 20) return 'sleepy';
128
+ if (stats.happiness < 30) return 'sad';
129
+ return 'happy';
130
+ }
131
+
132
+ function getArt(petType, stats) {
133
+ const mood = getMood(stats);
134
+ return PETS[petType].moods[mood];
135
+ }
136
+
137
+ module.exports = { PETS, getMood, getArt };
package/lib/rps.js ADDED
@@ -0,0 +1,84 @@
1
+ 'use strict';
2
+
3
+ const readline = require('readline');
4
+
5
+ const CHOICES = ['rock', 'paper', 'scissors'];
6
+ const EMOJI = { rock: '🪨', paper: '📄', scissors: '✂️' };
7
+
8
+ const c = {
9
+ reset: '\x1b[0m',
10
+ bold: '\x1b[1m',
11
+ green: '\x1b[32m',
12
+ red: '\x1b[31m',
13
+ yellow: '\x1b[33m',
14
+ cyan: '\x1b[36m',
15
+ gray: '\x1b[90m',
16
+ };
17
+
18
+ function getResult(player, computer) {
19
+ if (player === computer) return 'draw';
20
+ if (
21
+ (player === 'rock' && computer === 'scissors') ||
22
+ (player === 'paper' && computer === 'rock') ||
23
+ (player === 'scissors' && computer === 'paper')
24
+ ) return 'win';
25
+ return 'lose';
26
+ }
27
+
28
+ async function play(petName) {
29
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
30
+ const ask = (q) => new Promise(res => rl.question(q, res));
31
+
32
+ console.log(`\n${c.cyan}${c.bold} 🎮 Rock Paper Scissors with ${petName}!${c.reset}\n`);
33
+ console.log(`${c.gray} [1] Rock [2] Paper [3] Scissors [q] Quit${c.reset}\n`);
34
+
35
+ let wins = 0, losses = 0, draws = 0;
36
+ let xpEarned = 0;
37
+ let playing = true;
38
+
39
+ while (playing) {
40
+ const input = (await ask(` Your choice: `)).trim().toLowerCase();
41
+
42
+ if (input === 'q') { playing = false; break; }
43
+
44
+ const idx = parseInt(input) - 1;
45
+ if (isNaN(idx) || idx < 0 || idx > 2) {
46
+ console.log(`${c.yellow} Invalid choice. Pick 1, 2, or 3.${c.reset}\n`);
47
+ continue;
48
+ }
49
+
50
+ const playerChoice = CHOICES[idx];
51
+ const computerChoice = CHOICES[Math.floor(Math.random() * 3)];
52
+ const result = getResult(playerChoice, computerChoice);
53
+
54
+ console.log(`\n You: ${EMOJI[playerChoice]} ${playerChoice}`);
55
+ console.log(` ${petName}: ${EMOJI[computerChoice]} ${computerChoice}\n`);
56
+
57
+ if (result === 'win') {
58
+ wins++;
59
+ xpEarned += 15;
60
+ console.log(`${c.green}${c.bold} 🎉 You win! +15 XP${c.reset}\n`);
61
+ } else if (result === 'lose') {
62
+ losses++;
63
+ xpEarned += 5;
64
+ console.log(`${c.red} 😅 ${petName} wins this round! +5 XP${c.reset}\n`);
65
+ } else {
66
+ draws++;
67
+ xpEarned += 8;
68
+ console.log(`${c.yellow} 🤝 Draw! +8 XP${c.reset}\n`);
69
+ }
70
+
71
+ const again = (await ask(` Play again? [y/n]: `)).trim().toLowerCase();
72
+ if (again !== 'y') playing = false;
73
+ console.log('');
74
+ }
75
+
76
+ rl.close();
77
+
78
+ console.log(`${c.gray} Score — Wins: ${wins} | Losses: ${losses} | Draws: ${draws}${c.reset}`);
79
+ console.log(`${c.cyan} Total XP earned: +${xpEarned}${c.reset}\n`);
80
+
81
+ return { xpEarned, happinessBoost: wins * 8, energyCost: (wins + losses + draws) * 3 };
82
+ }
83
+
84
+ module.exports = { play };
package/lib/state.js ADDED
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ const STATE_DIR = path.join(os.homedir(), '.byte-cli');
8
+ const STATE_FILE = path.join(STATE_DIR, 'pet.json');
9
+
10
+ const DECAY_RATES = {
11
+ hunger: 0.8, // per hour
12
+ happiness: 0.5,
13
+ energy: 0.4,
14
+ health: 0.2,
15
+ };
16
+
17
+ function ensureDir() {
18
+ if (!fs.existsSync(STATE_DIR)) {
19
+ fs.mkdirSync(STATE_DIR, { recursive: true });
20
+ }
21
+ }
22
+
23
+ function load() {
24
+ ensureDir();
25
+ if (!fs.existsSync(STATE_FILE)) return null;
26
+ try {
27
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ function save(state) {
34
+ ensureDir();
35
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
36
+ }
37
+
38
+ function applyDecay(state) {
39
+ const now = Date.now();
40
+ const lastSeen = state.lastSeen || now;
41
+ const hoursElapsed = (now - lastSeen) / (1000 * 60 * 60);
42
+
43
+ if (hoursElapsed < 0.05) return state; // less than 3 mins, skip
44
+
45
+ const newState = { ...state, stats: { ...state.stats } };
46
+
47
+ for (const [stat, rate] of Object.entries(DECAY_RATES)) {
48
+ newState.stats[stat] = Math.max(0, newState.stats[stat] - rate * hoursElapsed);
49
+ }
50
+
51
+ // Health drops if hunger or happiness hits 0
52
+ if (newState.stats.hunger === 0 || newState.stats.happiness === 0) {
53
+ newState.stats.health = Math.max(0, newState.stats.health - 1 * hoursElapsed);
54
+ }
55
+
56
+ newState.lastSeen = now;
57
+ return newState;
58
+ }
59
+
60
+ function createPet(name, petType) {
61
+ return {
62
+ name,
63
+ petType,
64
+ stats: {
65
+ hunger: 80,
66
+ happiness: 80,
67
+ energy: 80,
68
+ health: 100,
69
+ xp: 0,
70
+ level: 1,
71
+ },
72
+ lastSeen: Date.now(),
73
+ born: Date.now(),
74
+ };
75
+ }
76
+
77
+ function addXP(state, amount) {
78
+ const newState = { ...state, stats: { ...state.stats } };
79
+ newState.stats.xp += amount;
80
+ const xpNeeded = newState.stats.level * 100;
81
+ if (newState.stats.xp >= xpNeeded) {
82
+ newState.stats.xp -= xpNeeded;
83
+ newState.stats.level += 1;
84
+ return { state: newState, leveledUp: true };
85
+ }
86
+ return { state: newState, leveledUp: false };
87
+ }
88
+
89
+ module.exports = { load, save, applyDecay, createPet, addXP };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "bytepet-cli",
3
+ "version": "0.1.0",
4
+ "description": "⚡ A terminal pet that lives in your CLI — feed it, play with it, watch it grow",
5
+ "main": "bin/byte.js",
6
+ "bin": {
7
+ "bytepet": "./bin/byte.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/byte.js"
11
+ },
12
+ "keywords": [
13
+ "cli",
14
+ "pet",
15
+ "tamagotchi",
16
+ "terminal",
17
+ "ascii",
18
+ "fun",
19
+ "game",
20
+ "developer"
21
+ ],
22
+ "author": "Muhammad Talha Khan",
23
+ "license": "UNLICENSED",
24
+ "private": false,
25
+ "engines": {
26
+ "node": ">=14"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/muhtalhakhan/bytepet-cli.git"
31
+ },
32
+ "homepage": "https://github.com/muhtalhakhan/bytepet-cli#readme",
33
+ "bugs": {
34
+ "url": "https://github.com/muhtalhakhan/bytepet-cli/issues"
35
+ }
36
+ }