BASIC Code

Hammurabi.BAS

Click on the game window below in order to type.

Hammurabi is a simplified version of The Sumerian Game, one of the first text based management sims. I've heavily refactored the version appearing in BASIC Computer Games, but left the overall structure intact.

The Listing

PRINT TAB(11); "**********************************************************"
PRINT TAB(11); "**                                                      **"
PRINT TAB(11); "**                     HAMMURABI                        **"
PRINT TAB(11); "**                                                      **"
PRINT TAB(11); "**     As seen in David Ahl's BASIC Computer Games      **"
PRINT TAB(11); "**     Converted and refactored by Michael Coorlim      **"
PRINT TAB(11); "**                                                      **"
PRINT TAB(11); "**********************************************************"
PRINT:PRINT

?"Instructions:"
?"As King of Sumer you must allocate workers and grain over 10 years."

I'm eschewing line numbers entirely, using labels instead. Because I can.

REM Initialization
D1 = 0
P1 = 0
YEAR = 0 : REM ## YEARS REIGNED
POPULATION = 95 : REM ** CURRENT POPULATION
GRAIN = 2800 : REM ** STORED GRAIN
HARVEST = 3000 : REM ** CURRENT HARVEST
SPOIL = HARVEST - GRAIN : REM ** SPOILAGE
YIELD = 3 : REM ** HARVEST YIELD PER ACRE
ACRES = HARVEST/YIELD : REM ** ACRES OF LAND
IMMIGRANTS = 5 : REM ** YEARLY IMMIGRATION **
Q = 1
PLAGUE = 1 : REM ** CHANCE OF PLAGUE - HITS IF ZERO
DEATHS = 0 : REM ** HOW MANY PEASANTS DIED LAST YEAR

In the original listing each of the variables were single letters with no indications as to what they were for, many of which were reused several times. I've given those that aren't placeholders and temporary more evocative names, explained with REM comments.

LOOP_START:
?:?

YEAR = YEAR +1
POPULATION = POPULATION + IMMIGRANTS
? "Hammurabi, I beg to report to you,"
?"In year ";YEAR;", ";DEATHS;" people starved, ";IMMIGRANTS;" came to the city,"
if PLAGUE < 0 THEN
	POPULATION = INT(POPULATION/2)
  ? "A horrible plague has struck, cutting our population in half."
END IF
? "Our current population is ";POPULATION
? "The city owns ";ACRES;" acres of land."
? "The people harvested ";YIELD;" bushels per acre."
? "Rats ate ";SPOIL;" bushels."
? "This leaves ";GRAIN;" bushels in our grainaries." :?
if YEAR > 10 THEN GOTO FINAL_REPORT

Our basic new turn report, updating the player as to how things stand. I didn't have to alter this much.

Next we get a series of questions that determine our actions for the turn. This is limited to deciding what to do with our food each year.

LF = INT (10 * RND(1)) + 17 : REM ** LF = LAND FACTOR, MODIFYING COST OF ACRAGE
? "Land is currently trading at ";LF;" bushels per acre."

LAND_PURCHASE_QUESTION:
input "How many acres do you wish to buy";Q
if Q < 0 THEN
	?"We can discuss selling in a moment.":?
  goto LAND_PURCHASE_QUESTION
end if
if LF * Q > GRAIN THEN
	?"You only have ";GRAIN;" bushels to trade, your grace.":?
	goto LAND_PURCHASE_QUESTION
end if
ACRES = ACRES + Q
GRAIN = GRAIN - (LF * Q)

LAND_SELL_QUESTION:
input "How many acres do you wish to sell"; Q
if Q < 0 THEN
	? "You can't sell negative land, my king.":?
  GOTO LAND_SELL_QUESTION
END IF
if Q > LAND THEN
	? "My king, we only have";ACRES;" acres of land.":?
  GOTO LAND_SELL_QUESTION
END IF
ACRES = ACRES - Q
GRAIN = GRAIN + (LF * Q)
?

FEED_QUESTION:
? "We have ";GRAIN;" bushels of grain and ";POPULATION;" mouths to feed."
input "How many bushels shall we use to feed our people";Q
if Q<0 THEN
	?"We cannot *take* food they do not have, my king."
  GOTO FEED_QUESTION
END IF
if Q > GRAIN THEN
	?"You only have ";GRAIN;" bushels to trade, your grace.":?
	goto FEED_QUESTION
end if
GRAIN = GRAIN - Q: C=1: ?

?"One bushel of grain seeds two acres, and each worker can tend ten acres. "

PLANT_QUESTION:
input "How many acres do you wish to seed";D
if D < 0 THEN
	?"We cannot plant negative acres, my king.":?
  GOTO PLANT_QUESTION
END IF
if D > ACRES THEN
	?"We only have ";ACRES;" acres, my King.": ?
  GOTO PLANT_QUESTION
END IF
if INT(D/2)>GRAIN THEN
	? "We only have ";GRAIN;" bushels, and that would require ";INT(D/2);", my king.":?
 	GOTO PLANT_QUESTION
END IF
if D > 10 * POPULATION THEN
	?"My king, our ";POPULATION;" can only handle ";POPULATION * 10;" acres.": ?
  GOTO PLANT_QUESTION
END IF

I made two major adjustments here. First, I eliminated superfluous subroutines each time the player enters a number that doesn't make sense - planting more grain than we have. In the original listing, trying to use a negative would have the game end.

Secondly, I add more useful information to each error message, reminding the player of how much grain, acres, etc they have. I also provide the hint that a single unit of food can seed two acres.

I considered mentioning that each worker needs 20 units of food per year to avoid starvation, but ultimately decided to let the player discover that in play.

GRAIN = GRAIN - INT (D/2)
YIELD=INT(RND(1)*5)+1 : REM ** RANDOMLY DETERMINING YIELD PER ACRE

REM HARVEST
HARVEST = D * YIELD
E = 0
REM ** CHECK FOR RATS. 25% chance of them eating 1/3, 1/5, or 1/7 of your crops.
C = INT(RND(1)*4)+1
IF C = 1 THEN
	
	REM ** RAT TROUBLES
  C = INT(RND(1)*3)+2
  SPOIL = INT(S/C)
  
END IF

Changed the math with the rat chance to be a little less esoteric.

REM ** IMMIGRATION

C = INT(RND(1)*5)+1
IMMIGRANTS = INT (C*(20*ACRES+GRAIN)/POPULATION/100+1)

REM ** HOW MANY WERE FED

C = INT(Q/20)

REM ** 15% chance of Plague
PLAGUE = INT (10*(2*RND(1)-.3))

if POPULATION < C THEN 
	
	DEATHS = 0
  GOTO LOOP_START
END IF

DEATHS = POPULATION - C : REM # STARVED TO DEATH
if .45 * POPULATION < DEATHS THEN 
	GOTO STARVATION_END
END IF

The game ends prematurely if you get too many deaths in one year.

P1 = ((YEAR-1)*P1+DEATHS*100/POPULATION)/YEAR
POPULATION = C
D1 = D1 + DEATHS
GOTO LOOP_START

STARVATION_END:
?:?"Your callous mismanagement has led to ";DEATHS; "starvation deaths this year!"
?"Not only have you been deposed and exiled, but your name has been"
?"stricken from the historical record!"
GOTO END_GAME

FINAL_REPORT:
?:? "In your ten year term,";P1;"% of the population"
?"starved per year on the average - a total of ";D1;" people."
L = A/P
?"Your reign began with 10 acres per person, and ended "
?"with "; L;"acres per person."
if P1 < 33 OR L < 7 THEN
	?"Not only have you been deposed and eiled, but your name has been"
	?"stricken from the historical record!"
	GOTO END_GAME
END IF
if P1>10 or L < 9 THEN
	?"You are remembered through history as one of the most ineffectual and buffoonish kings."
  ?"Just absolutely terrible. A synonym for mismanagement."
  ?"But hey, at least they remember you."
  GOTO END_GAME
end if
if P1 > 3 or l < 10 then
	?"Your historical record is one of mediocrity. Without great deeds or great scandal."
  ?"The Gods find your tenure serviceable, and you remain a historical footnote."
  GOTO END_GAME
end if
?"Your name goes down in history as one of the first great rulers."
?"Thousands of years from now you inspire a simplified remake of one"
?"of the first simulation games."
?"Now that's a legacy!"

END_GAME:
? : FOR N = 1 to 10: ? CHR$(7);: NEXT N
?"Until next time."
END

Finally, I rewrote all the end game text.

#David Ahl