Disclaimer: I am not a doctor, nor do I play one on TV.
Hamurabi – C# – Console – First Version
The first major step in converting Hamurabi from BASIC to the C# programming language, besides the obvious syntax changes, is to start to introduce meaningful variable names.
In the BASIC version of Hamurabi, variables are global and sometimes re-used for different purposes. Introducing more variable names can be useful in making the program easier to understand.
The next, and hopefully final, step in re-factoring the code is to switch to passing variables into C# methods, rather than the methods relying on global static C# variables. It may also be helpful to introduce a Game class for the storage of these “global” variables to faciliate playing multiple games.
Re-factoring the code into methods modularizes the code for easier understandability as well.
It also seems better to use proper capitalization than to use all capital letters, the latter being associated today with shouting.
Disclaimer:The code may not yet be perfectly tested.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Hammurabi
{
static Random rnd = new Random();
//static int C; // Unknown
static int Harvest; // Basic Variable H
static double Q; // Unknown
static int TotalDeaths; // Basic Variable D1
static int PercentPopulationStarvedPerYear; // Basic Variable P1
static int Year; // Year of Hammrabi's reign. Basic variable: Z
static int PeopleStarved; // Number of People that Starved. Basic Variable D
static int PeopleCameToCity; // Number of People that Came to City. Basic Variable I
static int Population; // City Population. Basic Variable P
static int Acres; // Acres. Basic Variable A
static int AcresToPlant = 0; // Basic Variable D
static int BushelsHarvestedPerAcre; // Basic Variable Y
static int BushelCostPerAcre; // Basic Variable Y
static int BushelsEatenByRats; // Basic Variable E
static int BushelsInStore; // Basic Variable S
static int BushelsToFeedPeople; // Basic Variable Q
static bool PlagueStruck = false;
public static void Main(string[] args)
{
// 90 REM RANDOMIZE REMOVED
// 95 D1=0:P1=0
TotalDeaths = 0; PercentPopulationStarvedPerYear = 0;
// 110 Z=0:P=95:S=2800:H=3000:E=H-S
Year = 0; Population = 95; BushelsInStore = 2800; Harvest = 3000; BushelsEatenByRats = Harvest - BushelsInStore;
// 120 Y=3:A=H/Y:I=5:Q=1
BushelCostPerAcre = BushelsHarvestedPerAcre = 3; Acres = Harvest / BushelsHarvestedPerAcre; PeopleCameToCity = 5; PlagueStruck = false;
PeopleStarved = 0; // 210 D=0
do
{
BasicReport();
BuyOrSellAcres();
FeedYourPeople();
PlantAcres();
ABountifulHarvest();
}
while (Year < 11);
// 270 IF Z=11 THEN 860 // End of Term Z (Year == 11)
PerformanceEvaluation();
}
static void BasicReport()
{
//210 D=0
//215 PRINT:PRINT:PRINT "HAMURABI: I BEG TO REPORT TO YOU,":Z=Z+1
//217 PRINT "IN YEAR"Z","D"PEOPLE STARVED,"I"CAME TO THE CITY."
//218 P=P+I
//227 IF Q>0 THEN 230
//228 P=INT(P/2)
//229 PRINT "A HORRIBLE PLAGUE STRUCK! HALF THE PEOPLE DIED."
//230 PRINT "POPULATION IS NOW"P
//232 PRINT "THE CITY NOW OWNS"A"ACRES."
//235 PRINT "YOU HARVESTED"Y"BUSHELS PER ACRE."
//250 PRINT "RATS ATE"E"BUSHELS."
//260 PRINT "YOU NOW HAVE"S"BUSHELS IN STORE.":PRINT
Console.WriteLine(); Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Hammurabi: I beg to report to you, ");
Year++ ;
Console.WriteLine("in year {0}, {1} people starved, {2} came to the city.",
Year, PeopleStarved, PeopleCameToCity);
Population += PeopleCameToCity;
if (PlagueStruck)
{
Population /= 2; // Population halved by plague.
Console.WriteLine("A horrible plague struck! Half the people died.");
}
Console.WriteLine("Population is now {0}", Population);
Console.WriteLine("The city now owns {0} acres.", Acres);
Console.WriteLine("You have harvested {0} bushels per acre.", BushelsHarvestedPerAcre);
Console.WriteLine("Rats ate {0} bushels.", BushelsEatenByRats);
Console.WriteLine("You now have {0} bushels in store.", BushelsInStore);
Console.WriteLine();
}
static void BuyOrSellAcres()
{
int AcresToBuy= 0; // Basic Variable Q
int AcresToSell = 0 ; // Basic Variable Q
//310 C=INT(10*RND(1)):Y=C+17
//312 PRINT "LAND IS TRADING AT"Y"BUSHELS PER ACRE."
//320 PRINT "HOW MANY ACRES DO YOU WISH TO BUY";
//321 INPUT Q:IF Q<0 THEN 850
//322 IF Y*Q<=S THEN 330
//323 GOSUB 710
//330 IF Q=0 THEN 340
//331 A=A+Q:S=S-Y*Q:C=0
//334 GOTO 400
int BushelsHarvestedPerAcre = RandomOneToFive() + 17;
string AcresToBuyString = null;
do
{
Console.WriteLine("Land is trading at {0} bushels per acre.", BushelsHarvestedPerAcre);
do
{
Console.Write("How many acres do you wish to buy? ");
AcresToBuyString = Console.ReadLine();
}
while (!int.TryParse(AcresToBuyString, out AcresToBuy));
Q = AcresToBuy;
if (AcresToBuy * BushelsHarvestedPerAcre > BushelsInStore)
YouOnlyHaveSoManyBushels();
if (AcresToBuy < 0)
{
NotAsYouWish();
}
}
while (( AcresToBuy * BushelsHarvestedPerAcre > BushelsInStore ) || AcresToBuy < 0 );
if (AcresToBuy != 0)
{
Acres += AcresToBuy;
BushelsInStore -= (AcresToBuy * BushelCostPerAcre);
//C = 0;
}
else if (AcresToBuy == 0)
{
//340 PRINT "HOW MANY ACRES DO YOU WISH TO SELL";
//341 INPUT Q:IF Q<0 THEN 850
//342 IF Q<A THEN 350
//343 GOSUB 720
//344 GOTO 340
//350 A=A-Q:S=S+Y*Q:C=0
//400 PRINT
string AcresToSellString = null;
do
{
Console.WriteLine("Land is trading at {0} bushels per acre.", BushelsHarvestedPerAcre);
do
{
Console.Write("How many acres do you wish to sell? ");
AcresToSellString = Console.ReadLine();
}
while (!int.TryParse(AcresToSellString, out AcresToSell));
Q = AcresToSell;
if (AcresToSell > Acres)
{
YouOnlyHaveSoManyAcres();
}
if (AcresToSell < 0)
{
NotAsYouWish();
}
}
while ((AcresToSell > Acres) || AcresToSell < 0);
if (AcresToSell > 0)
{
Acres -= AcresToSell;
BushelsInStore += (BushelCostPerAcre * AcresToSell);
//C = 0;
}
}
}
// Feed Your People
static void FeedYourPeople()
{
//400 PRINT
//410 PRINT "HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE";
//411 INPUT Q
//412 IF Q<0 THEN 850
//418 REM *** TRYING TO USE MORE GRAIN THAN IN THE SILOS?
//420 IF Q<=S THEN 430
//421 GOSUB 710
//422 GOTO 410
//430 S=S-Q:C=1:PRINT
Console.WriteLine();
do
{
string BushelsString = null;
do
{
Console.Write("How many bushels do you wish to feed your people? ");
BushelsString = Console.ReadLine();
}
while (!int.TryParse(BushelsString, out BushelsToFeedPeople));
//Q = BushelsToFeedPeople;
if (BushelsToFeedPeople < 0)
{
NotAsYouWish();
}
if (BushelsToFeedPeople > BushelsInStore) // Trying to use more grain than in the silos?
{
YouOnlyHaveSoManyBushels();
}
}
while (((BushelsToFeedPeople > BushelsInStore) || (BushelsToFeedPeople < 0)));
BushelsInStore -= BushelsToFeedPeople;
//C = 1 ;
Console.WriteLine () ;
}
//440 PRINT "HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED";
//441 INPUT D:IF D=0 THEN 511
//442 IF D<0 THEN 850
//444 REM *** TRYING TO PLANT MORE ACRES THAN YOU OWN?
//445 IF D<=A THEN 450
//446 GOSUB 720
//447 GOTO 440
//449 REM *** ENOUGH GRAIN FOR SEED?
//450 IF INT(D/2)<S THEN 455
//452 GOSUB 710
//453 GOTO 440
//454 REM *** ENOUGH PEOPLE TO TEND THE CROPS?
//455 IF D<10*P THEN 510
//460 PRINT "BUT YOU HAVE ONLY"P"PEOPLE TO TEND THE FIELDS. NOW THEN,"
//470 GOTO 440
//510 S=S-INT(D/2)
static void PlantAcres()
{
string AcresToPlantString;
do
{
do
{
Console.Write("How many acres do you wish to plant with seed? ");
AcresToPlantString = Console.ReadLine();
}
while (!int.TryParse(AcresToPlantString, out AcresToPlant));
if (AcresToPlant < 0)
{
NotAsYouWish();
continue;
}
// Trying to plant more acres than you own?
if (AcresToPlant > Acres)
{
YouOnlyHaveSoManyAcres();
continue;
}
// Enough grain for seed?
// It costs half a bushel to plant an acre.
if (((int)(AcresToPlant / 2)) > BushelsInStore)
{
YouOnlyHaveSoManyBushels();
continue;
}
// Enough people to tend the crops?
if (AcresToPlant > 10 * Population)
{
Console.WriteLine("But you only have {0} people to tend the fields. Now then,", Population);
}
}
while ((AcresToPlant > Acres) ||
(AcresToPlant < 0) ||
( AcresToPlant > Acres ) ||
(((int)(AcresToPlant / 2)) > BushelsInStore) ||
(AcresToPlant > 10 * Population));
// It costs half a bushel to plant an acre.
BushelsInStore -= (AcresToPlant / 2);
}
//511 GOSUB 800
//512 REM *** A BOUNTYFULL HARVEST!!
//515 Y=C:H=D*Y:E=0
//521 GOSUB 800
//522 IF INT(C/2)<>C/2 THEN 530
//523 REM *** THE RATS ARE RUNNING WILD!!
//525 E=INT(S/C)
//530 S=S-E+H
//531 GOSUB 800
//532 REM *** LET'S HAVE SOME BABIES
//533 I=INT(C*(20*A+S)/P/100+1)
//539 REM *** HOW MANY PEOPLE HAD FULL TUMMIES?
//540 C=INT(Q/20)
//541 REM *** HORRORS, A 15% CHANCE OF PLAGUE
//542 Q=INT(10*(2*RND(1)-.3))
//550 IF P<C THEN 210
static void ABountifulHarvest()
{
//511 GOSUB 800
BushelsHarvestedPerAcre = RandomOneToFive(); //515 Y=C
Harvest = AcresToPlant * BushelsHarvestedPerAcre; //515 H=D*Y
BushelsEatenByRats = 0; //515 E=0
//521 GOSUB 800
int val = RandomOneToFive();
if (val % 2 == 0) //522 IF INT(C/2)<>C/2 THEN 530
{ //523 REM *** THE RATS ARE RUNNING WILD!!
BushelsEatenByRats = (int)(BushelsInStore / val); //525 E=INT(S/C)
}
//530 S=S-E+H
BushelsInStore -= BushelsEatenByRats;
BushelsInStore += Harvest;
//531 GOSUB 800
//532 REM *** LET'S HAVE SOME BABIES
//533 I=INT(C*(20*A+S)/P/100+1)
PeopleCameToCity = (int)((RandomOneToFive() * ((20 * Acres) + BushelsInStore)) / Population / 100 + 1);
//539 REM *** HOW MANY PEOPLE HAD FULL TUMMIES?
int PeopleFed = BushelsToFeedPeople / 20; //540 C=INT(Q/20)
//541 REM *** HORRORS, A 15% CHANCE OF PLAGUE
//542 Q=INT(10*(2*RND(1)-.3))
PlagueStruck = (rnd.NextDouble() <= 0.15);
//550 IF P<C THEN 210
//551 REM *** STARVE ENOUGH FOR IMPEACHMENT?
//552 D=P-C:IF D>.45*P THEN 560
//553 P1=((Z-1)*P1+D*100/P)/Z
//555 P=C:D1=D1+D:GOTO 215
if (PeopleFed < Population )
{
int Deaths = Population - PeopleFed;
if (Deaths > 0.45 * Population)
{
YouStarvedTooManyPeople(Deaths); // No return from this method.
}
else
{
PercentPopulationStarvedPerYear = (((Year - 1) * PercentPopulationStarvedPerYear) + (Deaths * 100) / Population) / Year;
Population = PeopleFed;
TotalDeaths += Deaths;
}
}
}
//560 PRINT:PRINT "YOU STARVED"D"PEOPLE IN ONE YEAR!!!"
//565 PRINT "DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY"
//566 PRINT "BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE"
//567 PRINT "ALSO BEEN DECLARED 'NATIONAL FINK' !!":GOTO 990
static void YouStarvedTooManyPeople( int Deaths )
{
Console.WriteLine("You starved {0} people in one year!!!");
Console.WriteLine("Due to this extreme mismanagement you have not only");
Console.WriteLine("been impeached and thrown out of office but you have");
Console.WriteLine("also been declared a 'National Fink' !!");
SoLongForNow();
}
static void YouOnlyHaveSoManyBushels()
{
//710 PRINT "HAMURABI: THINK AGAIN. YOU HAVE ONLY"
//711 PRINT S"BUSHELS OF GRAIN. NOW THEN,"
//712 RETURN
Console.WriteLine("Hammurabi: Think again. You have only");
Console.WriteLine("{0} bushels of grain. Now then...", BushelsInStore);
}
static void YouOnlyHaveSoManyAcres()
{
//720 PRINT "HAMURABI: THINK AGAIN. YOU OWN ONLY"A"ACRES. NOW THEN,"
//730 RETURN
Console.WriteLine("\nHammurabi: Think again. You own only {0} acres. Now then...",Acres);
}
static void NotAsYouWish()
{
//850 PRINT:PRINT "HAMURABI: I CANNOT DO WHAT YOU WISH."
//855 PRINT "GET YOURSELF ANOTHER STEWARD!!!!!"
//857 GOTO 990
Console.WriteLine("\nHammurabi: I cannot do what you wish.");
Console.WriteLine("Get yourself another steward!!!!!");
}
//800 C=INT(RND(1)*5)+1
//801 RETURN
static int RandomOneToFive()
{
return ((int)(rnd.NextDouble() * 5.0)) + 1;
}
//860 PRINT "IN YOUR 10-YEAR TERM OF OFFICE,"P1"PERCENT OF THE"
//862 PRINT "POPULATION STARVED PER YEAR ON AVERAGE, I.E., A TOTAL OF"
//865 PRINT D1"PEOPLE DIED!!":L=A/P
//870 PRINT "YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH"
//875 PRINT L"ACRES PER PERSON.":PRINT
//880 IF P1>33 THEN 565
//885 IF L<7 THEN 565
//890 IF P1>10 THEN 940
//892 IF L<9 THEN 940
//895 IF P1>3 THEN 960
//896 IF L<10 THEN 960
//900 PRINT "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND"
//905 PRINT "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!":GOTO 990
//900 PRINT "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND"
//905 PRINT "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!":GOTO 990
//940 PRINT "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV."
//945 PRINT "THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,"
//950 PRINT "FRANKLY, HATE YOUR GUTS!":GOTO 990
//960 PRINT "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT"
//965 PRINT "REALLY WASN'T TOO BAD AT ALL. ";
//966 PRINT INT(P*.8*RND(1));"PEOPLE WOULD"
//970 PRINT "DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR"
//975 PRINT "TRIVIAL PROBLEMS."
static void PerformanceEvaluation()
{
Console.WriteLine("In your 10-year term of office, {0} percent of the", PercentPopulationStarvedPerYear);
Console.WriteLine("population starved per year on average, i.e. a total of");
Console.WriteLine("{0} people died!!", TotalDeaths);
double AcresPerPerson = Acres / Population; // Basic Variable L
Console.WriteLine("You started with 10 acres per person and ended with");
Console.WriteLine("{0} acres per person.", AcresPerPerson);
if ((PercentPopulationStarvedPerYear > 33) || (AcresPerPerson < 7))
{
//565 PRINT "DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY"
//566 PRINT "BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE"
//567 PRINT "ALSO BEEN DECLARED 'NATIONAL FINK' !!":GOTO 990
Console.WriteLine("Due to this extreme mismanagement you have not only");
Console.WriteLine("been impeached and thrown out of office but you have");
Console.WriteLine("also been declared 'National Fink' !!");
}
else if ((PercentPopulationStarvedPerYear > 10) || (AcresPerPerson < 9))
{
//940 PRINT "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV."
//945 PRINT "THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND,"
//950 PRINT "FRANKLY, HATE YOUR GUTS!":GOTO 990
Console.WriteLine("Your heavy-handed performance smacks of Nero and Ivan IV.");
Console.WriteLine("The people (remaining) find you an unpleasant ruler, and,");
Console.WriteLine("Frankly, hate your guts!");
}
else if ((PercentPopulationStarvedPerYear > 3) || (AcresPerPerson < 10))
{
//960 PRINT "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT"
//965 PRINT "REALLY WASN'T TOO BAD AT ALL. ";
//966 PRINT INT(P*.8*RND(1));"PEOPLE WOULD"
//970 PRINT "DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR"
//975 PRINT "TRIVIAL PROBLEMS."
Console.WriteLine("Your performance could have been somewhat better, but");
Console.WriteLine("really wasn't too bad at all.");
Console.WriteLine("{0} people would", (int)(0.8 * rnd.NextDouble()));
Console.WriteLine("dearly like to see you assassinated but we all have our");
Console.WriteLine("trivial problems.");
}
else
{
//900 PRINT "A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND"
//905 PRINT "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!":GOTO 990
Console.WriteLine("A fantastic performance!! Charlemagne, Disraeli, and");
Console.WriteLine("Jefferson combined could not have done better!");
}
SoLongForNow();
}
//990 PRINT:FOR N=1 TO 10:PRINT CHR$(7);:NEXT N
//995 PRINT "SO LONG FOR NOW.":PRINT
//999 END
static void SoLongForNow()
{
for (int n = 1; n <= 10; n++)
Console.WriteLine("\a\n");
Console.WriteLine("So long for now.\n");
System.Environment.Exit(0);
}
}