#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <stdbool.h>
typedef struct owner {
char *name;
int money;
int *Inventory;
void (*SetName)(struct owner *self, char *name);
} Owner;
Owner * Owner_New(void);
void Owner_SetName(Owner *self, char *st);
struct owner;
typedef struct owner Owner;
typedef struct pet {
char *name;
char type;
int hunger;
int thirst;
int coat;
int energy;
int age;
void (*SetName)(struct pet *self, char *name);
void (*Feed)(struct pet *self, Owner *owner);
void (*Play)(struct pet *self, Owner *owner);
void (*Wash)(struct pet *self, Owner *owner);
void (*Walk)(struct pet *self, Owner *owner);
void (*AssertBounds)(struct pet *self);
} Pet;
Pet * Pet_New(char type);
void Pet_SetName(Pet *self, char *name);
void Pet_AssertBounds(Pet *self);
void Dog_Feed(Pet *self, Owner *owner);
void Dog_Play(Pet *self, Owner *owner);
void Dog_Wash(Pet *self, Owner *owner);
void Dog_Walk(Pet *self, Owner *owner);
void Cat_Feed(Pet *self, Owner *owner);
void Cat_Play(Pet *self, Owner *owner);
void Cat_Wash(Pet *self, Owner *owner);
#define MAXST 20
#define MAXPETS 5
#define ITEMS 15
enum Index {DOGFOOD, DOGTREAT, CATFOOD, CATTREAT, WATER,
TENNISBALL, CHEWTOY, LURE, TOYMOUSE,
DOGSHAMPOO, LEASH, CATSHAMPOO
};
typedef struct shopitem {
int option;
int price;
int resellValue;
char *name;
int count;
} ShopItem;
void Game_Init(Owner **Player, Pet **MyPet);
void Game_Loop(Owner *Player, Pet *MyPet);
void Game_Exit(Owner *Player, Pet *MyPet);
char ShowMenu(Owner *Player, Pet *MyPet);
void Shop(Owner *Player);
void Save(Owner *Player, Pet *player);
void Load(Owner *Player, Pet *player);
char * s_gets(char * st, int n);
char chget(void);
void eatline(void);
extern const ShopItem ShopCatalog[12];
Owner * Owner_New(void) {
Owner *new = malloc(sizeof(Owner));
new->name = malloc(MAXST * sizeof(char));
new->Inventory = malloc(ITEMS * sizeof(int));
for (int i = 0; i < ITEMS; i++) {
new->Inventory[i] = 0;
}
new->SetName = Owner_SetName;
new->money = 100;
return new;
}
void Owner_SetName(Owner *self, char *name) {
strncpy(self->name, name, MAXST);
}
const ShopItem ShopCatalog[12] = {
/* ch $b $s name cnt */
{0, 20, 3, "Dog Food", 5},
{1, 10, 1, "Dog Treats", 5},
{2, 20, 3, "Cat Food", 5},
{3, 10, 1, "Cat Treats", 5},
{4, 10, 1, "Water", 5},
{5, 5, 2, "Tennis Ball", 1},
{6, 5, 2, "Chew Toy", 1},
{7, 5, 2, "Lure", 1},
{8, 5, 2, "Toy Mouse", 1},
{9, 10, 1, "Dog Shampoo", 5},
{10, 30, 20, "Dog Leash", 1},
{11, 10, 1, "Cat Shampoo", 5}
};
Pet * Pet_New(char type) {
Pet *NewPet = malloc(sizeof(Pet));
NewPet->name = malloc(MAXST * sizeof(char));
NewPet->hunger = NewPet->thirst = 0;
NewPet->coat = 10;
NewPet->energy = 50;
NewPet->age = 0;
NewPet->SetName = Pet_SetName;
NewPet->AssertBounds = Pet_AssertBounds;
switch(type) {
case 'd':
case 'D':
NewPet->Feed = Dog_Feed;
NewPet->Play = Dog_Play;
NewPet->Wash = Dog_Wash;
NewPet->Walk = Dog_Walk;
NewPet->type = 'd';
break;
case 'c':
case 'C':
// NewPet->Feed = Cat_Feed;
// NewPet->Play = Cat_Play;
// NewPet->Wash = Cat_Wash;
NewPet->type = 'c';
break;
}
return NewPet;
}
void Pet_SetName(Pet *self, char *name) {
strncpy(self->name, name, MAXST);
}
void Dog_Feed(Pet *self, Owner *owner) {
char choice;
if (owner->Inventory[DOGFOOD] == 0 && owner->Inventory[DOGTREAT] == 0
&& owner->Inventory[WATER] == 0) {
printf("You don't have any food!\nYou can buy supplies at the Shop.\n");
fflush(stdout);
sleep(2);
return;
}
printf("\nFood & Drink:\n\tf) Dog food (%d)\n\tt) Dog treat (%d)\n\tw) Water (%d)\n"
"What would you like to give to %s? ", owner->Inventory[DOGFOOD],
owner->Inventory[DOGTREAT], owner->Inventory[WATER], self->name);
fflush(stdout);
choice = chget();
if (choice == 'b') {
return;
}
while (strchr("ftw", choice) == NULL) {
puts("Please enter 'f' for Dog food, 't' for Dog treat, or 'w' for Water!");
fflush(stdout);
choice = chget();
}
switch (choice) {
case 'f':
if (self->hunger < 2) {
printf("%s to too full to eat right now!", self->name);
fflush(stdout);
sleep(1);
return;
}
if (owner->Inventory[DOGFOOD] == 0) {
puts("You don't have any dog food!\nYou can buy some at the Shop.");
fflush(stdout);
sleep(1);
return;
}
self->hunger -= 6;
self->energy += 25;
self->AssertBounds(self);
owner->Inventory[DOGFOOD] -= 1;
printf("%s is sniffing the bowl...", self->name);
fflush(stdout);
sleep(2);
printf("\n%s ate the dog food!\n", self->name);
fflush(stdout);
sleep(1);
break;
case 't':
if (owner->Inventory[DOGTREAT] == 0) {
puts("You don't have any dog treats!\nYou can buy some at the Shop.");
fflush(stdout);
sleep(1);
return;
}
self->hunger -= 2;
self->energy += 40;
self->AssertBounds(self);
owner->Inventory[DOGTREAT] -= 1;
printf("%s barks in excitement!", self->name);
fflush(stdout);
sleep(1);
printf("\n%s loved the dog treat!\n", self->name);
fflush(stdout);
sleep(1);
break;
case 'w':
if (self->thirst < 2) {
printf("%s has had enough water for now!", self->name);
fflush(stdout);
sleep(1);
return;
}
if (owner->Inventory[WATER] == 0) {
puts("You don't have any water!\nYou can buy some at the Shop.");
fflush(stdout);
sleep(1);
return;
}
printf("%s ran towards the water bowl!", self->name);
fflush(stdout);
sleep(1);
self->thirst -= 6;
self->energy += 15;
self->AssertBounds(self);
owner->Inventory[WATER] -= 1;
printf("\n%s drank it all!\n", self->name);
fflush(stdout);
sleep(1);
break;
}
}
void Dog_Play(Pet *self, Owner *owner) {
char choice;
putchar('\n');
if (self->energy < 11) {
printf("%s is too tired to play.\n", self->name);
fflush(stdout);
sleep(1);
return;
}
if (self->hunger > 7) {
printf("%s is too hungry to play.\n", self->name);
fflush(stdout);
sleep(1);
return;
}
if (self->thirst > 7) {
printf("%s is too thirsty to play.\n", self->name);
fflush(stdout);
sleep(1);
return;
}
if (owner->Inventory[TENNISBALL] == 0 && owner->Inventory[CHEWTOY] == 0) {
printf("You don't have any toys!\nYou can buy some at the Shop.\n");
fflush(stdout);
sleep(2);
return;
}
printf("Toys:\n\tt) Tennis Ball\n\tc) Chew Toy\n");
printf("What do you want to use to play with %s? ", self->name);
fflush(stdout);
choice = chget();
if (choice == 'b') {
return;
}
while (strchr("tc", choice) == NULL) {
puts("Please enter 't' for Tennis Ball or 'c' for Chew Toy.");
fflush(stdout);
choice = chget();
}
switch (choice) {
case 't':
if (owner->Inventory[TENNISBALL] == 0) {
puts("You don't have a tennis ball!\nYou can buy one at the Shop.");
fflush(stdout);
sleep(1);
return;
}
printf("%s is playing with the tennis ball!\n", self->name);
fflush(stdout);
sleep(4);
self->hunger += 1;
self->thirst += 3;
self->energy -= 20;
self->coat -= 2;
self->AssertBounds(self);
switch (self->energy) {
case 0 ... 11:
printf("%s got all tired out from playing!\n", self->name);
fflush(stdout);
sleep(1);
break;
case 12 ... 50:
printf("%s had a lot of fun playing!\n", self->name);
fflush(stdout);
sleep(1);
break;
}
break;
case 'c':
if (owner->Inventory[CHEWTOY] == 0) {
puts("You don't have a chew toy!\nYou can buy one at the Shop.");
fflush(stdout);
sleep(1);
return;
}
printf("%s is chewing happily on the toy...", self->name);
fflush(stdout);
sleep(4);
self->hunger += 3;
self->thirst += 1;
self->energy -= 10;
self->coat -= 4;
self->AssertBounds(self);
switch (self->energy) {
case 0 ... 11:
printf("%s is worn out.\n", self->name);
fflush(stdout);
sleep(1);
break;
case 12 ... 50:
printf("\n%s loved chewing on the chew toy!\n", self->name);
fflush(stdout);
sleep(1);
break;
}
break;
}
}
void Dog_Wash(Pet *self, Owner *owner) {
if (owner->Inventory[DOGSHAMPOO] == 0) {
puts("You don't have any dog shampoo!\nYou can buy some at the Shop.");
fflush(stdout);
sleep(2);
return;
}
switch (self->coat) {
case 0 ... 5:
printf("\n%s is really dirty!\nTime for a bath!", self->name);
fflush(stdout);
sleep(6);
printf("\n%s is much cleaner now!", self->name);
fflush(stdout);
break;
case 6 ... 10:
printf("%s could use a scrubbin'!", self->name);
fflush(stdout);
sleep(3);
printf("%s feels refreshed!", self->name);
fflush(stdout);
break;
}
self->coat += 7;
self->AssertBounds(self);
owner->Inventory[DOGSHAMPOO] -= 1;
}
void Dog_Walk(Pet *self, Owner *owner) {
if (owner->Inventory[LEASH] == 0) {
puts("You don't have a leash!\nYou can buy one at the Shop.");
fflush(stdout);
sleep(2);
return;
}
if (self->energy < 30) {
printf("%s is too tired for a walk.", self->name);
fflush(stdout);
sleep(1);
return;
}
if (self->hunger > 4) {
printf("%s is too hungry for a walk.", self->name);
fflush(stdout);
sleep(1);
return;
}
if (self->thirst > 4) {
printf("%s is too thirsty for a walk.", self->name);
fflush(stdout);
sleep(1);
return;
}
printf("\nYou and %s leave for a walk...", self->name);
fflush(stdout);
time_t t;
int item, amount;
char *animal;
int anml;
srand((unsigned) time(&t));
for (int duration = 0; duration < 15; duration++) {
sleep(8 - (self->energy / 10));
int event = rand() % 100;
switch (event) {
case 0 ... 10:
printf("\n%s found an item!", self->name);
fflush(stdout);
sleep(1);
item = rand() % 12;
char choice;
sleep(1);
printf("\n%s!\nt) Take it!\tl) Leave it!\nTake the %s? ",
ShopCatalog[item].name, ShopCatalog[item].name);
fflush(stdout);
while ((choice = chget()) != 't' && choice != 'l') {
printf("\nPlease enter 't' or 'l' to Take or Leave the %s! ",
ShopCatalog[item].name);
}
switch (choice) {
case 't':
printf("\n%s added to inventory! Thanks, %s!",
ShopCatalog[item].name, self->name);
fflush(stdout);
owner->Inventory[item] += 1;
sleep(1);
break;
case 'l':
printf("\nLeft the %s on the ground.",
ShopCatalog[item].name);
fflush(stdout);
sleep(1);
break;
}
break;
case 11 ... 20:
amount = rand() % 5 + 9;
printf("\n%s found some cash!\n$%d was added to your wallet.",
self->name, amount);
fflush(stdout);
owner->money += amount;
sleep(1);
break;
case 21 ... 30:
anml = event % 3;
switch (anml) {
case 0:
animal = "bird";
break;
case 1:
animal = "squirrel";
break;
case 2:
animal = "cat";
break;
}
printf("\nLook! There's a %s!", animal);
fflush(stdout);
sleep(1);
printf("\n%s chased after the %s!", self->name, animal);
fflush(stdout);
sleep(1);
self->energy -= 10;
break;
case 31 ... 35:
printf("\n%s jumped in a mud puddle!", self->name);
fflush(stdout);
self->coat = 0;
sleep(1);
printf("\n%s got really dirty!", self->name);
fflush(stdout);
sleep(1);
break;
case 36 ... 50:
printf("\n%s found a puddle!", self->name);
fflush(stdout);
sleep(1);
printf("\n%s drank some of the water! ...Ew.", self->name);
fflush(stdout);
sleep(1);
self->thirst -= 2;
self->energy += 5;
self->coat -= 5;
break;
}
}
printf("\n%s really enjoyed the walk!", self->name);
fflush(stdout);
sleep(1);
self->AssertBounds(self);
}
void Pet_AssertBounds(Pet *self) {
if (self->hunger < 0) {
self->hunger = 0;
}
if (self->thirst < 0) {
self->thirst = 0;
}
if (self->coat < 0) {
self->coat = 0;
}
if (self->energy < 0) {
self->energy = 0;
}
if (self->hunger > 10) {
self->hunger = 10;
}
if (self->thirst > 10) {
self->thirst = 10;
}
if (self->coat > 10) {
self->coat = 10;
}
if (self->energy > 50) {
self->energy = 50;
}
}
extern const ShopItem ShopCatalog[12];
void Game_Init(Owner **Player, Pet **MyPet) {
char type[4];
char PlayerName[MAXST];
char PetName[MAXST];
*Player = Owner_New();
printf("\n\n\n\n\n\n\n\n\n\nWelcome to MyPet!\nWhat is your name?\nName: ");
s_gets(PlayerName, MAXST);
(*Player)->SetName(*Player, PlayerName);
/* printf("Would you like to start with a dog, or a cat? ");
s_gets(type, 5);
while (strchr("DdCc", type[0]) == NULL) {
printf("Please enter \"dog\" or \"cat\": ");
s_gets(type, 5);
}
*/ (*MyPet) = Pet_New('d');
printf("What would you like to name your %s? ",
(*MyPet)->type == 'd' ? "dog" : "cat");
s_gets(PetName, MAXST);
(*MyPet)->SetName(*MyPet, PetName);
printf("%s is happy to join you!\n", (*MyPet)->name);
fflush(stdout);
sleep(1);
}
void Game_Loop(Owner *Player, Pet *MyPet) {
char ch = ShowMenu(Player, MyPet);
int time = 1;
while (ch != 'q') {
switch(ch) {
case 'p':
MyPet->Play(MyPet, Player);
break;
case 'f':
MyPet->Feed(MyPet, Player);
break;
case 'b':
MyPet->Wash(MyPet, Player);
break;
case 's':
Shop(Player);
break;
case 'w':
MyPet->Walk(MyPet, Player);
break;
}
ch = ShowMenu(Player, MyPet);
time++;
if (time % 10 == 0) {
MyPet->age++;
}
if (time % 5 == 0) {
MyPet->hunger++;
MyPet->thirst++;
MyPet->coat--;
}
MyPet->energy += 2;
MyPet->AssertBounds(MyPet);
}
}
void Game_Exit(Owner *Player, Pet *MyPet) {
printf("%s %s goodbye!\n",
MyPet->name, MyPet->type == 'd' ? "barks" : "meows");
fflush(stdout);
sleep(1);
free(Player->name);
free(Player->Inventory);
free(Player);
free(MyPet->name);
free(MyPet);
}
char ShowMenu(Owner *Player, Pet *MyPet) {
char *hunger;
char *thirst;
char *coat;
char *energy;
char choice;
switch (MyPet->hunger) {
case 0 ... 1:
hunger = "Full";
break;
case 2 ... 4:
hunger = "Normal";
break;
case 5 ... 7:
hunger = "Hungry";
break;
case 8 ... 10:
hunger = "Famished";
break;
}
switch (MyPet->thirst) {
case 0 ... 1:
thirst = "Quenched";
break;
case 2 ... 4:
thirst = "Normal";
break;
case 5 ... 7:
thirst = "Thirsty";
break;
case 8 ... 10:
thirst = "Parched";
break;
}
switch (MyPet->coat) {
case 0 ... 1:
coat = "Stinky";
break;
case 2 ... 4:
coat = "Dirty";
break;
case 5 ... 7:
coat = "Normal";
break;
case 8 ... 9:
coat = "Clean";
break;
case 10:
coat = "Perfect";
break;
}
printf("\n\n\n\n\n\n\n%s\t\t\t\t\tCash: $%d\n", Player->name, Player->money);
printf("%s\t%s\n", MyPet->name, MyPet->type == 'd' ? "Dog" : "Cat");
printf(" Age:\t%d\n Status:\n\tHunger:\t%s\n\tThirst:\t%s\n\tCoat:\t%s\n\n",
MyPet->age, hunger, thirst, coat);
printf("p) Play with %s\tf) Feed %s\n"
"b) Bathe %s\t\ts) Go to the Shop\nw) Walk %s\t\tq) Quit\n",
MyPet->name, MyPet->name, MyPet->name, MyPet->name);
printf("\nWhat would you like to do? ");
choice = chget();
while (strchr("PpFfBbSsWwQq", choice) == NULL) {
printf("Please enter an option from the menu (p, f, w, s, or q): ");
choice = chget();
}
choice = tolower(choice);
return choice;
}
void Shop(Owner *Player) {
char buyorsell;
int choice;
int itemsowned = 0;
bool emptyinventory = true;
int sellcount;
printf("\n\n\n\n\n\n\n\nWelcome to MyPet Shop!\n"
"How can I help you?\n\n"
"\tb) Buy supplies\n\ts) Sell items\n\n"
"What would you like to do? ");
buyorsell = chget();
while (buyorsell != 'b' && buyorsell != 's') {
printf("Please enter 'b' or 's' to buy or sell: ");
buyorsell = chget();
}
switch(buyorsell) {
case 'b':
puts("\n\n\n\nMyPet Shop");
puts("Catalog:\n");
for (int i = 0; i < 12; i++) {
printf("%2d) $%2d %s (%d)\t",
i, ShopCatalog[i].price, ShopCatalog[i].name,
ShopCatalog[i].count);
if ((i+1) % 2 == 0 && i > 0) {
putchar('\n');
}
}
putchar('\n');
printf("What would you like to buy? ");
if (scanf("%d", &choice) != 1) {
getchar();
return;
}
eatline();
while (choice < 0 || choice > 11) {
printf("Please enter a number between 0 and 11: ");
if (scanf("%d", &choice) != 1) {
eatline();
return;
}
}
if (Player->money < ShopCatalog[choice].price) {
printf("You don't have enough money for that!\n");
sleep(1);
return;
}
Player->Inventory[choice] += ShopCatalog[choice].count;
Player->money -= ShopCatalog[choice].price;
printf("%d %s added to your inventory.\n"
"Thank you for shopping at the MyPets Shop!\n",
ShopCatalog[choice].count, ShopCatalog[choice].name);
break;
case 's':
for (int i = 0; i < 12; i++) {
if (Player->Inventory[i] > 0) {
emptyinventory = false;
}
}
if (emptyinventory == true) {
puts("Your inventory is empty!");
sleep(1);
return;
}
puts("\n\n\n\nMyPet Shop");
puts("Your inventory:");
for (int i = 0; i < 12; i++) {
if (Player->Inventory[i] != 0) {
printf("%d ($%d) %s (%d)\t",
i, ShopCatalog[i].resellValue,
ShopCatalog[i].name, Player->Inventory[i]);
itemsowned++;
if (itemsowned % 2 == 0) {
putchar('\n');
}
}
}
printf("\nWhat would you like to sell? ");
if (scanf("%d", &choice) != 1) {
eatline();
return;
}
while (Player->Inventory[choice] == 0) {
printf("Please enter a number from the menu. " );
if (scanf("%d", &choice) != 1) {
eatline();
return;
}
}
printf("How many %s would you like to sell? ",
ShopCatalog[choice].name);
if (scanf("%d", &sellcount) != 1) {
eatline();
return;
}
while (sellcount == 0) {
printf("You cant sell 0 %s!\nHow many would you like to sell? ",
ShopCatalog[choice].name);
if (scanf("%d", &choice) != 1) {
eatline();
return;
}
}
while (sellcount > Player->Inventory[choice]) {
printf("You only have %d!\nHow many would you like to sell? ",
Player->Inventory[choice]);
if (scanf("%d", &sellcount) != 1) {
eatline();
return;
}
}
Player->Inventory[choice] -= sellcount;
Player->money += ShopCatalog[choice].resellValue * sellcount;
printf("Sold %d %s to the shop.\n$%d added to wallet.\n"
"Thank you for your business!", sellcount,
ShopCatalog[choice].name,
ShopCatalog[choice].resellValue * sellcount);
break;
}
fflush(stdout);
sleep(2);
}
char * s_gets(char * st, int n) {
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find)
*find = '\0';
} else {
while (getchar() != '\n')
continue;
}
return ret_val;
}
char chget(void) {
char str[3];
s_gets(str, 3);
return str[0];
}
void eatline(void) {
char ch = 0;
while (ch != '\n') {
ch = getchar();
}
}
int main(void) {
Pet *MyPet;
Owner *Player;
Game_Init(&Player, &MyPet);
Game_Loop(Player, MyPet);
Game_Exit(Player, MyPet);
return 0;
}