diff --git a/01_Acey_Ducey/python/acey_ducey.py b/01_Acey_Ducey/python/acey_ducey.py index 550d94b2..603e01af 100755 --- a/01_Acey_Ducey/python/acey_ducey.py +++ b/01_Acey_Ducey/python/acey_ducey.py @@ -24,7 +24,6 @@ cards = { def play_game() -> None: - """Play the game""" cash = 100 while cash > 0: print(f"You now have {cash} dollars\n") @@ -64,16 +63,6 @@ def play_game() -> None: def main() -> None: - """Main""" - keep_playing = True - - while keep_playing: - play_game() - keep_playing = input("Try again? (yes or no) ").lower().startswith("y") - print("Ok hope you had fun") - - -if __name__ == "__main__": print( """ Acey-Ducey is played in the following manner @@ -84,4 +73,13 @@ a value between the first two. If you do not want to bet, input a 0 """ ) + keep_playing = True + + while keep_playing: + play_game() + keep_playing = input("Try again? (yes or no) ").lower().startswith("y") + print("Ok hope you had fun") + + +if __name__ == "__main__": main() diff --git a/01_Acey_Ducey/python/acey_ducey_oo.py b/01_Acey_Ducey/python/acey_ducey_oo.py index 2fe88af8..35b26d84 100644 --- a/01_Acey_Ducey/python/acey_ducey_oo.py +++ b/01_Acey_Ducey/python/acey_ducey_oo.py @@ -7,16 +7,15 @@ From: BASIC Computer Games (1978) Python port by Aviyam Fischer, 2022 """ -from typing import List, Literal, TypeAlias, get_args +from typing import List, Literal, NamedTuple, TypeAlias, get_args Suit: TypeAlias = Literal["\u2665", "\u2666", "\u2663", "\u2660"] Rank: TypeAlias = Literal[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] -class Card: - def __init__(self, suit: Suit, rank: Rank) -> None: - self.suit = suit - self.rank = rank +class Card(NamedTuple): + suit: Suit + rank: Rank def __str__(self) -> str: r = str(self.rank) diff --git a/02_Amazing/python/amazing.py b/02_Amazing/python/amazing.py index bdffe7e7..9d7ab419 100644 --- a/02_Amazing/python/amazing.py +++ b/02_Amazing/python/amazing.py @@ -1,17 +1,13 @@ -import random import enum -from typing import List, Tuple +import random from dataclasses import dataclass +from typing import List, Tuple # Python translation by Frank Palazzolo - 2/2021 class Maze: - def __init__( - self, - width: int, - length: int, - ): + def __init__(self, width: int, length: int) -> None: assert width >= 2 and length >= 2 used: List[List[int]] = [] walls: List[List[int]] = [] @@ -77,18 +73,15 @@ EXIT_RIGHT = 2 def main() -> None: - welcome_header() + print_intro() width, length = get_maze_dimensions() maze = build_maze(width, length) maze.display() -def welcome_header() -> None: +def print_intro() -> None: print(" " * 28 + "AMAZING PROGRAM") - print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") def build_maze(width: int, length: int) -> Maze: @@ -120,7 +113,7 @@ def build_maze(width: int, length: int) -> Maze: else: while True: if position.col != width - 1: - position.col = position.col + 1 + position.col += 1 elif position.row != length - 1: position.row, position.col = position.row + 1, 0 else: diff --git a/03_Animal/python/animal.py b/03_Animal/python/animal.py index 10e9041f..618ef7d6 100644 --- a/03_Animal/python/animal.py +++ b/03_Animal/python/animal.py @@ -119,7 +119,7 @@ def avoid_void_input(message: str) -> str: return answer -def initial_message() -> None: +def print_intro() -> None: print(" " * 32 + "Animal") print(" " * 15 + "Creative Computing Morristown, New Jersey\n") print("Play ´Guess the Animal´") @@ -133,7 +133,7 @@ def main() -> None: root = Node("Does it swim?", yes_child, no_child) # Main loop of game - initial_message() + print_intro() keep_playing = parse_input("Are you thinking of an animal? ", True, root) == "y" while keep_playing: keep_asking = True diff --git a/04_Awari/python/awari.py b/04_Awari/python/awari.py index d05cb0ec..85669cee 100644 --- a/04_Awari/python/awari.py +++ b/04_Awari/python/awari.py @@ -81,14 +81,6 @@ MAX_HISTORY = 9 LOSING_BOOK_SIZE = 50 -def print_with_tab(space_count: int, msg: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - print(spaces + msg) - - def draw_pit(line: str, board, pit_index) -> str: val = board[pit_index] line = line + " " @@ -362,10 +354,8 @@ def player_move(board) -> Tuple[int, bool, int]: def main() -> None: - print_with_tab(34, "AWARI") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() + print(" " * 34 + "AWARI") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n") board = [0] * 14 # clear the board representation global losing_book diff --git a/05_Bagels/python/bagels.py b/05_Bagels/python/bagels.py index 77e8b473..c9c0ca84 100644 --- a/05_Bagels/python/bagels.py +++ b/05_Bagels/python/bagels.py @@ -106,8 +106,7 @@ def build_result_string(num: List[str], guess: str) -> str: def main() -> None: # Intro text print("\n Bagels") - print("Creative Computing Morristown, New Jersey") - print("\n\n") + print("Creative Computing Morristown, New Jersey\n\n") # Anything other than N* will show the rules response = input("Would you like the rules (Yes or No)? ") diff --git a/06_Banner/python/banner.py b/06_Banner/python/banner.py index 6e563e46..ad85b807 100644 --- a/06_Banner/python/banner.py +++ b/06_Banner/python/banner.py @@ -86,10 +86,10 @@ def print_banner() -> None: for statement_char in statement: s = letters[statement_char].copy() - xStr = character + x_str = character if character == "ALL": - xStr = statement_char - if xStr == " ": + x_str = statement_char + if x_str == " ": print("\n" * (7 * horizontal)) else: for u in range(0, 7): @@ -103,13 +103,13 @@ def print_banner() -> None: f[u] = 8 - k break for _t1 in range(1, horizontal + 1): - line_str = " " * int((63 - 4.5 * vertical) * g1 / len(xStr) + 1) + line_str = " " * int((63 - 4.5 * vertical) * g1 / len(x_str) + 1) for b in range(0, f[u] + 1): if j[b] == 0: for _ in range(1, vertical + 1): - line_str = line_str + " " * len(xStr) + line_str = line_str + " " * len(x_str) else: - line_str = line_str + xStr * vertical + line_str = line_str + x_str * vertical print(line_str) print("\n" * (2 * horizontal - 1)) # print("\n" * 75) # Feed some more paper from the printer diff --git a/07_Basketball/python/basketball.py b/07_Basketball/python/basketball.py index f9870ca8..758e5cb9 100644 --- a/07_Basketball/python/basketball.py +++ b/07_Basketball/python/basketball.py @@ -9,7 +9,7 @@ import random from typing import List, Literal, Optional -def explain_keyboard_inputs() -> None: +def print_intro() -> None: print("\t\t\t Basketball") print("\t Creative Computing Morristown, New Jersey\n\n\n") print("This is Dartmouth College basketball. ") @@ -35,7 +35,7 @@ class Basketball: self.shot_choices: List[Literal[0, 1, 2, 3, 4]] = [0, 1, 2, 3, 4] self.z1: Optional[float] = None - explain_keyboard_inputs() + print_intro() self.defense = get_defense_choice(self.defense_choices) @@ -154,7 +154,7 @@ class Basketball: # ball is passed back to you self.ball_passed_back() else: - print("") + print() self.dartmouth_non_jump_shot() else: print("Shot is good.") @@ -268,7 +268,7 @@ class Basketball: self.opponent_ball() else: if random.random() > 0.5: - print("") + print() self.opponent_non_jumpshot() else: print("Pass back to " + self.opponent + " guard.\n") @@ -304,14 +304,14 @@ class Basketball: self.opponent_ball() else: if random.random() > 0.5: - print("") + print() self.opponent_non_jumpshot() else: print("Pass back to " + self.opponent + " guard.\n") self.opponent_ball() else: if random.random() > 0.5: - print("") + print() self.opponent_non_jumpshot() else: print("Pass back to " + self.opponent + " guard\n") diff --git a/08_Batnum/python/batnum.py b/08_Batnum/python/batnum.py index 60c7aad9..3a54ee49 100644 --- a/08_Batnum/python/batnum.py +++ b/08_Batnum/python/batnum.py @@ -1,5 +1,5 @@ from enum import IntEnum -from typing import Tuple, Any +from typing import Any, Tuple class WinOptions(IntEnum): @@ -41,7 +41,7 @@ class StartOptions(IntEnum): def print_intro() -> None: - """Prints out the introduction and rules for the game.""" + """Print out the introduction and rules for the game.""" print("BATNUM".rjust(33, " ")) print("CREATIVE COMPUTING MORRISSTOWN, NEW JERSEY".rjust(15, " ")) print() @@ -64,12 +64,12 @@ def get_params() -> Tuple[int, int, int, StartOptions, WinOptions]: """This requests the necessary parameters to play the game. Returns a set with the five game parameters: - pileSize - the starting size of the object pile - minSelect - minimum selection that can be made on each turn - maxSelect - maximum selection that can be made on each turn - startOption - 1 if the computer is first + pile_size - the starting size of the object pile + min_select - minimum selection that can be made on each turn + max_select - maximum selection that can be made on each turn + start_option - 1 if the computer is first or 2 if the player is first - winOption - 1 if the goal is to take the last object + win_option - 1 if the goal is to take the last object or 2 if the goal is to not take the last object """ pile_size = get_pile_size() @@ -123,7 +123,7 @@ def player_move( to take and doing some basic validation around that input. Then it checks for any win conditions. - Returns a boolean indicating whether the game is over and the new pileSize.""" + Returns a boolean indicating whether the game is over and the new pile_size.""" player_done = False while not player_done: player_move = int(input("YOUR MOVE ")) @@ -167,7 +167,7 @@ def computer_move( win/lose conditions and then calculating how many objects the computer will take. - Returns a boolean indicating whether the game is over and the new pileSize.""" + Returns a boolean indicating whether the game is over and the new pile_size.""" # First, check for win conditions on this move # In this case, we win by taking the last object and # the remaining pile is less than max select @@ -200,7 +200,7 @@ def play_game( of the win/lose conditions is met. """ game_over = False - # playersTurn is a boolean keeping track of whether it's the + # players_turn is a boolean keeping track of whether it's the # player's or computer's turn players_turn = start_option == StartOptions.PlayerFirst diff --git a/10_Blackjack/python/blackjack.py b/10_Blackjack/python/blackjack.py index e4d6fa40..a2c38260 100644 --- a/10_Blackjack/python/blackjack.py +++ b/10_Blackjack/python/blackjack.py @@ -242,7 +242,7 @@ class Game: players.append(Player.new(PlayerType.Player, i)) if get_char_from_user_input("Do you want instructions", ["y", "n"]) == "y": - instructions() + print_instructions() print() return Game(players=players, decks=Decks.new(), games_played=0) @@ -284,7 +284,7 @@ class Game: # turn loop, ends when player finishes their turn while True: clear() - welcome() + print_welcome_screen() print(f"\n\t\t\tGame {game}") print(scores) print(player_hands_message) @@ -407,7 +407,7 @@ STARTING_BALANCE: int = 100 def main() -> None: game: Game - welcome() + print_welcome_screen() # create game game = Game.new( @@ -421,9 +421,7 @@ def main() -> None: char = get_char_from_user_input("Play Again?", ["y", "n"]) -def welcome() -> None: - """prints the welcome screen""" - # welcome message +def print_welcome_screen() -> None: print( """ BLACK JACK @@ -432,8 +430,7 @@ def welcome() -> None: ) -def instructions() -> None: - """prints the instructions""" +def print_instructions() -> None: print( """ THIS IS THE GAME OF 21. AS MANY AS 7 PLAYERS MAY PLAY THE diff --git a/11_Bombardment/python/bombardment.py b/11_Bombardment/python/bombardment.py index 2457a87a..b125987a 100755 --- a/11_Bombardment/python/bombardment.py +++ b/11_Bombardment/python/bombardment.py @@ -4,9 +4,9 @@ from functools import partial from typing import Callable, List, Set -def display_intro() -> None: - print("" * 33 + "BOMBARDMENT") - print("" * 15 + " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") +def print_intro() -> None: + print(" " * 33 + "BOMBARDMENT") + print(" " * 15 + " CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print("\n\n") print("YOU ARE ON A BATTLEFIELD WITH 4 PLATOONS AND YOU") print("HAVE 25 OUTPOSTS AVAILABLE WHERE THEY MAY BE PLACED.") @@ -28,7 +28,6 @@ def display_field() -> None: for row in range(5): initial = row * 5 + 1 print("\t".join([str(initial + column) for column in range(5)])) - print("\n" * 9) @@ -128,8 +127,8 @@ ENEMY_PROGRESS_MESSAGES = ( ) -def play() -> None: - display_intro() +def main() -> None: + print_intro() display_field() enemy_positions = generate_enemy_positions() @@ -162,4 +161,4 @@ def play() -> None: if __name__ == "__main__": - play() + main() diff --git a/14_Bowling/python/bowling.py b/14_Bowling/python/bowling.py index f4a566aa..c7773978 100644 --- a/14_Bowling/python/bowling.py +++ b/14_Bowling/python/bowling.py @@ -33,7 +33,7 @@ def calculate_score(rolls: List[int]) -> int: class Player: - def __init__(self, name: str): + def __init__(self, name: str) -> None: self.name = name self.rolls: List[int] = [] diff --git a/15_Boxing/python/boxing.py b/15_Boxing/python/boxing.py index f1c2ae59..1943e74e 100755 --- a/15_Boxing/python/boxing.py +++ b/15_Boxing/python/boxing.py @@ -77,7 +77,7 @@ def read_punch_profiles(filepath: Path) -> Dict[Literal[1, 2, 3, 4], PunchProfil return result # type: ignore -def play() -> None: +def main() -> None: print("BOXING") print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print("\n\n") @@ -179,4 +179,4 @@ def play_round(round_number: int, player: Player, opponent: Player) -> None: if __name__ == "__main__": - play() + main() diff --git a/16_Bug/python/bug.py b/16_Bug/python/bug.py index 4d93c158..846002f8 100644 --- a/16_Bug/python/bug.py +++ b/16_Bug/python/bug.py @@ -36,10 +36,6 @@ class State: print_legs(self.legs) -def print_n_whitespaces(n: int) -> None: - print(" " * n, end="") - - def print_n_newlines(n: int) -> None: for _ in range(n): print() @@ -47,7 +43,7 @@ def print_n_newlines(n: int) -> None: def print_feelers(n_feelers: int, is_player: bool = True) -> None: for _ in range(4): - print_n_whitespaces(10) + print(" " * 10, end="") for _ in range(n_feelers): print("A " if is_player else "F ", end="") print() @@ -77,7 +73,7 @@ def print_body(has_tail: bool = False) -> None: def print_legs(n_legs: int) -> None: for _ in range(2): - print_n_whitespaces(5) + print(" " * 5, end="") for _ in range(n_legs): print(" L", end="") print() @@ -156,10 +152,8 @@ def handle_roll(diceroll: Literal[1, 2, 3, 4, 5, 6], state: State) -> bool: def main() -> None: - print_n_whitespaces(34) - print("BUG") - print_n_whitespaces(15) - print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print(" " * 34 + "BUG") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print_n_newlines(3) print("THE GAME BUG") diff --git a/17_Bullfight/python/bullfight.py b/17_Bullfight/python/bullfight.py index 86a4a080..2bb789e2 100644 --- a/17_Bullfight/python/bullfight.py +++ b/17_Bullfight/python/bullfight.py @@ -3,10 +3,6 @@ import random from typing import Dict, List, Literal, Tuple, Union -def print_n_whitespaces(n: int) -> None: - print(" " * n, end="") - - def print_n_newlines(n: int) -> None: for _ in range(n): print() @@ -73,10 +69,8 @@ def calculate_final_score( def print_header() -> None: - print_n_whitespaces(34) - print("BULL") - print_n_whitespaces(15) - print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") + print(" " * 34 + "BULL") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print_n_newlines(2) diff --git a/19_Bunny/python/bunny.py b/19_Bunny/python/bunny.py index 1ebfe792..31b09eb3 100755 --- a/19_Bunny/python/bunny.py +++ b/19_Bunny/python/bunny.py @@ -1,27 +1,21 @@ #!/usr/bin/env python3 -# This data is meant to be read-only, so we are storing it in a tuple import json +# This data is meant to be read-only, so we are storing it in a tuple with open("data.json") as f: DATA = tuple(json.load(f)) -def display_intro() -> None: - print(tab(33) + "BUNNY") - print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") +def print_intro() -> None: + print(" " * 33 + "BUNNY") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print("\n\n") -def tab(column: int) -> str: - """Emulates the TAB command in BASIC. Returns a string with ASCII - codes for setting the cursor to the specified column.""" - return f"\r\33[{column}C" - - -def play() -> None: - display_intro() +def main() -> None: + print_intro() # Using an iterator will give us a similar interface to BASIC's READ # command. Instead of READ, we will call 'next(data)' to fetch the next element. @@ -55,7 +49,7 @@ def play() -> None: # position of a line segment. start = command # Position cursor at start - print(tab(start), end="") + print(" " * start, end="") # The following number, indicates the end of the segment. end = next(data) @@ -67,4 +61,4 @@ def play() -> None: if __name__ == "__main__": - play() + main() diff --git a/20_Buzzword/python/buzzword.py b/20_Buzzword/python/buzzword.py index e5809330..48552edc 100644 --- a/20_Buzzword/python/buzzword.py +++ b/20_Buzzword/python/buzzword.py @@ -1,23 +1,21 @@ -###################################################################### -# -# Buzzword Generator -# -# From: BASIC Computer Games (1978) -# Edited by David H. Ahl -# -# "This program is an invaluable aid for preparing speeches and -# briefings about education technology. This buzzword generator -# provides sets of three highly-acceptable words to work into your -# material. Your audience will never know that the phrases don't -# really mean much of anything because they sound so great! Full -# instructions for running are given in the program. -# -# "This version of Buzzword was written by David Ahl." -# -# -# Python port by Jeff Jetton, 2019 -# -###################################################################### +""" +Buzzword Generator + +From: BASIC Computer Games (1978) + Edited by David H. Ahl + +"This program is an invaluable aid for preparing speeches and + briefings about education technology. This buzzword generator + provides sets of three highly-acceptable words to work into your + material. Your audience will never know that the phrases don't + really mean much of anything because they sound so great! Full + instructions for running are given in the program. + +"This version of Buzzword was written by David Ahl." + + +Python port by Jeff Jetton, 2019 +""" import random @@ -91,7 +89,7 @@ def main() -> None: phrase += section[random.randint(0, len(section) - 1)] print(phrase) - print("") + print() response = input("? ") try: diff --git a/21_Calendar/python/calendar.py b/21_Calendar/python/calendar.py index e2072104..922e348e 100644 --- a/21_Calendar/python/calendar.py +++ b/21_Calendar/python/calendar.py @@ -1,24 +1,23 @@ -######################################################## -# Calendar -# -# From: BASIC Computer Games (1978) -# Edited by David Ahl# -# -# This program prints out a calendar -# for any year. You must specify the -# starting day of the week of the year in -# statement 130. (Sunday(0), Monday -# (-1), Tuesday(-2), etc.) You can determine -# this by using the program WEEKDAY. -# You must also make two changes -# for leap years in statement 360 and 620. -# The program listing describes the necessary -# changes. Running the program produces a -# nice 12-month calendar. -# The program was written by Geofrey -# Chase of the Abbey, Portsmouth, Rhode Island. -# -######################################################## +""" +Calendar + +From: BASIC Computer Games (1978) + Edited by David Ahl# + + This program prints out a calendar +for any year. You must specify the +starting day of the week of the year in +statement 130. (Sunday(0), Monday +(-1), Tuesday(-2), etc.) You can determine +this by using the program WEEKDAY. +You must also make two changes +for leap years in statement 360 and 620. +The program listing describes the necessary +changes. Running the program produces a +nice 12-month calendar. + The program was written by Geofrey +Chase of the Abbey, Portsmouth, Rhode Island. +""" from typing import Tuple @@ -150,8 +149,6 @@ def main() -> None: if __name__ == "__main__": main() -######################################################## -# ######################################################## # # Porting notes: diff --git a/22_Change/python/change.py b/22_Change/python/change.py index 19026857..14ee4d4f 100644 --- a/22_Change/python/change.py +++ b/22_Change/python/change.py @@ -88,17 +88,13 @@ def compute_change() -> None: print(f"{change_in_pennies} PENNY(S)") -def print_thanks() -> None: - print("THANK YOU, COME AGAIN.\n\n") - - def main() -> None: print_header("CHANGE") print_introduction() while True: compute_change() - print_thanks() + print("THANK YOU, COME AGAIN.\n\n") if __name__ == "__main__": diff --git a/24_Chemist/python/chemist.py b/24_Chemist/python/chemist.py index 0975b06d..561f67c3 100644 --- a/24_Chemist/python/chemist.py +++ b/24_Chemist/python/chemist.py @@ -11,15 +11,6 @@ import random MAX_LIVES = 9 -def print_with_tab(space_count: int, msg: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - - print(spaces + msg) - - def play_scenario() -> bool: acid_amount = random.randint(1, 50) @@ -58,8 +49,8 @@ def show_ending() -> None: def main() -> None: - print_with_tab(33, "CHEMIST") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") + print(" " * 33 + "CHEMIST") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print("THE FICTITIOUS CHEMICAL KRYPTOCYANIC ACID CAN ONLY BE") print("DILUTED BY THE RATIO OF 7 PARTS WATER TO 3 PARTS ACID.") diff --git a/25_Chief/python/chief.py b/25_Chief/python/chief.py index fee6735c..d8af319b 100644 --- a/25_Chief/python/chief.py +++ b/25_Chief/python/chief.py @@ -29,43 +29,45 @@ def game() -> None: print("\nTake a Number and ADD 3. Now, Divide this number by 5 and") print("multiply by 8. Now, Divide by 5 and add the same. Subtract 1") - resp = float(input("\nWhat do you have? ")) - comp_guess = (((resp - 4) * 5) / 8) * 5 - 3 - resp2 = input(f"\nI bet your number was {comp_guess} was I right(Yes or No)? ") + you_have = float(input("\nWhat do you have? ")) + comp_guess = (((you_have - 4) * 5) / 8) * 5 - 3 + first_guess_right = input( + f"\nI bet your number was {comp_guess} was I right(Yes or No)? " + ) - if resp2.lower() == "yes": + if first_guess_right.lower() == "yes": print("\nHuh, I Knew I was unbeatable") print("And here is how i did it") print_solution(comp_guess) - input("") + input() else: - resp3 = float(input("\nHUH!! what was you original number? ")) + original_number = float(input("\nHUH!! what was you original number? ")) - if resp3 == comp_guess: + if original_number == comp_guess: print("\nThat was my guess, AHA i was right") print( "Shamed to accept defeat i guess, don't worry you can master mathematics too" ) print("Here is how i did it") print_solution(comp_guess) - input("") + input() else: print("\nSo you think you're so smart, EH?") print("Now, Watch") - print_solution(resp3) + print_solution(original_number) - resp4 = input("\nNow do you believe me? ") + believe_me = input("\nNow do you believe me? ") - if resp4.lower() == "yes": + if believe_me.lower() == "yes": print("\nOk, Lets play again sometime bye!!!!") - input("") + input() else: print("\nYOU HAVE MADE ME VERY MAD!!!!!") print("BY THE WRATH OF THE MATHEMATICS AND THE RAGE OF THE GODS") print("THERE SHALL BE LIGHTNING!!!!!!!") print_lightning_bolt() print("\nI Hope you believe me now, for your own sake") - input("") + input() if __name__ == "__main__": @@ -75,4 +77,4 @@ if __name__ == "__main__": game() else: print("Ok, Nevermind. Let me go back to my great slumber, Bye") - input("") + input() diff --git a/26_Chomp/python/chomp.py b/26_Chomp/python/chomp.py index 28ae2819..69810a5f 100755 --- a/26_Chomp/python/chomp.py +++ b/26_Chomp/python/chomp.py @@ -1,13 +1,16 @@ #!/usr/bin/env python3 -# CHOMP -# -# Converted from BASIC to Python by Trevor Hobson + +""" +CHOMP + +Converted from BASIC to Python by Trevor Hobson +""" class Canvas: """For drawing the cookie""" - def __init__(self, width=9, height=9, fill="*"): + def __init__(self, width=9, height=9, fill="*") -> None: self._buffer = [] for _ in range(height): line = [] @@ -16,13 +19,13 @@ class Canvas: self._buffer.append(line) self._buffer[0][0] = "P" - def render(self): + def render(self) -> str: lines = [" 1 2 3 4 5 6 7 8 9"] for row, line in enumerate(self._buffer, start=1): lines.append(" " + str(row) + " " * 5 + " ".join(line)) return "\n".join(lines) - def chomp(self, r, c): + def chomp(self, r, c) -> str: if not 1 <= r <= len(self._buffer) or not 1 <= c <= len(self._buffer[0]): return "Empty" elif self._buffer[r - 1][c - 1] == " ": @@ -36,7 +39,7 @@ class Canvas: return "Chomp" -def play_game(): +def play_game() -> None: """Play one round of the game""" players = 0 while players == 0: @@ -69,9 +72,9 @@ def play_game(): player = 0 alive = True while alive: - print("") + print() print(cookie.render()) - print("") + print() player += 1 if player > players: player = 1 diff --git a/27_Civil_War/python/Civilwar.py b/27_Civil_War/python/Civilwar.py index 4878bffa..14b88e01 100644 --- a/27_Civil_War/python/Civilwar.py +++ b/27_Civil_War/python/Civilwar.py @@ -1,9 +1,95 @@ +""" +Original game design: Cram, Goodie, Hibbard Lexington H.S. +Modifications: G. Paul, R. Hess (Ties), 1973 +""" +import enum import math -from typing import List +import random +from dataclasses import dataclass +from typing import Dict, List, Literal, Tuple -def tab(n: int) -> str: - return " " * n +class AttackState(enum.Enum): + DEFENSIVE = 1 + BOTH_OFFENSIVE = 2 + OFFENSIVE = 3 + + +CONF = 1 +UNION = 2 + + +@dataclass +class PlayerStat: + food: float = 0 + salaries: float = 0 + ammunition: float = 0 + + desertions: float = 0 + casualties: float = 0 + morale: float = 0 + strategy: int = 0 + available_men: int = 0 + available_money: int = 0 + + army_c: float = 0 + army_m: float = 0 # available_men ???? + inflation: float = 0 + + r: float = 0 + t: float = 0 # casualties + desertions + q: float = 0 # accumulated cost? + p: float = 0 + m: float = 0 + + is_player = False + excessive_losses = False + + def set_available_money(self): + if self.is_player: + factor = 1 + (self.r - self.q) / (self.r + 1) + else: + factor = 1 + self.available_money = 100 * math.floor( + (self.army_m * (100 - self.inflation) / 2000) * factor + 0.5 + ) + + def get_cost(self) -> float: + return self.food + self.salaries + self.ammunition + + def get_army_factor(self) -> float: + return 1 + (self.p - self.t) / (self.m + 1) + + def get_present_men(self) -> float: + return self.army_m * self.get_army_factor() + + +def simulate_losses(player1: PlayerStat, player2: PlayerStat) -> float: + """Simulate losses of player 1""" + tmp = (2 * player1.army_c / 5) * ( + 1 + 1 / (2 * (abs(player1.strategy - player2.strategy) + 1)) + ) + tmp = tmp * (1.28 + (5 * player1.army_m / 6) / (player1.ammunition + 1)) + tmp = math.floor(tmp * (1 + 1 / player1.morale) + 0.5) + return tmp + + +def update_army(player: PlayerStat, enemy: PlayerStat, use_factor=False) -> None: + player.casualties = simulate_losses(player, enemy) + player.desertions = 100 / player.morale + + loss = player.casualties + player.desertions + if not use_factor: + present_men: float = player.available_men + else: + present_men = player.get_present_men() + if loss >= present_men: + factor = player.get_army_factor() + if not use_factor: + factor = 1 + player.casualties = math.floor(13 * player.army_m / 20 * factor) + player.desertions = 7 * player.casualties / 13 + player.excessive_losses = True def get_choice(prompt: str, choices: List[str]) -> str: @@ -14,7 +100,15 @@ def get_choice(prompt: str, choices: List[str]) -> str: return choice -def main(): +def get_morale(stat: PlayerStat, enemy: PlayerStat) -> float: + """Higher is better""" + enemy_strength = 5 * enemy.army_m / 6 + return (2 * math.pow(stat.food, 2) + math.pow(stat.salaries, 2)) / math.pow( + enemy_strength, 2 + ) + 1 + + +def main() -> None: battles = [ [ "JULY 21, 1861. GEN. BEAUREGARD, COMMANDING THE SOUTH, MET", @@ -73,42 +167,39 @@ def main(): ], ] - historical_data = [ - [], - ["BULL RUN", 18000, 18500, 1967, 2708, 1], - ["SHILOH", 40000.0, 44894.0, 10699, 13047, 3], - ["SEVEN DAYS", 95000.0, 115000.0, 20614, 15849, 3], - ["SECOND BULL RUN", 54000.0, 63000.0, 10000, 14000, 2], - ["ANTIETAM", 40000.0, 50000.0, 10000, 12000, 3], - ["FREDERICKSBURG", 75000.0, 120000.0, 5377, 12653, 1], - ["MURFREESBORO", 38000.0, 45000.0, 11000, 12000, 1], - ["CHANCELLORSVILLE", 32000, 90000.0, 13000, 17197, 2], - ["VICKSBURG", 50000.0, 70000.0, 12000, 19000, 1], - ["GETTYSBURG", 72500.0, 85000.0, 20000, 23000, 3], - ["CHICKAMAUGA", 66000.0, 60000.0, 18000, 16000, 2], - ["CHATTANOOGA", 37000.0, 60000.0, 36700.0, 5800, 2], - ["SPOTSYLVANIA", 62000.0, 110000.0, 17723, 18000, 2], - ["ATLANTA", 65000.0, 100000.0, 8500, 3700, 1], + historical_data: List[Tuple[str, float, float, float, int, AttackState]] = [ + ("", 0, 0, 0, 0, AttackState.DEFENSIVE), + ("BULL RUN", 18000, 18500, 1967, 2708, AttackState.DEFENSIVE), + ("SHILOH", 40000.0, 44894.0, 10699, 13047, AttackState.OFFENSIVE), + ("SEVEN DAYS", 95000.0, 115000.0, 20614, 15849, AttackState.OFFENSIVE), + ("SECOND BULL RUN", 54000.0, 63000.0, 10000, 14000, AttackState.BOTH_OFFENSIVE), + ("ANTIETAM", 40000.0, 50000.0, 10000, 12000, AttackState.OFFENSIVE), + ("FREDERICKSBURG", 75000.0, 120000.0, 5377, 12653, AttackState.DEFENSIVE), + ("MURFREESBORO", 38000.0, 45000.0, 11000, 12000, AttackState.DEFENSIVE), + ("CHANCELLORSVILLE", 32000, 90000.0, 13000, 17197, AttackState.BOTH_OFFENSIVE), + ("VICKSBURG", 50000.0, 70000.0, 12000, 19000, AttackState.DEFENSIVE), + ("GETTYSBURG", 72500.0, 85000.0, 20000, 23000, AttackState.OFFENSIVE), + ("CHICKAMAUGA", 66000.0, 60000.0, 18000, 16000, AttackState.BOTH_OFFENSIVE), + ("CHATTANOOGA", 37000.0, 60000.0, 36700.0, 5800, AttackState.BOTH_OFFENSIVE), + ("SPOTSYLVANIA", 62000.0, 110000.0, 17723, 18000, AttackState.BOTH_OFFENSIVE), + ("ATLANTA", 65000.0, 100000.0, 8500, 3700, AttackState.DEFENSIVE), ] - sa = {} - dollars_available = {} - food_array = {} - salaries = {} - ammunition = {} - oa = {} - print(tab(26) + "CIVIL WAR") - print(tab(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 + confederate_strategy_prob_distribution = {} + + # What do you spend money on? + stats: Dict[int, PlayerStat] = { + CONF: PlayerStat(), + UNION: PlayerStat(), + } + + print(" " * 26 + "CIVIL WAR") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") + # Union info on likely confederate strategy - sa[1] = 25 - sa[2] = 25 - sa[3] = 25 - sa[4] = 25 - party = -1 # number of players in the game + confederate_strategy_prob_distribution[1] = 25 + confederate_strategy_prob_distribution[2] = 25 + confederate_strategy_prob_distribution[3] = 25 + confederate_strategy_prob_distribution[4] = 25 print() show_instructions = get_choice( "DO YOU WANT INSTRUCTIONS? YES OR NO -- ", ["YES", "NO"] @@ -145,10 +236,12 @@ def main(): print() print() print("ARE THERE TWO GENERALS PRESENT ", end="") - bs = get_choice("(ANSWER YES OR NO) ", ["YES", "NO"]) - if bs == "YES": - party = 2 - elif bs == "NO": + two_generals = get_choice("(ANSWER YES OR NO) ", ["YES", "NO"]) == "YES" + stats[CONF].is_player = True + if two_generals: + party: Literal[1, 2] = 2 # number of players in the game + stats[UNION].is_player = True + else: party = 1 print() print("YOU ARE THE CONFEDERACY. GOOD LUCK!") @@ -165,282 +258,286 @@ def main(): print("AFTER REQUESTING A BATTLE, DO YOU WISH ", end="") print("BATTLE DESCRIPTIONS ", end="") xs = get_choice("(ANSWER YES OR NO) ", ["YES", "NO"]) - line = 0 - w = 0 - r1 = 0 - q1 = 0 - m3 = 0 - m4 = 0 - p1 = 0 - p2 = 0 - t1 = 0 - t2 = 0 - for i in range(1, 3): - dollars_available[i] = 0 - food_array[i] = 0 - salaries[i] = 0 - ammunition[i] = 0 - oa[i] = 0 - r2 = 0 - q2 = 0 - c6 = 0 - food = 0 - w0 = 0 - strategy_index = 0 - union_strategy_index = 0 - u = 0 - u2 = 0 - random_nb = 0 + confederacy_lost = 0 + confederacy_win = 0 + for i in [CONF, UNION]: + stats[i].p = 0 + stats[i].m = 0 + stats[i].t = 0 + stats[i].available_money = 0 + stats[i].food = 0 + stats[i].salaries = 0 + stats[i].ammunition = 0 + stats[i].strategy = 0 + stats[i].excessive_losses = False + confederacy_unresolved = 0 + random_nb: float = 0 while True: print() print() print() - simulated_battle_index = int(input("WHICH BATTLE DO YOU WISH TO SIMULATE? ")) + simulated_battle_index = int( + get_choice( + "WHICH BATTLE DO YOU WISH TO SIMULATE? (0-14) ", + [str(i) for i in range(15)], + ) + ) if simulated_battle_index < 1 or simulated_battle_index > 14: break if simulated_battle_index != 0 or random_nb == 0: - cs = historical_data[simulated_battle_index][0] - m1 = historical_data[simulated_battle_index][1] - m2 = historical_data[simulated_battle_index][2] - c1 = historical_data[simulated_battle_index][3] - c2 = historical_data[simulated_battle_index][4] - m = historical_data[simulated_battle_index][5] - u = 0 + loaded_battle = historical_data[simulated_battle_index] + battle_name = loaded_battle[0] + stats[CONF].army_m = loaded_battle[1] + stats[UNION].army_m = loaded_battle[2] + stats[CONF].army_c = loaded_battle[3] + stats[UNION].army_c = loaded_battle[4] + stats[CONF].excessive_losses = False + # Inflation calc - i1 = 10 + (line - w) * 2 - i2 = 10 + (w - line) * 2 - # Money available - dollars_available[1] = 100 * math.floor( - (m1 * (100 - i1) / 2000) * (1 + (r1 - q1) / (r1 + 1)) + 0.5 - ) - dollars_available[2] = 100 * math.floor(m2 * (100 - i2) / 2000 + 0.5) - if bs == "YES": - dollars_available[2] = 100 * math.floor( - (m2 * (100 - i2) / 2000) * (1 + (r2 - q2) / (r2 + 1)) + 0.5 - ) - # Men available - m5 = math.floor(m1 * (1 + (p1 - t1) / (m3 + 1))) - m6 = math.floor(m2 * (1 + (p2 - t2) / (m4 + 1))) - f1 = 5 * m1 / 6 + stats[CONF].inflation = 10 + (confederacy_lost - confederacy_win) * 2 + stats[UNION].inflation = 10 + (confederacy_win - confederacy_lost) * 2 + + # Money and Men available + for i in [CONF, UNION]: + stats[i].set_available_money() + stats[i].available_men = math.floor(stats[i].get_army_factor()) print() print() print() print() print() - print(f"THIS IS THE BATTLE OF {cs}") + print(f"THIS IS THE BATTLE OF {battle_name}") if xs != "NO": print("\n".join(battles[simulated_battle_index - 1])) else: - print(cs + " INSTANT REPLAY") + print(f"{battle_name} INSTANT REPLAY") print() - print(" \tCONFEDERACY\t UNION") - print(f"MEN\t {m5}\t\t {m6}") - print(f"MONEY\t ${dollars_available[1]}\t\t${dollars_available[2]}") - print(f"INFLATION\t {i1 + 15}%\t {i2}%") + print(" CONFEDERACY\t UNION") + print(f"MEN {stats[CONF].available_men}\t\t {stats[UNION].available_men}") + print( + f"MONEY ${stats[CONF].available_money}\t${stats[UNION].available_money}" + ) + print(f"INFLATION {stats[CONF].inflation + 15}%\t\t {stats[UNION].inflation}%") print() # ONLY IN PRINTOUT IS CONFED INFLATION = I1 + 15 % # IF TWO GENERALS, INPUT CONFED, FIRST - for i in range(1, party + 1): - if bs == "YES" and i == 1: + for player_index in range(1, party + 1): + if two_generals and player_index == 1: print("CONFEDERATE GENERAL---", end="") print("HOW MUCH DO YOU WISH TO SPEND FOR") while True: - food = int(input(" - FOOD...... ? ")) - if food < 0: - if r1 == 0: + food_input = int(input(" - FOOD...... ? ")) + if food_input < 0: + if stats[CONF].r == 0: print("NO PREVIOUS ENTRIES") continue print("ASSUME YOU WANT TO KEEP SAME ALLOCATIONS") print() break - food_array[i] = food + stats[player_index].food = food_input while True: - salaries[i] = int(input(" - SALARIES.. ? ")) - if salaries[i] >= 0: + stats[player_index].salaries = int(input(" - SALARIES.. ? ")) + if stats[player_index].salaries >= 0: break print("NEGATIVE VALUES NOT ALLOWED.") while True: - ammunition[i] = int(input(" - AMMUNITION ? ")) - if ammunition[i] >= 0: + stats[player_index].ammunition = int(input(" - AMMUNITION ? ")) + if stats[player_index].ammunition >= 0: break print("NEGATIVE VALUES NOT ALLOWED.") print() - if food_array[i] + salaries[i] + ammunition[i] > dollars_available[i]: - print("THINK AGAIN! YOU HAVE ONLY $" + dollars_available[i]) + if stats[player_index].get_cost() > stats[player_index].available_money: + print( + f"THINK AGAIN! YOU HAVE ONLY ${stats[player_index].available_money}" + ) else: break - if bs != "YES" or i == 2: + if not two_generals or player_index == 2: break print("UNION GENERAL---", end="") - for z in range(1, party + 1): - if bs == "YES": - if z == 1: + for player_index in range(1, party + 1): + if two_generals: + if player_index == 1: print("CONFEDERATE ", end="") else: print(" UNION ", end="") - # Find morale - o = (2 * math.pow(food_array[z], 2) + math.pow(salaries[z], 2)) / math.pow( - f1, 2 - ) + 1 - if o >= 10: + morale = get_morale(stats[player_index], stats[1 + player_index % 2]) + + if morale >= 10: print("MORALE IS HIGH") - elif o >= 5: + elif morale >= 5: print("MORALE IS FAIR") else: print("MORALE IS POOR") - if bs != "YES": + if not two_generals: break - oa[z] = o + stats[player_index].morale = morale # type: ignore - o2 = oa[2] - o = oa[1] + stats[UNION].morale = get_morale(stats[UNION], stats[CONF]) + stats[CONF].morale = get_morale(stats[CONF], stats[UNION]) print("CONFEDERATE GENERAL---") # Actual off/def battle situation - if m == 3: + if loaded_battle[5] == AttackState.OFFENSIVE: print("YOU ARE ON THE OFFENSIVE") - elif m == 1: + elif loaded_battle[5] == AttackState.DEFENSIVE: print("YOU ARE ON THE DEFENSIVE") else: print("BOTH SIDES ARE ON THE OFFENSIVE") print() # Choose strategies - if bs != "YES": + if not two_generals: while True: - strategy_index = int(input("YOUR STRATEGY ")) - if abs(strategy_index - 3) < 3: + stats[CONF].strategy = int(input("YOUR STRATEGY ")) + if abs(stats[CONF].strategy - 3) < 3: break - print(f"STRATEGY {strategy_index} NOT ALLOWED.") - if strategy_index == 5: + print(f"STRATEGY {stats[CONF].strategy} NOT ALLOWED.") + if stats[CONF].strategy == 5: print("THE CONFEDERACY HAS SURRENDERED.") break # Union strategy is computer chosen if simulated_battle_index == 0: while True: - union_strategy_index = int(input("UNION STRATEGY IS ")) - if union_strategy_index > 0 and union_strategy_index < 5: + stats[UNION].strategy = int(input("UNION STRATEGY IS ")) + if stats[UNION].strategy > 0 and stats[UNION].strategy < 5: break print("ENTER 1, 2, 3, OR 4 (USUALLY PREVIOUS UNION STRATEGY)") else: s0 = 0 - random_nb = math.random() * 100 - for i in range(1, 5): - s0 += sa[i] + random_nb = random.random() * 100 + for player_index in range(1, 5): + s0 += confederate_strategy_prob_distribution[player_index] # If actual strategy info is in program data statements # then r-100 is extra weight given to that strategy. if random_nb < s0: break - union_strategy_index = i - print(union_strategy_index) + stats[UNION].strategy = player_index + print(stats[UNION].strategy) else: - for i in range(1, 3): - if i == 1: + for player_index in [1, 2]: + if player_index == 1: print("CONFEDERATE STRATEGY ? ", end="") while True: - strategy_index = int(input()) - if abs(strategy_index - 3) < 3: + stats[CONF].strategy = int(input()) + if abs(stats[CONF].strategy - 3) < 3: break - print(f"STRATEGY {strategy_index} NOT ALLOWED.") + print(f"STRATEGY {stats[CONF].strategy} NOT ALLOWED.") print("YOUR STRATEGY ? ", end="") - if i == 2: - union_strategy_index = strategy_index - strategy_index = previous_strategy # noqa: F821 - if union_strategy_index != 5: + if player_index == 2: + stats[UNION].strategy = stats[CONF].strategy + stats[CONF].strategy = previous_strategy # type: ignore # noqa: F821 + if stats[UNION].strategy != 5: break else: - previous_strategy = strategy_index # noqa: F841 + previous_strategy = stats[CONF].strategy # noqa: F841 print("UNION STRATEGY ? ", end="") - # Simulated losses - North - c6 = (2 * c2 / 5) * ( - 1 + 1 / (2 * (abs(union_strategy_index - strategy_index) + 1)) - ) - c6 = c6 * (1.28 + (5 * m2 / 6) / (ammunition[2] + 1)) - c6 = math.floor(c6 * (1 + 1 / o2) + 0.5) - # If loss > men present, rescale losses - e2 = 100 / o2 - if math.floor(c6 + e2) >= m6: - c6 = math.floor(13 * m6 / 20) - e2 = 7 * c6 / 13 - u2 = 1 + + update_army(stats[UNION], stats[CONF], use_factor=False) + # Calculate simulated losses print() print() print() print("\t\tCONFEDERACY\tUNION") - c5 = (2 * c1 / 5) * ( - 1 + 1 / (2 * (abs(union_strategy_index - strategy_index) + 1)) - ) - c5 = math.floor(c5 * (1 + 1 / o) * (1.28 + f1 / (ammunition[1] + 1)) + 0.5) - e = 100 / o - if c5 + 100 / o >= m1 * (1 + (p1 - t1) / (m3 + 1)): - c5 = math.floor(13 * m1 / 20 * (1 + (p1 - t1) / (m3 + 1))) - e = 7 * c5 / 13 - u = 1 + update_army(stats[CONF], stats[UNION], use_factor=True) if party == 1: - c6 = math.floor(17 * c2 * c1 / (c5 * 20)) - e2 = 5 * o + stats[UNION].casualties = math.floor( + 17 + * stats[UNION].army_c + * stats[CONF].army_c + / (stats[CONF].casualties * 20) + ) + stats[CONF].desertions = 5 * morale - print("CASUALTIES\t" + str(c5) + "\t\t" + str(c6)) - print("DESERTIONS\t" + str(math.floor(e)) + "\t\t" + str(math.floor(e2))) + print( + "CASUALTIES\t" + + str(stats[CONF].casualties) + + "\t\t" + + str(stats[UNION].casualties) + ) + print( + "DESERTIONS\t" + + str(math.floor(stats[CONF].desertions)) + + "\t\t" + + str(math.floor(stats[UNION].desertions)) + ) print() - if bs == "YES": - print("COMPARED TO THE ACTUAL CASUALTIES AT " + str(cs)) + if two_generals: + print("COMPARED TO THE ACTUAL CASUALTIES AT " + str(battle_name)) print( "CONFEDERATE: " - + str(math.floor(100 * (c5 / c1) + 0.5)) + + str( + math.floor( + 100 * (stats[CONF].casualties / stats[CONF].army_c) + 0.5 + ) + ) + "% OF THE ORIGINAL" ) print( "UNION: " - + str(math.floor(100 * (c6 / c2) + 0.5)) + + str( + math.floor( + 100 * (stats[UNION].casualties / stats[UNION].army_c) + 0.5 + ) + ) + "% OF THE ORIGINAL" ) print() # Find who won - if u == 1 and u2 == 1 or (u != 1 and u2 != 1 and c5 + e == c6 + e2): + if ( + stats[CONF].excessive_losses + and stats[UNION].excessive_losses + or ( + not stats[CONF].excessive_losses + and not stats[UNION].excessive_losses + and stats[CONF].casualties + stats[CONF].desertions + == stats[UNION].casualties + stats[CONF].desertions + ) + ): print("BATTLE OUTCOME UNRESOLVED") - w0 += 1 - elif u == 1 or (u != 1 and u2 != 1 and c5 + e > c6 + e2): - print("THE UNION WINS " + str(cs)) + confederacy_unresolved += 1 + elif stats[CONF].excessive_losses or ( + not stats[CONF].excessive_losses + and not stats[UNION].excessive_losses + and stats[CONF].casualties + stats[CONF].desertions + > stats[UNION].casualties + stats[CONF].desertions + ): + print(f"THE UNION WINS {battle_name}") if simulated_battle_index != 0: - line += 1 + confederacy_lost += 1 else: - print("THE CONFEDERACY WINS " + str(cs)) + print(f"THE CONFEDERACY WINS {battle_name}") if simulated_battle_index != 0: - w += 1 + confederacy_win += 1 # Lines 2530 to 2590 from original are unreachable. if simulated_battle_index != 0: - t1 += c5 + e - t2 += c6 + e2 - p1 += c1 - p2 += c2 - q1 += food_array[1] + salaries[1] + ammunition[1] - q2 += food_array[2] + salaries[2] + ammunition[2] - r1 += m1 * (100 - i1) / 20 - r2 += m2 * (100 - i2) / 20 - m3 += m1 - m4 += m2 + for i in [CONF, UNION]: + stats[i].t += stats[i].casualties + stats[i].desertions + stats[i].p += stats[i].army_c + stats[i].q += stats[i].get_cost() + stats[i].r += stats[i].army_m * (100 - stats[i].inflation) / 20 + stats[i].m += stats[i].army_m # Learn present strategy, start forgetting old ones - # present startegy of south gains 3*s, others lose s + # 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(1, 5): - if sa[i] <= 5: + for player_index in range(1, 5): + if confederate_strategy_prob_distribution[player_index] <= 5: continue - sa[i] -= 5 + confederate_strategy_prob_distribution[player_index] -= 5 s0 += s - sa[strategy_index] += s0 + confederate_strategy_prob_distribution[stats[CONF].strategy] += s0 - u = 0 - u2 = 0 + stats[CONF].excessive_losses = False + stats[UNION].excessive_losses = False print("---------------") continue @@ -450,27 +547,39 @@ def main(): print() print() print() - print(f"THE CONFEDERACY HAS WON {w} BATTLES AND LOST {line}") - if strategy_index == 5 or (union_strategy_index != 5 and w <= line): + print( + f"THE CONFEDERACY HAS WON {confederacy_win} BATTLES AND LOST {confederacy_lost}" + ) + if stats[CONF].strategy == 5 or ( + stats[UNION].strategy != 5 and confederacy_win <= confederacy_lost + ): print("THE UNION HAS WON THE WAR") else: print("THE CONFEDERACY HAS WON THE WAR") print() - if r1 > 0: - print(f"FOR THE {w + line + w0} BATTLES FOUGHT (EXCLUDING RERUNS)") + if stats[CONF].r > 0: + print( + f"FOR THE {confederacy_win + confederacy_lost + confederacy_unresolved} BATTLES FOUGHT (EXCLUDING RERUNS)" + ) print(" \t \t ") print("CONFEDERACY\t UNION") - print(f"HISTORICAL LOSSES\t{math.floor(p1 + 0.5)}\t{math.floor(p2 + 0.5)}") - print(f"SIMULATED LOSSES\t{math.floor(t1 + 0.5)}\t{math.floor(t2 + 0.5)}") + print( + f"HISTORICAL LOSSES\t{math.floor(stats[CONF].p + 0.5)}\t{math.floor(stats[UNION].p + 0.5)}" + ) + print( + f"SIMULATED LOSSES\t{math.floor(stats[CONF].t + 0.5)}\t{math.floor(stats[UNION].t + 0.5)}" + ) print() print( - f" % OF ORIGINAL\t{math.floor(100 * (t1 / p1) + 0.5)}\t{math.floor(100 * (t2 / p2) + 0.5)}" + f" % OF ORIGINAL\t{math.floor(100 * (stats[CONF].t / stats[CONF].p) + 0.5)}\t{math.floor(100 * (stats[UNION].t / stats[UNION].p) + 0.5)}" ) - if bs != "YES": + if not two_generals: print() print("UNION INTELLIGENCE SUGGEST THAT THE SOUTH USED") print("STRATEGIES 1, 2, 3, 4 IN THE FOLLOWING PERCENTAGES") - print(f"{sa[1]} {sa[2]} {sa[3]} {sa[4]}") + print( + f"{confederate_strategy_prob_distribution[CONF]} {confederate_strategy_prob_distribution[UNION]} {confederate_strategy_prob_distribution[3]} {confederate_strategy_prob_distribution[4]}" + ) if __name__ == "__main__": diff --git a/28_Combat/python/combat.py b/28_Combat/python/combat.py index d6eed5eb..f8a7a5de 100644 --- a/28_Combat/python/combat.py +++ b/28_Combat/python/combat.py @@ -116,7 +116,7 @@ def attack_second() -> None: num_units = 0 unit_type = 0 - print("") + print() print(" YOU ME") print("ARMY ", end="") print("%-14s%s\n" % (usr_army, cpu_army), end="") @@ -176,7 +176,7 @@ def attack_second() -> None: plane_crash_win = True if not plane_crash_win: - print("") + print() print("FROM THE RESULTS OF BOTH OF YOUR ATTACKS,") if plane_crash_win or ( diff --git a/29_Craps/python/craps.py b/29_Craps/python/craps.py index 9d265e4e..dd01fa5e 100644 --- a/29_Craps/python/craps.py +++ b/29_Craps/python/craps.py @@ -20,10 +20,7 @@ def throw_dice() -> int: def main() -> None: print(" " * 33 + "Craps") - print(" " * 15 + "Creative Computing Morristown, New Jersey") - print() - print() - print() + print(" " * 15 + "Creative Computing Morristown, New Jersey\n\n\n") winnings = 0 print("2,3,12 are losers; 4,5,6,8,9,10 are points; 7,11 are natural winners.") diff --git a/30_Cube/python/cube.py b/30_Cube/python/cube.py index 393a494e..4928b08e 100755 --- a/30_Cube/python/cube.py +++ b/30_Cube/python/cube.py @@ -1,7 +1,10 @@ #!/usr/bin/env python3 -# CUBE -# -# Converted from BASIC to Python by Trevor Hobson + +""" +CUBE + +Converted from BASIC to Python by Trevor Hobson +""" import random from typing import Tuple diff --git a/31_Depth_Charge/python/depth_charge.py b/31_Depth_Charge/python/depth_charge.py index cce2984f..a177af9a 100644 --- a/31_Depth_Charge/python/depth_charge.py +++ b/31_Depth_Charge/python/depth_charge.py @@ -1,7 +1,9 @@ -# Original BASIC version as published in Basic Computer Games (1978) -# https://www.atariarchives.org/basicgames/showpage.php?page=55 -# -# Converted to Python by Anson VanDoren in 2021 +""" +Original BASIC version as published in Basic Computer Games (1978) +https://www.atariarchives.org/basicgames/showpage.php?page=55 + +Converted to Python by Anson VanDoren in 2021 +""" import math import random @@ -38,7 +40,7 @@ def get_num_charges() -> Tuple[int, int]: def ask_for_new_game() -> None: answer = input("Another game (Y or N): ") if answer.lower().strip()[0] == "y": - start_new_game() + main() else: print("OK. Hope you enjoyed yourself") exit() @@ -83,7 +85,7 @@ def get_shot_input() -> Tuple[int, int, int]: print("Please enter whole numbers only") -def play_game(search_area, num_charges): +def play_game(search_area, num_charges) -> None: print("\nYou are the captain of the destroyer USS Computer.") print("An enemy sub has been causing you trouble. Your") print(f"mission is to destroy it. You have {num_charges} shots.") @@ -112,10 +114,10 @@ def play_game(search_area, num_charges): ask_for_new_game() -def start_new_game() -> None: +def main() -> None: search_area, num_charges = get_num_charges() play_game(search_area, num_charges) if __name__ == "__main__": - start_new_game() + main() diff --git a/32_Diamond/python/diamond.py b/32_Diamond/python/diamond.py index 88713a88..5ebcd2aa 100644 --- a/32_Diamond/python/diamond.py +++ b/32_Diamond/python/diamond.py @@ -7,16 +7,8 @@ Ported by Dave LeCompte """ -def print_with_tab(space_count: int, msg: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - print(spaces + msg) - - def print_diamond(begin_width, end_width, step, width, count) -> None: - edgeString = "CC" + edge_string = "CC" fill = "!" n = begin_width @@ -24,10 +16,10 @@ def print_diamond(begin_width, end_width, step, width, count) -> None: line_buffer = " " * ((width - n) // 2) for across in range(count): for a in range(n): - if a >= len(edgeString): + if a >= len(edge_string): line_buffer += fill else: - line_buffer += edgeString[a] + line_buffer += edge_string[a] line_buffer += " " * ( (width * (across + 1) + (width - n) // 2) - len(line_buffer) ) @@ -38,11 +30,8 @@ def print_diamond(begin_width, end_width, step, width, count) -> None: def main() -> None: - print_with_tab(33, "DIAMOND") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 33, "DIAMOND") + print(" " * 15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print("FOR A PRETTY DIAMOND PATTERN,") print("TYPE IN AN ODD NUMBER BETWEEN 5 AND 21") width = int(input()) diff --git a/33_Dice/python/dice.py b/33_Dice/python/dice.py index 1529a739..5c47f2b6 100644 --- a/33_Dice/python/dice.py +++ b/33_Dice/python/dice.py @@ -1,30 +1,27 @@ -######################################################## -# -# Dice -# -# From: BASIC Computer Games (1978) -# Edited by David H. Ahl -# -# "Not exactly a game, this program simulates rolling -# a pair of dice a large number of times and prints out -# the frequency distribution. You simply input the -# number of rolls. It is interesting to see how many -# rolls are necessary to approach the theoretical -# distribution: -# -# 2 1/36 2.7777...% -# 3 2/36 5.5555...% -# 4 3/36 8.3333...% -# etc. -# -# "Daniel Freidus wrote this program while in the -# seventh grade at Harrison Jr-Sr High School, -# Harrison, New York." -# -# Python port by Jeff Jetton, 2019 -# -######################################################## +""" +Dice +From: BASIC Computer Games (1978) + Edited by David H. Ahl + +"Not exactly a game, this program simulates rolling + a pair of dice a large number of times and prints out + the frequency distribution. You simply input the + number of rolls. It is interesting to see how many + rolls are necessary to approach the theoretical + distribution: + + 2 1/36 2.7777...% + 3 2/36 5.5555...% + 4 3/36 8.3333...% + etc. + +"Daniel Freidus wrote this program while in the + seventh grade at Harrison Jr-Sr High School, + Harrison, New York." + +Python port by Jeff Jetton, 2019 +""" import random @@ -48,7 +45,7 @@ def main() -> None: still_playing = True while still_playing: - print("") + print() n = int(input("How many rolls? ")) # Roll the dice n times @@ -64,7 +61,7 @@ def main() -> None: print(" %-14d%d" % (i, freq[i])) # Keep playing? - print("") + print() response = input("Try again? ") if len(response) > 0 and response.upper()[0] == "Y": # Clear out the frequency list diff --git a/35_Even_Wins/python/evenwins.py b/35_Even_Wins/python/evenwins.py index b18806c7..066c7d57 100644 --- a/35_Even_Wins/python/evenwins.py +++ b/35_Even_Wins/python/evenwins.py @@ -1,41 +1,36 @@ -# evenwins.py +""" +This version of evenwins.bas based on game decscription and does *not* +follow the source. The computer chooses marbles at random. -# -# This version of evenwins.bas based on game decscription and does *not* -# follow the source. The computer chooses marbles at random. -# -# For simplicity, global variables are used to store the game state. -# A good exercise would be to replace this with a class. -# -# The code is not short, but hopefully it is easy for beginners to understand -# and modify. -# -# Infinite loops of the style "while True:" are used to simplify some of the -# code. The "continue" keyword is used in a few places to jump back to the top -# of the loop. The "return" keyword is also used to break out of functions. -# This is generally considered poor style, but in this case it simplifies the -# code and makes it easier to read (at least in my opinion). A good exercise -# would be to remove these infinite loops, and uses of continue, to follow a -# more structured style. -# +For simplicity, global variables are used to store the game state. +A good exercise would be to replace this with a class. +The code is not short, but hopefully it is easy for beginners to understand +and modify. -# global variables -marbles_in_middle = -1 -human_marbles = -1 -computer_marbles = -1 -whose_turn = "" +Infinite loops of the style "while True:" are used to simplify some of the +code. The "continue" keyword is used in a few places to jump back to the top +of the loop. The "return" keyword is also used to break out of functions. +This is generally considered poor style, but in this case it simplifies the +code and makes it easier to read (at least in my opinion). A good exercise +would be to remove these infinite loops, and uses of continue, to follow a +more structured style. +""" -def serious_error(msg): - """ - Only call this function during development for serious errors that are due - to mistakes in the program. Should never be called during a regular game. - """ - print("serious_error: " + msg) - exit(1) +from dataclasses import dataclass +from typing import Literal, Tuple + +PlayerType = Literal["human", "computer"] -def welcome_screen(): +@dataclass +class MarbleCounts: + middle: int + human: int + computer: int + + +def print_intro() -> None: print("Welcome to Even Wins!") print("Based on evenwins.bas from Creative Computing") print() @@ -50,22 +45,19 @@ def welcome_screen(): print() -def marbles_str(n): +def marbles_str(n: int) -> str: if n == 1: return "1 marble" return f"{n} marbles" -def choose_first_player(): - global whose_turn +def choose_first_player() -> PlayerType: while True: ans = input("Do you want to play first? (y/n) --> ") if ans == "y": - whose_turn = "human" - return + return "human" elif ans == "n": - whose_turn = "computer" - return + return "computer" else: print() print('Please enter "y" if you want to play first,') @@ -73,18 +65,15 @@ def choose_first_player(): print() -def next_player(): - global whose_turn +def toggle_player(whose_turn: PlayerType) -> PlayerType: if whose_turn == "human": - whose_turn = "computer" - elif whose_turn == "computer": - whose_turn = "human" + return "computer" else: - serious_error(f"play_game: unknown player {whose_turn}") + return "human" -# Converts a string s to an int, if possible. -def to_int(s): +def to_int(s: str) -> Tuple[bool, int]: + """Convert a string s to an int, if possible.""" try: n = int(s) return True, n @@ -92,142 +81,108 @@ def to_int(s): return False, 0 -def print_board() -> None: - global marbles_in_middle - global human_marbles - global computer_marbles +def print_board(marbles: MarbleCounts) -> None: print() - print(f" marbles in the middle: {marbles_in_middle} " + marbles_in_middle * "*") - print(f" # marbles you have: {human_marbles}") - print(f"# marbles computer has: {computer_marbles}") + print(f" marbles in the middle: {marbles.middle} " + marbles.middle * "*") + print(f" # marbles you have: {marbles.human}") + print(f"# marbles computer has: {marbles.computer}") print() -def human_turn(): - global marbles_in_middle - global human_marbles - - # get number in range 1 to min(4, marbles_in_middle) - max_choice = min(4, marbles_in_middle) +def human_turn(marbles: MarbleCounts) -> None: + """get number in range 1 to min(4, marbles.middle)""" + max_choice = min(4, marbles.middle) print("It's your turn!") while True: s = input(f"Marbles to take? (1 - {max_choice}) --> ") ok, n = to_int(s) if not ok: - print() - print(f" Please enter a whole number from 1 to {max_choice}") - print() + print(f"\n Please enter a whole number from 1 to {max_choice}\n") continue if n < 1: - print() - print(" You must take at least 1 marble!") - print() + print("\n You must take at least 1 marble!\n") continue if n > max_choice: - print() - print(f" You can take at most {marbles_str(max_choice)}") - print() + print(f"\n You can take at most {marbles_str(max_choice)}\n") continue - print() - print(f"Okay, taking {marbles_str(n)} ...") - marbles_in_middle -= n - human_marbles += n + print(f"\nOkay, taking {marbles_str(n)} ...") + marbles.middle -= n + marbles.human += n return -def game_over(): - global marbles_in_middle - global human_marbles - global computer_marbles +def game_over(marbles: MarbleCounts) -> None: print() print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print("!! All the marbles are taken: Game Over!") print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print() - print_board() - if human_marbles % 2 == 0: + print_board(marbles) + if marbles.human % 2 == 0: print("You are the winner! Congratulations!") else: print("The computer wins: all hail mighty silicon!") - print("") + print() -def computer_turn(): - global marbles_in_middle - global computer_marbles - global human_marbles - +def computer_turn(marbles: MarbleCounts) -> None: marbles_to_take = 0 print("It's the computer's turn ...") - r = marbles_in_middle - 6 * int(marbles_in_middle / 6) # line 500 + r = marbles.middle - 6 * int(marbles.middle / 6) - if int(human_marbles / 2) == human_marbles / 2: # line 510 - if r < 1.5 or r > 5.3: # lines 710 and 720 + if int(marbles.human / 2) == marbles.human / 2: + if r < 1.5 or r > 5.3: marbles_to_take = 1 else: marbles_to_take = r - 1 - elif marbles_in_middle < 4.2: # line 580 - marbles_to_take = marbles_in_middle - elif r > 3.4: # line 530 + elif marbles.middle < 4.2: + marbles_to_take = marbles.middle + elif r > 3.4: if r < 4.7 or r > 3.5: marbles_to_take = 4 else: marbles_to_take = r + 1 print(f"Computer takes {marbles_str(marbles_to_take)} ...") - marbles_in_middle -= marbles_to_take - computer_marbles += marbles_to_take + marbles.middle -= marbles_to_take + marbles.computer += marbles_to_take -def play_game(): - global marbles_in_middle - global human_marbles - global computer_marbles - - # initialize the game state - marbles_in_middle = 27 - human_marbles = 0 - computer_marbles = 0 - print_board() +def play_game(whose_turn: PlayerType) -> None: + marbles = MarbleCounts(middle=27, human=0, computer=0) + print_board(marbles) while True: - if marbles_in_middle == 0: - game_over() + if marbles.middle == 0: + game_over(marbles) return elif whose_turn == "human": - human_turn() - print_board() - next_player() + human_turn(marbles) + print_board(marbles) + whose_turn = toggle_player(whose_turn) elif whose_turn == "computer": - computer_turn() - print_board() - next_player() + computer_turn(marbles) + print_board(marbles) + whose_turn = toggle_player(whose_turn) else: - serious_error(f"play_game: unknown player {whose_turn}") + raise Exception(f"whose_turn={whose_turn} is not 'human' or 'computer'") def main() -> None: - global whose_turn - - welcome_screen() + print_intro() while True: - choose_first_player() - play_game() + whose_turn = choose_first_player() + play_game(whose_turn) - # ask if the user if they want to play again print() - again = input("Would you like to play again? (y/n) --> ") + again = input("Would you like to play again? (y/n) --> ").lower() if again == "y": - print() - print("Ok, let's play again ...") - print() + print("\nOk, let's play again ...\n") else: - print() - print("Ok, thanks for playing ... goodbye!") - print() + print("\nOk, thanks for playing ... goodbye!\n") return diff --git a/36_Flip_Flop/python/flipflop.py b/36_Flip_Flop/python/flipflop.py index 6472a58f..8ea7e5b1 100644 --- a/36_Flip_Flop/python/flipflop.py +++ b/36_Flip_Flop/python/flipflop.py @@ -61,7 +61,7 @@ def print_instructions() -> None: print("11 (ELEVEN).\n") -def main(): +def main() -> None: q = random.random() print("HERE IS THE STARTING LINE OF X'S.\n") @@ -75,9 +75,9 @@ def main(): if legal_move: print(" ".join([str(i) for i in range(1, 11)])) print(" ".join(row[1:]) + "\n") - m = input("INPUT THE NUMBER\n") + m_str = input("INPUT THE NUMBER\n") try: - m = int(m) + m = int(m_str) if m > 11 or m < 0: raise ValueError() except ValueError: diff --git a/38_Fur_Trader/python/furtrader.py b/38_Fur_Trader/python/furtrader.py index 069b2a9b..190b7c3f 100755 --- a/38_Fur_Trader/python/furtrader.py +++ b/38_Fur_Trader/python/furtrader.py @@ -1,7 +1,8 @@ -#! /usr/bin/env python3 +#!/usr/bin/env python3 import random # for generating random numbers import sys # for system function, like exit() +from typing import List # global variables for storing player's status player_funds: float = 0 # no money @@ -22,12 +23,6 @@ FORT_NEWYORK = 3 FORT_NAMES = ["HOCHELAGA (MONTREAL)", "STADACONA (QUEBEC)", "NEW YORK"] -def print_at_column(column: int, words: str) -> None: - """Print the words at the specified column""" - spaces = " " * column # make a fat string of spaces - print(spaces + words) - - def show_introduction() -> None: """Show the player the introductory message""" print("YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN ") @@ -36,7 +31,7 @@ def show_introduction() -> None: 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("") + print() def get_fort_choice() -> int: @@ -45,7 +40,7 @@ def get_fort_choice() -> int: prompting the user.""" result = 0 while result == 0: - print("") + 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.") @@ -68,9 +63,9 @@ def get_fort_choice() -> int: return result -def show_fort_comment(which_fort): +def show_fort_comment(which_fort) -> None: """Print the description for the fort""" - print("") + print() if which_fort == FORT_MONTREAL: print("YOU HAVE CHOSEN THE EASIEST ROUTE. HOWEVER, THE FORT") print("IS FAR FROM ANY SEAPORT. THE VALUE") @@ -89,15 +84,15 @@ def show_fort_comment(which_fort): else: print("Internal error #1, fort " + str(which_fort) + " does not exist") sys.exit(1) # you have a bug - print("") + print() -def get_yes_or_no(): +def get_yes_or_no() -> str: """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 + result = "" while result not in ("Y", "N"): print("ANSWER YES OR NO") player_choice = input(">> ") @@ -109,32 +104,30 @@ def get_yes_or_no(): return result -def get_furs_purchase(): +def get_furs_purchase() -> List[int]: """Prompt the player for how many of each fur type they want. Accept numeric inputs, re-prompting on incorrect input values""" - results = [] + results: List[int] = [] print("YOUR " + str(MAX_FURS) + " FURS ARE DISTRIBUTED AMONG THE FOLLOWING") print("KINDS OF PELTS: MINK, BEAVER, ERMINE AND FOX.") - print("") + print() - for i in range(len(FUR_NAMES)): - print("HOW MANY " + FUR_NAMES[i] + " DO YOU HAVE") + while len(results) < len(FUR_NAMES): + print(f"HOW MANY {FUR_NAMES[len(results)]} 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 + except Exception: # invalid input, prompt again by re-looping + pass return results -if __name__ == "__main__": - - print_at_column(31, "FUR TRADER") - print_at_column(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print_at_column(15, "(Ported to Python Oct 2012 krt@krt.com.au)") +def main() -> None: + 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" @@ -145,7 +138,7 @@ if __name__ == "__main__": if game_state == "starting": show_introduction() - player_funds = 600 # Initial player start money + player_funds: float = 600 # Initial player start money player_furs = [0, 0, 0, 0] # Player fur inventory print("DO YOU WISH TO TRADE FURS?") @@ -155,13 +148,13 @@ if __name__ == "__main__": game_state = "trading" elif game_state == "trading": - print("") + 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() print("YOU MAY NOT HAVE THAT MANY FURS.") print("DO NOT TRY TO CHEAT. I CAN ADD.") print("YOU MUST START AGAIN.") @@ -178,7 +171,7 @@ if __name__ == "__main__": game_state = "travelling" elif game_state == "travelling": - print("") + print() if which_fort == FORT_MONTREAL: mink_price = ( int((0.2 * random.random() + 0.70) * 100 + 0.5) / 100 @@ -234,7 +227,7 @@ if __name__ == "__main__": ) sys.exit(1) # you have a bug - print("") + print() print("SUPPLIES AT FORT STADACONA COST $125.00.") print("YOUR TRAVEL EXPENSES TO STADACONA WERE $15.00.") player_funds -= 140 @@ -281,7 +274,7 @@ if __name__ == "__main__": ) sys.exit(1) # you have a bug - print("") + print() print("SUPPLIES AT NEW YORK COST $85.00.") print("YOUR TRAVEL EXPENSES TO NEW YORK WERE $25.00.") player_funds -= 105 @@ -296,7 +289,7 @@ if __name__ == "__main__": ermine_value = ermine_price * player_furs[FUR_ERMINE] mink_value = mink_price * player_furs[FUR_MINK] - print("") + 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)) @@ -304,15 +297,19 @@ if __name__ == "__main__": player_funds += beaver_value + fox_value + ermine_value + mink_value - print("") + print() print( "YOU NOW HAVE $ %1.2f INCLUDING YOUR PREVIOUS SAVINGS" % (player_funds) ) - print("") + 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() diff --git a/39_Golf/python/golf.py b/39_Golf/python/golf.py index 9339c236..9132da2e 100644 --- a/39_Golf/python/golf.py +++ b/39_Golf/python/golf.py @@ -129,8 +129,8 @@ def clear_console() -> None: class Point(NamedTuple): - X: int - Y: int + x: int + y: int class GameObjType(enum.Enum): @@ -183,14 +183,14 @@ class HoleGeometry(NamedTuple): @dataclass class Plot: - X: int - Y: int - Offline: int + x: int + y: int + offline: int def get_distance(pt1: Point, pt2: Point) -> float: """distance between 2 points""" - return math.sqrt(math.pow((pt2.X - pt1.X), 2) + math.pow((pt2.Y - pt1.Y), 2)) + return math.sqrt(math.pow((pt2.x - pt1.x), 2) + math.pow((pt2.y - pt1.y), 2)) def is_in_rectangle(pt: CircleGameObj, rect: RectGameObj) -> bool: @@ -392,9 +392,9 @@ ace = 0b10000000000000 class Golf: - BALL: Ball - HOLE_NUM: int = 0 - STROKE_NUM: int = 0 + ball: Ball + hole_num: int = 0 + stroke_num: int = 0 handicap: int = 0 player_difficulty: int = 0 hole_geometry: HoleGeometry @@ -491,10 +491,10 @@ class Golf: self.new_hole() def new_hole(self) -> None: - self.HOLE_NUM += 1 - self.STROKE_NUM = 0 + self.hole_num += 1 + self.stroke_num = 0 - info: HoleInfo = CourseInfo[self.HOLE_NUM] + info: HoleInfo = CourseInfo[self.hole_num] yards: int = info.yards # from tee to cup @@ -517,19 +517,19 @@ class Golf: GameObjType.ROUGH, ) - self.BALL = Ball(0, yards, 0, GameObjType.BALL) + self.ball = Ball(0, yards, 0, GameObjType.BALL) self.score_card_start_new_hole() self.hole_geometry = HoleGeometry(cup, green, fairway, rough, info.hazards) - print(f" |> {self.HOLE_NUM}") + print(f" |> {self.hole_num}") print(" | ") print(" | ") print(" ^^^^^^^^^^^^^^^") print( - f"Hole #{self.HOLE_NUM}. You are at the tee. Distance {info.yards} yards, par {info.par}." + f"Hole #{self.hole_num}. You are at the tee. Distance {info.yards} yards, par {info.par}." ) print(info.description) @@ -537,7 +537,7 @@ class Golf: def set_putter_and_stroke(self, strength: float) -> None: putter = self.clubs[self.putt] - self.Stroke((putter[1] * (strength / 10.0)), self.putt) + self.stroke((putter[1] * (strength / 10.0)), self.putt) def ask_gauge(self, c: int) -> None: self.club = self.clubs[c] @@ -555,13 +555,13 @@ class Golf: ) def make_stroke(self, strength: float, c: int) -> None: - self.Stroke((self.club[1] * (strength / 10.0)), c) + self.stroke((self.club[1] * (strength / 10.0)), c) def tee_up(self) -> None: # on the green? automatically select putter # otherwise Ask club and swing strength - if self.is_on_green(self.BALL) and not self.is_in_hazard( - self.BALL, GameObjType.SAND + if self.is_on_green(self.ball) and not self.is_in_hazard( + self.ball, GameObjType.SAND ): self.putt = 10 print("[PUTTER: average 10 yards]") @@ -579,13 +579,13 @@ class Golf: else: self.ask("What club do you choose? (1-10)", 1, 10, self.ask_gauge) - def Stroke(self, clubAmt: float, clubIndex: int) -> None: - self.STROKE_NUM += 1 + def stroke(self, club_amt: float, club_index: int) -> None: + self.stroke_num += 1 flags = 0b000000000000 # fore! only when driving - if (self.STROKE_NUM == 1) and (clubAmt > 210) and odds(30): + if (self.stroke_num == 1) and (club_amt > 210) and odds(30): print('"...Fore !"') # dub @@ -596,37 +596,37 @@ class Golf: # if you're in the rough, or sand, you really should be using a wedge if ( ( - self.is_in_rough(self.BALL) - or self.is_in_hazard(self.BALL, GameObjType.SAND) + self.is_in_rough(self.ball) + or self.is_in_hazard(self.ball, GameObjType.SAND) ) - and not (clubIndex == 8 or clubIndex == 9) + and not (club_index == 8 or club_index == 9) and odds(40) ): flags |= dub # trap difficulty if ( - self.is_in_hazard(self.BALL, GameObjType.SAND) + self.is_in_hazard(self.ball, GameObjType.SAND) and self.player_difficulty == 4 ) and odds(20): flags |= dub # hook/slice # There's 10% chance of a hook or slice - # if it's a known playerDifficulty then increase chance to 30% - # if it's a putt & putting is a playerDifficulty increase to 30% + # if it's a known player_difficulty then increase chance to 30% + # if it's a putt & putting is a player_difficulty increase to 30% - randHookSlice: bool + rand_hook_slice: bool if ( self.player_difficulty == 1 or self.player_difficulty == 2 - or (self.player_difficulty == 5 and self.is_on_green(self.BALL)) + or (self.player_difficulty == 5 and self.is_on_green(self.ball)) ): - randHookSlice = odds(30) + rand_hook_slice = odds(30) else: - randHookSlice = odds(10) + rand_hook_slice = odds(10) - if randHookSlice: + if rand_hook_slice: if self.player_difficulty == 1: if odds(80): flags |= hook @@ -650,7 +650,7 @@ class Golf: # ace # there's a 10% chance of an Ace on a par 3 - if CourseInfo[self.HOLE_NUM].par == 3 and odds(10) and self.STROKE_NUM == 1: + if CourseInfo[self.hole_num].par == 3 and odds(10) and self.stroke_num == 1: flags |= ace # distance: @@ -659,29 +659,29 @@ class Golf: # If handicap is > 15, there's a 25% chance of reaching club average, # and 75% chance of falling short # The greater the handicap, the more the ball falls short - # If poor distance is a known playerDifficulty, then reduce distance by 10% + # If poor distance is a known player_difficulty, then reduce distance by 10% distance: float rnd = random.randint(1, 101) if self.handicap < 15: if rnd <= 25: - distance = clubAmt - (clubAmt * (self.handicap / 100.0)) + distance = club_amt - (club_amt * (self.handicap / 100.0)) elif rnd > 25 and rnd <= 75: - distance = clubAmt + distance = club_amt else: - distance = clubAmt + (clubAmt * 0.10) + distance = club_amt + (club_amt * 0.10) else: if rnd <= 75: - distance = clubAmt - (clubAmt * (self.handicap / 100.0)) + distance = club_amt - (club_amt * (self.handicap / 100.0)) else: - distance = clubAmt + distance = club_amt if self.player_difficulty == 3 and odds(80): # poor distance distance = distance * 0.80 if (flags & luck) == luck: - distance = clubAmt + distance = club_amt # angle # For all strokes, there's a possible "drift" of 4 degrees @@ -695,43 +695,45 @@ class Golf: if (flags & luck) == luck: angle = 0 - plot = self.plot_ball(self.BALL, distance, angle) + plot = self.plot_ball(self.ball, distance, angle) # calculate a new location - if (flags & luck) == luck and plot.Y > 0: - plot.Y = 2 + if (flags & luck) == luck and plot.y > 0: + plot.y = 2 flags = self.find_ball( - Ball(plot.X, plot.Y, plot.Offline, GameObjType.BALL), flags + Ball(plot.x, plot.y, plot.offline, GameObjType.BALL), flags ) self.interpret_results(plot, flags) - def plot_ball(self, ball: Ball, strokeDistance: float, degreesOff: float) -> Plot: - cupVector = Point(0, -1) - radFromCup = math.atan2(ball.Y, ball.X) - math.atan2(cupVector.Y, cupVector.X) - radFromBall = radFromCup - math.pi + def plot_ball(self, ball: Ball, stroke_distance: float, degrees_off: float) -> Plot: + cup_vector = Point(0, -1) + rad_from_cup = math.atan2(ball.Y, ball.X) - math.atan2( + cup_vector.y, cup_vector.x + ) + rad_from_ball = rad_from_cup - math.pi - hypotenuse = strokeDistance - adjacent = math.cos(radFromBall + to_radians(degreesOff)) * hypotenuse + hypotenuse = stroke_distance + adjacent = math.cos(rad_from_ball + to_radians(degrees_off)) * hypotenuse opposite = math.sqrt(math.pow(hypotenuse, 2) - math.pow(adjacent, 2)) - newPos: Point - if to_degrees_360(radFromBall + to_radians(degreesOff)) > 180: - newPos = Point(int(ball.X - opposite), int(ball.Y - adjacent)) + new_pos: Point + if to_degrees_360(rad_from_ball + to_radians(degrees_off)) > 180: + new_pos = Point(int(ball.X - opposite), int(ball.Y - adjacent)) else: - newPos = Point(int(ball.X + opposite), int(ball.Y - adjacent)) + new_pos = Point(int(ball.X + opposite), int(ball.Y - adjacent)) - return Plot(newPos.X, newPos.Y, int(opposite)) + return Plot(new_pos.x, new_pos.y, int(opposite)) def interpret_results(self, plot: Plot, flags: int) -> None: - cupDistance: int = int( + cup_distance: int = int( get_distance( - Point(plot.X, plot.Y), + Point(plot.x, plot.y), Point(self.hole_geometry.cup.X, self.hole_geometry.cup.Y), ) ) - travelDistance: int = int( - get_distance(Point(plot.X, plot.Y), Point(self.BALL.X, self.BALL.Y)) + travel_distance: int = int( + get_distance(Point(plot.x, plot.y), Point(self.ball.X, self.ball.Y)) ) print(" ") @@ -739,12 +741,12 @@ class Golf: if (flags & ace) == ace: print("Hole in One! You aced it.") self.score_card_record_stroke(Ball(0, 0, 0, GameObjType.BALL)) - self.ReportCurrentScore() + self.report_current_score() return if (flags & in_trees) == in_trees: print("Your ball is lost in the trees. Take a penalty stroke.") - self.score_card_record_stroke(self.BALL) + self.score_card_record_stroke(self.ball) self.tee_up() return @@ -754,19 +756,19 @@ class Golf: else: msg = "Your ball is lost in the water." print(msg + " Take a penalty stroke.") - self.score_card_record_stroke(self.BALL) + self.score_card_record_stroke(self.ball) self.tee_up() return if (flags & out_of_bounds) == out_of_bounds: print("Out of bounds. Take a penalty stroke.") - self.score_card_record_stroke(self.BALL) + self.score_card_record_stroke(self.ball) self.tee_up() return if (flags & dub) == dub: print("You dubbed it.") - self.score_card_record_stroke(self.BALL) + self.score_card_record_stroke(self.ball) self.tee_up() return @@ -776,8 +778,8 @@ class Golf: else: msg = "It's in!" print(msg) - self.score_card_record_stroke(Ball(plot.X, plot.Y, 0, GameObjType.BALL)) - self.ReportCurrentScore() + self.score_card_record_stroke(Ball(plot.x, plot.y, 0, GameObjType.BALL)) + self.report_current_score() return if ((flags & slice_) == slice_) and not ((flags & on_green) == on_green): @@ -785,22 +787,22 @@ class Golf: bad = "badly" else: bad = "" - print(f"You sliced{bad}: {plot.Offline} yards offline.") + print(f"You sliced{bad}: {plot.offline} yards offline.") if ((flags & hook) == hook) and not ((flags & on_green) == on_green): if (flags & out_of_bounds) == out_of_bounds: bad = "badly" else: bad = "" - print(f"You hooked{bad}: {plot.Offline} yards offline.") + print(f"You hooked{bad}: {plot.offline} yards offline.") - if self.STROKE_NUM > 1: - prevBall = self.score_card_get_previous_stroke() + if self.stroke_num > 1: + prev_ball = self.score_card_get_previous_stroke() d1 = get_distance( - Point(prevBall.X, prevBall.Y), + Point(prev_ball.X, prev_ball.Y), Point(self.hole_geometry.cup.X, self.hole_geometry.cup.Y), ) - d2 = cupDistance + d2 = cup_distance if d2 > d1: print("Too much club.") @@ -811,55 +813,55 @@ class Golf: print("You're in a sand trap.") if (flags & on_green) == on_green: - if cupDistance < 4: - pd = str(cupDistance * 3) + " feet" + if cup_distance < 4: + pd = str(cup_distance * 3) + " feet" else: - pd = f"{cupDistance} yards" + pd = f"{cup_distance} yards" print(f"You're on the green. It's {pd} from the pin.") if ((flags & on_fairway) == on_fairway) or ((flags & in_rough) == in_rough): print( - f"Shot went {travelDistance} yards. " - f"It's {cupDistance} yards from the cup." + f"Shot went {travel_distance} yards. " + f"It's {cup_distance} yards from the cup." ) - self.score_card_record_stroke(Ball(plot.X, plot.Y, 0, GameObjType.BALL)) + self.score_card_record_stroke(Ball(plot.x, plot.y, 0, GameObjType.BALL)) - self.BALL = Ball(plot.X, plot.Y, 0, GameObjType.BALL) + self.ball = Ball(plot.x, plot.y, 0, GameObjType.BALL) self.tee_up() - def ReportCurrentScore(self) -> None: - par = CourseInfo[self.HOLE_NUM].par - if len(self.score_card[self.HOLE_NUM]) == par + 1: + def report_current_score(self) -> None: + par = CourseInfo[self.hole_num].par + if len(self.score_card[self.hole_num]) == par + 1: print("A bogey. One above par.") - if len(self.score_card[self.HOLE_NUM]) == par: + if len(self.score_card[self.hole_num]) == par: print("Par. Nice.") - if len(self.score_card[self.HOLE_NUM]) == (par - 1): + if len(self.score_card[self.hole_num]) == (par - 1): print("A birdie! One below par.") - if len(self.score_card[self.HOLE_NUM]) == (par - 2): + if len(self.score_card[self.hole_num]) == (par - 2): print("An Eagle! Two below par.") - if len(self.score_card[self.HOLE_NUM]) == (par - 3): + if len(self.score_card[self.hole_num]) == (par - 3): print("Double Eagle! Unbelievable.") - totalPar: int = 0 - for i in range(1, self.HOLE_NUM + 1): - totalPar += CourseInfo[i].par + total_par: int = 0 + for i in range(1, self.hole_num + 1): + total_par += CourseInfo[i].par print(" ") print("-----------------------------------------------------") - if self.HOLE_NUM > 1: + if self.hole_num > 1: hole_str = "holes" else: hole_str = "hole" print( - f" Total par for {self.HOLE_NUM} {hole_str} is: {totalPar}. " + f" Total par for {self.hole_num} {hole_str} is: {total_par}. " f"Your total is: {self.score_card_get_total()}." ) print("-----------------------------------------------------") print(" ") - if self.HOLE_NUM == 18: + if self.hole_num == 18: self.game_over() else: time.sleep(2) @@ -930,10 +932,10 @@ class Golf: def score_card_record_stroke(self, ball: Ball) -> None: clone = Ball(ball.X, ball.Y, 0, GameObjType.BALL) - self.score_card[self.HOLE_NUM].append(clone) + self.score_card[self.hole_num].append(clone) def score_card_get_previous_stroke(self) -> Ball: - return self.score_card[self.HOLE_NUM][len(self.score_card[self.HOLE_NUM]) - 1] + return self.score_card[self.hole_num][len(self.score_card[self.hole_num]) - 1] def score_card_get_total(self) -> int: total: int = 0 @@ -986,9 +988,7 @@ class Golf: print(" ") def quit_game(self) -> None: - print("") - print("Looks like rain. Goodbye!") - print("") + print("\nLooks like rain. Goodbye!\n") return def game_over(self) -> None: diff --git a/40_Gomoko/python/Gomoko.py b/40_Gomoko/python/Gomoko.py index db3e02b7..7036d7f2 100644 --- a/40_Gomoko/python/Gomoko.py +++ b/40_Gomoko/python/Gomoko.py @@ -2,10 +2,6 @@ import random from typing import Any, List, Tuple -def print_n_whitespaces(n: int) -> None: - print(" " * n, end="") - - def print_board(A: List[List[Any]], n: int) -> None: """PRINT THE BOARD""" for i in range(n): @@ -23,25 +19,17 @@ def check_move(_I, _J, _N) -> bool: # 910 def print_banner() -> None: - print_n_whitespaces(33) - print("GOMOKU") - print_n_whitespaces(15) - print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() - print("WELCOME TO THE ORIENTAL GAME OF GOMOKO.") - print() + print(" " * 33 + "GOMOKU") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") + print("WELCOME TO THE ORIENTAL GAME OF GOMOKO.\n") print("THE GAME IS PLAYED ON AN N BY N GRID OF A SIZE") print("THAT YOU SPECIFY. DURING YOUR PLAY, YOU MAY COVER ONE GRID") print("INTERSECTION WITH A MARKER. THE OBJECT OF THE GAME IS TO GET") print("5 ADJACENT MARKERS IN A ROW -- HORIZONTALLY, VERTICALLY, OR") print("DIAGONALLY. ON THE BOARD DIAGRAM, YOUR MOVES ARE MARKED") - print("WITH A '1' AND THE COMPUTER MOVES WITH A '2'.") - print() + print("WITH A '1' AND THE COMPUTER MOVES WITH A '2'.\n") print("THE COMPUTER DOES NOT KEEP TRACK OF WHO HAS WON.") - print("TO END THE GAME, TYPE -1,-1 FOR YOUR MOVE.") - print() + print("TO END THE GAME, TYPE -1,-1 FOR YOUR MOVE.\n") def get_board_dimensions() -> int: @@ -74,10 +62,10 @@ def initialize_board(n: int) -> List[List[int]]: # Initialize the board board = [] for _x in range(n): - subA = [] + sub_a = [] for _y in range(n): - subA.append(0) - board.append(subA) + sub_a.append(0) + board.append(sub_a) return board diff --git a/41_Guess/python/guess.py b/41_Guess/python/guess.py index 8786119b..8c1775f4 100644 --- a/41_Guess/python/guess.py +++ b/41_Guess/python/guess.py @@ -1,24 +1,22 @@ -######################################################## -# -# Guess -# -# From: Basic Computer Games (1978) -# -# "In program Guess, the computer chooses a random -# integer between 0 and any limit and any limit you -# set. You must then try to guess the number the -# computer has choosen using the clues provideed by -# the computer. -# You should be able to guess the number in one less -# than the number of digits needed to represent the -# number in binary notation - i.e. in base 2. This ought -# to give you a clue as to the optimum search technique. -# Guess converted from the original program in FOCAL -# which appeared in the book "Computers in the Classroom" -# by Walt Koetke of Lexington High School, Lexington, -# Massaschusetts. -# -######################################################## +""" +Guess + +From: Basic Computer Games (1978) + + "In program Guess, the computer chooses a random + integer between 0 and any limit and any limit you + set. You must then try to guess the number the + computer has choosen using the clues provideed by + the computer. + You should be able to guess the number in one less + than the number of digits needed to represent the + number in binary notation - i.e. in base 2. This ought + to give you a clue as to the optimum search technique. + Guess converted from the original program in FOCAL + which appeared in the book "Computers in the Classroom" + by Walt Koetke of Lexington High School, Lexington, + Massaschusetts. +""" # Altough the introduction says that the computer chooses # a number between 0 and any limit, it actually chooses @@ -28,13 +26,14 @@ from math import log from random import random +from typing import Tuple def insert_whitespaces() -> None: print("\n\n\n\n\n") -def limit_set(): +def limit_set() -> Tuple[int, int]: print(" Guess") print("Creative Computing Morristown, New Jersey") print("\n\n\n") diff --git a/42_Gunner/python/gunner.py b/42_Gunner/python/gunner.py index ad421e7c..06d55d18 100644 --- a/42_Gunner/python/gunner.py +++ b/42_Gunner/python/gunner.py @@ -71,12 +71,10 @@ def gunner() -> None: return -if __name__ == "__main__": +def main() -> None: print(" " * 33 + "GUNNER") print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print("\n\n\n") - print("YOU ARE THE OFFICER-IN-CHARGE, GIVING ORDERS TO A GUN") print("CREW, TELLING THEM THE DEGREES OF ELEVATION YOU ESTIMATE") print("WILL PLACE A PROJECTILE ON TARGET. A HIT WITHIN 100 YARDS") @@ -85,7 +83,11 @@ if __name__ == "__main__": while True: gunner() - Y = input("TRY AGAIN (Y OR N)? ") - if Y != "Y": + not_again = input("TRY AGAIN (Y OR N)? ").upper() != "Y" + if not_again: print("\nOK. RETURN TO BASE CAMP.") break + + +if __name__ == "__main__": + main() diff --git a/45_Hello/python/hello.py b/45_Hello/python/hello.py index 7293ee28..ccf0501c 100644 --- a/45_Hello/python/hello.py +++ b/45_Hello/python/hello.py @@ -12,14 +12,6 @@ import time from typing import Optional, Tuple -def print_with_tab(space_count: int, msg: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - print(spaces + msg) - - def get_yes_or_no() -> Tuple[bool, Optional[bool], str]: msg = input() if msg.upper() == "YES": @@ -30,7 +22,7 @@ def get_yes_or_no() -> Tuple[bool, Optional[bool], str]: return False, None, msg -def ask_enjoy_question(user_name): +def ask_enjoy_question(user_name: str) -> None: print(f"HI THERE, {user_name}, ARE YOU ENJOYING YOURSELF HERE?") while True: @@ -49,7 +41,7 @@ def ask_enjoy_question(user_name): print("PLEASE ANSWER 'YES' OR 'NO'. DO YOU LIKE IT HERE?") -def prompt_for_problems(user_name): +def prompt_for_problems(user_name: str) -> str: print() print(f"SAY, {user_name}, I CAN SOLVE ALL KINDS OF PROBLEMS EXCEPT") print("THOSE DEALING WITH GREECE. WHAT KIND OF PROBLEMS DO") @@ -179,14 +171,9 @@ def happy_goodbye(user_name: str) -> None: def main() -> None: - print_with_tab(33, "HELLO") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() - print("HELLO. MY NAME IS CREATIVE COMPUTER.") - print() - print() + print(" " * 33 + "HELLO") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") + print("HELLO. MY NAME IS CREATIVE COMPUTER.\n\n") print("WHAT'S YOUR NAME?") user_name = input() print() diff --git a/47_Hi-Lo/python/hilo.py b/47_Hi-Lo/python/hilo.py index d0badf73..5850b3f7 100755 --- a/47_Hi-Lo/python/hilo.py +++ b/47_Hi-Lo/python/hilo.py @@ -5,7 +5,7 @@ MAX_ATTEMPTS = 6 QUESTION_PROMPT = "? " -def play(): +def main() -> None: print("HI LO") print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print("THIS IS THE GAME OF HI LO.\n") @@ -50,4 +50,4 @@ def play(): if __name__ == "__main__": - play() + main() diff --git a/48_High_IQ/python/High_IQ.py b/48_High_IQ/python/High_IQ.py index 16843553..6dcceaf5 100644 --- a/48_High_IQ/python/High_IQ.py +++ b/48_High_IQ/python/High_IQ.py @@ -1,43 +1,46 @@ -def new_board(): - # Using a dictionary in python to store the board, since we are not including all numbers within a given range. - board = {} - for i in [ - 13, - 14, - 15, - 22, - 23, - 24, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 38, - 39, - 40, - 42, - 43, - 44, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 58, - 59, - 60, - 67, - 68, - 69, - ]: - board[i] = "!" - board[41] = "O" - return board +from typing import Dict + + +def new_board() -> Dict[int, str]: + """ + Using a dictionary in python to store the board, + since we are not including all numbers within a given range. + """ + return { + 13: "!", + 14: "!", + 15: "!", + 22: "!", + 23: "!", + 24: "!", + 29: "!", + 30: "!", + 31: "!", + 32: "!", + 33: "!", + 34: "!", + 35: "!", + 38: "!", + 39: "!", + 40: "!", + 42: "!", + 43: "!", + 44: "!", + 47: "!", + 48: "!", + 49: "!", + 50: "!", + 51: "!", + 52: "!", + 53: "!", + 58: "!", + 59: "!", + 60: "!", + 67: "!", + 68: "!", + 69: "!", + 41: "O", + } def print_instructions() -> None: @@ -73,7 +76,7 @@ NUMBERS. OK, LET'S BEGIN. ) -def print_board(board) -> None: +def print_board(board: Dict[int, str]) -> None: """Prints the boards using indexes in the passed parameter""" print(" " * 2 + board[13] + board[14] + board[15]) print(" " * 2 + board[22] + board[23] + board[24]) @@ -131,7 +134,7 @@ def play_game() -> None: print("SAVE THIS PAPER AS A RECORD OF YOUR ACCOMPLISHMENT!") -def move(board): +def move(board: Dict[int, str]) -> bool: """Queries the user to move. Returns false if the user puts in an invalid input or move, returns true if the move was successful""" start_input = input("MOVE WHICH PIECE? ") @@ -154,7 +157,7 @@ def move(board): return False difference = abs(start - end) - center = (end + start) / 2 + center = int((end + start) / 2) if ( (difference == 2 or difference == 18) and board[end] == "O" @@ -175,20 +178,20 @@ def main() -> None: play_game() -def is_game_finished(board): - # Checks all locations and whether or not a move is possible at that location. +def is_game_finished(board) -> bool: + """Check all locations and whether or not a move is possible at that location.""" for pos in board.keys(): if board[pos] == "!": for space in [1, 9]: # Checks if the next location has a peg - nextToPeg = ((pos + space) in board) and board[pos + space] == "!" + next_to_peg = ((pos + space) in board) and board[pos + space] == "!" # Checks both going forward (+ location) or backwards (-location) - hasMovableSpace = ( + has_movable_space = ( not ((pos - space) in board and board[pos - space] == "!") ) or ( not ((pos + space * 2) in board and board[pos + space * 2] == "!") ) - if nextToPeg and hasMovableSpace: + if next_to_peg and has_movable_space: return False return True diff --git a/50_Horserace/python/horserace.py b/50_Horserace/python/horserace.py index fad52ec5..b00a6316 100644 --- a/50_Horserace/python/horserace.py +++ b/50_Horserace/python/horserace.py @@ -1,7 +1,7 @@ import math import random import time -from typing import List +from typing import List, Tuple def basic_print(*zones, **kwargs) -> None: @@ -81,7 +81,7 @@ def setup_players() -> List[str]: return player_names -def setup_horses(): +def setup_horses() -> List[float]: """Generates random odds for each horse. Returns a list of odds, indexed by the order of the global HORSE_NAMES.""" @@ -102,14 +102,14 @@ def print_horse_odds(odds) -> None: basic_print("") -def get_bets(player_names): +def get_bets(player_names: List[str]) -> List[Tuple[int, float]]: """For each player, get the number of the horse to bet on, as well as the amount of money to bet""" basic_print("--------------------------------------------------") basic_print("PLACE YOUR BETS...HORSE # THEN AMOUNT") - bets = [] + bets: List[Tuple[int, float]] = [] for name in player_names: horse = basic_input(name, int) amount = None @@ -125,7 +125,7 @@ def get_bets(player_names): return bets -def get_distance(odd): +def get_distance(odd: float) -> int: """Advances a horse during one step of the racing simulation. The amount travelled is random, but scaled by the odds of the horse""" @@ -181,7 +181,7 @@ def print_race_state(total_distance, race_pos) -> None: basic_print("XXXXFINISHXXXX") -def simulate_race(odds): +def simulate_race(odds) -> List[int]: num_horses = len(HORSE_NAMES) # in spirit of the original implementation, using two arrays to diff --git a/51_Hurkle/python/hurkle.py b/51_Hurkle/python/hurkle.py index 62cffecb..c8e2ca9b 100644 --- a/51_Hurkle/python/hurkle.py +++ b/51_Hurkle/python/hurkle.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -# -# Ported to Python by @iamtraction + +"""Ported to Python by @iamtraction""" from random import random -def direction(A, B, X, Y): - """Prints the direction hint for finding the hurkle.""" +def direction(A, B, X, Y) -> None: + """Print the direction hint for finding the hurkle.""" print("GO ", end="") if Y < B: @@ -22,7 +22,7 @@ def direction(A, B, X, Y): print() -if __name__ == "__main__": +def main() -> None: print(" " * 33 + "HURKLE") print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") @@ -63,3 +63,7 @@ if __name__ == "__main__": continue print("\n\nLET'S PLAY AGAIN, HURKLE IS HIDING.\n") + + +if __name__ == "__main__": + main() diff --git a/52_Kinema/python/kinema.py b/52_Kinema/python/kinema.py index 65fbd08f..2a4831a7 100644 --- a/52_Kinema/python/kinema.py +++ b/52_Kinema/python/kinema.py @@ -20,15 +20,7 @@ g = 10 EXPECTED_ACCURACY_PERCENT = 15 -def print_with_tab(spaces_count, msg) -> None: - if spaces_count > 0: - spaces = " " * spaces_count - else: - spaces = "" - print(spaces + msg) - - -def do_quiz(): +def do_quiz() -> None: print() print() num_questions_correct = 0 @@ -58,7 +50,7 @@ def do_quiz(): print(" NOT BAD.") -def ask_player(question, answer): +def ask_player(question: str, answer) -> int: print(question) player_answer = float(input()) @@ -75,11 +67,8 @@ def ask_player(question, answer): def main() -> None: - print_with_tab(33, "KINEMA") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 33 + "KINEMA") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") while True: do_quiz() diff --git a/54_Letter/python/letter.py b/54_Letter/python/letter.py index 77c87c7f..ca4599ee 100644 --- a/54_Letter/python/letter.py +++ b/54_Letter/python/letter.py @@ -15,15 +15,6 @@ import random BELLS_ON_SUCCESS = False -def print_with_tab(space_count: int, msg: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - - print(spaces + msg) - - def print_instructions() -> None: print("LETTER GUESSING GAME") print() @@ -32,7 +23,7 @@ def print_instructions() -> None: print("AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER.") -def play_game(): +def play_game() -> None: target_value = random.randint(ord("A"), ord("Z")) num_guesses = 0 print() @@ -52,8 +43,8 @@ def play_game(): print("GOOD JOB !!!!!") if BELLS_ON_SUCCESS: - bellStr = chr(7) * 15 - print(bellStr) + bell_str = chr(7) * 15 + print(bell_str) print() print("LET'S PLAY AGAIN.....") @@ -67,11 +58,8 @@ def play_game(): def main() -> None: - print_with_tab(33, "LETTER") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 33 + "LETTER") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print_instructions() diff --git a/55_Life/python/life.py b/55_Life/python/life.py index b473632e..5a71dfa8 100644 --- a/55_Life/python/life.py +++ b/55_Life/python/life.py @@ -6,6 +6,7 @@ An implementation of John Conway's popular cellular automaton Ported by Dave LeCompte """ +from typing import Dict PAGE_WIDTH = 64 @@ -26,11 +27,11 @@ def print_header(title) -> None: print() -def get_pattern(): +def get_pattern() -> Dict[int, str]: print("ENTER YOUR PATTERN:") c = 0 - pattern = {} + pattern: Dict[int, str] = {} while True: line = input() if line == "DONE": @@ -98,8 +99,8 @@ def main() -> None: print() for x in range(min_x, max_x + 1): - print - line = [" "] * MAX_WIDTH + print() + line_list = [" "] * MAX_WIDTH for y in range(min_y, max_y + 1): if a[x][y] == 2: a[x][y] = 0 @@ -109,15 +110,14 @@ def main() -> None: elif a[x][y] != 1: continue - # line 261 - line[y] = "*" + line_list[y] = "*" next_min_x = min(x, next_min_x) next_max_x = max(x, next_max_x) next_min_y = min(y, next_min_y) next_max_y = max(y, next_max_y) - print("".join(line)) + print("".join(line_list)) # line 295 for _ in range(max_x + 1, MAX_HEIGHT): diff --git a/57_Literature_Quiz/python/litquiz.py b/57_Literature_Quiz/python/litquiz.py index d9e581d3..9af12398 100644 --- a/57_Literature_Quiz/python/litquiz.py +++ b/57_Literature_Quiz/python/litquiz.py @@ -6,20 +6,19 @@ A children's literature quiz Ported by Dave LeCompte """ +from typing import List, NamedTuple + PAGE_WIDTH = 64 -class Question: - def __init__( - self, question, answer_list, correct_number, incorrect_message, correct_message - ): - self.question = question - self.answer_list = answer_list - self.correct_number = correct_number - self.incorrect_message = incorrect_message - self.correct_message = correct_message +class Question(NamedTuple): + question: str + answer_list: List[str] + correct_number: int + incorrect_message: str + correct_message: str - def ask(self): + def ask(self) -> bool: print(self.question) options = [f"{i+1}){self.answer_list[i]}" for i in range(len(self.answer_list))] @@ -69,7 +68,6 @@ questions = [ def print_centered(msg: str) -> None: spaces = " " * ((64 - len(msg)) // 2) - print(spaces + msg) diff --git a/58_Love/python/love.py b/58_Love/python/love.py index a15237ba..2bb93c68 100644 --- a/58_Love/python/love.py +++ b/58_Love/python/love.py @@ -1,24 +1,22 @@ -###################################################################### -# -# LOVE -# -# From: BASIC Computer Games (1978) -# Edited by David H. Ahl -# -# "This program is designed to reproduce Robert Indiana's great art -# work 'Love' with a message of your choice up to 60 characters long. -# -# "The [DATA variable is] an alternating count of the number -# of characters and blanks which form the design. These data give -# the correct proportions for a standard 10 character per inch -# Teletype or line printer. -# -# "The LOVE program was created by David Ahl." -# -# -# Python port by Jeff Jetton, 2019 -# -###################################################################### +""" +LOVE + +From: BASIC Computer Games (1978) + Edited by David H. Ahl + +"This program is designed to reproduce Robert Indiana's great art + work 'Love' with a message of your choice up to 60 characters long. + +"The [DATA variable is] an alternating count of the number + of characters and blanks which form the design. These data give + the correct proportions for a standard 10 character per inch + Teletype or line printer. + +"The LOVE program was created by David Ahl." + + +Python port by Jeff Jetton, 2019 +""" # Image data. Each top-level element is a row. Each row element @@ -108,7 +106,7 @@ def main() -> None: position += length print(line_text) - print("") + print() if __name__ == "__main__": diff --git a/59_Lunar_LEM_Rocket/python/lunar.py b/59_Lunar_LEM_Rocket/python/lunar.py index 5d5cfa3e..82f21fc0 100644 --- a/59_Lunar_LEM_Rocket/python/lunar.py +++ b/59_Lunar_LEM_Rocket/python/lunar.py @@ -7,6 +7,7 @@ Ported by Dave LeCompte """ import math +from dataclasses import dataclass from typing import Any, NamedTuple PAGE_WIDTH = 64 @@ -122,23 +123,15 @@ class SimulationClock: self.time_until_next_prompt -= delta_t +@dataclass class Capsule: - def __init__( - self, - altitude: float = 120, - velocity: float = 1, - mass_with_fuel: float = 33000, - mass_without_fuel: float = 16500, - g: float = 1e-3, - z: float = 1.8, - ) -> None: - self.a = altitude # in miles above the surface - self.v = velocity # downward - self.m = mass_with_fuel - self.n = mass_without_fuel - self.g = g - self.z = z - self.fuel_per_second: float = 0 + altitude: float = 120 # in miles above the surface + velocity: float = 1 # downward + m: float = 33000 # mass_with_fuel + n: float = 16500 # mass_without_fuel + g: float = 1e-3 + z: float = 1.8 + fuel_per_second: float = 0 def remaining_fuel(self) -> float: return self.m - self.n @@ -151,8 +144,8 @@ class Capsule: ) -> None: sim_clock.advance(delta_t) self.m = self.m - delta_t * self.fuel_per_second - self.a = new_state.altitude - self.v = new_state.velocity + self.altitude = new_state.altitude + self.velocity = new_state.velocity def fuel_time_remaining(self) -> float: # extrapolates out how many seconds we have at the current fuel burn rate @@ -166,16 +159,16 @@ class Capsule: # new velocity new_velocity = ( - self.v + self.velocity + self.g * delta_t + self.z * (-q - q**2 / 2 - q**3 / 3 - q**4 / 4 - q**5 / 5) ) # new altitude new_altitude = ( - self.a + self.altitude - self.g * delta_t**2 / 2 - - self.v * delta_t + - self.velocity * delta_t + self.z * delta_t * (q / 2 + q**2 / 6 + q**3 / 12 + q**4 / 20 + q**5 / 30) @@ -185,9 +178,9 @@ class Capsule: def make_state_display_string(self, sim_clock: SimulationClock) -> str: seconds = sim_clock.elapsed_time - miles = int(self.a) - feet = int(5280 * (self.a - miles)) - velocity = int(3600 * self.v) + miles = int(self.altitude) + feet = int(5280 * (self.altitude - miles)) + velocity = int(3600 * self.velocity) fuel = int(self.remaining_fuel()) burn_rate = " ? " @@ -203,7 +196,7 @@ class Capsule: def show_landing(sim_clock: SimulationClock, capsule: Capsule) -> None: - w = 3600 * capsule.v + w = 3600 * capsule.velocity print( f"ON MOON AT {sim_clock.elapsed_time:.2f} SECONDS - IMPACT VELOCITY {w:.2f} MPH" ) @@ -223,9 +216,10 @@ def show_landing(sim_clock: SimulationClock, capsule: Capsule) -> None: def show_out_of_fuel(sim_clock: SimulationClock, capsule: Capsule) -> None: print(f"FUEL OUT AT {sim_clock.elapsed_time} SECONDS") delta_t = ( - -capsule.v + math.sqrt(capsule.v**2 + 2 * capsule.a * capsule.g) + -capsule.velocity + + math.sqrt(capsule.velocity**2 + 2 * capsule.altitude * capsule.g) ) / capsule.g - capsule.v += capsule.g * delta_t + capsule.velocity += capsule.g * delta_t sim_clock.advance(delta_t) show_landing(sim_clock, capsule) @@ -243,15 +237,15 @@ def process_final_tick( return # line 35 average_vel = ( - capsule.v + capsule.velocity + math.sqrt( - capsule.v**2 + capsule.velocity**2 + 2 - * capsule.a + * capsule.altitude * (capsule.g - capsule.z * capsule.fuel_per_second / capsule.m) ) ) / 2 - delta_t = capsule.a / average_vel + delta_t = capsule.altitude / average_vel new_state = capsule.predict_motion(delta_t) capsule.update_state(sim_clock, delta_t, new_state) @@ -269,11 +263,11 @@ def handle_flyaway(sim_clock: SimulationClock, capsule: Capsule) -> bool: w = (1 - capsule.m * capsule.g / (capsule.z * capsule.fuel_per_second)) / 2 delta_t = ( capsule.m - * capsule.v + * capsule.velocity / ( capsule.z * capsule.fuel_per_second - * math.sqrt(w**2 + capsule.v / capsule.z) + * math.sqrt(w**2 + capsule.velocity / capsule.z) ) ) + 0.05 @@ -285,7 +279,7 @@ def handle_flyaway(sim_clock: SimulationClock, capsule: Capsule) -> bool: capsule.update_state(sim_clock, delta_t, new_state) - if (new_state.velocity > 0) or (capsule.v <= 0): + if (new_state.velocity > 0) or (capsule.velocity <= 0): # return to normal sim return False @@ -329,7 +323,7 @@ def run_simulation() -> None: process_final_tick(delta_t, sim_clock, capsule) return - if capsule.v > 0 and new_state.velocity < 0: + if capsule.velocity > 0 and new_state.velocity < 0: # moving away from the moon landed = handle_flyaway(sim_clock, capsule) diff --git a/60_Mastermind/python/mastermind.py b/60_Mastermind/python/mastermind.py index 94b92385..acf7cf6b 100644 --- a/60_Mastermind/python/mastermind.py +++ b/60_Mastermind/python/mastermind.py @@ -178,7 +178,7 @@ def main() -> None: # 470 -def get_invalid_letters(user_command): +def get_invalid_letters(user_command) -> str: """Makes sure player input consists of valid colors for selected game configuration.""" valid_colors = color_letters[:num_colors] invalid_letters = "" @@ -190,7 +190,7 @@ def get_invalid_letters(user_command): # 2000 def print_board(guesses) -> None: - """Prints previous guesses within the round.""" + """Print previous guesses within the round.""" print("Board") print("Move\tGuess\tBlack White") for idx, guess in enumerate(guesses): @@ -204,7 +204,7 @@ def print_board(guesses) -> None: # "We did try a version that kept an actual list of all possible combinations # (as a string array), which was significantly faster than this versionn but # which ate tremendous amounts of memory." -def get_possibility(possibility): +def get_possibility(possibility) -> List[int]: # print(possibility) if possibility[0] > -1: # 3530 current_position = 0 # Python arrays are zero-indexed @@ -248,7 +248,7 @@ def compare_two_positions(guess: str, answer: str) -> List[Union[str, int]]: # 5000 + logic from 1160 def print_score(computer_score, human_score, is_final_score: bool = False) -> None: - """Prints score after each turn ends, including final score at end of game.""" + """Print score after each turn ends, including final score at end of game.""" if is_final_score: print("GAME OVER") print("FINAL SCORE:") diff --git a/62_Mugwump/python/mugwump.py b/62_Mugwump/python/mugwump.py index 6eb63ccc..d1e3f7c3 100644 --- a/62_Mugwump/python/mugwump.py +++ b/62_Mugwump/python/mugwump.py @@ -1,5 +1,6 @@ from math import sqrt from random import randint +from typing import List, Tuple def introduction() -> None: @@ -18,7 +19,7 @@ you how far you are from each mugwump.""" ) -def generate_mugwumps(n=4): +def generate_mugwumps(n: int = 4) -> List[List[int]]: mugwumps = [] for _ in range(n): current = [randint(0, 9), randint(0, 9)] @@ -26,14 +27,14 @@ def generate_mugwumps(n=4): return mugwumps -def reveal_mugwumps(mugwumps): +def reveal_mugwumps(mugwumps: List[List[int]]) -> None: print("Sorry, that's 10 tries. Here's where they're hiding.") for idx, mugwump in enumerate(mugwumps, 1): if mugwump[0] != -1: print(f"Mugwump {idx} is at {mugwump[0]},{mugwump[1]}") -def calculate_distance(guess, mugwump): +def calculate_distance(guess: Tuple[int, int], mugwump: List[int]) -> float: d = sqrt(((mugwump[0] - guess[0]) ** 2) + ((mugwump[1] - guess[1]) ** 2)) return d @@ -47,7 +48,7 @@ def play_again() -> None: exit() -def play_round(): +def play_round() -> None: mugwumps = generate_mugwumps() turns = 1 score = 0 diff --git a/63_Name/python/name.py b/63_Name/python/name.py index 6574a363..3d7eeb1c 100644 --- a/63_Name/python/name.py +++ b/63_Name/python/name.py @@ -7,14 +7,6 @@ Ported by Dave LeCompte """ -def print_with_tab(space_count: int, msg: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - print(spaces + msg) - - def is_yes_ish(answer: str) -> bool: cleaned = answer.strip().upper() if cleaned in ["Y", "YES"]: @@ -23,29 +15,21 @@ def is_yes_ish(answer: str) -> bool: def main() -> None: - print_with_tab(34, "NAME") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 34 + "NAME") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print("HELLO.") print("MY NAME iS CREATIVE COMPUTER.") name = input("WHAT'S YOUR NAME (FIRST AND LAST)?") print() name_as_list = list(name) reversed_name = "".join(name_as_list[::-1]) - print(f"THANK YOU, {reversed_name}.") - print() + print(f"THANK YOU, {reversed_name}.\n") print("OOPS! I GUESS I GOT IT BACKWARDS. A SMART") - print("COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!") - print() - print() + print("COMPUTER LIKE ME SHOULDN'T MAKE A MISTAKE LIKE THAT!\n\n") print("BUT I JUST NOTICED YOUR LETTERS ARE OUT OF ORDER.") sorted_name = "".join(sorted(name_as_list)) - print(f"LET'S PUT THEM IN ORDER LIKE THIS: {sorted_name}") - print() - print() + print(f"LET'S PUT THEM IN ORDER LIKE THIS: {sorted_name}\n\n") print("DON'T YOU LIKE THAT BETTER?") like_answer = input() diff --git a/64_Nicomachus/python/nicomachus.py b/64_Nicomachus/python/nicomachus.py index abc48293..84f47703 100644 --- a/64_Nicomachus/python/nicomachus.py +++ b/64_Nicomachus/python/nicomachus.py @@ -15,15 +15,7 @@ Ported by Dave LeCompte import time -def print_with_tab(spaces_count: int, msg: str) -> None: - if spaces_count > 0: - spaces = " " * spaces_count - else: - spaces = "" - print(spaces + msg) - - -def get_yes_or_no(): +def get_yes_or_no() -> bool: while True: response = input().upper() if response == "YES": @@ -33,7 +25,7 @@ def get_yes_or_no(): print(f"EH? I DON'T UNDERSTAND '{response}' TRY 'YES' OR 'NO'.") -def play_game(): +def play_game() -> None: print("PLEASE THINK OF A NUMBER BETWEEN 1 AND 100.") print("YOUR NUMBER DIVIDED BY 3 HAS A REMAINDER OF") a = int(input()) @@ -62,11 +54,8 @@ def play_game(): def main() -> None: - print_with_tab(33, "NICOMA") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 33 + "NICOMA") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print("BOOMERANG PUZZLE FROM ARITHMETICA OF NICOMACHUS -- A.D. 90!") print() diff --git a/65_Nim/python/Traditional_NIM.py b/65_Nim/python/Traditional_NIM.py index 6c3a2d08..bd1470c5 100644 --- a/65_Nim/python/Traditional_NIM.py +++ b/65_Nim/python/Traditional_NIM.py @@ -1,12 +1,12 @@ import random +from typing import Tuple -# Class of the Game class NIM: - def __init__(self): + def __init__(self) -> None: self.piles = {1: 7, 2: 5, 3: 3, 4: 1} - def remove_pegs(self, command): + def remove_pegs(self, command) -> None: try: pile, num = command.split(",") @@ -29,7 +29,7 @@ class NIM: else: print("\nInvalid value of either Peg or Pile\n") - def get_ai_move(self): + def get_ai_move(self) -> Tuple[int, int]: possible_pile = [] for k, v in self.piles.items(): if v != 0: @@ -41,14 +41,14 @@ class NIM: return pile, num - def _command_integrity(self, num, pile): + def _command_integrity(self, num, pile) -> bool: return pile <= 4 and pile >= 1 and num <= self.piles[pile] def print_pegs(self) -> None: for pile, peg in self.piles.items(): print("Pile {} : {}".format(pile, "O " * peg)) - def help(self): + def help(self) -> None: print("-" * 10) print('\nThe Game is player with a number of Piles of Objects("O" == one peg)') print("\nThe Piles are arranged as given below(Tradional NIM)\n") @@ -62,7 +62,7 @@ class NIM: print("\nThe winner is defined as the one that picks the last remaning object") print("-" * 10) - def check_for_win(self): + def check_for_win(self) -> bool: sum = 0 for v in self.piles.values(): sum += v @@ -96,13 +96,13 @@ def main() -> None: break # Computers Move - command = game.get_ai_move() + ai_command = game.get_ai_move() print( "\nA.I MOVE - A.I Removed {} pegs from Pile {}".format( - command[1], command[0] + ai_command[1], ai_command[0] ) ) - game.remove_pegs(str(command[0]) + "," + str(command[1])) + game.remove_pegs(str(ai_command[0]) + "," + str(ai_command[1])) end = game.check_for_win() if end: print("\nComputer Wins the Game, Better Luck Next Time\n") diff --git a/66_Number/python/number.py b/66_Number/python/number.py index e58dd20b..e6840d92 100644 --- a/66_Number/python/number.py +++ b/66_Number/python/number.py @@ -9,15 +9,6 @@ Ported by Dave LeCompte import random -def print_with_tab(num_spaces: int, msg: str) -> None: - if num_spaces > 0: - spaces = " " * num_spaces - else: - spaces = "" - - print(spaces + msg) - - def print_instructions() -> None: print("YOU HAVE 100 POINTS. BY GUESSING NUMBERS FROM 1 TO 5, YOU") print("CAN GAIN OR LOSE POINTS DEPENDING UPON HOW CLOSE YOU GET TO") @@ -28,16 +19,13 @@ def print_instructions() -> None: print() -def fnr(): +def fnr() -> int: return random.randint(1, 5) def main() -> None: - print_with_tab(33, "NUMBER") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 33 + "NUMBER") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print_instructions() diff --git a/67_One_Check/python/onecheck.py b/67_One_Check/python/onecheck.py index b866ebd9..21ffbd6e 100644 --- a/67_One_Check/python/onecheck.py +++ b/67_One_Check/python/onecheck.py @@ -1,22 +1,17 @@ -# ONE CHECK +""" +ONE CHECK -# Port to python by imiro +Port to Python by imiro +""" - -def tab(x): - return " " * x +from typing import Tuple def main() -> None: - # Initial instructions - print(tab(30) + "ONE CHECK") - print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() - print("SOLITAIRE CHECKER PUZZLE BY DAVID AHL") - print() + print(" " * 30 + "ONE CHECK") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") + print("SOLITAIRE CHECKER PUZZLE BY DAVID AHL\n") print("48 CHECKERS ARE PLACED ON THE 2 OUTSIDE SPACES OF A") print("STANDARD 64-SQUARE CHECKERBOARD. THE OBJECT IS TO") print("REMOVE AS MANY CHECKERS AS POSSIBLE BY DIAGONAL JUMPS") @@ -25,35 +20,29 @@ def main() -> None: print("THE BOARD PRINTED OUT ON EACH TURN '1' INDICATES A") print("CHECKER AND '0' AN EMPTY SQUARE. WHEN YOU HAVE NO") print("POSSIBLE JUMPS REMAINING, INPUT A '0' IN RESPONSE TO") - print("QUESTION 'JUMP FROM ?'") - print() - print("HERE IS THE NUMERICAL BOARD:") - print() + print("QUESTION 'JUMP FROM ?'\n") + print("HERE IS THE NUMERICAL BOARD:\n") while True: for j in range(1, 64, 8): for i in range(j, j + 7): print(i, end=(" " * (3 if i < 10 else 2))) print(j + 7) - print() - print("AND HERE IS THE OPENING POSITION OF THE CHECKERS.") - print() + print("\nAND HERE IS THE OPENING POSITION OF THE CHECKERS.\n") (jumps, left) = play_game() print() - print("YOU MADE " + jumps + " JUMPS AND HAD " + left + " PIECES") - print("REMAINING ON THE BOARD.") - print() + print(f"YOU MADE {jumps} JUMPS AND HAD {left} PIECES") + print("REMAINING ON THE BOARD.\n") if not (try_again()): break - print() - print("O.K. HOPE YOU HAD FUN!!") + print("\nO.K. HOPE YOU HAD FUN!!") -def play_game(): +def play_game() -> Tuple[str, str]: # Initialize board # Give more than 64 elements to accomodate 1-based indexing board = [1] * 70 @@ -71,13 +60,13 @@ def play_game(): while True: print("JUMP FROM", end=" ") - f = input() - f = int(f) + f_str = input() + f = int(f_str) if f == 0: break print("TO", end=" ") - t = input() - t = int(t) + t_str = input() + t = int(t_str) print() # Check legality of move @@ -113,15 +102,15 @@ def play_game(): return (str(jumps), str(left)) -def try_again(): +def try_again() -> bool: print("TRY AGAIN", end=" ") - answer = input() - if answer.upper() == "YES": + answer = input().upper() + if answer == "YES": return True - elif answer.upper() == "NO": + elif answer == "NO": return False print("PLEASE ANSWER 'YES' OR 'NO'.") - try_again() + return try_again() if __name__ == "__main__": diff --git a/69_Pizza/python/pizza.py b/69_Pizza/python/pizza.py index bb8ed3ed..e4e36bea 100644 --- a/69_Pizza/python/pizza.py +++ b/69_Pizza/python/pizza.py @@ -89,7 +89,7 @@ def print_instructions() -> str: return player_name -def yes_no_prompt(msg): +def yes_no_prompt(msg: str) -> bool: while True: print(msg) response = input().upper() @@ -113,11 +113,11 @@ def print_more_directions(player_name: str) -> None: print() -def calculate_customer_index(x, y): +def calculate_customer_index(x: int, y: int) -> int: return 4 * (y - 1) + x - 1 -def deliver_to(customer_index, customer_name, player_name): +def deliver_to(customer_index, customer_name, player_name) -> bool: print(f" DRIVER TO {player_name}: WHERE DOES {customer_name} LIVE?") coords = input() @@ -133,7 +133,7 @@ def deliver_to(customer_index, customer_name, player_name): return False -def play_game(num_turns, player_name): +def play_game(num_turns, player_name) -> None: for _turn in range(num_turns): x = random.randint(1, 4) y = random.randint(1, 4) diff --git a/70_Poetry/python/poetry.py b/70_Poetry/python/poetry.py index 84b0b2ae..30212630 100644 --- a/70_Poetry/python/poetry.py +++ b/70_Poetry/python/poetry.py @@ -6,24 +6,20 @@ A poetry generator Ported by Dave LeCompte """ -# PORTING EDITORIAL NOTE: -# -# The original code is a pretty convoluted mesh of GOTOs and global -# state. This adaptation pulls things apart into phrases, but I have -# left the variables as globals, which makes goes against decades of -# wisdom that global state is bad. import random +from dataclasses import dataclass PAGE_WIDTH = 64 -# globals -u = 0 -i = 0 -j = 0 -k = 0 -phrase = 1 -line = "" +@dataclass +class State: + u: int = 0 + i: int = 0 + j: int = 0 + k: int = 0 + phrase: int = 1 + line: str = "" def print_centered(msg: str) -> None: @@ -31,9 +27,7 @@ def print_centered(msg: str) -> None: print(spaces + msg) -def process_phrase_1() -> str: - global line - +def process_phrase_1(state: State) -> str: line_1_options = [ "MIDNIGHT DREARY", "FIERY EYES", @@ -41,15 +35,11 @@ def process_phrase_1() -> str: "THING OF EVIL", "PROPHET", ] - - line = line + line_1_options[i] - return line + state.line = state.line + line_1_options[state.i] + return state.line -def process_phrase_2() -> None: - global line - global u - +def process_phrase_2(state: State) -> None: line_2_options = [ ("BEGUILING ME", 2), ("THRILLED ME", None), @@ -57,15 +47,13 @@ def process_phrase_2() -> None: ("NEVER FLITTING", 2), ("BURNED", None), ] - words, u_modifier = line_2_options[i] - line += words + words, u_modifier = line_2_options[state.i] + state.line += words if not (u_modifier is None): - u = u_modifier + state.u = u_modifier -def process_phrase_3() -> None: - global line - +def process_phrase_3(state: State) -> None: phrases = [ (False, "AND MY SOUL"), (False, "DARKNESS THERE"), @@ -74,14 +62,12 @@ def process_phrase_3() -> None: (True, "SIGN OF PARTING"), ] - only_if_u, words = phrases[i] - if (not only_if_u) or (u > 0): - line = line + words + only_if_u, words = phrases[state.i] + if (not only_if_u) or (state.u > 0): + state.line = state.line + words -def process_phrase_4() -> None: - global line - +def process_phrase_4(state: State) -> None: phrases = [ ("NOTHING MORE"), ("YET AGAIN"), @@ -90,55 +76,42 @@ def process_phrase_4() -> None: ("NEVERMORE"), ] - line += phrases[i] + state.line += phrases[state.i] -def maybe_comma(): - # line 210 - global u - global line - - if len(line) > 0 and line[-1] == ".": +def maybe_comma(state: State) -> None: + if len(state.line) > 0 and state.line[-1] == ".": # don't follow a period with a comma, ever return - if u != 0 and random.random() <= 0.19: - line += ", " - u = 2 - # line 212 + if state.u != 0 and random.random() <= 0.19: + state.line += ", " + state.u = 2 if random.random() <= 0.65: - line += " " - u += 1 + state.line += " " + state.u += 1 else: - # line 214 - print(line) - line = "" - u = 0 + print(state.line) + state.line = "" + state.u = 0 -def pick_phrase(): - global phrase - global line - global i, j, k +def pick_phrase(state: State) -> None: + state.i = random.randint(0, 4) + state.j += 1 + state.k += 1 - i = random.randint(0, 4) - j += 1 - k += 1 - - if u <= 0 and (j % 2) != 0: + if state.u <= 0 and (state.j % 2) != 0: # random indentation is fun! - line += " " * 5 - phrase = j + 1 + state.line += " " * 5 + state.phrase = state.j + 1 def main() -> None: print_centered("POETRY") - print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") - global line, phrase, j, k, u + state = State() phrase_processors = { 1: process_phrase_1, @@ -148,21 +121,21 @@ def main() -> None: } while True: - if phrase >= 1 and phrase <= 4: - phrase_processors[phrase]() - maybe_comma() - elif phrase == 5: - j = 0 - print(line) - line = "" - if k > 20: + if state.phrase >= 1 and state.phrase <= 4: + phrase_processors[state.phrase](state) + maybe_comma(state) + elif state.phrase == 5: + state.j = 0 + print(state.line) + state.line = "" + if state.k > 20: print() - u = 0 - k = 0 + state.u = 0 + state.k = 0 else: - phrase = 2 + state.phrase = 2 continue - pick_phrase() + pick_phrase(state) if __name__ == "__main__": diff --git a/72_Queen/python/queen.py b/72_Queen/python/queen.py index 201ea5d0..94f377a1 100755 --- a/72_Queen/python/queen.py +++ b/72_Queen/python/queen.py @@ -134,17 +134,10 @@ SAFE_SPOTS: Final[FrozenSet[Tuple[int, int]]] = COMPUTER_SAFE_SPOTS | frozenset( ) -def str_with_tab(indent: int, text: str, uppercase: bool = True) -> str: - """Create a string with ``indent`` spaces followed by ``text``.""" - if uppercase: - text = text.upper() - return " " * indent + text - - def intro() -> None: """Print the intro and print instructions if desired.""" - print(str_with_tab(33, "Queen")) - print(str_with_tab(15, "Creative Computing Morristown, New Jersey")) + print(" " * 33 + "Queen") + print(" " * 15 + "Creative Computing Morristown, New Jersey") print("\n" * 2) if ask("DO YOU WANT INSTRUCTIONS"): print(INSTR_TXT) diff --git a/73_Reverse/python/reverse.py b/73_Reverse/python/reverse.py index b72aa320..f75ece2f 100755 --- a/73_Reverse/python/reverse.py +++ b/73_Reverse/python/reverse.py @@ -5,7 +5,7 @@ import textwrap NUMCNT = 9 # How many numbers are we playing with? -def play(): +def main() -> None: print("REVERSE".center(72)) print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY".center(72)) print() @@ -14,7 +14,7 @@ def play(): print() if not input("DO YOU WANT THE RULES? (yes/no) ").lower().startswith("n"): - rules() + print_rules() while True: game_loop() @@ -23,7 +23,7 @@ def play(): return -def game_loop(): +def game_loop() -> None: """Play the main game.""" # Make a random list from 1 to NUMCNT numbers = list(range(1, NUMCNT + 1)) @@ -67,12 +67,10 @@ def game_loop(): def print_list(numbers) -> None: - """Print out the list""" print(" ".join(map(str, numbers))) -def rules(): - """Print out the rules""" +def print_rules() -> None: help = textwrap.dedent( """ THIS IS THE GAME OF "REVERSE". TO WIN, ALL YOU HAVE @@ -103,6 +101,6 @@ def rules(): if __name__ == "__main__": try: - play() + main() except KeyboardInterrupt: pass diff --git a/74_Rock_Scissors_Paper/python/rockscissors.py b/74_Rock_Scissors_Paper/python/rockscissors.py index 09d63d2d..898f709c 100644 --- a/74_Rock_Scissors_Paper/python/rockscissors.py +++ b/74_Rock_Scissors_Paper/python/rockscissors.py @@ -6,7 +6,7 @@ import random -def play_game(): +def play_game() -> None: """Play one round of the game""" while True: diff --git a/75_Roulette/python/roulette.py b/75_Roulette/python/roulette.py index b20b00e6..7a21d36d 100644 --- a/75_Roulette/python/roulette.py +++ b/75_Roulette/python/roulette.py @@ -75,8 +75,8 @@ def query_bets() -> Tuple[List[int], List[int]]: for i in range(bet_count): while bet_ids[i] == -1: try: - inString = input("NUMBER " + str(i + 1) + "? ").split(",") - id_, val = int(inString[0]), int(inString[1]) + in_string = input("NUMBER " + str(i + 1) + "? ").split(",") + id_, val = int(in_string[0]), int(in_string[1]) # check other bet_IDs for j in range(i): @@ -93,7 +93,7 @@ def query_bets() -> Tuple[List[int], List[int]]: return bet_ids, bet_values -def bet_results(bet_ids: List[int], bet_values: List[int], result): +def bet_results(bet_ids: List[int], bet_values: List[int], result) -> int: """Computes the results, prints them, and returns the total net winnings""" total_winnings = 0 @@ -134,7 +134,7 @@ def bet_results(bet_ids: List[int], bet_values: List[int], result): def print_check(amount: int) -> None: - """Prints a check of a given amount""" + """Print a check of a given amount""" name = input("TO WHOM SHALL I MAKE THE CHECK? ") print("-" * 72) diff --git a/76_Russian_Roulette/python/russianroulette.py b/76_Russian_Roulette/python/russianroulette.py index 3af23515..f402fb03 100644 --- a/76_Russian_Roulette/python/russianroulette.py +++ b/76_Russian_Roulette/python/russianroulette.py @@ -1,19 +1,17 @@ -######################################################## -# -# Russian Roulette -# -# From Basic Computer Games (1978) -# -# In this game, you are given by the computer a -# revolver loaded with one bullet and five empty -# chambers. You spin the chamber and pull the trigger -# by inputting a "1", or, if you want to quit, input -# a "2". You win if you play ten times and are still -# alive. -# Tom Adametx wrote this program while a student at -# Curtis Jr. High School in Sudbury, Massachusetts. -# -######################################################## +""" +Russian Roulette + +From Basic Computer Games (1978) + + In this game, you are given by the computer a + revolver loaded with one bullet and five empty + chambers. You spin the chamber and pull the trigger + by inputting a "1", or, if you want to quit, input + a "2". You win if you play ten times and are still + alive. + Tom Adametx wrote this program while a student at + Curtis Jr. High School in Sudbury, Massachusetts. +""" from random import random diff --git a/77_Salvo/python/salvo.py b/77_Salvo/python/salvo.py index 456ad755..368b15da 100644 --- a/77_Salvo/python/salvo.py +++ b/77_Salvo/python/salvo.py @@ -1,17 +1,14 @@ import random import re +from typing import List, Optional, Tuple -################### -# -# static variables -# -################### +BoardType = List[List[Optional[int]]] +CoordinateType = Tuple[int, int] BOARD_WIDTH = 10 BOARD_HEIGHT = 10 -# game ships -# + # data structure keeping track of information # about the ships in the game. for each ship, # the following information is provided: @@ -35,26 +32,21 @@ VALID_MOVES = [ [1, 0], # South [1, -1], # South West [0, -1], # West - [-1, -1], -] # North West + [-1, -1], # North West +] COORD_REGEX = "[ \t]{0,}(-?[0-9]{1,3})[ \t]{0,},[ \t]{0,}(-?[0-9]{1,2})" -#################### -# -# global variables -# -#################### # array of BOARD_HEIGHT arrays, BOARD_WIDTH in length, # representing the human player and computer -player_board = [] -computer_board = [] +player_board: BoardType = [] +computer_board: BoardType = [] # array representing the coordinates # for each ship for player and computer # array is in the same order as SHIPS -computer_ship_coords = [] +computer_ship_coords: List[List[CoordinateType]] = [] #################################### @@ -88,10 +80,9 @@ num_player_shots = 7 # #################################### -# flag indicating whose turn -# it currently is -COMPUTER = 0 -PLAYER = 1 +# flag indicating whose turn it currently is +COMPUTER = False +PLAYER = True active_turn = COMPUTER #################### @@ -108,26 +99,27 @@ random.seed() # random_x_y # -# generate a valid x,y coordinate on the board -# returns: x,y -# x: integer between 1 and BOARD_HEIGHT -# y: integer between 1 and BOARD WIDTH -def random_x_y(): + + +def random_x_y() -> CoordinateType: + """Generate a valid x,y coordinate on the board""" + x = random.randrange(1, BOARD_WIDTH + 1) y = random.randrange(1, BOARD_HEIGHT + 1) return (x, y) -# input_coord -# -# ask user for single (x,y) coordinate -# validate the coordinates are within the bounds -# of the board width and height. mimic the behavior -# of the original program which exited with error -# messages if coordinates where outside of array bounds. -# if input is not numeric, print error out to user and -# let them try again. -def input_coord(): +def input_coord() -> CoordinateType: + """ + Ask user for single (x,y) coordinate + + validate the coordinates are within the bounds + of the board width and height. mimic the behavior + of the original program which exited with error + messages if coordinates where outside of array bounds. + if input is not numeric, print error out to user and + let them try again. + """ match = None while not match: coords = input("? ") @@ -148,25 +140,25 @@ def input_coord(): return x, y -# generate_ship_coordinates -# -# given a ship from the SHIPS array, generate -# the coordinates of the ship. the starting point -# of the ship's first coordinate is generated randomly. -# once the starting coordinates are determined, the -# possible directions of the ship, accounting for the -# edges of the board, are determined. once possible -# directions are found, a direction is randomly -# determined and the remaining coordinates are -# generated by adding or substraction from the starting -# coordinates as determined by direction. -# -# arguments: -# ship - index into the SHIPS array -# -# returns: -# array of sets of coordinates (x,y) -def generate_ship_coordinates(ship): +def generate_ship_coordinates(ship: int) -> List[CoordinateType]: + """ + given a ship from the SHIPS array, generate + the coordinates of the ship. the starting point + of the ship's first coordinate is generated randomly. + once the starting coordinates are determined, the + possible directions of the ship, accounting for the + edges of the board, are determined. once possible + directions are found, a direction is randomly + determined and the remaining coordinates are + generated by adding or substraction from the starting + coordinates as determined by direction. + + arguments: + ship - index into the SHIPS array + + returns: + array of sets of coordinates (x,y) + """ # randomly generate starting x,y coordinates start_x, start_y = random_x_y() @@ -213,25 +205,18 @@ def generate_ship_coordinates(ship): return coords -# create_blank_board -# -# helper function to create a game board -# that is blank -def create_blank_board(): - return [[None for y in range(BOARD_WIDTH)] for x in range(BOARD_HEIGHT)] +def create_blank_board() -> BoardType: + """Create a blank game board""" + return [[None for _y in range(BOARD_WIDTH)] for _x in range(BOARD_HEIGHT)] -# print_board -# -# print out the game board for testing -# purposes -def print_board(board) -> None: - +def print_board(board: BoardType) -> None: + """Print out the game board for testing purposes""" # print board header (column numbers) print(" ", end="") for z in range(BOARD_WIDTH): print(f"{z+1:3}", end="") - print("") + print() for x in range(len(board)): print(f"{x+1:2}", end="") @@ -240,30 +225,34 @@ def print_board(board) -> None: print(f"{' ':3}", end="") else: print(f"{board[x][y]:3}", end="") - print("") + print() -# place_ship -# -# place a ship on a given board. updates -# the board's row,column value at the given -# coordinates to indicate where a ship is -# on the board. -# -# inputs: board - array of BOARD_HEIGHT by BOARD_WIDTH -# coords - array of sets of (x,y) coordinates of each -# part of the given ship -# ship - integer repreesnting the type of ship (given in SHIPS) -def place_ship(board, coords, ship): +def place_ship(board: BoardType, coords: List[CoordinateType], ship: int) -> None: + """ + Place a ship on a given board. + + updates + the board's row,column value at the given + coordinates to indicate where a ship is + on the board. + + inputs: board - array of BOARD_HEIGHT by BOARD_WIDTH + coords - array of sets of (x,y) coordinates of each + part of the given ship + ship - integer representing the type of ship (given in SHIPS) + """ for coord in coords: board[coord[0] - 1][coord[1] - 1] = ship -# NOTE: A little quirk that exists here and in the orginal -# game: Ships are allowed to cross each other! -# For example: 2 destroyers, length 2, one at -# [(1,1),(2,2)] and other at [(2,1),(1,2)] -def generate_board(): +def generate_board() -> Tuple[BoardType, List[List[CoordinateType]]]: + """ + NOTE: A little quirk that exists here and in the orginal + game: Ships are allowed to cross each other! + For example: 2 destroyers, length 2, one at + [(1,1),(2,2)] and other at [(2,1),(1,2)] + """ board = create_blank_board() ship_coords = [] @@ -284,7 +273,9 @@ def generate_board(): return board, ship_coords -def execute_shot(turn, board, x, y, current_turn): +def execute_shot( + turn: bool, board: BoardType, x: int, y: int, current_turn: int +) -> int: """ given a board and x, y coordinates, execute a shot. returns True if the shot @@ -298,12 +289,8 @@ def execute_shot(turn, board, x, y, current_turn): return ship_hit -# calculate_shots -# -# function to examine each board -# and determine how many shots remaining -def calculate_shots(board): - +def calculate_shots(board: BoardType) -> int: + """Examine each board and determine how many shots remaining""" ships_found = [0 for x in range(len(SHIPS))] for x in range(BOARD_HEIGHT): for y in range(BOARD_WIDTH): @@ -318,19 +305,12 @@ def calculate_shots(board): return shots -# initialize -# -# function to initialize global variables used -# during game play. -def initialize_game(): - - # initialize the global player and computer - # boards +def initialize_game() -> None: + # initialize the global player and computer boards global player_board player_board = create_blank_board() - # generate the ships for the computer's - # board + # generate the ships for the computer's board global computer_board global computer_ship_coords computer_board, computer_ship_coords = generate_board() @@ -338,7 +318,7 @@ def initialize_game(): # print out the title 'screen' print("{:>38}".format("SALVO")) print("{:>57s}".format("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")) - print("") + print() print("{:>52s}".format("ORIGINAL BY LAWRENCE SIEGEL, 1973")) print("{:>56s}".format("PYTHON 3 PORT BY TODD KAISER, MARCH 2021")) print("\n") @@ -355,8 +335,8 @@ def initialize_game(): ship_coords.append(list) # add ships to the user's board - for ship in range(len(SHIPS)): - place_ship(player_board, ship_coords[ship], ship) + for ship_index in range(len(SHIPS)): + place_ship(player_board, ship_coords[ship_index], ship_index) # see if the player wants the computer's ship # locations printed out and if the player wants to @@ -366,9 +346,9 @@ def initialize_game(): while input_loop: player_start = input("DO YOU WANT TO START? ") if player_start == "WHERE ARE YOUR SHIPS?": - for ship in range(len(SHIPS)): - print(SHIPS[ship][0]) - coords = computer_ship_coords[ship] + for ship_index in range(len(SHIPS)): + print(SHIPS[ship_index][0]) + coords = computer_ship_coords[ship_index] for coord in coords: x = coord[0] y = coord[1] @@ -384,14 +364,11 @@ def initialize_game(): print_computer_shots = True global first_turn - global second_turn if player_start.lower() != "yes": first_turn = COMPUTER - second_turn = PLAYER # calculate the initial number of shots for each - global num_computer_shots - global num_player_shots + global num_computer_shots, num_player_shots num_player_shots = calculate_shots(player_board) num_computer_shots = calculate_shots(computer_board) @@ -407,31 +384,22 @@ def initialize_game(): # forth, replicating the gotos in the original game -# initialize the first_turn function to the -# player's turn +# initialize the first_turn function to the player's turn first_turn = PLAYER -# initialize the second_turn to the computer's -# turn -second_turn = COMPUTER +def execute_turn(turn: bool, current_turn: int) -> int: + global num_computer_shots, num_player_shots - -def execute_turn(turn, current_turn): - - global num_computer_shots - global num_player_shots - - # print out the number of shots the current - # player has + # print out the number of shots the current player has board = None num_shots = 0 if turn == COMPUTER: - print("I HAVE", num_computer_shots, "SHOTS.") + print(f"I HAVE {num_computer_shots} SHOTS.") board = player_board num_shots = num_computer_shots else: - print("YOU HAVE", num_player_shots, "SHOTS.") + print(f"YOU HAVE {num_player_shots} SHOTS.") board = computer_board num_shots = num_player_shots @@ -486,34 +454,22 @@ def execute_turn(turn, current_turn): def main() -> None: - # keep track of the turn current_turn = 0 - - # initialize the player and computer - # boards initialize_game() # execute turns until someone wins or we run # out of squares to shoot - game_over = False while not game_over: - - # increment the turn - current_turn = current_turn + 1 + current_turn += 1 print("\n") print("TURN", current_turn) - # print("computer") - # print_board(computer_board) - # print("player") - # print_board(player_board) - - if execute_turn(first_turn, current_turn) == 0: - game_over = True - continue - if execute_turn(second_turn, current_turn) == 0: + if ( + execute_turn(first_turn, current_turn) == 0 + or execute_turn(not first_turn, current_turn) == 0 + ): game_over = True continue diff --git a/79_Slalom/python/slalom.py b/79_Slalom/python/slalom.py index 1db5d5d8..a6833331 100644 --- a/79_Slalom/python/slalom.py +++ b/79_Slalom/python/slalom.py @@ -7,17 +7,17 @@ medals = { } -def ask(question): +def ask(question: str) -> str: print(question, end="? ") return input().upper() -def ask_int(question): +def ask_int(question: str) -> int: reply = ask(question) return int(reply) if reply.isnumeric() else -1 -def pre_run(gates, max_speeds): +def pre_run(gates, max_speeds) -> None: print('\nType "INS" for instructions') print('Type "MAX" for approximate maximum speeds') print('Type "RUN" for the beginning of the race') @@ -50,10 +50,10 @@ def pre_run(gates, max_speeds): cmd = ask(f'"{cmd}" is an illegal command--Retry') -def run(gates, lvl, max_speeds): +def run(gates, lvl, max_speeds) -> None: global medals print("The starter counts down...5...4...3...2...1...Go!") - time = 0 + time: float = 0 speed = int(random() * (18 - 9) + 9) print("You're off") for i in range(0, gates): diff --git a/80_Slots/python/slots.py b/80_Slots/python/slots.py index e54f3b4e..22c2b3a3 100644 --- a/80_Slots/python/slots.py +++ b/80_Slots/python/slots.py @@ -34,9 +34,10 @@ import sys from collections import Counter from random import choices +from typing import List -def initial_message(): +def initial_message() -> None: print(" " * 30 + "Slots") print(" " * 15 + "Creative Computing Morrison, New Jersey") print("\n" * 3) @@ -45,7 +46,7 @@ def initial_message(): print("To pull the arm, punch the return key after making your bet.") -def input_betting(): +def input_betting() -> int: print("\n") b = -1 while b < 1 or b > 100: @@ -61,7 +62,7 @@ def input_betting(): return int(b) -def beeping(): +def beeping() -> None: # Function to produce a beep sound. # In the original program is the subroutine at line 1270 for _ in range(5): @@ -69,7 +70,7 @@ def beeping(): sys.stdout.flush() -def spin_wheels(): +def spin_wheels() -> List[str]: possible_fruits = ["Bar", "Bell", "Orange", "Lemon", "Plum", "Cherry"] wheel = choices(possible_fruits, k=3) @@ -79,7 +80,7 @@ def spin_wheels(): return wheel -def adjust_profits(wheel, m, profits): +def adjust_profits(wheel: List[str], m: int, profits: int) -> int: # we remove the duplicates s = set(wheel) @@ -117,7 +118,7 @@ def adjust_profits(wheel, m, profits): return profits -def final_message(profits) -> None: +def final_message(profits: int) -> None: if profits < 0: print("Pay up! Please leave your money on the terminal") elif profits == 0: @@ -140,7 +141,7 @@ def main() -> None: answer = input("Again?") try: - if not answer[0].lower() == "y": + if answer[0].lower() != "y": keep_betting = False except IndexError: keep_betting = False diff --git a/81_Splat/python/splat.py b/81_Splat/python/splat.py index 665494b3..30ec74b5 100644 --- a/81_Splat/python/splat.py +++ b/81_Splat/python/splat.py @@ -24,22 +24,22 @@ Ported in 2021 by Jonas Nockert / @lemonad """ from math import sqrt from random import choice, random, uniform -from typing import List +from typing import List, Tuple PAGE_WIDTH = 72 -def numeric_input(question, default=0): +def numeric_input(question, default=0) -> float: """Ask user for a numeric value.""" while True: - answer = input(f"{question} [{default}]: ").strip() or default + answer_str = input(f"{question} [{default}]: ").strip() or default try: - return float(answer) + return float(answer_str) except ValueError: pass -def yes_no_input(question, default="YES"): +def yes_no_input(question: str, default="YES") -> bool: """Ask user a yes/no question and returns True if yes, otherwise False.""" answer = input(f"{question} (YES OR NO) [{default}]: ").strip() or default while answer.lower() not in ["n", "no", "y", "yes"]: @@ -47,7 +47,7 @@ def yes_no_input(question, default="YES"): return answer.lower() in ["y", "yes"] -def get_terminal_velocity(): +def get_terminal_velocity() -> float: """Terminal velocity by user or picked by computer.""" if yes_no_input("SELECT YOUR OWN TERMINAL VELOCITY", default="NO"): v1 = numeric_input("WHAT TERMINAL VELOCITY (MI/HR)", default=100) @@ -60,7 +60,7 @@ def get_terminal_velocity(): return v1 * (5280 / 3600) -def get_acceleration(): +def get_acceleration() -> float: """Acceleration due to gravity by user or picked by computer.""" if yes_no_input("WANT TO SELECT ACCELERATION DUE TO GRAVITY", default="NO"): a2 = numeric_input("WHAT ACCELERATION (FT/SEC/SEC)", default=32.16) @@ -70,14 +70,14 @@ def get_acceleration(): return a2 -def get_freefall_time(): +def get_freefall_time() -> float: """User-guessed freefall time. The idea of the game is to pick a freefall time, given initial altitude, terminal velocity and acceleration, so the parachute as close to the ground as possible without going splat. """ - t_freefall = 0 + t_freefall: float = 0 # A zero or negative freefall time is not handled by the motion # equations during the jump. while t_freefall <= 0: @@ -85,13 +85,13 @@ def get_freefall_time(): return t_freefall -def jump(): +def jump() -> float: """Simulate a jump and returns the altitude where the chute opened. The idea is to open the chute as late as possible -- but not too late. """ - v = 0 # Terminal velocity. - a = 0 # Acceleration. + v: float = 0 # Terminal velocity. + a: float = 0 # Acceleration. initial_altitude = int(9001 * random() + 1000) v1 = get_terminal_velocity() @@ -181,9 +181,9 @@ def jump(): return altitude -def pick_random_celestial_body(): +def pick_random_celestial_body() -> Tuple[str, float]: """Pick a random planet, the moon, or the sun with associated gravity.""" - body, gravity = choice( + return choice( [ ("MERCURY", 12.2), ("VENUS", 28.3), @@ -197,10 +197,9 @@ def pick_random_celestial_body(): ("THE SUN", 896.0), ] ) - return body, gravity -def jump_stats(previous_jumps, chute_altitude): +def jump_stats(previous_jumps, chute_altitude) -> Tuple[int, int]: """Compare altitude when chute opened with previous successful jumps. Return the number of previous jumps and the number of times diff --git a/82_Stars/python/stars.py b/82_Stars/python/stars.py index 00e17bb5..d2024d6b 100644 --- a/82_Stars/python/stars.py +++ b/82_Stars/python/stars.py @@ -47,14 +47,12 @@ def print_stars(secret_number, guess) -> None: print(stars) -def get_guess(): - valid_response = False - while not valid_response: - guess = input("Your guess? ") - if guess.isdigit(): - valid_response = True - guess = int(guess) - return guess +def get_guess(prompt: str) -> int: + while True: + guess_str = input(prompt) + if guess_str.isdigit(): + guess = int(guess_str) + return guess def main() -> None: @@ -80,8 +78,8 @@ def main() -> None: player_has_won = False while (guess_number < MAX_GUESSES) and not player_has_won: - print("") - guess = get_guess() + print() + guess = get_guess("Your guess? ") guess_number += 1 if guess == secret_number: diff --git a/83_Stock_Market/python/Stock_Market.py b/83_Stock_Market/python/Stock_Market.py index 2798cba3..e32572ca 100644 --- a/83_Stock_Market/python/Stock_Market.py +++ b/83_Stock_Market/python/Stock_Market.py @@ -1,10 +1,9 @@ import random +from typing import Any, Dict, List -# Stock_Market class Stock_Market: - def __init__(self): - + def __init__(self) -> None: # Hard Coded Names short_names = ["IBM", "RCA", "LBJ", "ABC", "CBS"] full_names = [ @@ -16,7 +15,7 @@ class Stock_Market: ] # Initializing Dictionary to hold all the information systematically - self.data = {} + self.data: Dict[str, Any] = {} for sn, fn in zip(short_names, full_names): # A dictionary for each stock temp = {"Name": fn, "Price": None, "Holdings": 0} @@ -31,20 +30,17 @@ class Stock_Market: self.cash_assets = 10000 self.stock_assets = 0 - def total_assets(self): - + def total_assets(self) -> float: return self.cash_assets + self.stock_assets - def _generate_day_change(self): - + def _generate_day_change(self) -> None: self.changes = [] for _ in range(len(self.data)): self.changes.append( round(random.uniform(-5, 5), 2) ) # Random % Change b/w -5 and 5 - def update_prices(self): - + def update_prices(self) -> None: self._generate_day_change() for stock, change in zip(self.data.values(), self.changes): stock["Price"] = round(stock["Price"] + (change / 100) * stock["Price"], 2) @@ -57,9 +53,8 @@ class Stock_Market: print(f"\nNEW YORK STOCK EXCHANGE AVERAGE: ${sum / 5:.2f}") - def get_average_change(self): - - sum = 0 + def get_average_change(self) -> float: + sum: float = 0 for change in self.changes: sum += change @@ -77,8 +72,7 @@ class Stock_Market: self.print_exchange_average() self.print_assets() - def take_inputs(self): - + def take_inputs(self) -> List[str]: print("\nWHAT IS YOUR TRANSACTION IN") flag = False while not flag: @@ -92,7 +86,7 @@ class Stock_Market: if len(new_holdings) == 5: flag = self._check_transaction(new_holdings) - return new_holdings + return new_holdings # type: ignore def print_trading_day(self) -> None: @@ -107,8 +101,7 @@ class Stock_Market: ) ) - def update_cash_assets(self, new_holdings): - + def update_cash_assets(self, new_holdings) -> None: sell = 0 buy = 0 for stock, holding in zip(self.data.values(), new_holdings): @@ -120,8 +113,7 @@ class Stock_Market: self.cash_assets = self.cash_assets + sell - buy - def update_stock_assets(self): - + def update_stock_assets(self) -> None: sum = 0 for data in self.data.values(): sum += data["Price"] * data["Holdings"] @@ -129,13 +121,11 @@ class Stock_Market: self.stock_assets = round(sum, 2) def print_assets(self) -> None: - print(f"\nTOTAL STOCK ASSETS ARE: ${self.stock_assets:.2f}") print(f"TOTAL CASH ASSETS ARE: ${self.cash_assets:.2f}") print(f"TOTAL ASSETS ARE: ${self.total_assets():.2f}") - def _check_transaction(self, new_holdings): - + def _check_transaction(self, new_holdings) -> bool: sum = 0 for stock, holding in zip(self.data.values(), new_holdings): if holding > 0: @@ -156,8 +146,7 @@ class Stock_Market: return True - def update_holdings(self, new_holdings): - + def update_holdings(self, new_holdings) -> None: for stock, new_holding in zip(self.data.values(), new_holdings): stock["Holdings"] += new_holding @@ -186,8 +175,7 @@ HAVE $10,000 TO INVEST. USE INTEGERS FOR ALL YOUR INPUTS. ) -if __name__ == "__main__": - +def main() -> None: print("\t\t STOCK MARKET") help = input("\nDO YOU WANT INSTRUCTIONS(YES OR NO)? ") @@ -225,4 +213,8 @@ if __name__ == "__main__": print("\n------------END OF TRADING DAY--------------\n") print("\nHOPE YOU HAD FUN!!!!") - input("") + input() + + +if __name__ == "__main__": + main() diff --git a/85_Synonym/python/synonym.py b/85_Synonym/python/synonym.py index 6d1636e6..0680bb78 100644 --- a/85_Synonym/python/synonym.py +++ b/85_Synonym/python/synonym.py @@ -53,7 +53,7 @@ def print_right() -> None: print(random.choice(right_words)) -def ask_question(question_number): +def ask_question(question_number: int) -> None: words = synonym_words[question_number] clues = words[:] base_word = clues.pop(0) diff --git a/86_Target/python/target.py b/86_Target/python/target.py index f10f0a56..122c82d1 100644 --- a/86_Target/python/target.py +++ b/86_Target/python/target.py @@ -8,6 +8,7 @@ Ported by Dave LeCompte import math import random +from typing import List PAGE_WIDTH = 64 @@ -41,7 +42,7 @@ def print_instructions() -> None: print() -def prompt(): +def prompt() -> List[float]: while True: response = input("INPUT ANGLE DEVIATION FROM X, DEVIATION FROM Z, DISTANCE? ") if "," not in response: @@ -54,14 +55,14 @@ def prompt(): return [float(t) for t in terms] -def next_target(): +def next_target() -> None: for _ in range(5): print() print("NEXT TARGET...") print() -def describe_miss(x, y, z, x1, y1, z1, d): +def describe_miss(x, y, z, x1, y1, z1, d) -> None: x2 = x1 - x y2 = y1 - y z2 = z1 - z @@ -88,7 +89,7 @@ def describe_miss(x, y, z, x1, y1, z1, d): print() -def do_shot_loop(p1, x, y, z): +def do_shot_loop(p1, x, y, z) -> None: shot_count = 0 while True: shot_count += 1 @@ -137,11 +138,11 @@ def do_shot_loop(p1, x, y, z): describe_miss(x, y, z, x1, y1, z1, distance) -def show_radians(a, b): +def show_radians(a, b) -> None: print(f"RADIANS FROM X AXIS = {a:.4f} FROM Z AXIS = {b:.4f}") -def play_game(): +def play_game() -> None: while True: a = random.uniform(0, 2 * math.pi) # random angle b = random.uniform(0, 2 * math.pi) # random angle diff --git a/88_3-D_Tic-Tac-Toe/python/qubit.py b/88_3-D_Tic-Tac-Toe/python/qubit.py index 4081e70d..5f2f0e77 100644 --- a/88_3-D_Tic-Tac-Toe/python/qubit.py +++ b/88_3-D_Tic-Tac-Toe/python/qubit.py @@ -1,10 +1,11 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # Ported from the BASIC source for 3D Tic Tac Toe # in BASIC Computer Games, by David H. Ahl # The code originated from Dartmouth College from enum import Enum +from typing import Optional, Tuple, Union class Move(Enum): @@ -31,8 +32,7 @@ class Player(Enum): class TicTacToe3D: """The game logic for 3D Tic Tac Toe and the machine opponent""" - def __init__(self): - + def __init__(self) -> None: # 4x4x4 board keeps track of which player occupies each place # and used by machine to work out its strategy self.board = [0] * 64 @@ -120,7 +120,7 @@ class TicTacToe3D: [12, 25, 38, 51], ] - def get(self, x, y, z): + def get(self, x, y, z) -> Player: m = self.board[4 * (4 * z + y) + x] if m == 40: return Player.MACHINE @@ -129,11 +129,11 @@ class TicTacToe3D: else: return Player.EMPTY - def move3D(self, x, y, z, player): + def move_3d(self, x, y, z, player) -> bool: m = 4 * (4 * z + y) + x return self.move(m, player) - def move(self, m, player): + def move(self, m, player) -> bool: if self.board[m] > 1: return False @@ -143,13 +143,13 @@ class TicTacToe3D: self.board[m] = 8 return True - def get3DPosition(self, m): + def get_3d_position(self, m) -> Tuple[int, int, int]: x = m % 4 y = (m // 4) % 4 z = m // 16 return x, y, z - def evaluateLines(self): + def evaluate_lines(self) -> None: self.lineValues = [0] * 76 for j in range(76): value = 0 @@ -157,18 +157,18 @@ class TicTacToe3D: value += self.board[self.lines[j][k]] self.lineValues[j] = value - def strategyMarkLine(self, i): + def strategy_mark_line(self, i) -> None: for j in range(4): m = self.lines[i][j] if self.board[m] == 0: self.board[m] = 1 - def clearStrategyMarks(self): + def clear_strategy_marks(self) -> None: for i in range(64): if self.board[i] == 1: self.board[i] = 0 - def markAndMove(self, vlow, vhigh, vmove): + def mark_and_move(self, vlow, vhigh, vmove) -> Optional[Tuple[Move, int]]: """ mark lines that can potentially win the game for the human or the machine and choose best place to play @@ -180,37 +180,37 @@ class TicTacToe3D: self.lineValues[i] = value if vlow <= value < vhigh: if value > vlow: - return self.moveTriple(i) - self.strategyMarkLine(i) - self.evaluateLines() + return self.move_triple(i) + self.strategy_mark_line(i) + self.evaluate_lines() for i in range(76): value = self.lineValues[i] if value == 4 or value == vmove: - return self.moveDiagonals(i, 1) + return self.move_diagonals(i, 1) return None - def machineMove(self): + def machine_move(self) -> Union[None, Tuple[Move, int], Tuple[Move, int, int]]: """machine works out what move to play""" - self.clearStrategyMarks() + self.clear_strategy_marks() - self.evaluateLines() + self.evaluate_lines() for value, event in [ - (32, self.humanWin), - (120, self.machineWin), - (24, self.blockHumanWin), + (32, self.human_win), + (120, self.machine_win), + (24, self.block_human_win), ]: for i in range(76): if self.lineValues[i] == value: return event(i) - m = self.markAndMove(80, 88, 43) + m = self.mark_and_move(80, 88, 43) if m is not None: return m - self.clearStrategyMarks() + self.clear_strategy_marks() - m = self.markAndMove(16, 24, 11) + m = self.mark_and_move(16, 24, 11) if m is not None: return m @@ -222,11 +222,11 @@ class TicTacToe3D: if (32 <= value < 40) or (72 <= value < 80): for s in [1, 0]: for i in range(4 * k, 4 * k + 4): - m = self.moveDiagonals(i, s) + m = self.move_diagonals(i, s) if m is not None: return m - self.clearStrategyMarks() + self.clear_strategy_marks() for y in self.corners: if self.board[y] == 0: @@ -238,24 +238,24 @@ class TicTacToe3D: return (Move.DRAW, -1) - def humanWin(self, i): + def human_win(self, i) -> Tuple[Move, int, int]: return (Move.HUMAN_WIN, -1, i) - def machineWin(self, i): + def machine_win(self, i) -> Optional[Tuple[Move, int, int]]: for j in range(4): m = self.lines[i][j] if self.board[m] == 0: return (Move.MACHINE_WIN, m, i) return None - def blockHumanWin(self, i): + def block_human_win(self, i) -> Optional[Tuple[Move, int]]: for j in range(4): m = self.lines[i][j] if self.board[m] == 0: return (Move.NICE_TRY, m) return None - def moveTriple(self, i): + def move_triple(self, i) -> Tuple[Move, int]: """make two lines-of-3 or prevent human from doing this""" for j in range(4): m = self.lines[i][j] @@ -267,7 +267,7 @@ class TicTacToe3D: return (Move.CONCEDES, -1) # choose move in corners or center boxes of square 4x4 - def moveDiagonals(self, i, s): + def move_diagonals(self, i, s) -> Optional[Tuple[Move, int]]: if 0 < (i % 4) < 3: jrange = [1, 2] else: @@ -280,15 +280,15 @@ class TicTacToe3D: class Qubit: - def moveCode(self, board, m): + def move_code(self, board, m) -> str: x, y, z = board.get3DPosition(m) return f"{z + 1:d}{y + 1:d}{x + 1:d}" - def showWin(self, board, i): + def show_win(self, board, i) -> None: for m in board.lines[i]: - print(self.moveCode(board, m)) + print(self.move_code(board, m)) - def showBoard(self, board): + def show_board(self, board) -> None: c = " YM" for z in range(4): for y in range(4): @@ -299,15 +299,15 @@ class Qubit: print("\n") print("\n") - def humanMove(self, board): - print("") + def human_move(self, board) -> bool: + print() c = "1234" while True: h = input("Your move?\n") if h == "1": return False if h == "0": - self.showBoard(board) + self.show_board(board) continue if (len(h) == 3) and (h[0] in c) and (h[1] in c) and (h[2] in c): x = c.find(h[2]) @@ -322,7 +322,7 @@ class Qubit: return True - def play(self): + def play(self) -> None: print("Qubic\n") print("Create Computing Morristown, New Jersey\n\n\n") while True: @@ -356,7 +356,7 @@ class Qubit: break print("Incorrect answer. Please type 'yes' or 'no'.") - skipHuman = s[0] in "nN" + skip_human = s[0] in "nN" move_text = [ "Machine moves to", @@ -368,22 +368,23 @@ class Qubit: ] while True: - if not skipHuman and not self.humanMove(board): + if not skip_human and not self.human_move(board): break - skipHuman = False + skip_human = False - m = board.machineMove() + m = board.machine_move() + assert m is not None if m[0] == Move.HUMAN_WIN: print("You win as follows,") - self.showWin(board, m[2]) + self.show_win(board, m[2]) # type: ignore break elif m[0] == Move.MACHINE_WIN: print( "Machine moves to {}, and wins as follows".format( - self.moveCode(board, m[1]) + self.move_code(board, m[1]) ) ) - self.showWin(board, m[2]) + self.show_win(board, m[2]) # type: ignore break elif m[0] == Move.DRAW: print("The game is a draw.") @@ -393,10 +394,10 @@ class Qubit: break else: print(move_text[m[0].value - Move.MOVES.value]) - print(self.moveCode(board, m[1])) + print(self.move_code(board, m[1])) board.move(m[1], Player.MACHINE) - self.showBoard(board) + self.show_board(board) print(" ") while True: diff --git a/89_Tic-Tac-Toe/python/TicTacToe_Hard.py b/89_Tic-Tac-Toe/python/TicTacToe_Hard.py index 400ec7f1..b5708d80 100644 --- a/89_Tic-Tac-Toe/python/TicTacToe_Hard.py +++ b/89_Tic-Tac-Toe/python/TicTacToe_Hard.py @@ -1,15 +1,18 @@ +from typing import List, Tuple, Union + + class TicTacToe: - def __init__(self, pick, sz=3): + def __init__(self, pick, sz=3) -> None: self.pick = pick self.dim_sz = sz self.board = self.clear_board() - def clear_board(self): + def clear_board(self) -> List[List[str]]: board = [["blur" for i in range(self.dim_sz)] for j in range(self.dim_sz)] # made a 3x3 by-default board return board - def move_record(self, r, c): + def move_record(self, r, c) -> Union[str, bool]: if r > self.dim_sz or c > self.dim_sz: return "Out of Bounds" if self.board[r][c] != "blur": @@ -17,7 +20,7 @@ class TicTacToe: self.board[r][c] = self.pick return True - def check_win(self): # 1 you won, 0 computer won, -1 tie + def check_win(self) -> int: # 1 you won, 0 computer won, -1 tie # Flag syntax -> first player no. , # User is Player#1 ; # Check set 1 -> row and '\' diagonal & Check set 2 -> col and '/' diagonal @@ -88,7 +91,7 @@ class TicTacToe: return -1 - def next_move(self): + def next_move(self) -> Union[Tuple[int, int], Tuple[List[int], List[int]]]: available_moves = [] # will carry all available moves player_win_spot = [] # if player (user Wins) comp_pick = "O" @@ -113,7 +116,6 @@ class TicTacToe: if len(player_win_spot) != 0: self.board[player_win_spot[0][0]][player_win_spot[0][1]] = comp_pick return player_win_spot[0][0], player_win_spot[0][1] - # print(AvailableMoves) if len(available_moves) == 1: self.board[available_moves[0][0]][available_moves[0][1]] = comp_pick return [available_moves[0][0]], [available_moves[0][1]] @@ -121,7 +123,6 @@ class TicTacToe: return -1, -1 c1, c2 = self.dim_sz // 2, self.dim_sz // 2 - # print(c1,c2,self.dim_sz) if (c1, c2) in available_moves: # CENTER self.board[c1][c2] = comp_pick return c1, c2 @@ -163,34 +164,33 @@ class TicTacToe: ) in available_moves: # RIGHT TOP TO RIGHT BOTTOM self.board[c1 - gap + i][c2 + gap] = comp_pick return c1 - gap + i, c2 + gap + raise RuntimeError("No moves available") -def display(Game: TicTacToe) -> None: +def display(game: TicTacToe) -> None: line1 = "" - for i in range(0, Game.dim_sz): - for j in range(0, Game.dim_sz - 1): - if Game.board[i][j] == "blur": + for i in range(0, game.dim_sz): + for j in range(0, game.dim_sz - 1): + if game.board[i][j] == "blur": line1 = line1 + " |" else: - line1 = line1 + " " + Game.board[i][j] + " |" - if Game.board[i][Game.dim_sz - 1] == "blur": + line1 = line1 + " " + game.board[i][j] + " |" + if game.board[i][game.dim_sz - 1] == "blur": line1 = line1 + " \n" else: - line1 = line1 + " " + Game.board[i][Game.dim_sz - 1] + " \n" - # line1 = line1 + " " + Game.board[i][Game.dim_sz-1] + "\n" + line1 = line1 + " " + game.board[i][game.dim_sz - 1] + " \n" print(line1, "\n\n") -def play() -> None: - Pick = input("Pick 'X' or 'O' ").strip().upper() - if Pick == "O": - Game = TicTacToe("O") +def main() -> None: + pick = input("Pick 'X' or 'O' ").strip().upper() + if pick == "O": + game = TicTacToe("O") else: - Game = TicTacToe("X") - display(Game=Game) + game = TicTacToe("X") + display(game=game) while True: - # Display(Game) - temp = False + temp: Union[bool, str] = False while not temp: move = list( map( @@ -198,25 +198,25 @@ def play() -> None: input("Make A Move in Grid System from (0,0) to (2,2) ").split(), ) ) - temp = Game.move_record(move[0], move[1]) + temp = game.move_record(move[0], move[1]) if not temp: print(temp) - if Game.check_win() == 1: + if game.check_win() == 1: print("You Won!") break print("Your Move:- ") - display(Game) - C1, C2 = Game.next_move() + display(game) + C1, C2 = game.next_move() if C1 == -1 and C2 == -1: print("Game Tie!") break - if Game.check_win() == 0: + if game.check_win() == 0: print("You lost!") break print("Computer's Move :-") - display(Game) + display(game) if __name__ == "__main__": - play() + main() diff --git a/89_Tic-Tac-Toe/python/tictactoe2.py b/89_Tic-Tac-Toe/python/tictactoe2.py index 519cd7d3..210ff2e7 100755 --- a/89_Tic-Tac-Toe/python/tictactoe2.py +++ b/89_Tic-Tac-Toe/python/tictactoe2.py @@ -191,7 +191,7 @@ def prompt_player(board): return move -def play(): +def main() -> None: print(" " * 30 + "TIC-TAC-TOE") print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") print("\n\n") @@ -247,4 +247,4 @@ def play(): if __name__ == "__main__": - play() + main() diff --git a/90_Tower/python/tower.py b/90_Tower/python/tower.py index 982f8bb3..7d30c9eb 100644 --- a/90_Tower/python/tower.py +++ b/90_Tower/python/tower.py @@ -1,11 +1,12 @@ import sys +from typing import List, Optional class Disk: - def __init__(self, size): + def __init__(self, size: int) -> None: self.__size = size - def size(self): + def size(self) -> int: return self.__size def print(self) -> None: @@ -13,28 +14,29 @@ class Disk: class Tower: - def __init__(self): - self.__disks = [] + def __init__(self) -> None: + self.__disks: List[Disk] = [] - def empty(self): + def empty(self) -> bool: return len(self.__disks) == 0 - def top(self): + def top(self) -> Optional[Disk]: if self.empty(): return None else: return self.__disks[-1] - def add(self, disk): + def add(self, disk: Disk) -> None: if not self.empty(): t = self.top() + assert t is not None # cannot happen as it's not empty if disk.size() > t.size(): raise Exception( "YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE, IT MIGHT CRUSH IT!" ) self.__disks.append(disk) - def pop(self): + def pop(self) -> Disk: if self.empty(): raise Exception("empty pop") return self.__disks.pop() @@ -45,7 +47,7 @@ class Tower: class Game: - def __init__(self): + def __init__(self) -> None: # use fewer sizes to make debugging easier # self.__sizes = [3, 5, 7] # ,9,11,13,15] self.__sizes = [3, 5, 7, 9, 11, 13, 15] @@ -60,23 +62,23 @@ class Game: disk = Disk(size) self.__towers[0].add(disk) - def winner(self): + def winner(self) -> bool: return self.__towers[0].empty() and self.__towers[1].empty() def print(self) -> None: for t in self.__towers: t.print() - def moves(self): + def moves(self) -> int: return self.__moves - def which_disk(self): + def which_disk(self) -> int: w = int(input("WHICH DISK WOULD YOU LIKE TO MOVE\n")) if w in self.__sizes: return w raise Exception() - def pick_disk(self): + def pick_disk(self) -> Optional[Tower]: which = None while which is None: try: @@ -93,7 +95,7 @@ class Game: assert valids[0].top().size() == which return valids[0] - def which_tower(self): + def which_tower(self) -> Optional[Tower]: try: needle = int(input("PLACE DISK ON WHICH NEEDLE\n")) tower = self.__towers[needle - 1] @@ -105,7 +107,7 @@ class Game: else: return tower - def take_turn(self): + def take_turn(self) -> None: from_tower = None while from_tower is None: from_tower = self.pick_disk() diff --git a/91_Train/python/train.py b/91_Train/python/train.py index d7ac55d8..2affcc0a 100644 --- a/91_Train/python/train.py +++ b/91_Train/python/train.py @@ -6,14 +6,14 @@ import random -def play_game(): +def play_game() -> None: """Play one round of the game""" car_speed = random.randint(40, 65) time_difference = random.randint(5, 20) train_speed = random.randint(20, 39) print("\nA car travelling", car_speed, "MPH can make a certain trip in") print(time_difference, "hours less than a train travelling at", train_speed, "MPH") - time_answer = 0 + time_answer: float = 0 while time_answer == 0: try: time_answer = float(input("How long does the trip take by car ")) diff --git a/92_Trap/python/trap.py b/92_Trap/python/trap.py index 5f74a760..64220234 100644 --- a/92_Trap/python/trap.py +++ b/92_Trap/python/trap.py @@ -10,7 +10,7 @@ number_max = 100 guess_max = 6 -def play_game(): +def play_game() -> None: """Play one round of the game""" number_computer = random.randint(1, number_max) diff --git a/93_23_Matches/python/23matches.py b/93_23_Matches/python/23matches.py index 5488f08b..5375a176 100755 --- a/93_23_Matches/python/23matches.py +++ b/93_23_Matches/python/23matches.py @@ -6,7 +6,7 @@ import random -def play_game(): +def play_game() -> None: """Play one round of the game""" matches = 23 diff --git a/94_War/python/cards.json b/94_War/python/cards.json new file mode 100644 index 00000000..b27e9bd4 --- /dev/null +++ b/94_War/python/cards.json @@ -0,0 +1,54 @@ +[ + "S-2", + "H-2", + "C-2", + "D-2", + "S-3", + "H-3", + "C-3", + "D-3", + "S-4", + "H-4", + "C-4", + "D-4", + "S-5", + "H-5", + "C-5", + "D-5", + "S-6", + "H-6", + "C-6", + "D-6", + "S-7", + "H-7", + "C-7", + "D-7", + "S-8", + "H-8", + "C-8", + "D-8", + "S-9", + "H-9", + "C-9", + "D-9", + "S-10", + "H-10", + "C-10", + "D-10", + "S-J", + "H-J", + "C-J", + "D-J", + "S-Q", + "H-Q", + "C-Q", + "D-Q", + "S-K", + "H-K", + "C-K", + "D-K", + "S-A", + "H-A", + "C-A", + "D-A" +] diff --git a/94_War/python/war.py b/94_War/python/war.py index f8d34004..48137c38 100755 --- a/94_War/python/war.py +++ b/94_War/python/war.py @@ -1,75 +1,27 @@ #!/usr/bin/env python3 -# WAR -# -# Converted from BASIC to Python by Trevor Hobson +""" +WAR + +Converted from BASIC to Python by Trevor Hobson +""" + +import json import random +from pathlib import Path +from typing import List -def card_value(input): +def card_value(input: str) -> int: return ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"].index( input.split("-")[1] ) -cards = [ - "S-2", - "H-2", - "C-2", - "D-2", - "S-3", - "H-3", - "C-3", - "D-3", - "S-4", - "H-4", - "C-4", - "D-4", - "S-5", - "H-5", - "C-5", - "D-5", - "S-6", - "H-6", - "C-6", - "D-6", - "S-7", - "H-7", - "C-7", - "D-7", - "S-8", - "H-8", - "C-8", - "D-8", - "S-9", - "H-9", - "C-9", - "D-9", - "S-10", - "H-10", - "C-10", - "D-10", - "S-J", - "H-J", - "C-J", - "D-J", - "S-Q", - "H-Q", - "C-Q", - "D-Q", - "S-K", - "H-K", - "C-K", - "D-K", - "S-A", - "H-A", - "C-A", - "D-A", -] - - -def play_game(): +def play_game() -> None: """Play one round of the game""" + with open(Path(__file__).parent / "cards.json") as f: + cards: List[str] = json.load(f) random.shuffle(cards) score_you = 0 diff --git a/95_Weekday/python/weekday.py b/95_Weekday/python/weekday.py index 6da78bb2..15cdae44 100644 --- a/95_Weekday/python/weekday.py +++ b/95_Weekday/python/weekday.py @@ -12,35 +12,28 @@ Ported by Dave LeCompte. """ import datetime +from typing import Tuple GET_TODAY_FROM_SYSTEM = True -def print_with_tab(space_count: int, s: str) -> None: - if space_count > 0: - spaces = " " * space_count - else: - spaces = "" - print(spaces + s) - - -def get_date_from_user(prompt): +def get_date_from_user(prompt: str) -> Tuple[int, int, int]: while True: print(prompt) date_str = input() try: month_num, day_num, year_num = (int(x) for x in date_str.split(",")) + return month_num, day_num, year_num except Exception: print("I COULDN'T UNDERSTAND THAT. TRY AGAIN.") - return month_num, day_num, year_num -def get_date_from_system(): +def get_date_from_system() -> Tuple[int, int, int]: dt = datetime.datetime.today() return dt.month, dt.day, dt.year -def get_day_of_week(weekday_index, day): +def get_day_of_week(weekday_index, day) -> str: day_names = { 1: "SUNDAY", 2: "MONDAY", @@ -56,13 +49,13 @@ def get_day_of_week(weekday_index, day): return day_names[weekday_index] -def previous_day(b): +def previous_day(b) -> int: if b == 0: b = 6 return b - 1 -def is_leap_year(year): +def is_leap_year(year: int) -> bool: if (year % 4) != 0: return False if (year % 100) != 0: @@ -113,7 +106,7 @@ def deduct_time(frac, days, years_remain, months_remain, days_remain): def time_report(msg, years, months, days): leading_spaces = 23 - len(msg) - print_with_tab(leading_spaces, msg + f"\t{years}\t{months}\t{days}") + print(" " * leading_spaces + f"{msg}\t{years}\t{months}\t{days}") def make_occupation_label(years): @@ -141,17 +134,14 @@ def calculate_day_of_week(year, month, day): return b -def end(): +def end() -> None: for _ in range(5): print() def main() -> None: - print_with_tab(32, "WEEKDAY") - print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY") - print() - print() - print() + print(" " * 32 + "WEEKDAY") + print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n") print("WEEKDAY IS A COMPUTER DEMONSTRATION THAT") print("GIVES FACTS ABOUT A DATE OF INTEREST TO YOU.") print() @@ -226,8 +216,8 @@ def main() -> None: print("***HAPPY BIRTHDAY***") # print report - print_with_tab(23, "\tYEARS\tMONTHS\tDAYS") - print_with_tab(23, "\t-----\t------\t----") + print(" " * 23 + "\tYEARS\tMONTHS\tDAYS") + print(" " * 23 + "\t-----\t------\t----") print(f"YOUR AGE (IF BIRTHDATE)\t{el_years}\t{el_months}\t{el_days}") life_days = (el_years * 365) + (el_months * 30) + el_days + int(el_months / 2) @@ -255,11 +245,9 @@ def main() -> None: # Calculate retirement date e = year + 65 - print_with_tab(16, f"*** YOU MAY RETIRE IN {e} ***") + print(" " * 16 + f"*** YOU MAY RETIRE IN {e} ***") end() if __name__ == "__main__": main() - - # test_harness() diff --git a/96_Word/python/word.py b/96_Word/python/word.py old mode 100644 new mode 100755 index fcb3fc11..8b7f0d51 --- a/96_Word/python/word.py +++ b/96_Word/python/word.py @@ -1,7 +1,10 @@ #!/usr/bin/env python3 -# WORD -# -# Converted from BASIC to Python by Trevor Hobson + +""" +WORD + +Converted from BASIC to Python by Trevor Hobson +""" import random @@ -21,7 +24,7 @@ words = [ ] -def play_game(): +def play_game() -> None: """Play one round of the game""" random.shuffle(words) @@ -54,16 +57,15 @@ def play_game(): if i == j: guess_progress[j] = guess_word[i] print( - "There were", - matches, - "matches and the common letters were... " + common_letters, + f"There were {matches}", + f"matches and the common letters were... {common_letters}", ) print( "From the exact letter matches, you know............ " + "".join(guess_progress) ) if "".join(guess_progress) == guess_word: - print("\nYou have guessed the word. It took", guess_count, "guesses!") + print(f"\nYou have guessed the word. It took {guess_count} guesses!") break elif matches == 0: print("\nIf you give up, type '?' for you next guess.")