The game of Hamurabi with a new coat
Posted: Mon Feb 18, 2019 10:00 am
The internal mechanisms are based on my earlier text version "old school Hamurabi", with a few extentions.
Code: Select all
' Hamurabi, version 18-02-2019
'
init_prog()
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()
' *** 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.15 ' probability of the plaque striking
.p_gh=0.2 ' probability of grasshoppers eating bushels
.p_el=0.15 ' probability of acres taken by the Elamites
''
.b=.bo ! .dc=.dco ! .dv=.dvo ! .eff=.effo
graphics ! graphics clear .8,.8,.8 ! draw color 0,0,0
set toolbar off ! get screen size .sw,.sh
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)
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)
diag_text()
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)
.SQ+=dQ ! put_msg(dQ&" bushels have been produced")
if rnd(1)<.p_gh then
gr=100+rnd(300) ! .SQ=max(.1,.SQ-gr)
put_msg("*** Grasshoppers ate "&gr&" bushels!!! ***")
end if
stock()
art(572,70,180,400)
end def
def decisions()
field "inp" text " How many bushels food for the "&(.C+.V)&" people?"
.Et=numpad(0,.SQ) ! .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")
.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
field "inp" text " Touch next period button to continue"
end def
def period_results()
phi=max(.05,.Et/.e/(.C+.V)) ! phip=int(100*phi)
.b=0.6*.b+0.4*phi*.bo ! .eff=0.9*.eff+0.1*phi*.effo
.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.3 then
dV=int((phi-1)*rnd(.V/10)) ! .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)
put_msg("*** The plague killed "&f&" percent of the people!! ***")
f/=100 ! .C=int((1-f)*.C) ! .V=int((1-f)*.V) ! pause 1
end if
if rnd(1)<.p_el then
f=10+rnd(9)
put_msg("*** Elamite warlords took "&f&" percent of your land!! ***")
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()
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
' 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=200 ' 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 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 diag_text()
option angle degrees
a$="Reserved for future use."
draw font name "Papyrus" ! draw font size 60
draw text a$ at 50,880 ! tl=text_width(a$)
sprite "diag" scan 50,880,tl,60
fill color .8,.8,.8 ! fill rect 50,880 to 50+tl,940
SPRITE "diag" AT 50,870 SCALE 1 ANGLE -13
sprite "diag" stamp ! sprite "diag" delete
end def
def b_p(a$) = button_pressed(a$)