Use docstrings

This commit is contained in:
Martin Thoma
2022-04-02 07:58:37 +02:00
parent c500424956
commit 4b3b991273
12 changed files with 268 additions and 323 deletions

View File

@@ -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()

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -6,7 +6,7 @@ from random import random
def direction(A, B, X, Y) -> None:
"""Prints the direction hint for finding the hurkle."""
"""Print the direction hint for finding the hurkle."""
print("GO ", end="")
if Y < B:

View File

@@ -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

View File

@@ -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):
@@ -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:")

View File

@@ -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)

View File

@@ -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

View File

@@ -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,20 +205,13 @@ 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):
@@ -243,27 +228,31 @@ def print_board(board) -> None:
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()
@@ -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