mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-12 07:40:50 -08:00
print_with_tab / print_with_whitespace is trivial with Python string formatting and was mostly used in only 2 lines.
316 lines
12 KiB
Python
Executable File
316 lines
12 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
|
|
import random # for generating random numbers
|
|
import sys # for system function, like exit()
|
|
|
|
# global variables for storing player's status
|
|
player_funds: float = 0 # no money
|
|
player_furs = [0, 0, 0, 0] # no furs
|
|
|
|
|
|
# Constants
|
|
FUR_MINK = 0
|
|
FUR_BEAVER = 1
|
|
FUR_ERMINE = 2
|
|
FUR_FOX = 3
|
|
MAX_FURS = 190
|
|
FUR_NAMES = ["MINK", "BEAVER", "ERMINE", "FOX"]
|
|
|
|
FORT_MONTREAL = 1
|
|
FORT_QUEBEC = 2
|
|
FORT_NEWYORK = 3
|
|
FORT_NAMES = ["HOCHELAGA (MONTREAL)", "STADACONA (QUEBEC)", "NEW YORK"]
|
|
|
|
|
|
def show_introduction() -> None:
|
|
"""Show the player the introductory message"""
|
|
print("YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN ")
|
|
print("1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET")
|
|
print("SUPPLIES FOR THE NEXT YEAR. YOU HAVE A CHOICE OF THREE")
|
|
print("FORTS AT WHICH YOU MAY TRADE. THE COST OF SUPPLIES")
|
|
print("AND THE AMOUNT YOU RECEIVE FOR YOUR FURS WILL DEPEND")
|
|
print("ON THE FORT THAT YOU CHOOSE.")
|
|
print()
|
|
|
|
|
|
def get_fort_choice() -> int:
|
|
"""Show the player the choices of Fort, get their input, if the
|
|
input is a valid choice (1,2,3) return it, otherwise keep
|
|
prompting the user."""
|
|
result = 0
|
|
while result == 0:
|
|
print()
|
|
print("YOU MAY TRADE YOUR FURS AT FORT 1, FORT 2,")
|
|
print("OR FORT 3. FORT 1 IS FORT HOCHELAGA (MONTREAL)")
|
|
print("AND IS UNDER THE PROTECTION OF THE FRENCH ARMY.")
|
|
print("FORT 2 IS FORT STADACONA (QUEBEC) AND IS UNDER THE")
|
|
print("PROTECTION OF THE FRENCH ARMY. HOWEVER, YOU MUST")
|
|
print("MAKE A PORTAGE AND CROSS THE LACHINE RAPIDS.")
|
|
print("FORT 3 IS FORT NEW YORK AND IS UNDER DUTCH CONTROL.")
|
|
print("YOU MUST CROSS THROUGH IROQUOIS LAND.")
|
|
print("ANSWER 1, 2, OR 3.")
|
|
|
|
player_choice = input(">> ") # get input from the player
|
|
|
|
# try to convert the player's string input into an integer
|
|
try:
|
|
result = int(player_choice) # string to integer
|
|
except Exception:
|
|
# Whatever the player typed, it could not be interpreted as a number
|
|
pass
|
|
|
|
return result
|
|
|
|
|
|
def show_fort_comment(which_fort):
|
|
"""Print the description for the fort"""
|
|
print()
|
|
if which_fort == FORT_MONTREAL:
|
|
print("YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT")
|
|
print("IS FAR FROM ANY SEAPORT. THE VALUE")
|
|
print("YOU RECEIVE FOR YOUR FURS WILL BE LOW AND THE COST")
|
|
print("OF SUPPLIES HIGHER THAN AT FORTS STADACONA OR NEW YORK.")
|
|
elif which_fort == FORT_QUEBEC:
|
|
print("YOU HAVE CHOSEN A HARD ROUTE. IT IS, IN COMPARSION,")
|
|
print("HARDER THAN THE ROUTE TO HOCHELAGA BUT EASIER THAN")
|
|
print("THE ROUTE TO NEW YORK. YOU WILL RECEIVE AN AVERAGE VALUE")
|
|
print("FOR YOUR FURS AND THE COST OF YOUR SUPPLIES WILL BE AVERAGE.")
|
|
elif which_fort == FORT_NEWYORK:
|
|
print("YOU HAVE CHOSEN THE MOST DIFFICULT ROUTE. AT")
|
|
print("FORT NEW YORK YOU WILL RECEIVE THE HIGHEST VALUE")
|
|
print("FOR YOUR FURS. THE COST OF YOUR SUPPLIES")
|
|
print("WILL BE LOWER THAN AT ALL THE OTHER FORTS.")
|
|
else:
|
|
print("Internal error #1, fort " + str(which_fort) + " does not exist")
|
|
sys.exit(1) # you have a bug
|
|
print()
|
|
|
|
|
|
def get_yes_or_no():
|
|
"""Prompt the player to enter 'YES' or 'NO'. Keep prompting until
|
|
valid input is entered. Accept various spellings by only
|
|
checking the first letter of input.
|
|
Return a single letter 'Y' or 'N'"""
|
|
result = 0
|
|
while result not in ("Y", "N"):
|
|
print("ANSWER YES OR NO")
|
|
player_choice = input(">> ")
|
|
player_choice = player_choice.strip().upper() # trim spaces, make upper-case
|
|
if player_choice.startswith("Y"):
|
|
result = "Y"
|
|
elif player_choice.startswith("N"):
|
|
result = "N"
|
|
return result
|
|
|
|
|
|
def get_furs_purchase():
|
|
"""Prompt the player for how many of each fur type they want.
|
|
Accept numeric inputs, re-prompting on incorrect input values"""
|
|
results = []
|
|
|
|
print("YOUR " + str(MAX_FURS) + " FURS ARE DISTRIBUTED AMONG THE FOLLOWING")
|
|
print("KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX.")
|
|
print()
|
|
|
|
for i in range(len(FUR_NAMES)):
|
|
print("HOW MANY " + FUR_NAMES[i] + " DO YOU HAVE")
|
|
count_str = input(">> ")
|
|
try:
|
|
count = int(count_str)
|
|
results.append(count)
|
|
except Exception:
|
|
# invalid input, prompt again by re-looping
|
|
i -= 1
|
|
return results
|
|
|
|
|
|
def main():
|
|
print(" " * 31 + "FUR TRADER")
|
|
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
|
|
print(" " * 15 + "(Ported to Python Oct 2012 krt@krt.com.au)")
|
|
print("\n\n\n")
|
|
|
|
game_state = "starting"
|
|
fox_price = None # sometimes this takes the "last" price (probably this was a bug)
|
|
|
|
while True:
|
|
|
|
if game_state == "starting":
|
|
show_introduction()
|
|
|
|
player_funds = 600 # Initial player start money
|
|
player_furs = [0, 0, 0, 0] # Player fur inventory
|
|
|
|
print("DO YOU WISH TO TRADE FURS?")
|
|
should_trade = get_yes_or_no()
|
|
if should_trade == "N":
|
|
sys.exit(0) # STOP
|
|
game_state = "trading"
|
|
|
|
elif game_state == "trading":
|
|
print()
|
|
print("YOU HAVE $ %1.2f IN SAVINGS" % (player_funds))
|
|
print("AND " + str(MAX_FURS) + " FURS TO BEGIN THE EXPEDITION")
|
|
player_furs = get_furs_purchase()
|
|
|
|
if sum(player_furs) > MAX_FURS:
|
|
print()
|
|
print("YOU MAY NOT HAVE THAT MANY FURS.")
|
|
print("DO NOT TRY TO CHEAT. I CAN ADD.")
|
|
print("YOU MUST START AGAIN.")
|
|
game_state = "starting" # T/N: Wow, harsh.
|
|
else:
|
|
game_state = "choosing fort"
|
|
|
|
elif game_state == "choosing fort":
|
|
which_fort = get_fort_choice()
|
|
show_fort_comment(which_fort)
|
|
print("DO YOU WANT TO TRADE AT ANOTHER FORT?")
|
|
change_fort = get_yes_or_no()
|
|
if change_fort == "N":
|
|
game_state = "travelling"
|
|
|
|
elif game_state == "travelling":
|
|
print()
|
|
if which_fort == FORT_MONTREAL:
|
|
mink_price = (
|
|
int((0.2 * random.random() + 0.70) * 100 + 0.5) / 100
|
|
) # INT((.2*RND(1)+.7)*10^2+.5)/10^2
|
|
ermine_price = (
|
|
int((0.2 * random.random() + 0.65) * 100 + 0.5) / 100
|
|
) # INT((.2*RND(1)+.65)*10^2+.5)/10^2
|
|
beaver_price = (
|
|
int((0.2 * random.random() + 0.75) * 100 + 0.5) / 100
|
|
) # INT((.2*RND(1)+.75)*10^2+.5)/10^2
|
|
fox_price = (
|
|
int((0.2 * random.random() + 0.80) * 100 + 0.5) / 100
|
|
) # INT((.2*RND(1)+.8)*10^2+.5)/10^2
|
|
|
|
print("SUPPLIES AT FORT HOCHELAGA COST $150.00.")
|
|
print("YOUR TRAVEL EXPENSES TO HOCHELAGA WERE $10.00.")
|
|
player_funds -= 160
|
|
|
|
elif which_fort == FORT_QUEBEC:
|
|
mink_price = (
|
|
int((0.30 * random.random() + 0.85) * 100 + 0.5) / 100
|
|
) # INT((.3*RND(1)+.85)*10^2+.5)/10^2
|
|
ermine_price = (
|
|
int((0.15 * random.random() + 0.80) * 100 + 0.5) / 100
|
|
) # INT((.15*RND(1)+.8)*10^2+.5)/10^2
|
|
beaver_price = (
|
|
int((0.20 * random.random() + 0.90) * 100 + 0.5) / 100
|
|
) # INT((.2*RND(1)+.9)*10^2+.5)/10^2
|
|
fox_price = (
|
|
int((0.25 * random.random() + 1.10) * 100 + 0.5) / 100
|
|
) # INT((.25*RND(1)+1.1)*10^2+.5)/10^2
|
|
event_picker = int(10 * random.random()) + 1
|
|
|
|
if event_picker <= 2:
|
|
print("YOUR BEAVER WERE TOO HEAVY TO CARRY ACROSS")
|
|
print("THE PORTAGE. YOU HAD TO LEAVE THE PELTS, BUT FOUND")
|
|
print("THEM STOLEN WHEN YOU RETURNED.")
|
|
player_furs[FUR_BEAVER] = 0
|
|
elif event_picker <= 6:
|
|
print("YOU ARRIVED SAFELY AT FORT STADACONA.")
|
|
elif event_picker <= 8:
|
|
print("YOUR CANOE UPSET IN THE LACHINE RAPIDS. YOU")
|
|
print("LOST ALL YOUR FURS.")
|
|
player_furs = [0, 0, 0, 0]
|
|
elif event_picker <= 10:
|
|
print("YOUR FOX PELTS WERE NOT CURED PROPERLY.")
|
|
print("NO ONE WILL BUY THEM.")
|
|
player_furs[FUR_FOX] = 0
|
|
else:
|
|
print(
|
|
"Internal Error #3, Out-of-bounds event_picker"
|
|
+ str(event_picker)
|
|
)
|
|
sys.exit(1) # you have a bug
|
|
|
|
print()
|
|
print("SUPPLIES AT FORT STADACONA COST $125.00.")
|
|
print("YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00.")
|
|
player_funds -= 140
|
|
|
|
elif which_fort == FORT_NEWYORK:
|
|
mink_price = (
|
|
int((0.15 * random.random() + 1.05) * 100 + 0.5) / 100
|
|
) # INT((.15*RND(1)+1.05)*10^2+.5)/10^2
|
|
ermine_price = (
|
|
int((0.15 * random.random() + 0.95) * 100 + 0.5) / 100
|
|
) # INT((.15*RND(1)+.95)*10^2+.5)/10^2
|
|
beaver_price = (
|
|
int((0.25 * random.random() + 1.00) * 100 + 0.5) / 100
|
|
) # INT((.25*RND(1)+1.00)*10^2+.5)/10^2
|
|
if fox_price is None:
|
|
# Original Bug? There is no Fox price generated for New York, it will use any previous "D1" price
|
|
# So if there was no previous value, make one up
|
|
fox_price = (
|
|
int((0.25 * random.random() + 1.05) * 100 + 0.5) / 100
|
|
) # not in orginal code
|
|
event_picker = int(10 * random.random()) + 1
|
|
|
|
if event_picker <= 2:
|
|
print("YOU WERE ATTACKED BY A PARTY OF IROQUOIS.")
|
|
print("ALL PEOPLE IN YOUR TRADING GROUP WERE")
|
|
print("KILLED. THIS ENDS THE GAME.")
|
|
sys.exit(0)
|
|
elif event_picker <= 6:
|
|
print("YOU WERE LUCKY. YOU ARRIVED SAFELY")
|
|
print("AT FORT NEW YORK.")
|
|
elif event_picker <= 8:
|
|
print("YOU NARROWLY ESCAPED AN IROQUOIS RAIDING PARTY.")
|
|
print("HOWEVER, YOU HAD TO LEAVE ALL YOUR FURS BEHIND.")
|
|
player_furs = [0, 0, 0, 0]
|
|
elif event_picker <= 10:
|
|
mink_price /= 2
|
|
fox_price /= 2
|
|
print("YOUR MINK AND BEAVER WERE DAMAGED ON YOUR TRIP.")
|
|
print("YOU RECEIVE ONLY HALF THE CURRENT PRICE FOR THESE FURS.")
|
|
else:
|
|
print(
|
|
"Internal Error #4, Out-of-bounds event_picker"
|
|
+ str(event_picker)
|
|
)
|
|
sys.exit(1) # you have a bug
|
|
|
|
print()
|
|
print("SUPPLIES AT NEW YORK COST $85.00.")
|
|
print("YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00.")
|
|
player_funds -= 105
|
|
|
|
else:
|
|
print("Internal error #2, fort " + str(which_fort) + " does not exist")
|
|
sys.exit(1) # you have a bug
|
|
|
|
# Calculate sales
|
|
beaver_value = beaver_price * player_furs[FUR_BEAVER]
|
|
fox_value = fox_price * player_furs[FUR_FOX]
|
|
ermine_value = ermine_price * player_furs[FUR_ERMINE]
|
|
mink_value = mink_price * player_furs[FUR_MINK]
|
|
|
|
print()
|
|
print("YOUR BEAVER SOLD FOR $%6.2f" % (beaver_value))
|
|
print("YOUR FOX SOLD FOR $%6.2f" % (fox_value))
|
|
print("YOUR ERMINE SOLD FOR $%6.2f" % (ermine_value))
|
|
print("YOUR MINK SOLD FOR $%6.2f" % (mink_value))
|
|
|
|
player_funds += beaver_value + fox_value + ermine_value + mink_value
|
|
|
|
print()
|
|
print(
|
|
"YOU NOW HAVE $ %1.2f INCLUDING YOUR PREVIOUS SAVINGS" % (player_funds)
|
|
)
|
|
|
|
print()
|
|
print("DO YOU WANT TO TRADE FURS NEXT YEAR?")
|
|
should_trade = get_yes_or_no()
|
|
if should_trade == "N":
|
|
sys.exit(0) # STOP
|
|
else:
|
|
game_state = "trading"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|