Added MiniScript version of 27_Civil_War.

This commit is contained in:
JoeStrout
2023-07-30 21:18:59 -07:00
parent 29766bc6f6
commit 382df64a77
3 changed files with 457 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html).
Conversion to [MiniScript](https://miniscript.org).
Ways to play:
1. Command-Line MiniScript:
Download for your system from https://miniscript.org/cmdline/, install, and then run the program with a command such as:
miniscript civilwar.ms
2. Mini Micro:
Download Mini Micro from https://miniscript.org/MiniMicro/, launch, and then click the top disk slot and chose "Mount Folder..." Select the folder containing the BASIC program. Then, at the Mini Micro command prompt, enter:
load "civilwar"
run

View File

@@ -0,0 +1,437 @@
print " "*26 + "Civil War"
print " "*15 + "Creative Computing Morristown, New Jersey"
print; print; print
// ORIGINAL GAME DESIGN: CRAM, GOODIE, HIBBARD LEXINGTON H.S.
// MODIFICATIONS: G. PAUL, R. HESS (TIES), 1973
// Conversion to MiniScript: J. Strout, 2023
sides = ["Confederate", "Union"]
getYesNo = function(prompt)
while true
yn = input(prompt + "? ").lower
if yn and yn[0] == "y" then return "YES"
if yn and yn[0] == "n" then return "NO"
print "Yes or no -- "
end while
end function
instructions = function
print; print; print; print
print "This is a civil war simulation."
print "To play type a response when the computer asks."
print "Remember that all factors are interrelated and that your"
print "responses could change history. Facts and figures used are"
print "based on the actual occurrence. Most battles tend to result"
print "as they did in the civil war, but it all depends on you!!"
print
print "The object of the game is to win as many battles as ";
print "possible."
print
print "Your choices for defensive strategy are:"
print " (1) artillery attack"
print " (2) fortification against frontal attack"
print " (3) fortification against flanking maneuvers"
print " (4) falling back"
print " Your choices for offensive strategy are:"
print " (1) artillery attack"
print " (2) frontal attack"
print " (3) flanking maneuvers"
print " (4) encirclement"
print "You may surrender by typing a '5' for your strategy."
end function
historicalBattles = []
addBattle = function(name, men0, men1, cas0, cas1, offDef, desc)
battle = {}
battle.name = name
battle.men = [men0, men1]
battle.casualties = [cas0, cas1]
battle.offDef = offDef // 1=Confederate Defense, 2=both Offense, 3=Confederate Offense
battle.description = desc
historicalBattles.push battle
end function
loadData = function
// Historical data
addBattle "Bull Run",18000,18500,1967,2708,1, [
"July 21, 1861. Gen. Beauregard, commanding the South, met",
"Union forces with Gen. Mcdowell in a premature battle at",
"Bull Run. Gen. Jackson helped push back the Union attack."]
addBattle "Shiloh",40000.,44894.,10699,13047,3, [
"April 6-7, 1862. The Confederate surprise attack at",
"Shiloh failed due to poor organization."]
addBattle "Seven Days",95000.,115000.,20614,15849,3, [
"June 25-july 1, 1862. General Lee (CSA) upheld the",
"offensive throughout the battle and forced Gen. McClellan",
"and the Union forces away from Richmond."]
addBattle "Second Bull Run",54000.,63000.,10000,14000,2, [
"Aug 29-30, 1862. The combined Confederate forces under Lee",
"and Jackson drove the Union forces back into washington."]
addBattle "Antietam",40000.,50000.,10000,12000,3, [
"Sept 17, 1862. The South failed to incorporate Maryland",
"into the Confederacy."]
addBattle "Fredericksburg",75000.,120000.,5377,12653,1, [
"Dec 13, 1862. The Confederacy under Lee successfully",
"repulsed an attack by the Union under Gen. Burnside."]
addBattle "Murfreesboro",38000.,45000.,11000,12000,1, [
"Dec 31, 1862. The South under Gen. Bragg won a close battle."]
addBattle "Chancellorsville",32000,90000.,13000,17197,2, [
"May 1-6, 1863. The South had a costly victory and lost",
"one of their outstanding generals, 'Stonewall' Jackson."]
addBattle "Vicksburg",50000.,70000.,12000,19000,1, [
"July 4, 1863. Vicksburg was a costly defeat for the South",
"because it gave the Union access to the Mississippi."]
addBattle "Gettysburg",72500.,85000.,20000,23000,3, [
"July 1-3, 1863. A Southern mistake by Gen. Lee at Gettysburg",
"cost them one of the most crucial battles of the war."]
addBattle "Chickamauga",66000.,60000.,18000,16000,2, [
"Sept. 15, 1863. Confusion in a forest near Chickamauga led",
"to a costly Southern victory."]
addBattle "Chattanooga",37000.,60000.,36700.,5800,2, [
"Nov. 25, 1863. After the South had sieged Gen. Rosencrans'",
"army for three months, Gen. Grant broke the siege."]
addBattle "Spotsylvania",62000.,110000.,17723,18000,2, [
"May 5, 1864. Grant's plan to keep Lee isolated began to",
"fail here, and continued at Cold Harbor and Petersburg."]
addBattle "Atlanta",65000.,100000.,8500,3700,1, [
"August, 1864. Sherman and three veteran armies converged",
"on Atlanta and dealt the death blow to the Confederacy."]
end function
setup = function
print; print; print
if getYesNo("Are there two generals present") == "YES" then
globals.numPlayers = 2
else
globals.numPlayers = 1
print; print "You are the Confederacy. Good luck!"
print
end if
print "Select a battle by typing a number from 1 to 14 on"
print "request. Type any other number to end the simulation."
print "But '0' brings back exact previous battle situation"
print "allowing you to replay it."
print
print "Note: a negative food$ entry causes the program to "
print "use the entries from the previous battle."
print
yn = getYesNo("After requesting a battle, do you wish battle descriptions")
globals.battleDesc = (yn == "YES")
end function
// Game variables -- the 2-element arrays below represent the stats for
// player 0 (Confederacy) and 1 (Union)
D = [0,0] // money
F = [0,0] // food budget
H = [0,0] // salary budget
B = [0,0] // ammo budget
men = [0,0] // men at start of battle? (M1, M2)
menAdded = [0,0] // men added (M3, M4)
menAvail = [0,0] // men available (M5, M6)
P = [0,0] // casualties?
T = [0,0] // total losses?
resources = [0,0] // total resources (money) available to each side (R1, R2)
spending = [0,0] // total expenditures for each side (Q1, Q2)
morale = [0,0] // troop morale (O)
strategy = [0,0] // strategy choice (Y1, Y2)
inflation = [0,0] // inflation (I1, I2)
R = 0 // previous battle
losses = 0 // Confederate losses
wins = 0 // Confederate wins
unresolved = 0 // battles where neither side clearly won
printInColumns = function(a, b, c)
print (a + " "*20)[:20] + (b + " "*16)[:16] + c
end function
pickBattle = function
print; print; print
globals.replay = false
while true
num = input("Which battle do you wish to simulate? ").val
if num == 0 and R > 0 then
num = R
globals.replay = true
end if
if 0 < num <= historicalBattles.len then break
end while
globals.bat = historicalBattles[num - 1]
if not replay then
men[0] = bat.men[0]
men[1] = bat.men[1]
// inflation calc
inflation[0] = 10 + (losses - wins) * 2
inflation[1] = 10 + (wins - losses) * 2
// money available
D[0] = 100 * floor((men[0]*(100-inflation[0])/2000) * (1+(resources[0]-spending[0])/(resources[0]+1))+0.5)
D[1] = 100 * floor(men[1]*(100-inflation[1])/2000 + 0.5)
if numPlayers == 2 then
D[1] = 100 * floor((men[1]*(100-inflation[1])/2000) * (1+(resources[1]-spending[1])/(resources[1]+1))+0.5)
end if
// men available
menAvail[0] = floor(men[0]*(1 + (P[0]-T[0])/(menAdded[0]+1)))
menAvail[1] = floor(men[1]*(1 + (P[1]-T[1])/(menAdded[1]+1)))
globals.F1 = 5/6 * men[0] // ?!?
print; print; print; print; print
print "P:" + P + "; T:" + T + "; menAdded:" + menAdded
print "men[0]:" + men[0] + " ...F1:" + F1
print "This is the battle of " + bat.name
if battleDesc then
for line in bat.description
print line
end for
end if
else
print bat.name + " Instant Replay"
end if
print
printInColumns " ", "CONFEDERACY", " UNION"
printInColumns "MEN", " "+menAvail[0], " "+menAvail[1]
printInColumns "MONEY", "$ "+D[0], "$ "+D[1]
printInColumns "INFLATION", " "+(inflation[0]+15)+" %", " " +inflation[1]+" %"
// (Note: printout lies and shows confederate inflation 15% higher than actual)
print
end function
getBudget = function(player)
print sides[player] + " General---How much do you wish to spend for"
getNum = function(prompt, allowNegative)
while true
n = input(prompt)
if not n then continue
if n[-1] == "k" then n = n[:-1] + "000" // (allow entries like "60k")
if n.val >= 0 or allowNegative then return n.val
print "Negative values are not allowed."
end while
end function
while true
f = getNum(" - Food......? ", true)
if f < 0 then
if resources[player] == 0 then
print "No previous entries."
print "How much do you wish to spend for"
continue
end if
break // keep all previous entries
end if
F[player] = f
H[player] = getNum(" - Salaries..? ", false)
B[player] = getNum(" - Ammunition? ", false)
if F[player] + H[player] + B[player] <= D[player] then break
print "Think again! You have only $" + D[player]
end while
end function
calcMorale = function(player)
m = ((2*F[player]^2 + H[player]^2) / F1^2 + 1)
print (" "*11 + sides[player])[-11:], " "
if m >= 10 then
print "morale is high"
else if m >= 5 then
print "morale is fair"
else
print "morale is poor"
end if
morale[player] = m
end function
getStrategy = function(player)
if numPlayers == 1 then prompt = "Your strategy" else prompt = sides[player] + " strategy"
while true
strat = input(prompt + "? ").val
if 0 < strat < 6 then break
print "Strategy " + strat + " not allowed."
end while
strategy[player] = strat
if strat == 5 then
print "The " + ["Confederacy", "Union"][player] + " has surrendered."
globals.gameOver = true
end if
end function
calcComputerStrategy = function
// Union strategy is computer chosen
print "Union strategy is ", ""
s0 = 0
r = 100 * rnd
for i in range(0, 3)
s0 += unionStrats[i]
if r < s0 then
strategy[1] = i+1
break
end if
end for
print strategy[1]
end function
learnStrategy = function
// Learn present strategy, start forgetting old ones.
// - Present strategy of south gains 3*s, others lose s
// probability points, unless a strategy falls below 5%.
s = 3; s0 = 0
for i in range(0,3)
if unionStrats[i] < 5 then continue
unionStrats[i] -= s
s0 += s
end for
unionStrats[strategy[1]-1] += s0
end function
doBattle = function
U = 0; U2 = 0
// simulated losses -- North
C6 = (2 * bat.casualties[1]/5) * (1+1/(2*(abs(strategy[1]-strategy[0])+1)))
C6 = C6 * (1.28 + (5*men[1]/6) / (B[1]+1))
C6 = floor(C6 * (1+1/morale[1]) + .5)
// - IF LOSS > MEN PRESENT, RESCALE LOSSES
E2 = 100/morale[1] // desertions (Union)
if floor(C6 + E2) >= menAvail[1] then
C6 = floor(13*menAvail[1]/20)
E2 = 7 * C6/13
U2=1 // Union loss
end if
// simulated losses -- South
C5 = (2 * bat.casualties[0]/5) * (1+1/(2*(abs(strategy[1]-strategy[0])+1)))
print "step A:" + C5
C5 = floor(C5 * (1+1/morale[0])*(1.28+F1/(B[0]+1))+.5)
print "step B:" + C5
print "based on morale[0]:"+morale[0]+", F1:"+F1+", B[0]:"+B[0]
E=100/morale[0]
if C5+100/morale[0] >= men[0]*(1+(P1-T1)/(menAdded[0]+1)) then
C5 = floor(13*men[0]/20 * (1+(P1-T1)/(menAdded[0]+1)))
print "step C:" + C5
print "men: " + men; print "menAdded: " + menAdded; print "P1,T1:" + P1 + "," + T1
E=7*C5/13 // desertions (Confed)
U=1 // Confederate loss
end if
print
print; print; printInColumns "", "CONFEDERACY", "UNION"
if numPlayers == 1 then
C6 = floor(17 * bat.casualties[1] * bat.casualties[0] / (C5*20))
E2 = 5 * morale[0]
end if
printInColumns "CASUALTIES", C5, C6
printInColumns "DESERTIONS", floor(E), floor(E2)
print
if numPlayers == 2 then
print "Compared to the actual casualties at " + bat.name
print "Confederate: " + round(100*C5/bat.casualties[0]) + "% of the original"
print "Union: " + round(100*C6/bat.casualties[1]) + "% of the original"
print
// Who won?
print "U:"+U+ " U2:"+U2
if (U == 1 and U2 != 1) or (U == U2 and C5+E > C6+E2) then
print "The Union wins " + bat.name
globals.losses += 1
else if (U2 == 1 and U != 1) or (U == U2 and C5+E < C6+E2) then
print "The confederacy wins " + bat.name
globals.wins += 1
else
print "Battle outcome unresolved"
globals.unresolved += 1
end if
else
print "Your casualties were " + round(100*C5/bat.casualties[0]) + "% of"
print "the actual casualties at " + bat.name
print
if U == 1 or C5+E >= 17*bat.casualties[1]*bat.casualties[0]/(C5*20)+5*morale[0] then
print "You lose " + bat.name
if not replay then globals.losses += 1
else
print "You win " + bat.name
if not replay then globals.wins += 1
end if
end if
if not replay then
// Cumulative battle factors which alter historical
// resources availeble. (If a replay, don't update.)
T[0] += C5 + E
T[1] += C6 + E2
P[0] += bat.casualties[0]
P[1] += bat.casualties[1]
spending[0] += F[0] + H[0] + B[0]
spending[1] += F[1] + H[1] + B[1]
resources[0] += men[0]*(100-inflation[0])/20
resources[1] += men[1]*(100-inflation[1])/20
menAdded[0] += men[0]
menAdded[1] += men[1]
learnStrategy
end if
print "---------------"
end function
// Main Program
loadData
unionStrats = [25, 25, 25, 25]
P1=0; P2=0; T1=0; T2=0 // cumulative stat thingies
print
if getYesNo("Do you want instructions") == "YES" then instructions
setup
gameOver = false
while not gameOver
pickBattle
if gameOver then break
for i in range(0, numPlayers-1)
getBudget i
end for
for i in range(0, numPlayers-1)
calcMorale i
end for
print "Confederate General---", ""
if bat.offDef == 3 then
print "you are on the offensive"
else if bat.offDef == 1 then
print "you are on the defensive"
else
print "both sides are on the offensive "
end if
print
getStrategy 0
if numPlayers == 2 then getStrategy 1 else calcComputerStrategy
if gameOver then break
doBattle
end while
// Finish off
print; print; print; print; print; print
print "The Confederacy has won " + wins + " battles and lost " + losses
if strategy[0] == 5 or (strategy[1] != 5 and losses > wins) then
print "The Union has won the war"
else
print "The Confederacy has won the war"
end if
print "For the " + (wins + losses + unresolved) + " battles fought (excluding reruns)"
print
printInColumns "", "Confederacy", "Union"
printInColumns "Historical Losses", round(P[0]), round(P[1])
printInColumns "Simulated Losses", round(T[0]), round(T[1])
print
printInColumns " % of Original", round(100*T[0]/P[0]), round(100*T[1]/P[1])
if numPlayers == 1 then
print
print "Union intelligence suggsets that the South used "
print "strategies 1, 2, 3, 4 in the following percentages"
print unionStrats.join
end if

View File

@@ -17,6 +17,10 @@ As published in Basic Computer Games (1978):
Downloaded from Vintage Basic at
http://www.vintage-basic.net/games.html
#### Known Bugs
- At the end of a single-player game, the program reports strategies used by "THE SOUTH", but these are in fact strategies used by the North (the computer player) -- the South is always a human player.
#### Porting Notes
(please note any difficulties or challenges in porting here)