Game of Hamurabi (modified)

Post Reply
Henko
Posts: 828
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Game of Hamurabi (modified)

Post by Henko »

I played this old game again a couple of times, and made some modifications.
The number of periods has been augmented from 10 to 15 ‘years’, mainly to provide more time to recover from the nasty disasters that may happen each year (loss of citizens due to the plague, loss of fertile ground to the Elamite warriors, loss of bushels of wheat due to some billions of grasshoppers)
In the graphical representation of the 15 periods, the production figures over the years are added.
As before, each year a classic Babylonian tapestry is made by Elamitian slaves for the royal palace of king Hamurabi. Those tapestries are shown each year in the right upper corner of the screen.

IMG_1336.png
IMG_1336.png (354.58 KiB) Viewed 129 times


Furthermore i made it somewhat more difficult to attain a good final report by the boss, pharao Neferhotep1 of Egypt.


IMG_1337.png
IMG_1337.png (381.08 KiB) Viewed 129 times


The code:

Code: Select all

' Hamurabi, version august 2025
' by Henko
'
init_prog(15)
do
  start_next_period()
  decisions()
  period_results()
  do slowdown
    if b_p("stop") then stop
    until b_p("go")
  until forever
end


def init_prog(periods)
' *** parameters
'y'
.C=120    ' starting # of kids
.V=300    ' starting # of adults
.bo=0.04  ' starting value of birth rate
.dco=0.01 ' starting value of mortuality of kids
.dvo=0.02 ' starting value of mortuality of adults
.S=100    ' starting value of acres of land
.e=2      ' needed # of bushels food per person
.m=3      ' needed # of adults per acre
.z=2      ' needed # bushels seed per acre
.q=13     ' basic # of bushels produced per acre 
.k=30     ' starting cost of additional purchased acre
.effo=1   ' starting value of production efficiency
.SQ=100   ' starting stock of bushels
.Zt=200   ' starting value of bushels of seed
.p_pl=0.12 ' probability of the plaque striking
.p_gh=0.12 ' probability of grasshoppers eating bushels
.p_el=0.12 ' probability of acres taken by the Elamites
''
.b=.bo ! .dc=.dco ! .dv=.dvo ! .eff=.effo ! .per=periods
graphics ! graphics clear .8,.8,.8 ! draw color 0,0,0
set toolbar off ! get screen size .sw,.sh
randomize
draw font name "Papyrus" 
draw font size 40 ! draw text "The game of Hamurabi" at 170,10
draw font name "Courier-Bold" ! draw font size 18
.nmax=200
dim txt$(.nmax+1),dis(4,4)
field "inp" text "" at 20,746 size 530,60 RO
field "inp" font name "Papyrus" ! field "inp" font size 24
draw text "Bushels on stock" at 574,530 ! draw font size 20
field "stock" text "" at 570,550 size 180,40 RO
field "stock" font name "Papyrus" ! field "stock" font size 32
button "stop" text chr$(10060) at 700,10 size 50,50
button "go" text "Next period" at 570,480 size 180,30
msg()
put_msg("REMEMBER!")
put_msg("one person needs about 2 bushels of food/year")
put_msg("one acre of land needs about 3 adults to harvest")
put_msg("one acre of land needs about 2 bushels of seed")
init_numpad(570,600,40,.5,.8,.8,1)
hist()
end def

def start_next_period()
yr+=1 ! put_msg(" ") ! put_msg("      Year "& yr &" of your reign")
Sv=max(1,.V/.m) ! Sz=max(1,.Zt/.z) ! Sc=min(Sv,Sz) ! Sc=min(Sc,.S)
dQ=int(.eff*.q*Sc) ! .Pr=dQ
.SQ+=dQ ! put_msg(dQ&" bushels have been produced")
if rnd(1)<.p_gh then
  gr=100+rnd(300) ! .SQ=max(.1,.SQ-gr)
  .dis(2,1)+=1 ! .dis(2,2)+=gr ! .dis(2,3)+=(2-yr/10)*gr
  put_msg("*** Grasshoppers ate "&gr&" bushels!!! ***")
  end if
stock()
art(572,70,180,400)
end def

def decisions()
.k=max(10,int(.6*.k+.4*(rnd(61))))
field "inp" text "How many bushels for buying land at "&.k&"/acre?"
Kt=numpad(0,.SQ)
if Kt>0 then
  .SQ=max(1,.SQ-Kt) ! dS=int(Kt/.k) ! .S+=dS
  put_msg(dS&" acres of land bought for "&Kt&" bushels")
  field ("stock") text "        "&.SQ
  end if
ks=.k-2-rnd(7)
field "inp" text "How many acres to sell at "&ks&" bushels/acre?"
dS=numpad(0,.S)
if dS>0 then
  dSQ=int(dS*.k) !.SQ=max(1,.SQ+dSQ) ! .S-=dS
  put_msg(dS&" acres of land sold for "&dSQ&" bushels")
  field ("stock") text "        "&.SQ
  end if
for i=1 to 2
  field "inp" text "  How many bushels food for the "&(.C+.V)&" people?"
  .Et=numpad(0,.SQ)
  if i=2 or .Et>.7*.e*(.C+.V) or .SQ-.Et<.7*.z*.S then break
  field "inp" text "  *** Are you sure? A lot of people will starve!!"
  pause 2
  next i
.SQ=max(1,.SQ-.Et)
field ("stock") text "        "&.SQ
put_msg(.Et&" bushels food for the population")
field "inp" text "How many bushels as seed for new crops?"
.Zt=numpad(0,.SQ) ! .SQ=max(1,.SQ-.Zt)
field ("stock") text "        "&.SQ
put_msg(.Zt&" bushels used as seed for new crop")
field "inp" text " Touch next period button to continue"
end def

def period_results()
Ptot=.C+.V ! rat= .Et/.e/Ptot ! yr=start_next_period.yr
phi=max(.05,rat) ! phip=int(100*phi)
.b=0.6*.b+0.4*phi*.bo ! .eff=0.9*.eff+0.1*phi*.effo
if rat<0.7 then
  rat/=0.7 ! starve=int((1-rat)*Ptot)
  put_msg("*** "&starve&" people starved by lack of food!! ***")
  .C*=rat ! .V*=rat
  end if
.dc=0.2*.dc+0.8*.dco/phi ! .dv=0.4*.dv+0.6*.dvo/phi
adr=int(1000*(.dc*.C+.dv*.V)/(.C+.V))/10
aux=.C
.C=int(.C+.b*.V-(.dc+0.1)*.C) ! .V=int(.V+.1*aux-.dv*.V)
if phi>1.25 then
  dV=8+int((phi-1)*rnd(.V/8)) ! .V+=dV
  put_msg("*** "&dV&" Immigrants came to this paradise of milk and honey!! ***") ! pause 1 
  end if
if rnd(1)<.p_pl then
  f=10+rnd(16) ! Pt=.C+.V
  put_msg("*** The plague killed "&f&" percent of the people!! ***")
  f/=100 ! .C=int((1-f)*.C) ! .V=int((1-f)*.V) ! pause 1
  .dis(3,1)+=1 ! .dis(3,2)+=f*Pt ! .dis(3,3)+=(2-yr/10)*f*Pt
  end if
if rnd(1)<.p_el then
  f=10+rnd(9) ! loss=f*.S/100
  put_msg("*** Elamite warlords took "&f&" percent of your land!! ***")
  .dis(1,1)+=1 ! .dis(1,2)+=loss ! .dis(1,3)+=(2-yr/10)*loss
  f/=100 ! .S=int((1-f)*.S) ! pause 1
  end if
put_msg("Population is now "&.C&" kids & "&.V&" adults") ! pause .3
put_msg("Average health of the people was "&phip&"%") ! pause .3
put_msg("Birth rate was "&int(1000*.b)/10&"%") ! pause .3
put_msg("Average death rate was "&adr&"%") ! pause .3
put_msg("Production efficiency is "&int(100*.eff)&"%") ! pause .3
put_msg("You now own "&.S&" acres of land") ! pause .3
stock() ! graph()
if yr=.per then eval()
end def

def eval()
Pt=.C+.V ! pnts=int(30*(Pt-420)+20*(.S-100)+.SQ-100)
dispnts=int(20*.dis(1,3)+.dis(2,3)+20*.dis(3,3))
pnts+=dispnts ! fig=int(10*min(10,pnts/900))/10
for i=1 to 3 ! ndis+=.dis(i,1) ! next i
put_msg(" ") ! put_msg(" ")
put_msg("*** EVALUATION ***") ! put_msg(" ")
put_msg("After 15 years of reign by king Hamurabi, his doings are evaluated and")
put_msg("rated by the king of kings Pharao Neferhotep I of Egypt.")
put_msg("He speaks to the Babylonian king as follows:")
pause 2
put_msg(" ") ! put_msg("Hamurabi, ")
put_msg("- you started with 100 acres, and ended up with "&.S&" acres")
if .dis(1,1)>0 then
  put_msg("but you suffered from "&.dis(1,1)&" Elimitian raids,")
  put_msg("for wich you will be compensated in the rating")
  end if
put_msg("- you started with 100 bushels, and ended up with "&.SQ&" bushels")
if .dis(2,1)>0 then
  put_msg("but you suffered from "&.dis(2,1)&" grasshopper disasters,")
  put_msg("for wich you will be compensated in the rating")
  end if
put_msg("- you started with 420 people, and ended up with "&Pt&" people")
if .dis(3,1)>0 then
  put_msg("but you suffered from "&.dis(3,1)&" plague epidemics,")
  put_msg("for wich you will be compensated in the rating")
  end if
pause 1 ! put_msg(" ")
put_msg("You are allotted "&pnts&" points, which translates to a rating")
put_msg("of "&fig&" on a scale from 0 to 10")
if fig>=9 then
  put_msg("Excellent, but a threat to me, hence watch your six")
  end if
if fig>=8 and fig<9 then
  put_msg("An really good king you are, no need to do better.")
  end if
if fig>=6.5 and fig<8 then
  put_msg("An adequate king you are, keep on like this.")
  end if
if fig>=4 and fig<6.5 then
  put_msg("You have another period of 15 years to perform better than this.")
  end if
if fig<4 then
  put_msg("This task is clearly beyond your possibilities. You will accompany me")
  put_msg("to Memphis, where a less demanding position for you will be found")
  end if
pause 1
put_msg(" ") ! put_msg("You may now stop the game, or wait a moment to proceed to")
put_msg("the 11th year of your reign")
end def

def stock()
  put_msg("you have "&int(.SQ)&" bushels left.")
  field ("stock") text "        "&.SQ
  end def

' numerical keypad
' 
' produce a simple keypad to quickly enter a number in an app
' upon entry, the keypad disappears
' initialize once, multiple use after
' left upper corner is placed at "xtop,ytop"
' "bs" is the button size (keypad becomes 4.3 times larger)
'
def init_numpad(xtop,ytop,bs,R,G,B,alpha)
name$="numpad" ! cn=10
page name$ set 
page name$ frame xtop,ytop,0,0
set buttons custom
if bs<20 then bs=20
sp=4 ! th=.5*bs+4 ! ww=4*bs+5*sp ! hh=th+4*bs+6*sp
fsize=.5*bs
draw font size fsize ! set buttons font size fsize
draw color 1,1,1 ! fill color .6,.6,.6
button "rec" title "" at 0,0 size ww,hh
button "res" title "" at 0,0 size ww,th+4
fill color R,G,B ! fill alpha alpha
button "0" title "0" at sp,th+3*bs+5*sp size bs,bs
for k=1 to 9
  x=(k-1)%3 ! y=2-floor((k-1)/3)
  button k title k at (x+1)*sp+x*bs,th+y*bs+(y+2)*sp size bs,bs
  next k
button "-" title "-" at 2*sp+bs,th+3*bs+5*sp size bs,bs
button "." title "." at 3*sp+2*bs,th+3*bs+5*sp size bs,bs
button "Cl" title "C" at 4*sp+3*bs,th+2*sp size bs,bs
button "del" title "<-" at 4*sp+3*bs,th+bs+3*sp size bs,bs
button "ok" title "ok" at 4*sp+3*bs,th+2*bs+4*sp size bs,2*bs+sp
page name$ hide 
page name$ frame xtop,ytop,ww,hh
set buttons default ! set buttons font size 20
page "" set ! draw font size 20 ! draw color 0,0,0
end def

' size of number is accepted between "minval" and "maxval"
' if both "minval" and "maxval" are zero, then no restrictions apply
' max number of tokens in the number is 10 (minus and dot included)
' works for option base 0 and 1
'
def numpad(minval,maxval)
page "numpad" set ! page "numpad" show
a$="" ! pflag=0 ! sflag=0 ! ob=1-option_base()
nump1:
if b_p("stop") then stop
if b_p("ok") then
  number=val(a$) ! a$="" ! button "res" text ""
  if minval<>0 or maxval<>0 then
    if number<minval or number>maxval then
      button "res" text "range error"
      pflag=0 ! a$="" ! pause 1
      button "res" text ""
      goto nump1
      end if
    end if
  page "numpad" hide ! page "" set
  return number
  end if
if b_p("Cl") then
  a$ = "" ! pflag=0 ! sflag=0 ! goto nump3
  end if
if b_p("del") and len(a$) then
  ll=len(a$) ! if substr$(a$,ll-ob,ll-ob)="." then pflag=0
  a$ = left$(a$,ll-1) ! sflag=0 ! goto nump3
  end if
if b_p("-") then
  a$ = "-" ! pflag=0 ! sflag=0 ! goto nump3
  end if
if b_p(".") and not pflag and not sflag then
  a$ &= "." ! pflag=1 ! goto nump3
  end if
for k=0 to 9
  t$=k
  if b_p(t$) and not sflag then
    a$ &= t$ ! goto nump3
    end if
  next k
goto nump1
nump3:
if len(a$)>10 then ! sflag=1 ! goto nump1 ! end if
button "res" text a$
goto nump1
end def

def msg()   ' *** define name, position, size of the message window
'y'
nmax=300         ' max # of kept messages in the (FIFO) table
dim txt$(nmax+1) ' table with messages
n$  ="msg"       ' name (handle) of the list
t$  ="Messages"  ' title of the list
x   =20          ' x position of the left upper window corner
y   =70         ' y position
w   =530         ' width
h   =660         ' height (determines the # of displayed messages)
''
end def

def hist()   ' *** define history arrays and init running graph
nt=200 ! max_a=200 ! max_b=2000 ! max_p=600 ! max_pr=1500
dim acre(nt+1),bush(nt+1),pers(nt+1),prod(nt+1)
acre(0)=100 ! bush(0)=100 ! pers(0)=420 ! prod(0)=1300
graph.ma=100 ! graph.mb=100 ! graph.mp=420
draw size 3
draw line 20,830 to 20,1000 ! draw line 550,830 to 550,1000
draw line 20,1000 to 550,1000
draw font name "Papyrus" ! draw font size 30
draw text "Legenda" at 600,840
draw font name "Courier-Bold" ! draw font size 20
draw size 5 ! yo=900 ! dy=30
draw color 0,0,1 ! draw line 570,yo to 620,yo
draw color 0,0,0 ! draw text "Population" at 630,yo-10
draw color 0,1,0 ! draw line 570,yo+dy to 620,yo+dy
draw color 0,0,0 ! draw text "Acres land" at 630,yo+dy-10
draw color 1,0,0 ! draw line 570,yo+2*dy to 620,yo+2*dy
draw color 0,0,0 ! draw text "Bushels" at 630,yo+2*dy-10
draw color 0,0,0 ! draw line 570,yo+3*dy to 620,yo+3*dy
draw color 0,0,0 ! draw text "Production" at 630,yo+3*dy-10
end def

def graph()
np=start_next_period.yr
if np>hist.nt then return
hist.acre(np)=.S ! hist.bush(np)=.SQ
hist.pers(np)=.C+.V ! hist.prod(np)=.Pr
fill color .8,.8,.8 ! fill rect 21,828 to 549,999
ma=max(ma,.S) ! mb=max(mb,.SQ)
mp=max(mp,hist.pers(np)) ! mpr=max(mpr,.Pr)
sca=170/ma ! scb=170/mb ! scp=170/mp ! scpr=170/mpr
dx=530/np ! xo=20 ! yo=1000 ! draw size 2
for i=0 to np-1
  if i>=0 then
    draw color .4,.4,.4 ! draw alpha .4 ! draw size 1
    draw line xo+(i+1)*dx,yo to xo+(i+1)*dx,yo-170
    draw alpha 1 ! draw size 2
    end if
  draw color 0,1,0
  dy1=sca*hist.acre(i) ! dy2=sca*hist.acre(i+1)
  draw line xo+i*dx,yo-dy1 to xo+(i+1)*dx,yo-dy2
  draw color 1,0,0
  dy1=scb*hist.bush(i) ! dy2=scb*hist.bush(i+1)
  draw line xo+i*dx,yo-dy1 to xo+(i+1)*dx,yo-dy2
  draw color 0,0,1
  dy1=scp*hist.pers(i) ! dy2=scp*hist.pers(i+1)
  draw line xo+i*dx,yo-dy1 to xo+(i+1)*dx,yo-dy2
  draw color 0,0,0
  dy1=scpr*hist.prod(i) ! dy2=scpr*hist.prod(i+1)
  draw line xo+i*dx,yo-dy1 to xo+(i+1)*dx,yo-dy2
  next i
end def

def put_msg(a$)
pt+=1 ! if pt>msg.nmax then pt=1 ! m+=1 ! msg.txt$(pt)=a$
c_list(msg.n$,msg.t$,msg.txt$,msg.nmax,pt,msg.x,msg.y,msg.w,msg.h)
end def

' id$ = object name
' cont$ = array met elementen
' size = aantal elementen in de list
' pt = current pointer
'
def c_list(id$,title$,cont$(),size,pt,xt,yt,w,h)
set lists font size 14
if pt=size then full=1
if full then dm=size+1 else dm=pt+1
dim temp$(dm)
k=0
if full then
  for i=pt+1 to size ! k+=1 ! temp$(k)=cont$(i) ! next i
  end if
for i=1 to pt ! k+=1 ! temp$(k)=cont$(i) ! next i
list id$ text temp$ at xt+2,yt+32 size w-4,h-34
list id$ select k
draw size 3
draw rect xt,yt to xt+w,yt+h ! draw line xt,yt+30 to xt+w,yt+30
draw color 0,0,1
if not done then
  draw text title$ at (2*xt+w-text_width(title$))/2,yt+5 
  done=1
  end if
end def

' museum of modern art, free tour along the paintings
' graphics mode assumed
' x,y,w,h are position and size of the paintings
' p is admiration time in seconds for each painting
' button$ is the name of the button in the calling app
'    that is used to activate the function
' press the button again to stop and to restore 
'    the original background of the app
'
def art(x,y,w,h)
refresh off ! draw color .5,.5,.5
w-=odd(w) ! t=6 ! npx=w/2-t ! npy=h/2-t
xs=x+t/3-1 ! ys=y+t/3-1 ! toggle=0
dim va(npx+2),vb(npx+2),r(11)
draw size t ! draw rect x,y to x+w-t-1,y+h-t ! randomize
  for i=1 to 10 ! r(i)=rnd(4) ! next i
  for i=1 to npx ! va(i)=rnd(4) ! next i
  for k=0 to npy ! yy=ys+2*k+2
    for i=1 to npx
      if toggle=0 then ! s=r(va(i-1)+va(i)+va(i+1)) ! vb(i)=s
        else ! s=r(vb(i-1)+vb(i)+vb(i+1)) ! va(i)=s
        end if
      if s=0 then fill color 0,0,0 ! if s=1 then fill color 1,0,0
      if s=2 then fill color 0,1,0 ! if s=3 then fill color 0,0,1
      xx=xs+2*i ! fill rect xx,yy to xx+1,yy+1
      next i ! toggle=1-toggle
    next k
refresh on
end def

def b_p(a$) = button_pressed(a$)

User avatar
Dutchman
Posts: 872
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: Game of Hamurabi (modified)

Post by Dutchman »

Nice game, but it gets a bit boring towards the end.
You might want to add more disasters or costs for the inhabitants of the growing community.

I also discovered a small mistake.
After 15 rounds (years) I received the evaluation and the invitation for the 11th year.
screeshot.jpg
screeshot.jpg (62.52 KiB) Viewed 116 times

Post Reply