Skip to content

Instantly share code, notes, and snippets.

@lewdev
Last active June 7, 2025 01:40
Show Gist options
  • Select an option

  • Save lewdev/115484d7aaa2e7a023dcc0eb2d2a11f5 to your computer and use it in GitHub Desktop.

Select an option

Save lewdev/115484d7aaa2e7a023dcc0eb2d2a11f5 to your computer and use it in GitHub Desktop.
🐢 Simple Pet Sim
<!DOCTYPE html>
<head><title>🐢 Pet Sim</title></head>
<body>
<div id="start">
<h2>🐢 What would you like to name your pet?</h2>
<input id="n" onkeyup="event.keyCode===13&&n.value?start_game(n.value):null"/>
<button onclick="start_game(n.value)">Start</button>
</div>
<div id="controls" style="display:none">
What would you like to do?
<button onclick="pet.feed()">πŸ– Feed</button>
<button onclick="pet.give_water()">πŸ’§ Water</button>
<button onclick="pet.play()">πŸƒβ€β™‚οΈ Play</button>
<button onclick="pet.put_to_bed()">πŸ›Œ Put to Bed</button>
<button onclick="pet.put_to_bath()">πŸ› Put to Bath</button>
</div>
<p id="loopCount"></p>
<p id="petStatus"></p>
<p id=o></p>
<script>
const logs = [];
const log = (...arg) => {
logs.push(...arg.map(s => `<div>${s}</div>`));
o.innerHTML = logs.reverse().join``;
};
const clearLog = () => o.innerHTML = "";
const randint = (max, min = 0) => ~~(Math.random() * max + min);
const EVENTS = [
{affectedStats: [["tiredness", 10], ["boredom", -20]], msg: `found a toy and is no longer bored`},
{affectedStats: [["tiredness", 10], ["hunger", 10]], msg: `eaten something bad and is sick`},
{affectedStats: [["tiredness", 10], ["thirst", 10]], msg: `been running around`},
{affectedStats: [["boredom", 10], ["dirtiness", 10]], msg: `been sprayed by a skunk and needs a bath`},
{affectedStats: [["hunger", -20], ["tiredness", 20]], msg: `found a treat and is very happy`},
];
let action, event, name, pet, count = 0;
log("Welcome to Virtual Pet!");
const loop = () => {
loopCount.innerHTML = `${count++} days`;
if (!pet.is_alive()) {
log(`Game Over. Survived ${count} days. <button onclick="start.style.display='block';petStatus.innerHTML=''">Restart</button>`);
controls.style.display = "none";
return;
}
if (randint(6) === 5) {
event = EVENTS[randint(EVENTS.length)];
pet.updateStats(event.affectedStats, event.msg);
}
pet.showStats();
if (pet.is_alive()) setTimeout(() => loop(), 1000);
};
const start_game = async name => {
if (!name) return;
start.style.display = "none";
controls.style.display = "block";
count = 0;
clearLog();
pet = new VirtualPet(name);
log(`You now have a new pet named ${name}.`);
loop();
};
const showStatColor = stat => {
return `<span style="width:1rem; height: 1rem; background-color: #${stat < 40 ? "0A0" : stat < 60 ? "AA0" : "A00"}">&nbsp;</span>`;
};
const cap = s => s.charAt(0).toUpperCase() + s.substring(1);
const PET_STATS = "hunger,thirst,boredom,tiredness,dirtiness".split`,`;
const STAT_EMOJIS = [..."πŸ–πŸ’§πŸŽˆπŸ˜©πŸ§Ό"];
class VirtualPet {
constructor(name) {
this.name = name;
PET_STATS.forEach(stat => this[stat] = 50);
}
updateStat(stat, amount) {
this[stat] = Math.max(Math.min(this[stat] + amount, 100), 0);
}
updateStats(arr, action) {
for (const newStat of arr) {
this.updateStat(...newStat);
}
this.logAction(action);
this.showStats();
}
logAction(action) { log(`${this.name} has ${action}.`); }
showStats() {
petStatus.innerHTML = `${this.name}'s stats:${PET_STATS.map(s => (
`<br>${STAT_EMOJIS[PET_STATS.indexOf(s)]} ${cap(s)}: ${this[s]} ${showStatColor(this[s])}`
)).join``}`
}
feed() { this.updateStats([["hunger", -20], ["thirst", 10]], `been fed`); }
give_water() { this.updateStats([["boredom", 10], ["thirst", -20]], `been given water`); }
play() { this.updateStats([["boredom", -20], ["tiredness", 10]], `played with you`); }
put_to_bed() { this.updateStats([["hunger", 10], ["tiredness", -30]], `been put to bed`); }
put_to_bath() { this.updateStats([["dirtiness", -20], ["tiredness", -10]], `been put to bed`); }
is_alive() { return PET_STATS.reduce((alive, stat) => {
if (alive && this[stat] >= 100) {
this.logAction(`died of ${stat}.`);
return false;
}
return true;
}, true);
}
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment