From 287e6fa0f59c30990b8a0174a4d85613ad843ad2 Mon Sep 17 00:00:00 2001 From: David Meyer Date: Sat, 20 Jun 2020 01:19:33 +0900 Subject: [PATCH] Work through 6/19 --- hammurabi.c | 237 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 209 insertions(+), 28 deletions(-) diff --git a/hammurabi.c b/hammurabi.c index 380b455..365220d 100644 --- a/hammurabi.c +++ b/hammurabi.c @@ -8,14 +8,17 @@ #include #include +/* Constants */ #define MAXYEARS 10 #define INITPOP 100 #define INITGRAIN 2800 #define INITLAND 1000 +/* Types */ typedef enum {FALSE, TRUE} Boolean; typedef enum {BUY, SELL, FEED, PLANT, RESET, EXEC, CALC, QUIT} Plancmd; +/* Message texts */ char MSGDIV[] = "------------------------------<<<<>>>>-----------------------------------\n"; @@ -27,6 +30,19 @@ One person can farm ten acres of land.\n\ One person needs to eat 20 bushels of grain per year to stay healthy.\n\ "; +char MSGMENU[]= +"You may use your grain to ...\n\ +(F)eed your people,\n\ +(P)lant crops on your land, or\n\ +(B)uy more land. \n\ +Or ...\n\ +(S)ell land to increase your grain.\n\ +You may also ...\n\ +(E)xecute your current plan,\n\ +(R)eset your current plan and start over, or\n\ +(Q)uit the game.\n\ +"; + char MSGSPLASH[] = " ___ ___ ___. .__ \n\ / | \\_____ _____ _____ __ ______________ \\_ |__ |__|\n\ @@ -52,12 +68,20 @@ char MSGSPLASH[] = ':==:'\n\ "; +/* Honorifics */ #define MAXHONOR 9 char *HONORIFIC[] = {"Great", "Mighty", "Wise", "Benevolent", "Merciful", "Just", "Sublime", "Glorious", "Serene", "Majestic"}; +/* Function prototypes */ void completedterm(void); +int inputbuy(void); +int inputfood(void); int inputiexpr(void); +int inputplant(void); +int inputsell(void); +void microcalc(void); +Plancmd planmenu(void); Boolean planyear(void); void printdeposed(void); void printgreeting(void); @@ -67,25 +91,30 @@ void printyearrept(void); Boolean scanyes(char *prompt); void setlandprice(void); +/* Constant variables */ +int CONSCTL; + +/* Game state */ int Year = 0; -int Population = INITPOP; +int Pop = INITPOP; int Grain = INITGRAIN; int Land = INITLAND; +int StarvedTot = 0; +int StarvedPctTot = 0; -int consctl; - +/* Annual plan */ int foodgrain, landsale, plantland; +/* Annual events */ int harvyield, landprice, newpop, plaguedeath, popfed, ratgrain, starvedeath, starvepct; -int totstarved = 0, totstarvepct = 0; Boolean terminated = FALSE; void main(void) { - consctl = open("/dev/consctl", OWRITE); - if(consctl == -1) exits("can't open consctl: %r\n"); + CONSCTL = open("/dev/consctl", OWRITE); + if(CONSCTL == -1) exits("can't open CONSCTL: %r\n"); srand(time(0)); print(MSGSPLASH); @@ -122,11 +151,11 @@ main(void) } Grain = Grain + (plantland * harvyield) - ratgrain; - newpop = (nrand(5) + 1) * (20 * Land + Grain) / Population / 100 + 1; + newpop = (nrand(5) + 1) * (20 * Land + Grain) / Pop / 100 + 1; popfed = foodgrain / 20; - starvedeath = ((popfed < Population) ? (Population - popfed) : 0); - totstarved = totstarved + starvedeath; - starvepct = 100 * starvedeath / Population; + starvedeath = ((popfed < Pop) ? (Pop - popfed) : 0); + StarvedTot = StarvedTot + starvedeath; + starvepct = 100 * starvedeath / Pop; if(starvepct > 45) { printgreeting(); @@ -136,10 +165,10 @@ main(void) } else { - totstarvepct = totstarvepct + starvepct; - Population = Population + newpop - starvedeath; - plaguedeath = ((nrand(100) < 15) ? (Population / 2) : 0); - Population = Population - plaguedeath; + StarvedPctTot = StarvedPctTot + starvepct; + Pop = Pop + newpop - starvedeath; + plaguedeath = ((nrand(100) < 15) ? (Pop / 2) : 0); + Pop = Pop - plaguedeath; printgreeting(); printyearrept(); @@ -155,11 +184,11 @@ main(void) void completedterm(void) { - int avgstarvepct = totstarvepct / MAXYEARS; - int landperperson = Land / Population; - int likeassassination = Population * 0.8 * frand(); + int avgstarvepct = StarvedPctTot / MAXYEARS; + int landperperson = Land / Pop; + int likeassassination = Pop * 0.8 * frand(); printgreeting(); - print("In your %d-year reign, %d people died of starvation, an average of %d people per year.\n", MAXYEARS, totstarved, avgstarvepct); + print("In your %d-year reign, %d people died of starvation, an average of %d people per year.\n", MAXYEARS, StarvedTot, avgstarvepct); print("You started with %d acres per person and ended with %d acres per person.\n", INITLAND / INITPOP, landperperson); if(avgstarvepct > 33 || landperperson < 7) printdeposed(); else if(avgstarvepct > 10 || landperperson < 9) print("Your heavy-handed performance smacks of Nero and Ivan IV. Your (surviving) people find you an unpleasant ruler, and, frankly, hate your guts!"); @@ -171,6 +200,49 @@ completedterm(void) else print("A fantastic performance! Charlemagne, Disraeli, and Jefferson combined could not have done better!"); } +int +inputbuy(void) +{ + int buy, grainbal, price; + Boolean valid = FALSE; + + grainbal = Grain - foodgrain - (plantland / 2); + do + { + print("The price of land is %d bushels per acre.\n", landprice); + print("How many acres do you wish to buy? "); + buy = inputiexpr(); + price = buy * landprice; + if(buy < 0) + print("Sire, it is impossible to buy a negative amount of land.\nIf you wish to sell land, enter \"0\", then select (S)ell from the menu.\n"); + else if(price > grainbal) + print("Sire, %d acres of land costs %d bushels of grain, and you have only %d bushels.\n", + buy, price, grainbal); + else valid = TRUE; + } while(valid == FALSE); + return buy; +} + +int +inputfood(void) +{ + int food, grainbal; + Boolean valid = FALSE; + + grainbal = Grain + (landsale * landprice) - (plantland / 2); + do + { + print("How much grain do you wish to give your people for food? "); + food = inputiexpr(); + if(food < 0) + print("Sire, it is impossible to give the people a negative amount of grain.\nEnter \"0\" to return to the menu.\n"); + else if(food > grainbal) + print("Sire, you only have %d bushels of grain in the granaries.\n", grainbal); + else valid = TRUE; + } while(valid == FALSE); + return food; +} + int inputiexpr(void) { @@ -225,38 +297,147 @@ inputiexpr(void) return result; } +int +inputplant(void) +{ + int grainbal, landbal, plant; + Boolean valid = FALSE; + + grainbal = Grain - foodgrain + (landsale * landprice); + landbal = Land + landsale; + do + { + print("How many acres do you wish to plant? "); + plant = inputiexpr(); + if(plant < 0) + print("Sire, it is impossible to plant a negative amount of land.\nEnter \"0\" to return to the menu.\n"); + else if(plant > landbal) print("Sire, you have only %d acres of lands.\n", landbal); + else if((plant / 2) > grainbal) + print("Sire, you have only %d bushels of grain in the granaries.\n", grainbal); + else if(plant > (10 * Pop)) print("Sire, you have only enough people to plant %d acres.\n", 10 * Pop); + else valid = TRUE; + } while(valid == FALSE); + return plant; +} + +int +inputsell(void) +{ + int landbal, sell, price; + Boolean valid = FALSE; + + landbal = Land - plantland; + do + { + print("The price of land is %d bushels per acre.\n", landprice); + print("How many acres do you wish to sell? "); + sell = inputiexpr(); + if(sell < 0) + print("Sire, it is impossible to sell a negative amount of land.\nIf you wish to buy land, enter \"0\", then select (B)uy from the menu.\n"); + else if(sell > landbal) print("Sire, you have only %d acres of land.\n", landbal); + else valid = TRUE; + } while(valid == FALSE); + return sell; +} + +void +microcalc(void) +{ + +} + +Plancmd +planmenu(void) +{ + int cmdch = 0; + Plancmd cmd; + + if(foodgrain > 0 || landsale != 0 || plantland > 0) + { + print("You are currently planning ...\n"); + if(foodgrain > 0) + print("to provide %d bushels of grain to feed the people\n", foodgrain); + if(plantland > 0) + print("to plant %d acres of land using %d bushels of grain for seed\n", + plantland, plantland / 2); + if(landsale > 0) + print("to sell %d acres of land for %d bushels of grain\n", landsale, + landsale * landprice); + if(landsale < 0) + print("to buy %d acres of land for %d bushels of grain\n", landsale * -1, + landsale * landprice * -1); + } + print(MSGMENU); + if(write(CONSCTL, "rawon", 5) != 5) exits("\ncan't turn off echo\n"); + while(cmdch == 0) + { + print("What is your choice? [fpbserq] "); + cmdch = getchar(); + if(cmdch == EOF) exits("\nerror reading terminal input\n"); + print("%c\n", cmdch); + switch(cmdch) + { + case 'b': + cmd = BUY; + break; + case 'e': + cmd = EXEC; + break; + case 'f': + cmd = FEED; + break; + case 'p': + cmd = PLANT; + break; + case 'q': + cmd = QUIT; + break; + case 'r': + cmd = RESET; + break; + case 's': + cmd = SELL; + break; + default: + cmdch = 0; + } + } + if(write(CONSCTL, "rawoff", 6) != 6) exits("\ncan't turn on echo\n"); + return cmd; +} + Boolean planyear(void) { Boolean play = TRUE; Plancmd cmd; - foodgrain = landsale = planland = 0; + foodgrain = landsale = plantland = 0; do { cmd = planmenu(); switch(cmd) { case BUY: - + landsale = -1 * inputbuy(); break; case SELL: - + landsale = inputsell(); break; case FEED: - + foodgrain = inputfood(); break; case PLANT: - + plantland = inputplant(); break; case RESET: - foodgrain = landsale = planland = 0; + foodgrain = landsale = plantland = 0; break; case EXEC: break; case CALC: - ezintcalc(); + microcalc(); break; case QUIT: play = FALSE; @@ -288,7 +469,7 @@ printlandprice(void) void printstatus(void) { - print("The population is %d.\n", Population); + print("The population is %d.\n", Pop); print("You own %d acres.\n", Land); print("You have %d bushels of grain.\n", Grain); } @@ -309,7 +490,7 @@ scanyes(char *prompt) { int in = 0; - if(write(consctl, "rawon", 5) != 5) exits("\ncan't turn off echo\n"); + if(write(CONSCTL, "rawon", 5) != 5) exits("\ncan't turn off echo\n"); while(in != 'y' && in != 'n') { print("%s [y/n] ", prompt); @@ -317,7 +498,7 @@ scanyes(char *prompt) if(in == EOF) exits("\nerror reading terminal input\n"); print("%c\n", in); } - if(write(consctl, "rawoff", 6) != 6) exits("\ncan't turn on echo\n"); + if(write(CONSCTL, "rawoff", 6) != 6) exits("\ncan't turn on echo\n"); print("\n"); return (in == 'y' ? TRUE : FALSE); }