27

Moses


This is a simulation in which you have to make decisions, the results of which interact with other conditions and events to produce other conditions. In short, one is conducting a sort of balancing act between conflicting necessities, learning the rules as one goes along. In that, it mirrors life, of course, which makes simulations so interesting.
   As lines 20 and 30 of the listing say, the user has to help Moses guide the Israelites to the Promised Land. They have just crossed the Red Sea and in front of them is the Sinai Desert. As newly freed slaves they have not ability to survive in the desert, no fighting skills, no tribal or social cohesion, and no laws. The only thing that they do have is a high standing in the sight of God, and the leadership of Moses - plus your help, of course! You win the game if, after 10 rounds or game years, you have travelled not less than 1000 miles to reach the River Jordan, achieved a popularity rating of not less than 80 per cent, retained standing with God of not less than 80 per cent, and achieved a combat ability of 80 per cent, too. The reasons for excuses, if you like) are contained in lines 210 to 400 of the listing.
   The listing is a long one, which may deter some people, but if you glance at the game loop, contained between lines 100 and 160, you will see that it is modular of course; what is more to the point, PROCEVENT can be omitted. In its turn, PROCEVENT calls no less than nine other procedures which would be omitted too. So if you don't like typing, or wish to sample the program before typing all of it in, omit line 140, and all lines 570 to 2270!
   In play, on the left of the display is information about current conditions, and on the right are boxes for six inputs. The user is asked to divide up his time between these six, which entails decisions about the importance of each at every step. The six are: (a) combat ability, (b) desert survival skills, (c) travelling, (d) tribal or social activities, (e) law making, and (f) religious duties. Inputs take the form of percentages, with all adding up to 100 per cent. At the outset, how important is it that the Israelites should learn to fight and defend themselves, as against travelling or fulfilling their religious obligations? As we have said, these things interact: you will not travel far or fast if desert survival skills are low, while if your social cohesion is low, the population will fall off rapidly as old folk or the weak are left behind and the tribe begins to disintegrate. In the meantime, if you neglect religious duties, your standing in the eyes of God will fall off and He will support you less often in times of need. The pattern of interaction is illustrated in the diagram. This is the model upon which the program was based and will bear close comparison with the mathematical model as carried out in PROCCALCULATE beginning at line 2330.
   When the user has made an input into the first five boxes, the program calculates the percentage remaining for the last and asks you if these inputs are all right. If so, the results are calculated. PROCEVENT is then called, which selects one of PROCDROUGHT, PROCSTARVE, PROCFIGHT, PROCCOMMAND, PROCCALF, PROCFIRE, PROCPLAGUE, PROCMUTINY or PROCQUAKE. These events too affect, and are affected by, existing conditions, with PROCLIMIT setting numeric limits on the parameters.
   This cycle of input-event-output continues for nine game years and then performance is assessed.
   Despite its length, the program is really rather simple, although a few of the procedures are interesting. PROCCOMMAND, for example, mixes up the Ten Commandments and asks the user to rearrange them. The variable F1 is a flag that prevents this procedure being used twice in one game. C%(X%) is an array with pointers to the Commandments; these pointers are mixed up and the appropriate DATA lines are read and printed in line 1330. This method of mixing the pointers rather than the texts themselves is not only much faster, but also effects an enormous saving of memory.
   The user is required to type the number against the first Commandment, which is accepted in line 1370, is marked right or wrong, and then loops ten times. The score is given in line 1430. This procedure will stand on its own as a rather nice little program.
   PROCCALF is another rather interesting procedure, requiring some thought on the part of the user, and could well be adapted for many types of program. The user is given a choice of six alternatives and asked to choose two of them. There is a call to PROCTWIN which accepts two single-digit inputs, putting them in variables G and H. Different combinations of digits are awarded for different points in lines 1580 to 1630, the last three actually being penalised. The best pair is given a bonus in line 1640.
   A similar arrangement takes place in PROCMUTINY (lines 1810 to 2010), with the additional provision that one particular digital response is considered to be fatal - see line 1930.
   In line 2110 I have been rather naughty and many people will want to spank me for it. Strictly speaking, a proceudre should be entirely self-contained, but as long as BASIC finds an ENDPROC command after a PROC, it doesn't care. What I should have done is to take lines 1720 to 1750 out of PROCFIRE and called it by another procedure name - perhaps PROCDEATHS. PROCFIRE and PROCQUAKE would then each call PROCDEATHS. All three would of course end with an ENDPROC command. Don't do as I do - do as I say!

Variables

AD(13)Game parameters, where:
1 = Combat training input
2 = Desert survival training input
3 = Time spent travelling in current year
4 = Time spent in social activities
5 = Time given over to administration
6 = Time given over to religious duties
7 = Actual combat ability
8 = Desert survival ability
9 = Tribal cohesion
10 = Standing with God
11 = Population
12 = Distance travelled in last game period
13 = Popularity
XGeneral counter
F0'Egyptians attack' flag
F1'10 Commandments' flag
F2'Golden Calf' flag
C%(10)Commandments pointer array
TTotal distance travelled
SC%Score
E%Random event
L%Population losses
N%Commandment number
Y%General counter
G,HDigital inputs from PROCTWIN
G%Losses to be mitigated by God
G$General input string

   10 MODE7:PROCTITLE("MOSES")
   20 PRINT''"In which you lead the Children of"
   30 PRINT"Israel to the Promised Land.":PROCRET
   40 DIM A(13),C%(10)
   50 FORX=1TO13:A(X)=0:NEXT:F0=0:F1=0:F2=0
   60 A(10)=99:A(11)=9950+RND(100):A(13)=99:T=0
   70  
   80 REM - Game loop
   90  
  100 FOR YEAR%=0 TO 9
  110 PROCDISPLAY
  120 PROCCALCULATE
  130 IF RND(1)>.95 PROCNIL:GOTO150
  140 PROCEVENT
  150 PROCLIMIT
  160 NEXT YEAR%
  170  
  180 REM - Last year; assessment
  190  
  200 CLS:IF T>=1000 GOTO240
  210 PROCTITLE("TIME UP!")
  220 PRINT''"You have not reached the River Jordan"
  230 GOTO420
  240 PROCTITLE("THE RIVER JORDAN!")
  250 PRINT''CHR$131;"You have reached the River Jordan"''
  260 IFA(13)>80 GOTO300
  270 PRINT;"Your popularity is only ";A(13);"%"
  280 PRINT"and the people will not follow you"
  290 PRINT"across the river to the Promised Land.":GOTO420
  300 IFA(10)>=80 GOTO340
  310 PRINT;"Your standing with God is only ";A(10);"%"
  320 PRINT"and He will not let you cross the river"
  330 PRINT"into the Promised Land.":GOTO420
  340 IFA(7)>=80 GOTO380
  350 PRINT;"Your combat ability is only ";A(7);"%"
  360 PRINT"and waiting on the other side of the river"
  370 PRINT"are the enemy, much stronger than you.":GOTO420
  380 PROCDBL(0,10,131,"YOU CROSS OVER INTO THE PROMISED LAND")
  390 PROCDBL(5,13,133,CHR$136+"YOU WIN THE GAME!")
  400 SC%=A(7)+A(8)+A(9)+2*A(10)+2*A(11)+A(13)
  410 PRINT'';"YOUR SCORE IS ";SC%:END
  420 PRINT''CHR$136;CHR$134;"SORRY - YOU LOSE":END
  430  
  440 REM - Procedures start
  450  
  460 DEFPROCLIMIT
  470 FORX=7TO10:A(X)=INT(A(X))
  480 IFA(X)>99 A(X)=99
  490 IFA(X)<0A(X)=0
  500 NEXT
  510 IFA(13)>99A(13)=99
  520 IFA(13)<0A(13)=0
  530 A(11)=INT(A(11))
  540 A(13)=INT(A(13))
  550 ENDPROC
  560  
  570 DEFPROCEVENT
  580 IF T<100 AND RND(1)>.5 PROCEGYPT:ENDPROC
  590 E%=RND(12)
  600 ONE%GOTO630,610,620,630,640,650,660,670,680,690,630,630
  610 PROCDROUGHT:ENDPROC
  620 PROCSTARVE:ENDPROC
  630 PROCFIGHT:ENDPROC
  640 PROCCOMMAND:ENDPROC
  650 PROCCALF:ENDPROC
  660 PROCFIRE:ENDPROC
  670 PROCPLAGUE:ENDPROC
  680 PROCMUTINY:ENDPROC
  690 PROCQUAKE:ENDPROC
  700  
  710 DEFPROCDROUGHT
  720 CLS:PROCTITLE("DROUGHT!")
  730 IFA(10)>80 GOTO770
  740 L%=(A(11)*(100-A(8))/100)*RND(1)
  750 PROCGOD(L%)
  760 A(11)=A(11)-L%:A(13)=A(13)-L%*.2:PROCRET
  765 PRINT;''L%;" people die of thirst.":ENDPROC
  770 PRINT'"God tells Moses where to strike the"
  780 PRINT"desert with his rod.  Water gushes out"
  790 PRINT"and all can drink."
  800 A(13)=A(13)+RND(10):PROCRET:ENDPROC
  810  
  820 DEFPROCSTARVE
  830 CLS:PROCTITLE("FAMINE!")
  840 IFA(10)>80 GOTO890
  850 L%=(A(11)*(100-A(8))/100)*RND(1)
  860 PROCGOD(L%)
  870 PRINT;''L%;" people die of starvation."
  880 A(11)=A(11)-L%:A(13)=A(13)-L%*.2:PROCRET:ENDPROC
  890 PRINT''"Moses shows the people how to find and"
  900 PRINT"eat manna.":GOTO800
  910  
  920 DEFPROCFIGHT
  930 CLS:PROCTITLE("ATTACKED!"):RESTORE
  940 FORA=1TORND(3):READQ$:NEXTA
  950 PRINT''"You are attacked by the ";Q$
  960 DATAmelkites,Canaanites,Midianites
  970 PROCLOSSES:ENDPROC
  980  
  990 DEFPROCLOSSES
 1000 L%=A(11)*(100-A(7))/100*RND(1):PROCGOD(L%)
 1010 IF L%<25 GOTO1040
 1020 PRINT''L%;" of your people are killed."
 1030 A(11)=A(11)-L%:A(13)=A(13)-L%*.02:PROCRET:ENDPROC
 1040 PRINT;''"You win the battle, losing ";L%;" men."
 1050 A(11)=A(11)-L%:A(13)=A(13)*1.125+20:PROCRET:ENDPROC
 1060  
 1070 DEFPROCCOMMAND
 1080 IF F1 ENDPROC
 1090 DATAThou shalt have no other God
 1100 DATADo not make graven images
 1110 DATADo not take the Lord's name in vain
 1120 DATAKeep the Sabbath Day holy
 1130 DATAHonour thy father and mother
 1140 DATAThou shalt not kill
 1150 DATADo not commit adultery
 1160 DATAThou shalt not steal
 1170 DATADo not bear false witness
 1180 DATAThou shalt not covet
 1190 FORX%=1TO10:C%(X%)=0:NEXT
 1200 REM - Mix them up
 1210 FORX%=1TO10
 1220 N%=RND(10):IFC%(N%)<>0GOTO1220
 1230 C%(N%)=X%:NEXT X%
 1240 CLS:PROCTITLE("THE TEN COMMANDMENTS")
 1250 PRINT'"God handed down to Moses the Ten"
 1260 PRINT"Commandments on tablets of stone.  Your"
 1270 PRINT"job is to put them in order.":PROCRET
 1280 CLS
 1290 PROCDBL(2,1,131,CHR$131+CHR$136+"Put these in order -")
 1300 PRINT
 1310 FORX%=1TO10:PRINT;X%;" ";:RESTORE1090
 1320 FORY%=1TOC%(X%):READX$:NEXT
 1330 PRINTCHR$134;X$:NEXT:PRINT
 1340 SC%=0
 1350 FORX%=1TO10:REPEAT
 1360 PRINT;CHR$131;"Position ";X%;" - Number ";
 1370 INPUT Q%:UNTIL Q%>0 AND Q%<11:PRINTCHR$11;
 1380 FORZ=1TO24:PRINTCHR$9;:NEXT
 1390 IF C%(Q%)<>X% GOTO1410
 1400 SC%=SC%+1:PRINTCHR$130;"RIGHT!":GOTO1420
 1410 PRINTCHR$129;"WRONG"
 1420 NEXT:A(10)=A(10)+3*SC%
 1430 F1=1:PRINT"SCORE ";SC%;"/10":PROCRET:ENDPROC
 1440  
 1450 DEFPROCCALF
 1460 IF F2 ENDPROC
 1470 CLS:PROCTITLE("THE GOLDEN CALF")
 1480 PRINT'"Moses returns to camp to find that the"
 1490 PRINT"people have made a golden calf and are"
 1500 PRINT"worshipping it.";CHR$131;"What should he do - ?"
 1510 PRINTCHR$130;"1 - Join them"
 1520 PRINTCHR$130;"2 - Smash the calf"
 1530 PRINTCHR$130;"3 - Do nothing"
 1540 PRINTCHR$130;"4 - Think that they are stupid"
 1550 PRINTCHR$130;"5 - Punish them"
 1560 PRINTCHR$130;"6 - Have a special religious service"
 1570 PROCTWIN
 1580 IFG=2ORG=5 SC%=SC%+5
 1590 IFG=6ORH=6 SC%=SC%+3
 1600 IFH=2ORH=5 SC%=SC%+5
 1610 IFH=1ORG=1 SC%=SC%-10
 1620 IFG=3ORH=3 SC%=SC%-5
 1630 IFG=4ORH=4 SC%=SC%-3
 1640 IF(G=2ORG=5)AND(H=2ORH=5)SC%=SC%+5
 1650 FORX%=1TO3:PRINTCHR$9;:NEXT
 1660 PRINTCHR$131;"Score ";SC%;"/25":PROCRET
 1670 A(10)=A(10)+SC%-10:A(13)=A(13)-SC%:F2=1:ENDPROC
 1680  
 1690 DEFPROCFIRE
 1700 CLS:PROCTITLE("FIRE I CAMP!")
 1710 PRINT''"There is a fire among your tents."
 1720 L%=A(11)*(100-A(10))/100*RND(1):PROCGOD(L%)
 1730 PRINT''L%;" people are killed."
 1740 A(11)=A(11)-L%:A(13)=A(13)-L%*.2:PROCRET
 1750 ENDPROC
 1760  
 1770 DEFPROCPLAGUE
 1780 CLS:PROCTITLE("PLAGUE!"):RESTORE
 1790 PRINT''"Your people are struck by the plague.":GOTO1720
 1800 DEFPROCMUTINY
 1810 CLS:PROCTITLE("MUTINY!")
 1820 PRINT'"The people shout,";CHR$129;"'Why did Moses bring"
 1830 PRINTCHR$129;"us out of Egypt - to die in the desert?"
 1840 PRINTCHR$129;"Down with Moses!'"
 1850 PRINTCHR$135;"What should Moses do?"
 1860 PRINTCHR$130;"1 - Leave them in the desert"
 1870 PRINTCHR$130;"2 - Punch a few heads"
 1880 PRINTCHR$130;"3 - Punish the ringleaders"
 1890 PRINTCHR$130;"4 - Ask God to help him"
 1900 PRINTCHR$130;"5 - Take them back to Egypt"
 1910 PRINTCHR$130;"6 - Show them a few miracles."
 1920 PROCWIN
 1930 IFG=1 OR H=1 PROCDONE
 1940 IFG=2ORH=2SC%=SC%-5
 1950 IFG=4ORH=4SC%=SC%+5
 1960 IFG=6ORH=6SC%=SC%+5
 1970 IF(G=6ORH=4)AND(H=6OR=4)SC%=SC%+5
 1980 IFG=3ORH=3SC%=SC%+3
 1990 PRINTCHR$131;"SCORE ";SC%;"/25":SC%=SC%-10
 2000 A(9)=A(9)+SC%*.5:A(10)=A(10)+SC%:A(13)=A(13)-SC%
 2010 PROCRET:ENDPROC
 2020  
 2030 DEFPROCDONE
 2040 CLS:PROCTITLE("RESIGNATION")
 2050 PRINT''"Since you do not want Moses to lead the"
 2060 PRINT"people any longer, there is no point in continuing."
 2070 PRINTCHR$130;"Goodbye!":END
 2080  
 2090 DEFPROCQUAKE
 2100 CLS:PROCTITLE("EARTHQUAKE!")
 2110 PRINT''"Your camp is struck by an earthquake.":GOTO1720
 2120  
 2130 DEFPROCEGYPT
 2140 IF F0 THEN ENDPROC
 2150 CLS:PROCTITLE("EGYPTIANS!"):RESTORE
 2160 PRINT'"You are too near Egypt. You are"
 2170 PRINT"attacked by cavalry."
 2180 PROCLOSSES:ENDPROC
 2190  
 2200 DEFPROCGOD(G%)
 2210 L%=G%*(100-A(10))/100*RND(1)*.5:IFL%<0 L%=0 
 2220 ENDPROC
 2230  
 2240 DEFPROCNIL
 2250 CLS:PROCTITLE("NOTHING TO REPORT")
 2260 PRINT''"There have been no special events this year."
 2270 PROCRET:ENDPROC
 2280  
 2290 DEFPROCRET
 2300 PRINT''CHR$131;"Press";CHR$132;CHR$157;CHR$129;
 2310 PRINT"RETURN ";CHR$156;:INPUTQ$:ENDPROC
 2320  
 2330 DEFPROCCALCULATE
 2340 REM - COMBAT ABILITY
 2350 A(7)=A(1)*.7+A(2)*.1+A(4)*.07+A(5)*.1+A(7)*.825
 2360 REM - DESERT SURVIVAL
 2370 A(8)=A(2)*.72+A(3)*.1+A(7)*.05+A(8)*.77+A(9)*.1
 2380 REM - TRIBAL COHESION
 2390 A(9)=A(9)*.8+A(1)*.1-A(3)*.1+A(4)*.7+A(5)*.8
 2400 A(9)=A(9)+A(6)*.1+A(8)*.1
 2410 REM - STANDING WITH GOD
 2420 A(10)=A(5)*.2+A(6)*.6+A(10)*.8
 2430 REM - POPULATION
 2440 P=A(11)
 2450 A(11)=A(11)*.99-(A(1)+A(2)+A(3))*.2+A(4)*.65
 2460 A(11)=A(11)+A(5)*.55+A(8)*.87+A(9)*.3
 2470 REM - DISTANCE COVERED
 2480 A(12)=INT(A(3)*.21*(A(8)*.175+A(9)*.1)-A(11)*.005)
 2490 IFA(12)<5 A(12)=INT(A(3)*.1)
 2500 T=T+A(12)
 2510 REM - POPULARITY
 2520 A(13)=A(13)*.925-(A(1)+A(2)+A(3))*.1+A(5)*.25
 2530 A(13)=A(13)+A(6)*.3+A(8)*.2-(100-A(9))*.3
 2540 A(13)=A(13)-(P-A(11))*.025+A(4)*.66
 2550 ENDPROC
 2560  
 2570 DEFPROCbox(L%,H%,C%)
 2580 LOCALV%,W%,I%,J%
 2590 V%=VPOS:W%=POS
 2600 PRINTTAB(W%,V%-H%);CHR$(C%+144);"7";
 2610 FORI%=0TOL%+1:PRINT"£";:NEXT:PRINT"k"
 2620 PRINTTAB(W%,V%+1);CHR$(C%+144);"u";
 2630 FORI%=0TOL%+1:PRINT"p";:NEXT:PRINT"z"
 2640 FORJ%=V%-H%+1TOV%:PRINTTAB(W%,J%);CHR$(C%+144);"5";CHR$135
 2650 NEXT
 2660 FORJ%=V%-H%+1TOV%
 2670 PRINTTAB(W%+L%+3,J%);CHR$(C%+144);"j":NEXT
 2680 PRINTTAB(W%+3,V%);"";
 2690 IF NOT(FLAG) ENDPROC
 2700 FORI%=1TOL%:PRINT".";:NEXT
 2710 PRINTTAB(W%+3,V%);
 2720 ENDPROC
 2730  
 2740 DEFPROCDISPLAY
 2750 X$=CHR$133+"MOSES - YEAR "+STR$(YEAR%+1)+""
 2760 DATACombat ability,Desert ability,Travelling
 2770 DATATribal activity,Law making,Reiligion
 2780 CLS:PRINTTAB(12);X$'"   NOW";TAB(34);"INPUT"
 2790 RESTORE 2760:FOR X=3TO13STEP 2:READ X$
 2800 PRINTTAB(11,X);CHR$131;;X$:PRINTTAB(0,X);
 2810 FLAG=FALSE:PROCbox(3,1,4):PRINTTAB(32,X);
 2820 FLAG=TRUE:PROCbox(3,1,4):NEXT
 2830 PRINTTAB(0,16);CHR$130;
 2840 PRINT"POPULATION   TOT.DISTANCE   POPULARITY"
 2850 PRINTTAB(0,18);:FLAG=FALSE:PROCbox(5,1,4)
 2860 PRINTTAB(16,18);:PROCbox(4,1,4)
 2870 PRINTTAB(32,18);:PROCbox(3,1,4)
 2880 PRINTTAB(3,3);A(7);"%";
 2890 PRINTTAB(3,5);A(8);"%";
 2900 PRINTTAB(3,7);A(12);
 2910 PRINTTAB(3,9);A(9);"%";
 2920 PRINTTAB(3,11);A(5);"%";
 2930 PRINTTAB(3,13);A(10);"%";
 2940 PRINTTAB(3,18);A(11);
 2950 PRINTTAB(19,18);T;
 2960 PRINTTAB(35,18);A(13);"%";
 2970 I%=100:FOR X%=1TO5:PRINTTAB(35,X%*2+1);
 2980 INPUTX:IF X>I% PROCtoobig:GOTO2750
 2990 A(X%)=X:I%=I%-X:NEXT:A(6)=I%
 3000 PRINTTAB(35,13);I%;"%";
 3010 PRINTTAB(0,21);"Are those figures OK (Y-N)?";
 3020 REPEAT:G$=GET$:UNTILG$="Y"ORG$="N":IF G$="N"GOTO2750
 3030 ENDPROC
 3040  
 3050 DEFPROCDBL(X%,Y%,C%,X$)
 3060 PRINTTAB(X%,Y%);CHR$141;CHR$C%;X$
 3070 PRINTTAB(X%,Y%+1);CHR$141;CHR$C%;X$:ENDPROC
 3080  
 3090 DEFPROCTITLE(X$)
 3100 PRINTCHR$132;STRING$(19,"Oo")
 3110 PROCDBL((36-LEN(X$))/2,4,131,X$) 
 3120 PRINTCHR$132;STRING$(19,"Oo")
 3130 ENDPROC
 3140  
 3150 DEFPROCinput:X$=""
 3160 G$=GET$:IF ASCG$=13 GOTO3230
 3170 IF ASCG$<>127GOTO3200
 3180 IF X$="" GOTO 3160 ELSE X$=LEFT$(X$,1)
 3190 GOTO3160
 3200 IF ASCG$<=47 OR ASCG$>=58 GOTO3160
 3210 PRINT;G$;:X$=X$+G$
 3220 IFLENX$<>2 GOTO 3160 ELSE 3240
 3230 IFX$=""PRINT;" 0";
 3240 IFLENX$=1PRINTCHR$8;" ";VALX$;
 3250 PRINT;"%":X=VALX$:ENDPROC
 3260  
 3270 DEFPROCtoobig
 3280 PRINTTAB(0,22);"The total of all six input boxes cannot"
 3290 PRINT"be greater than 100%.  Press RETURN and"
 3300 PRINT"try again...";:INPUTQ$:ENDPROC
 3310 DEFPROCTWIN
 3315  
 3320 PRINT''"TYPE";CHR$136;"TWO";CHR$137;"CHOICES ";
 3330 PROCbox(2,1,4):REPEAT:G=GET:UNTIL G-48>=1 AND G-48<=6
 3340 PRINTCHR$G;
 3350 REPEAT:H=GET:UNTIL H-48>=1 AND H-48<=6 AND G<>H
 3360 PRINTCHR$H;
 3370 G=G-48:H=H-48:SC%=10
 3380 ENDPROC