This commit is contained in:
jwbruce
2022-04-07 12:54:56 -05:00
120 changed files with 13316 additions and 3497 deletions
@@ -0,0 +1,72 @@
:root {
--terminal-font: 1rem "Lucida Console", "Courier New", monospace;
--background-color: transparent;
--text-color: var(--text);
--prompt-char: '$ ';
--cursor-char: '_';
}
/* Basic terminal style.
* If you wan t to overwrite them use custom properties (variables).
*/
.terminal {
display: block;
font: var(--terminal-font);
background-color: var(--background-color);
color: var(--text-color);
overflow-y: scroll;
width: 100%;
max-width: 60rem;
margin: 0 auto;
}
/* The terminal consits of multiple "line" elements
* Because sometimes we want to add a simulates "prompt" at the end of a line
* we need to make it an "inline" element and handle line-breaks
* by adding <br> elements */
.terminal pre.line {
display: inline-block;
font: var(--terminal-font);
margin: 0;
padding: 0;
}
/* The "terminal" has one "prompt" element.
* This prompt is not any kind of input, but just a simple <span>
* with an id "prompt" and a
*/
@keyframes prompt-blink {
100% {
opacity: 0;
}
}
.terminal #prompt {
display: inline-block;
}
.terminal #prompt:before {
display: inline-block;
content: var(--prompt-char);
font: var(--terminal-font);
}
.terminal #prompt:after {
display: inline-block;
content: var(--cursor-char);
background: var(--text);
animation: prompt-blink 1s steps(2) infinite;
width: 0.75rem;
opacity: 1;
}
/* Terminal scrollbar */
::-webkit-scrollbar {
width: 3px;
height: 3px;
}
::-webkit-scrollbar-track {
background: var(--background-color);
}
::-webkit-scrollbar-thumb {
background: var(--text-color);
}
@@ -0,0 +1,195 @@
/**
* @class HtmlTerminal
*
* This class is a very basic implementation of a "terminal" in the browser.
* It provides simple functions like "write" and an "input" Callback.
*
* @license AGPL-2.0
* @author Alexaner Wunschik <https://github.com/mojoaxel>
*/
class HtmlTerminal {
/**
* Input callback.
* If the prompt is activated by calling the input function
* a callback is defined. If this member is not set this means
* the prompt is not active.
*
* @private
* @type {function}
*/
#inputCallback = undefined;
/**
* A html element to show a "prompt".
*
* @private
* @type {HTMLElement}
*/
#$prompt = undefined;
/**
* Constructor
* Creates a basic terminal simulation on the provided HTMLElement.
*
* @param {HTMLElement} $output - a dom element
*/
constructor($output) {
// Store the output DOM element in a local variable.
this.$output = $output;
// Clear terminal.
this.clear();
// Add the call "terminal" to the $output element.
this.$output.classList.add('terminal');
// Create a prompt element.
// This element gets added if input is needed
this.#$prompt = document.createElement("span");
this.#$prompt.setAttribute("id", "prompt");
this.#$prompt.innerText = "";
//TODO: this handler shouls be only on the propt element and only active if cursor is visible
document.addEventListener("keyup", this.#handleKey.bind(this));
}
/**
* Creates a new HTMLElement with the given text content.
* This element than gets added to the $output as a new "line".
*
* @private
* @memberof MinimalTerminal
* @param {String} text - text that should be displayed in the new "line".
* @returns {HTMLElement} return a new DOM Element <pre class="line"></pre>
*/
#newLine(text) {
const $lineNode = document.createElement("pre");
$lineNode.classList.add("line");
$lineNode.innerText = text;
return $lineNode;
}
/**
* TODO
*
* @private
* @param {*} e
*/
#handleKey(e) {
// if no input-callback is defined
if (!this.#inputCallback) {
return;
}
if (e.keyCode === 13 /* ENTER */) {
// create a new line with the text input and remove the prompt
const text = this.#$prompt.innerText;
this.write(text + "\n");
this.#$prompt.innerText = "";
this.#$prompt.remove();
// return the inputed text
this.#inputCallback(text);
// remove the callback and the key handler
this.#inputCallback = undefined;
} else if (e.keyCode === 8 /* BACKSPACE */) {
this.#$prompt.innerText = this.#$prompt.innerText.slice(0, -1);
} else if (
e.keyCode == 16 // "Shift"
|| e.keyCode == 17 // "Control"
|| e.keyCode == 20 // "CapsLock"
|| !e.key.match(/^[a-z0-9!"§#$%&'()*+,.\/:;<=>?@\[\] ^_`{|}~-]$/i)
) {
// ignore non-visible characters
return e;
} else {
this.#$prompt.innerHtml = '';
const key = e.shiftKey ? e.key.toUpperCase() : e.key;
this.#$prompt.innerText = this.#$prompt.innerText + key;
}
}
/**
* Clear the terminal.
* Remove all lines.
*
* @public
*/
clear() {
this.$output.innerText = "";
}
/**
* TODO:
*
* @public
* @param {*} htmlContent
*/
inserHtml(htmlContent) {
const $htmlNode = document.createElement("div");
$htmlNode.innerHTML = htmlContent;
this.$output.appendChild($htmlNode);
document.body.scrollTo(0, document.body.scrollHeight);
}
/**
* Write a text to the terminal.
* By default there is no linebreak at the end of a new line
* except the line ensd with a "\n".
* If the given text has multible linebreaks, multibe lines are inserted.
*
* @public
* @param {string} text
*/
write(text) {
if (!text || text.length <= 0) {
// empty line
this.$output.appendChild(document.createElement("br"));
} else if (text.endsWith("\n")) {
// single line with linebrank
const $lineNode = this.#newLine(text);
this.$output.appendChild(this.#newLine(text));
this.$output.appendChild(document.createElement("br"));
} else if (text.includes("\n")) {
// multible lines
const lines = text.split("\n");
lines.forEach((line) => {
this.write(line);
});
} else {
// single line
this.$output.appendChild(this.#newLine(text));
}
// scroll to the buttom of the page
document.body.scrollTo(0, document.body.scrollHeight);
}
/**
* Like "write" but with a newline at the end.
*
* @public
* @param {*} text
*/
writeln(text) {
this.write(text + "\n");
}
/**
* Query from user input.
* This is done by adding a input-element at the end of the terminal,
* that showes a prompt and a blinking cursor.
* If a key is pressed the input is added to the prompt element.
* The input ends with a linebreak.
*
* @public
* @param {*} callback
*/
input(callback) {
// show prompt with a blinking prompt
this.$output.appendChild(this.#$prompt);
this.#inputCallback = callback;
}
}
@@ -0,0 +1,129 @@
<html>
<head>
<title>Minimal node.js terminal</title>
<meta name="viewport" content="width=device-width, initial-scale=.75">
<link
rel="stylesheet"
href="../../../00_Utilities/javascript/style_terminal.css"
/>
<link rel="stylesheet" href="HtmlTerminal.css" />
<style>
header {
position: sticky;
top: 0;
left: 0;
right: 0;
border-bottom: 1px solid var(--text);
padding: 0.25rem 0.5rem;
margin: 0;
margin-bottom: 1rem;
background: black;
display: flex;
justify-content: space-between;
}
header h1 {
font-size: small;
color: var(--text),
}
header div {
font-size: small;
}
</style>
</head>
<body>
<header>
<h1><a href="../../../">BASIC Computer Games</a></h1>
</header>
<main id="output"></main>
<script src="HtmlTerminal.js" type="text/javascript"></script>
<script>
const $output = document.getElementById("output");
const term = new HtmlTerminal($output);
function getGameScriptFromHash() {
const hash = window.location.hash;
// if no game-script was provided redirect to the overview.
if (!hash) {
// show error message and link back to the index.html
console.debug("[HtmlTerminal] No game script found!");
term.writeln(`no game script found :-(\n`);
term.inserHtml(`<a href="/">>> Back to game overview!</a>`);
return;
}
// remove the hash
const gameFile = hash.replace("#", "");
return gameFile;
}
function addGitHubLink(gameFile) {
const gameFolder = gameFile.split("/")[0];
$gitHubLink = document.createElement("a");
$gitHubLink.href = `https://github.com/coding-horror/basic-computer-games/tree/main/${gameFolder}`;
$gitHubLink.innerText = `show source-code`;
var $gitHubBanner = document.createElement("div");
$gitHubBanner.classList.add("githublink");
$gitHubBanner.appendChild($gitHubLink);
const $header = document.getElementsByTagName('header')[0];
$header.append($gitHubBanner);
}
function loadGameScript(gameFile) {
// clear terminal
term.clear();
// load game-script
console.debug("[HtmlTerminal] Game script found: ", gameFile);
const gameScript = `../../../${gameFile}`;
var $scriptTag = document.createElement("script");
$scriptTag.async = "async";
$scriptTag.type = "module";
$scriptTag.src = gameScript;
$scriptTag.onerror = () => {
term.clear();
term.writeln(`Error loading game-script "${gameFile}" :-(\n`);
term.inserHtml(`<a href="/">>> Back to game overview!</a>`);
};
$scriptTag.addEventListener("load", function () {
console.log("[HtmlTerminal] Game script loaded!");
});
document.body.append($scriptTag);
}
/**
* Determine how much chars will fit in each terminal line.
*/
function getOutputColumns($element) {
const fontWidth = 10; //TODO: this width could be measured but it may be complicated!
const columnWidth = Math.trunc($element.clientWidth / fontWidth);
console.warn(`[terminal] document.body.clientWidth:${$element.clientWidth} fontsize:${fontWidth} columnWidth:${columnWidth}`);
return columnWidth;
}
/* Redirect stdin/stdout to the HtmlTerminal.
* This is VERY hacky and should never be done in a serious project!
* We can use this here because we know what we are doing and...
* ...it's just simple games ;-) */
window.process = {
stdout: {
write: (t) => term.write(t),
columns: getOutputColumns($output)
},
stdin: {
on: (event, callback) => term.input(callback),
},
exit: (code) => {},
};
// let's play 🚀
const gameFile = getGameScriptFromHash();
addGitHubLink(gameFile);
loadGameScript(gameFile);
</script>
</body>
</html>
@@ -0,0 +1,30 @@
#!/usr/bin/env node
import { print, println, tab, input } from '../common.mjs';
async function main() {
println(tab(30), "Minimal node.js terminal emulator");
println();
println(tab(0), "tab 0");
println(tab(5), "tab 5");
println(tab(10), "tab 10");
println(tab(15), "tab 15");
println(tab(20), "tab 20");
println(tab(25), "tab 25");
println();
println("1234567890", " _ ", "ABCDEFGHIJKLMNOPRSTUVWXYZ");
println();
print("\nHallo"); print(" "); print("Welt!\n");
println("");
println("Line 1\nLine 2\nLine 3\nLine 4");
println("----------------------------------------------");
const value = await input("input");
println(`input value was "${value}"`);
println("End of script");
// 320 END
process.exit(0);
}
main();
+67
View File
@@ -0,0 +1,67 @@
/**
* Print multible strings to the terminal.
* Strings get concatinated (add together) without any space betweent them.
* There will be no newline at the end!
* If you want a linebrak at the end use `println`.
*
* This function is normally used if you want to put something on the screen
* and later add some content to the same line.
* For normal output (similar to `console.log`) use `println`!
*
* @param {...string} messages - the strings to print to the terminal.
*/
export function print(...messages) {
process.stdout.write(messages.join(""));
}
/**
* Add multible strings as a new line to the terminal.
* Strings get concatinated (add together) without any space betweent them.
* There will be a newline at the end!
* If you want the terminal to stay active on the current line use `print`.
*
* @param {...any} messages - the strings to print to the terminal.
*/
export function println(...messages) {
process.stdout.write(messages.join("") + "\n");
}
/**
* Create an empty string with a given length
*
* @param {number} length - the length of the string in space-characters.
* @returns {string} returns a string containing only ampty spaces with a length of `count`.
*/
export function tab(length) {
return " ".repeat(length);
}
/**
* Read input from the keyboard and return it as a string.
* TODO: to would be very helpfull to only allow a certain class of input (numbers, letters)
* TODO: also we could convert all inputs to uppercase (where it makes sence).
*
* @param {string=''} message - a message or question to print befor the input.
* @returns {Promise<string>} - returns the entered text as a string
* @async
*/
export async function input(message = '') {
/* First we need to print the mesage
* We append a space by default to seperate the message from the imput.
* TODO: If the message already contains a space at the end this is not needed! */
process.stdout.write(message + ' ');
return new Promise(resolve => {
process.stdin.on('data', (input) => {
/* onData returns a Buffer.
* First we need to convert it into a string. */
const data = input.toString();
/* The result fo onData is a string ending with an `\n`.
* We just need the actual content so let's remove the newline at the end: */
const content = data[data.length] === '\n' ? data.slice(0, -1) : data;
resolve(content);
});
});
}
+5 -5
View File
@@ -10,7 +10,7 @@
07_Basketball | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️
08_Batnum | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅
09_Battle | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
10_Blackjack | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ✅ | ⬜️
10_Blackjack | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | | ✅ | ⬜️
11_Bombardment | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
12_Bombs_Away | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
13_Bounce | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️
@@ -47,13 +47,13 @@
44_Hangman | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
45_Hello | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
46_Hexapawn | ✅ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
47_Hi-Lo | ✅ | ✅ | ✅ | ✅ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
47_Hi-Lo | ✅ | ✅ | ✅ | ✅ | ⬜️ | ✅ | ✅ | ✅ | | ⬜️
48_High_IQ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
49_Hockey | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️
50_Horserace | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
51_Hurkle | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
52_Kinema | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
53_King | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️
53_King | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | | ⬜️ | ⬜️ | ⬜️
54_Letter | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
55_Life | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
56_Life_for_Two | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️ | ⬜️
@@ -64,7 +64,7 @@
61_Math_Dice | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ✅ | ⬜️
62_Mugwump | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
63_Name | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
64_Nicomachus | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
64_Nicomachus | | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
65_Nim | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️
66_Number | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ✅ | ⬜️
67_One_Check | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
@@ -82,7 +82,7 @@
79_Slalom | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
80_Slots | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
81_Splat | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
82_Stars | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️
82_Stars | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ✅ | ✅ | ⬜️ | | ⬜️
83_Stock_Market | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
84_Super_Star_Trek | ✅ | ✅ | ✅ | ⬜️ | ⬜️ | ⬜️ | ✅ | ⬜️ | ⬜️ | ⬜️
85_Synonym | ✅ | ✅ | ✅ | ✅ | ⬜️ | ✅ | ✅ | ✅ | ⬜️ | ⬜️
+33 -15
View File
@@ -14,16 +14,29 @@ const path = require('path');
const TITLE = 'BASIC Computer Games';
const JAVASCRIPT_FOLDER = 'javascript';
const IGNORE_FOLDERS_START_WITH = ['.', '00_', 'buildJvm', 'Sudoku'];
const IGNORE_FILES = [
// "84 Super Star Trek" has it's own node/js implementation (using xterm)
'cli.mjs', 'superstartrek.mjs'
];
function createGameLinks(game) {
if (game.htmlFiles.length > 1) {
const entries = game.htmlFiles.map(htmlFile => {
const name = path.basename(htmlFile).replace('.html', '');
const creatFileLink = (file, name = path.basename(file)) => {
if (file.endsWith('.html')) {
return `
<li>
<a href="${htmlFile}">${name}</a>
</li>
<li><a href="${file}">${name.replace('.html', '')}</a></li>
`;
} else if (file.endsWith('.mjs')) {
return `
<li><a href="./00_Common/javascript/WebTerminal/terminal.html#${file}">${name.replace('.mjs', '')} (node.js)</a></li>
`;
} else {
throw new Error(`Unknown file-type found: ${file}`);
}
}
if (game.files.length > 1) {
const entries = game.files.map(file => {
return creatFileLink(file);
});
return `
<li>
@@ -32,7 +45,7 @@ function createGameLinks(game) {
</li>
`;
} else {
return `<li><a href="${game.htmlFiles}">${game.name}</a></li>`;
return creatFileLink(game.files[0], game.name);
}
}
@@ -73,11 +86,11 @@ function createIndexHtml(title, games) {
`.trim().replace(/\s\s+/g, '');
}
function findHtmlFilesInFolder(folder) {
function findJSFilesInFolder(folder) {
// filter folders that do not include a subfolder called "javascript"
const hasJavascript = fs.existsSync(`${folder}/${JAVASCRIPT_FOLDER}`);
if (!hasJavascript) {
throw new Error(`Game "${folder}" is missing a javascript implementation`);
throw new Error(`Game "${folder}" is missing a javascript folder`);
}
// get all files in the javascript folder
@@ -85,12 +98,17 @@ function findHtmlFilesInFolder(folder) {
// filter files only allow .html files
const htmlFiles = files.filter(file => file.endsWith('.html'));
const mjsFiles = files.filter(file => file.endsWith('.mjs'));
const entries = [
...htmlFiles,
...mjsFiles
].filter(file => !IGNORE_FILES.includes(file));
if (htmlFiles.length == 0) {
throw new Error(`Game "${folder}" is missing a html file in the "${folder}/${JAVASCRIPT_FOLDER}" folder`);
if (entries.length == 0) {
throw new Error(`Game "${folder}" is missing a HTML or node.js file in the folder "${folder}/${JAVASCRIPT_FOLDER}"`);
}
return htmlFiles.map(htmlFile => path.join(folder, JAVASCRIPT_FOLDER, htmlFile));
return entries.map(file => path.join(folder, JAVASCRIPT_FOLDER, file));
}
function main() {
@@ -111,10 +129,10 @@ function main() {
// get name and javascript file from folder
const games = folders.map(folder => {
const name = folder.replace('_', ' ');
let htmlFiles;
let files;
try {
htmlFiles = findHtmlFilesInFolder(folder);
files = findJSFilesInFolder(folder);
} catch (error) {
console.warn(`Game "${name}" is missing a javascript implementation: ${error.message}`);
return null;
@@ -122,7 +140,7 @@ function main() {
return {
name,
htmlFiles
files
}
}).filter(game => game !== null);
+9 -2
View File
@@ -31,7 +31,11 @@ body {
background-color: var(--background);
color: var(--text);
font: var(--font);
padding: 3rem;
margin: 0;
}
#output {
padding: 1rem;
}
/* format input fields */
@@ -80,7 +84,10 @@ a:hover {
}
/* add all the face flicker effects (only on desktop) */
@media screen and (min-width: 640px) {
@media screen and (min-width: 960px) {
main {
padding: 3rem;
}
@keyframes flicker {
0% {
opacity: 0.27861;
+9 -11
View File
@@ -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()
+5 -6
View File
@@ -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)
@@ -115,7 +114,7 @@ def game_loop() -> None:
game_over = True
def main():
def main() -> None:
print(
"""
Acey Ducey is a card game where you play against the computer.
+7 -14
View File
@@ -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:
+2 -2
View File
@@ -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
+2 -12
View File
@@ -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
+1 -2
View File
@@ -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)? ")
+6 -6
View File
@@ -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
+7 -7
View File
@@ -6,10 +6,10 @@ You are able to choose your shot types as well as defensive formations
"""
import random
from typing import Optional, List, Literal
from typing import List, Literal, Optional
def explain_keyboard_inputs():
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")
+10 -10
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()
@@ -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
+5 -8
View File
@@ -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
+6 -7
View File
@@ -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()
+1 -1
View File
@@ -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] = []
+2 -2
View File
@@ -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()
+4 -10
View File
@@ -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")
+5 -11
View File
@@ -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)
@@ -112,10 +106,10 @@ def print_intro() -> None:
def ask_bool(prompt: str) -> bool:
while True:
answer = input(prompt)
if answer == "YES":
answer = input(prompt).lower()
if answer == "yes":
return True
elif answer == "NO":
elif answer == "no":
return False
else:
print("INCORRECT ANSWER - - PLEASE TYPE 'YES' OR 'NO'.")
+11 -248
View File
@@ -1,258 +1,21 @@
#!/usr/bin/env python3
import json
# This data is meant to be read-only, so we are storing it in a tuple
DATA = (
2,
21,
14,
14,
25,
1,
2,
-1,
0,
2,
45,
50,
-1,
0,
5,
43,
52,
-1,
0,
7,
41,
52,
-1,
1,
9,
37,
50,
-1,
2,
11,
36,
50,
-1,
3,
13,
34,
49,
-1,
4,
14,
32,
48,
-1,
5,
15,
31,
47,
-1,
6,
16,
30,
45,
-1,
7,
17,
29,
44,
-1,
8,
19,
28,
43,
-1,
9,
20,
27,
41,
-1,
10,
21,
26,
40,
-1,
11,
22,
25,
38,
-1,
12,
22,
24,
36,
-1,
13,
34,
-1,
14,
33,
-1,
15,
31,
-1,
17,
29,
-1,
18,
27,
-1,
19,
26,
-1,
16,
28,
-1,
13,
30,
-1,
11,
31,
-1,
10,
32,
-1,
8,
33,
-1,
7,
34,
-1,
6,
13,
16,
34,
-1,
5,
12,
16,
35,
-1,
4,
12,
16,
35,
-1,
3,
12,
15,
35,
-1,
2,
35,
-1,
1,
35,
-1,
2,
34,
-1,
3,
34,
-1,
4,
33,
-1,
6,
33,
-1,
10,
32,
34,
34,
-1,
14,
17,
19,
25,
28,
31,
35,
35,
-1,
15,
19,
23,
30,
36,
36,
-1,
14,
18,
21,
21,
24,
30,
37,
37,
-1,
13,
18,
23,
29,
33,
38,
-1,
12,
29,
31,
33,
-1,
11,
13,
17,
17,
19,
19,
22,
22,
24,
31,
-1,
10,
11,
17,
18,
22,
22,
24,
24,
29,
29,
-1,
22,
23,
26,
29,
-1,
27,
29,
-1,
28,
29,
-1,
4096,
)
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) -> 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.
@@ -286,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)
@@ -298,4 +61,4 @@ def play() -> None:
if __name__ == "__main__":
play()
main()
+235
View File
@@ -0,0 +1,235 @@
[
2,
21,
14,
14,
25,
1,
2,
-1,
0,
2,
45,
50,
-1,
0,
5,
43,
52,
-1,
0,
7,
41,
52,
-1,
1,
9,
37,
50,
-1,
2,
11,
36,
50,
-1,
3,
13,
34,
49,
-1,
4,
14,
32,
48,
-1,
5,
15,
31,
47,
-1,
6,
16,
30,
45,
-1,
7,
17,
29,
44,
-1,
8,
19,
28,
43,
-1,
9,
20,
27,
41,
-1,
10,
21,
26,
40,
-1,
11,
22,
25,
38,
-1,
12,
22,
24,
36,
-1,
13,
34,
-1,
14,
33,
-1,
15,
31,
-1,
17,
29,
-1,
18,
27,
-1,
19,
26,
-1,
16,
28,
-1,
13,
30,
-1,
11,
31,
-1,
10,
32,
-1,
8,
33,
-1,
7,
34,
-1,
6,
13,
16,
34,
-1,
5,
12,
16,
35,
-1,
4,
12,
16,
35,
-1,
3,
12,
15,
35,
-1,
2,
35,
-1,
1,
35,
-1,
2,
34,
-1,
3,
34,
-1,
4,
33,
-1,
6,
33,
-1,
10,
32,
34,
34,
-1,
14,
17,
19,
25,
28,
31,
35,
35,
-1,
15,
19,
23,
30,
36,
36,
-1,
14,
18,
21,
21,
24,
30,
37,
37,
-1,
13,
18,
23,
29,
33,
38,
-1,
12,
29,
31,
33,
-1,
11,
13,
17,
17,
19,
19,
22,
22,
24,
31,
-1,
10,
11,
17,
18,
22,
22,
24,
24,
29,
29,
-1,
22,
23,
26,
29,
-1,
27,
29,
-1,
28,
29,
-1,
4096
]
+21 -23
View File
@@ -1,30 +1,28 @@
######################################################################
#
# 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
def main() -> None:
WORDS = [
words = [
[
"Ability",
"Basal",
@@ -85,13 +83,13 @@ def main() -> None:
still_running = True
while still_running:
phrase = ""
for section in WORDS:
for section in words:
if len(phrase) > 0:
phrase += " "
phrase += section[random.randint(0, len(section) - 1)]
print(phrase)
print("")
print()
response = input("? ")
try:
+24 -28
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
@@ -65,7 +64,7 @@ def parse_input() -> Tuple[int, bool]:
return day, leap_day
def calendar(weekday, leap_year):
def calendar(weekday: int, leap_year: bool) -> None:
"""
function to print a year's calendar.
@@ -104,9 +103,8 @@ def calendar(weekday, leap_year):
for n in range(1, 13):
days_count += months_days[n - 1]
print(
"** {} ****************** {} ****************** {} **\n".format(
days_count, months_names[n - 1], years_day - days_count
)
f"** {days_count} ****************** {months_names[n - 1]} "
f"****************** {years_day - days_count} **\n"
)
print(days)
print(sep)
@@ -121,7 +119,7 @@ def calendar(weekday, leap_year):
break
if d2 <= 0:
print("{}".format(" "), end=" ")
print(" ", end=" ")
elif d2 < 10:
print(f" {d2}", end=" ")
else:
@@ -151,8 +149,6 @@ def main() -> None:
if __name__ == "__main__":
main()
########################################################
#
########################################################
#
# Porting notes:
+5 -17
View File
@@ -16,23 +16,17 @@ def print_centered(msg: str) -> None:
def print_header(title: str) -> None:
print_centered(title)
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
def print_introduction() -> None:
print("I, YOUR FRIENDLY MICROCOMPUTER, WILL DETERMINE")
print("THE CORRECT CHANGE FOR ITEMS COSTING UP TO $100.")
print()
print()
print("THE CORRECT CHANGE FOR ITEMS COSTING UP TO $100.\n\n")
def pennies_to_dollar_string(p):
def pennies_to_dollar_string(p: float) -> str:
d = p / 100
ds = f"${d:0.2f}"
return ds
return f"${d:0.2f}"
def compute_change() -> None:
@@ -94,19 +88,13 @@ def compute_change() -> None:
print(f"{change_in_pennies} PENNY(S)")
def print_thanks() -> None:
print("THANK YOU, COME AGAIN.")
print()
print()
def main() -> None:
print_header("CHANGE")
print_introduction()
while True:
compute_change()
print_thanks()
print("THANK YOU, COME AGAIN.\n\n")
if __name__ == "__main__":
+4 -12
View File
@@ -37,10 +37,7 @@ def print_centered(msg: str) -> None:
def print_header(title: str) -> None:
print_centered(title)
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
def get_coordinates(prompt: str) -> Tuple[int, int]:
@@ -373,20 +370,15 @@ def print_instructions() -> None:
print("(7,0) IS THE LOWER RIGHT CORNER")
print("(7,7) IS THE UPPER RIGHT CORNER")
print("THE COMPUTER WILL TYPE '+TO' WHEN YOU HAVE ANOTHER")
print("JUMP. TYPE TWO NEGATIVE NUMBERS IF YOU CANNOT JUMP.")
print()
print()
print()
print("JUMP. TYPE TWO NEGATIVE NUMBERS IF YOU CANNOT JUMP.\n\n\n")
def print_human_won() -> None:
print()
print("YOU WIN.")
print("\nYOU WIN.")
def print_computer_won() -> None:
print()
print("I WIN.")
print("\nI WIN.")
def play_game() -> None:
+7 -20
View File
@@ -11,16 +11,7 @@ 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():
def play_scenario() -> bool:
acid_amount = random.randint(1, 50)
water_amount = 7 * acid_amount / 3
@@ -43,27 +34,23 @@ def play_scenario():
return True
def show_failure():
def show_failure() -> None:
print(" SIZZLE! YOU HAVE JUST BEEN DESALINATED INTO A BLOB")
print(" OF QUIVERING PROTOPLASM!")
def show_success():
print(" GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!")
print()
def show_success() -> None:
print(" GOOD JOB! YOU MAY BREATHE NOW, BUT DON'T INHALE THE FUMES!\n")
def show_ending():
def show_ending() -> None:
print(f" YOUR {MAX_LIVES} LIVES ARE USED, BUT YOU WILL BE LONG REMEMBERED FOR")
print(" YOUR CONTRIBUTIONS TO THE FIELD OF COMIC BOOK CHEMISTRY.")
def main() -> None:
print_with_tab(33, "CHEMIST")
print_with_tab(15, "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
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.")
@@ -1,5 +1,4 @@
def print_lightning_bolt() -> None:
print("*" * 36)
n = 24
while n > 16:
@@ -17,8 +16,7 @@ def print_lightning_bolt() -> None:
print("*" * 36)
def print_solution(n: int) -> None:
def print_solution(n: float) -> None:
print(f"\n{n} plus 3 gives {n + 3}. This Divided by 5 equals {(n + 3) / 5}")
print(f"This times 8 gives {((n + 3) / 5) * 8}. If we divide 5 and add 5.")
print(
@@ -27,58 +25,56 @@ def print_solution(n: int) -> None:
)
def Game():
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 == "Yes" or resp2 == "YES" or resp2 == "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 == "Yes" or resp4 == "YES" or resp4 == "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__":
print("I am CHIEF NUMBERS FREEK, The GREAT INDIAN MATH GOD.")
play = input("\nAre you ready to take the test you called me out for(Yes or No)? ")
if play == "Yes" or play == "YES" or play == "yes":
Game()
if play.lower() == "yes":
game()
else:
print("Ok, Nevermind. Let me go back to my great slumber, Bye")
input("")
input()
+12 -10
View File
@@ -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
@@ -125,7 +128,6 @@ def main() -> None:
keep_playing = True
while keep_playing:
play_game()
keep_playing = input("\nAgain (1=Yes, 0=No!) ") == "1"
+318 -209
View File
@@ -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__":
+2 -2
View File
@@ -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 (
+1 -4
View File
@@ -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.")
+6 -3
View File
@@ -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
+20 -17
View File
@@ -1,13 +1,16 @@
# 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
from typing import Tuple
def show_welcome():
def show_welcome() -> None:
# Clear screen. chr(27) is `Esc`, and the control sequence is
# initiated by Ctrl+[
# `J` is "Erase in Display" and `2J` means clear the entire screen
@@ -18,14 +21,14 @@ def show_welcome():
print("Creative Computing Morristown, New Jersey\n\n".center(45))
def get_num_charges():
def get_num_charges() -> Tuple[int, int]:
print("Depth Charge game\n")
while True:
search_area = input("Dimensions of search area? ")
search_area_str = input("Dimensions of search area? ")
# Make sure the input is an integer
try:
search_area = int(search_area)
search_area = int(search_area_str)
break
except ValueError:
print("Must enter an integer number. Please try again...")
@@ -34,16 +37,16 @@ def get_num_charges():
return search_area, num_charges
def ask_for_new_game():
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()
def show_shot_result(shot, location):
def show_shot_result(shot, location) -> None:
result = "Sonar reports shot was "
if shot[1] > location[1]: # y-direction
result += "north"
@@ -66,23 +69,23 @@ def show_shot_result(shot, location):
return
def get_shot_input():
def get_shot_input() -> Tuple[int, int, int]:
while True:
raw_guess = input("Enter coordinates: ")
try:
x, y, z = raw_guess.split()
xyz = raw_guess.split()
except ValueError:
print("Please enter coordinates separated by spaces")
print("Example: 3 2 1")
continue
try:
x, y, z = (int(num) for num in [x, y, z])
x, y, z = (int(num) for num in xyz)
return x, y, z
except ValueError:
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.")
@@ -111,10 +114,10 @@ def play_game(search_area, num_charges):
ask_for_new_game()
def start_new_game():
def main() -> None:
search_area, num_charges = get_num_charges()
play_game(search_area, num_charges)
if __name__ == "__main__":
start_new_game()
main()
+5 -16
View File
@@ -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())
+25 -28
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
@@ -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
+3 -2
View File
@@ -1,4 +1,5 @@
import random
from typing import List
def print_intro() -> None:
@@ -30,7 +31,7 @@ def print_instructions() -> None:
print()
def read_10_numbers():
def read_10_numbers() -> List[int]:
print("TEN NUMBERS, PLEASE ? ")
numbers = []
@@ -47,7 +48,7 @@ def read_10_numbers():
return numbers
def read_continue_choice():
def read_continue_choice() -> bool:
print("\nDO YOU WANT TO TRY AGAIN (1 FOR YES, 0 FOR NO) ? ")
try:
choice = int(input())
+80 -125
View File
@@ -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
+3 -3
View File
@@ -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:
+35 -38
View File
@@ -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,13 +23,7 @@ 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():
def show_introduction() -> None:
"""Show the player the introductory message"""
print("YOU ARE THE LEADER OF A FRENCH FUR TRADING EXPEDITION IN ")
print("1776 LEAVING THE LAKE ONTARIO AREA TO SELL FURS AND GET")
@@ -36,16 +31,16 @@ def show_introduction():
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():
def get_fort_choice() -> int:
"""Show the player the choices of Fort, get their input, if the
input is a valid choice (1,2,3) return it, otherwise keep
prompting the user."""
result = 0
while result == 0:
print("")
print()
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():
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()
+98 -98
View File
@@ -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:
+8 -20
View File
@@ -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
+21 -22
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
@@ -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")
+7 -5
View File
@@ -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()
+9 -8
View File
@@ -1,31 +1,32 @@
from random import random, seed
def gen_random():
def gen_random() -> int:
return int(random() * 5) + 1
def bad_input_850():
def bad_input_850() -> None:
print("\nHAMURABI: I CANNOT DO WHAT YOU WISH.")
print("GET YOURSELF ANOTHER STEWARD!!!!!")
def bad_input_710(S):
def bad_input_710(grain_bushels: int) -> None:
print("HAMURABI: THINK AGAIN. YOU HAVE ONLY")
print(S, "BUSHELS OF GRAIN. NOW THEN,")
print(f"{grain_bushels} BUSHELS OF GRAIN. NOW THEN,")
def bad_input_720(A):
print("HAMURABI: THINK AGAIN. YOU OWN ONLY", A, "ACRES. NOW THEN,")
def bad_input_720(acres: float) -> None:
print(f"HAMURABI: THINK AGAIN. YOU OWN ONLY {acres} ACRES. NOW THEN,")
def national_fink():
def national_fink() -> None:
print("DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY")
print("BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE")
print("ALSO BEEN DECLARED NATIONAL FINK!!!!")
def b_input(promptstring): # emulate BASIC input. It rejects non-numeric values
def b_input(promptstring: str) -> int:
"""emulate BASIC input. It rejects non-numeric values"""
x = input(promptstring)
while x.isalpha():
x = input("?REDO FROM START\n? ")
+25 -21
View File
@@ -1,15 +1,19 @@
#!/usr/bin/env python3
# HANGMAN
#
# Converted from BASIC to Python by Trevor Hobson and Daniel Piron
"""
HANGMAN
Converted from BASIC to Python by Trevor Hobson and Daniel Piron
"""
import random
from typing import List
class Canvas:
"""For drawing text-based figures"""
def __init__(self, width=12, height=12, fill=" "):
def __init__(self, width: int = 12, height: int = 12, fill: str = " ") -> None:
self._buffer = []
for _ in range(height):
line = []
@@ -19,12 +23,12 @@ class Canvas:
self.clear()
def clear(self, fill=" "):
def clear(self, fill: str = " ") -> None:
for row in self._buffer:
for x in range(len(row)):
row[x] = fill
def render(self):
def render(self) -> str:
lines = []
for line in self._buffer:
# Joining by the empty string ("") smooshes all of the
@@ -32,13 +36,13 @@ class Canvas:
lines.append("".join(line))
return "\n".join(lines)
def put(self, s, x, y):
def put(self, s: str, x: int, y: int) -> None:
# In an effort to avoid distorting the drawn image, only write the
# first character of the given string to the buffer.
self._buffer[y][x] = s[0]
def init_gallows(canvas):
def init_gallows(canvas: Canvas) -> None:
for i in range(12):
canvas.put("X", 0, i)
for i in range(7):
@@ -46,7 +50,7 @@ def init_gallows(canvas):
canvas.put("X", 6, 1)
def draw_head(canvas):
def draw_head(canvas: Canvas) -> None:
canvas.put("-", 5, 2)
canvas.put("-", 6, 2)
canvas.put("-", 7, 2)
@@ -59,47 +63,47 @@ def draw_head(canvas):
canvas.put("-", 7, 4)
def draw_body(canvas):
def draw_body(canvas: Canvas) -> None:
for i in range(5, 9, 1):
canvas.put("X", 6, i)
def draw_right_arm(canvas):
def draw_right_arm(canvas: Canvas) -> None:
for i in range(3, 7):
canvas.put("\\", i - 1, i)
def draw_left_arm(canvas):
def draw_left_arm(canvas: Canvas) -> None:
canvas.put("/", 10, 3)
canvas.put("/", 9, 4)
canvas.put("/", 8, 5)
canvas.put("/", 7, 6)
def draw_right_leg(canvas):
def draw_right_leg(canvas: Canvas) -> None:
canvas.put("/", 5, 9)
canvas.put("/", 4, 10)
def draw_left_leg(canvas):
def draw_left_leg(canvas: Canvas) -> None:
canvas.put("\\", 7, 9)
canvas.put("\\", 8, 10)
def draw_left_hand(canvas):
def draw_left_hand(canvas: Canvas) -> None:
canvas.put("\\", 10, 2)
def draw_right_hand(canvas):
def draw_right_hand(canvas: Canvas) -> None:
canvas.put("/", 2, 2)
def draw_left_foot(canvas):
def draw_left_foot(canvas: Canvas) -> None:
canvas.put("\\", 9, 11)
canvas.put("-", 10, 11)
def draw_right_foot(canvas):
def draw_right_foot(canvas: Canvas) -> None:
canvas.put("-", 2, 11)
canvas.put("/", 3, 11)
@@ -172,11 +176,11 @@ words = [
]
def play_game(guess_target):
def play_game(guess_target: str) -> None:
"""Play one round of the game"""
wrong_guesses = 0
guess_progress = ["-"] * len(guess_target)
guess_list = []
guess_list: List[str] = []
gallows = Canvas()
init_gallows(gallows)
@@ -206,7 +210,7 @@ def play_game(guess_target):
]
for i in indices:
guess_progress[i] = guess_letter
if guess_progress == guess_target:
if "".join(guess_progress) == guess_target:
print("You found the word!")
break
else:
+17 -29
View File
@@ -9,17 +9,10 @@ Ported by Dave LeCompte
"""
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():
def get_yes_or_no() -> Tuple[bool, Optional[bool], str]:
msg = input()
if msg.upper() == "YES":
return True, True, msg
@@ -29,7 +22,7 @@ def get_yes_or_no():
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:
@@ -48,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")
@@ -58,7 +51,7 @@ def prompt_for_problems(user_name):
return problem_type
def prompt_too_much_or_too_little():
def prompt_too_much_or_too_little() -> Tuple[bool, Optional[bool]]:
answer = input().upper()
if answer == "TOO MUCH":
return True, True
@@ -67,7 +60,7 @@ def prompt_too_much_or_too_little():
return False, None
def solve_sex_problem(user_name):
def solve_sex_problem(user_name: str) -> None:
print("IS YOUR PROBLEM TOO MUCH OR TOO LITTLE?")
while True:
valid, too_much = prompt_too_much_or_too_little()
@@ -85,31 +78,31 @@ def solve_sex_problem(user_name):
print("WITH 'TOO MUCH' OR 'TOO LITTLE'. WHICH IS IT?")
def solve_money_problem(user_name):
def solve_money_problem(user_name: str) -> None:
print(f"SORRY, {user_name}, I'M BROKE TOO. WHY DON'T YOU SELL")
print("ENCYCLOPEADIAS OR MARRY SOMEONE RICH OR STOP EATING")
print("SO YOU WON'T NEED SO MUCH MONEY?")
def solve_health_problem(user_name):
def solve_health_problem(user_name: str) -> None:
print(f"MY ADVICE TO YOU {user_name} IS:")
print(" 1. TAKE TWO ASPRIN")
print(" 2. DRINK PLENTY OF FLUIDS (ORANGE JUICE, NOT BEER!)")
print(" 3. GO TO BED (ALONE)")
def solve_job_problem(user_name):
def solve_job_problem(user_name: str) -> None:
print(f"I CAN SYMPATHIZE WITH YOU {user_name}. I HAVE TO WORK")
print("VERY LONG HOURS FOR NO PAY -- AND SOME OF MY BOSSES")
print(f"REALLY BEAT ON MY KEYBOARD. MY ADVICE TO YOU, {user_name},")
print("IS TO OPEN A RETAIL COMPUTER STORE. IT'S GREAT FUN.")
def alert_unknown_problem_type(user_name, problem_type):
def alert_unknown_problem_type(user_name: str, problem_type: str) -> None:
print(f"OH, {user_name}, YOUR ANSWER OF {problem_type} IS GREEK TO ME.")
def ask_question_loop(user_name):
def ask_question_loop(user_name: str) -> None:
while True:
problem_type = prompt_for_problems(user_name)
if problem_type == "SEX":
@@ -137,7 +130,7 @@ def ask_question_loop(user_name):
print(f"JUST A SIMPLE 'YES' OR 'NO' PLEASE, {user_name}.")
def ask_for_fee(user_name):
def ask_for_fee(user_name: str) -> None:
print()
print(f"THAT WILL BE $5.00 FOR THE ADVICE, {user_name}.")
print("PLEASE LEAVE THE MONEY ON THE TERMINAL.")
@@ -166,26 +159,21 @@ def ask_for_fee(user_name):
print("PLEASE RESPOND WITH 'YES' or 'NO'.")
def unhappy_goodbye(user_name):
def unhappy_goodbye(user_name: str) -> None:
print()
print(f"TAKE A WALK, {user_name}.")
print()
print()
def happy_goodbye(user_name):
def happy_goodbye(user_name: str) -> None:
print(f"NICE MEETING YOU, {user_name}, HAVE A NICE DAY.")
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()
+49 -45
View File
@@ -44,8 +44,8 @@ Port to Python by Dave LeCompte
# BoardLayout matches the current board, as well as removing losing move
# have been moved into methods of this class.
import collections
import random
from typing import Iterator, List, NamedTuple, Optional, Tuple
PAGE_WIDTH = 64
@@ -53,9 +53,13 @@ HUMAN_PIECE = 1
EMPTY_SPACE = 0
COMPUTER_PIECE = -1
ComputerMove = collections.namedtuple(
"ComputerMove", ["board_index", "move_index", "m1", "m2"]
)
class ComputerMove(NamedTuple):
board_index: int
move_index: int
m1: int
m2: int
wins = 0
losses = 0
@@ -68,10 +72,7 @@ def print_centered(msg: str) -> None:
def print_header(title: str) -> None:
print_centered(title)
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
def print_instructions() -> None:
@@ -110,7 +111,7 @@ GO FIRST.
)
def prompt_yes_no(msg):
def prompt_yes_no(msg: str) -> bool:
while True:
print(msg)
response = input().upper()
@@ -120,7 +121,7 @@ def prompt_yes_no(msg):
return False
def reverse_space_name(space_name):
def reverse_space_name(space_name: int) -> int:
# reverse a space name in the range 1-9 left to right
assert 1 <= space_name <= 9
@@ -128,36 +129,38 @@ def reverse_space_name(space_name):
return reflections[space_name]
def is_space_in_center_column(space_name):
def is_space_in_center_column(space_name: int) -> bool:
return reverse_space_name(space_name) == space_name
class BoardLayout:
def __init__(self, cells, move_list):
def __init__(self, cells: List[int], move_list: List[Tuple[int, int]]) -> None:
self.cells = cells
self.moves = move_list
def _check_match_no_mirror(self, cell_list):
def _check_match_no_mirror(self, cell_list: List[int]) -> bool:
return all(
board_contents == cell_list[space_index]
for space_index, board_contents in enumerate(self.cells)
)
def _check_match_with_mirror(self, cell_list):
def _check_match_with_mirror(self, cell_list: List[int]) -> bool:
for space_index, board_contents in enumerate(self.cells):
reversed_space_index = reverse_space_name(space_index + 1) - 1
if board_contents != cell_list[reversed_space_index]:
return False
return True
def check_match(self, cell_list):
def check_match(self, cell_list: List[int]) -> Tuple[bool, Optional[bool]]:
if self._check_match_with_mirror(cell_list):
return True, True
elif self._check_match_no_mirror(cell_list):
return True, False
return False, None
def get_random_move(self, reverse_board):
def get_random_move(
self, reverse_board: Optional[bool]
) -> Optional[Tuple[int, int, int]]:
if not self.moves:
return None
move_index = random.randrange(len(self.moves))
@@ -193,7 +196,7 @@ boards = [
]
def get_move(board_index, move_index):
def get_move(board_index: int, move_index: int) -> Tuple[int, int]:
assert board_index >= 0 and board_index < len(boards)
board = boards[board_index]
@@ -202,7 +205,7 @@ def get_move(board_index, move_index):
return board.moves[move_index]
def remove_move(board_index, move_index):
def remove_move(board_index: int, move_index: int) -> None:
assert board_index >= 0 and board_index < len(boards)
board = boards[board_index]
@@ -211,11 +214,11 @@ def remove_move(board_index, move_index):
del board.moves[move_index]
def init_board():
def init_board() -> List[int]:
return [COMPUTER_PIECE] * 3 + [EMPTY_SPACE] * 3 + [HUMAN_PIECE] * 3
def print_board(board) -> None:
def print_board(board: List[int]) -> None:
piece_dict = {COMPUTER_PIECE: "X", EMPTY_SPACE: ".", HUMAN_PIECE: "O"}
space = " " * 10
@@ -231,7 +234,7 @@ def print_board(board) -> None:
print()
def get_coordinates():
def get_coordinates() -> Tuple[int, int]:
while True:
try:
print("YOUR MOVE?")
@@ -246,15 +249,15 @@ def print_illegal() -> None:
print("ILLEGAL MOVE.")
def board_contents(board, space_number):
def board_contents(board: List[int], space_number: int) -> int:
return board[space_number - 1]
def set_board(board, space_number, new_value):
def set_board(board: List[int], space_number: int, new_value: int) -> None:
board[space_number - 1] = new_value
def is_legal_human_move(board, m1, m2):
def is_legal_human_move(board: List[int], m1: int, m2: int) -> bool:
if board_contents(board, m1) != HUMAN_PIECE:
# Start space doesn't contain player's piece
return False
@@ -285,30 +288,30 @@ def is_legal_human_move(board, m1, m2):
return True
def player_piece_on_back_row(board):
def player_piece_on_back_row(board: List[int]) -> bool:
return any(board_contents(board, space) == HUMAN_PIECE for space in range(1, 4))
def computer_piece_on_front_row(board):
def computer_piece_on_front_row(board: List[int]) -> bool:
return any(board_contents(board, space) == COMPUTER_PIECE for space in range(7, 10))
def all_human_pieces_captured(board):
def all_human_pieces_captured(board: List[int]) -> bool:
return len(list(get_human_spaces(board))) == 0
def all_computer_pieces_captured(board):
def all_computer_pieces_captured(board: List[int]) -> bool:
return len(list(get_computer_spaces(board))) == 0
def human_win(last_computer_move):
def human_win(last_computer_move: ComputerMove) -> None:
print("YOU WIN")
remove_move(last_computer_move.board_index, last_computer_move.move_index)
global losses
losses += 1
def computer_win(has_moves):
def computer_win(has_moves: bool) -> None:
if not has_moves:
msg = "YOU CAN'T MOVE, SO "
else:
@@ -319,12 +322,11 @@ def computer_win(has_moves):
wins += 1
def show_scores():
print(f"I HAVE WON {wins} AND YOU {losses} OUT OF {wins + losses} GAMES.")
print()
def show_scores() -> None:
print(f"I HAVE WON {wins} AND YOU {losses} OUT OF {wins + losses} GAMES.\n")
def human_has_move(board):
def human_has_move(board: List[int]) -> bool:
for i in get_human_spaces(board):
if board_contents(board, i - 3) == EMPTY_SPACE:
# can move piece forward
@@ -353,31 +355,31 @@ def human_has_move(board):
return False
def get_board_spaces():
def get_board_spaces() -> Iterator[int]:
"""generates the space names (1-9)"""
yield from range(1, 10)
def get_board_spaces_with(board, val):
def get_board_spaces_with(board: List[int], val: int) -> Iterator[int]:
"""generates spaces containing pieces of type val"""
for i in get_board_spaces():
if board_contents(board, i) == val:
yield i
def get_human_spaces(board):
def get_human_spaces(board: List[int]) -> Iterator[int]:
yield from get_board_spaces_with(board, HUMAN_PIECE)
def get_empty_spaces(board):
def get_empty_spaces(board: List[int]) -> Iterator[int]:
yield from get_board_spaces_with(board, EMPTY_SPACE)
def get_computer_spaces(board):
def get_computer_spaces(board: List[int]) -> Iterator[int]:
yield from get_board_spaces_with(board, COMPUTER_PIECE)
def has_computer_move(board):
def has_computer_move(board: List[int]) -> bool:
for i in get_computer_spaces(board):
if board_contents(board, i + 3) == EMPTY_SPACE:
# can move forward (down)
@@ -406,7 +408,7 @@ def has_computer_move(board):
return False
def find_board_index_that_matches_board(board):
def find_board_index_that_matches_board(board: List[int]) -> Tuple[int, Optional[bool]]:
for board_index, board_layout in enumerate(boards):
matches, is_reversed = board_layout.check_match(board)
if matches:
@@ -417,7 +419,7 @@ def find_board_index_that_matches_board(board):
raise RuntimeError("ILLEGAL BOARD PATTERN.")
def pick_computer_move(board):
def pick_computer_move(board: List[int]) -> Optional[ComputerMove]:
if not has_computer_move(board):
return None
@@ -434,7 +436,7 @@ def pick_computer_move(board):
return ComputerMove(board_index, move_index, m1, m2)
def get_human_move(board):
def get_human_move(board: List[int]) -> Tuple[int, int]:
while True:
m1, m2 = get_coordinates()
@@ -444,12 +446,12 @@ def get_human_move(board):
return m1, m2
def apply_move(board, m1, m2, piece_value):
def apply_move(board: List[int], m1: int, m2: int, piece_value: int) -> None:
set_board(board, m1, EMPTY_SPACE)
set_board(board, m2, piece_value)
def play_game():
def play_game() -> None:
last_computer_move = None
board = init_board()
@@ -464,11 +466,13 @@ def play_game():
print_board(board)
if player_piece_on_back_row(board) or all_computer_pieces_captured(board):
assert last_computer_move is not None
human_win(last_computer_move)
return
computer_move = pick_computer_move(board)
if computer_move is None:
assert last_computer_move is not None
human_win(last_computer_move)
return
+2 -2
View File
@@ -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()
+51 -48
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
+9 -8
View File
@@ -1,6 +1,7 @@
import math
import random
import time
from typing import List, Tuple
def basic_print(*zones, **kwargs) -> None:
@@ -17,7 +18,7 @@ def basic_print(*zones, **kwargs) -> None:
print(" " * identation + line, end=end)
def basic_input(prompt, type_conversion=None):
def basic_input(prompt: str, type_conversion=None):
"""BASIC INPUT command with optional type conversion"""
while True:
@@ -45,7 +46,7 @@ HORSE_NAMES = [
]
def introduction():
def introduction() -> None:
"""Print the introduction, and optional the instructions"""
basic_print("HORSERACE", indent=31)
@@ -66,7 +67,7 @@ def introduction():
basic_print("")
def setup_players():
def setup_players() -> List[str]:
"""Gather the number of players and their names"""
# ensure we get an integer value from the user
@@ -80,7 +81,7 @@ def setup_players():
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."""
@@ -101,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
@@ -124,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"""
@@ -180,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
+9 -5
View File
@@ -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()
+4 -15
View File
@@ -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()
+25 -1
View File
@@ -21,7 +21,9 @@ http://www.vintage-basic.net/games.html
#### Porting Notes
Implementers should be aware that this game contains at least one bug.
Implementers should be aware that this game contains bugs.
### Bug 1
On basic line 1450
@@ -41,4 +43,26 @@ A quick fix for this bug in the original code would be
1410 PRINT " YOU MADE";ABS(INT(V1-V2));"RALLODS FROM TOURIST TRADE."
### Bug 2
On basic line 1330 following was the variable T1 never assigned:
1330 PRINT " YOU HARVESTED ";INT(J-U2);"SQ. MILES OF CROPS."
1340 IF U2=0 THEN 1370
1344 IF T1>=2 THEN 1370
1350 PRINT " (DUE TO ";
1355 IF T1=0 THEN 1365
1360 PRINT "INCREASED ";
Likely it should be the difference of the current years crop loss compared to the
last years crop loss.
### Bug 3
On basic line 1997 it is:
1997 PRINT " AND 10,000 SQ. MILES OF FOREST LAND."
but it should be:
1997 PRINT " AND 1,000 SQ. MILES OF FOREST LAND."
+41
View File
@@ -1,3 +1,44 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Python](https://www.python.org/about/)
## Porting notes
Variables:
* A: Available rallods (money)
* B: Current countrymen
* C: foreign_workers
* C1: foreign_workers_influx
* D: Available land (farmland=D-1000)
* F1: polution_deaths (last round)
* B5: died_contrymen (starvation + pollution)
* H: sm_sell_to_industry
* I: distributed_rallods
* J: planted_sq in a round
* K: pollution_control_spendings in a round
* X5: years in office
* N5: YEARS_IN_TERM - how many years one term in office has
* P1: population_change (positive means people come, negative means people leave)
* W: land_buy_price
* V9: planting_cost
* U2: crop_loss
* V1-V2: Earnings from tourist trade
* V3: tourism_earnings
* T1: crop_loss_last_year
* W: land_buy_price
* X: only show an error message once
Functions:
* `RND(1)`: `random.random()`
* `INT(...)`: `int(...)`
* `ABS(...)`: `abs(...)`
Bugs: See [53 King README](../README.md)
Implicit knowledge:
* `COST_OF_LIVING`: One countryman needs 100 for food. Otherwise they will die of starvation
* `COST_OF_FUNERAL`: A funeral costs 9
+444
View File
@@ -0,0 +1,444 @@
"""
KING
A strategy game where the player is the king.
Ported to Python by Martin Thoma in 2022
"""
import sys
from dataclasses import dataclass
from random import randint, random
FOREST_LAND = 1000
INITIAL_LAND = FOREST_LAND + 1000
COST_OF_LIVING = 100
COST_OF_FUNERAL = 9
YEARS_IN_TERM = 8
POLLUTION_CONTROL_FACTOR = 25
def ask_int(prompt) -> int:
while True:
try:
return int(input(prompt))
except ValueError:
continue
@dataclass
class GameState:
rallods: int = -1
countrymen: int = -1
land: int = INITIAL_LAND
foreign_workers: int = 0
years_in_office: int = 0
# previous year stats
crop_loss_last_year: int = 0
# current year stats
died_contrymen: int = 0
pollution_deaths: int = 0
population_change: int = 0
# current year - market situation (in rallods per square mile)
planting_cost: int = -1
land_buy_price: int = -1
tourism_earnings: int = 0
def set_market_conditions(self) -> None:
self.land_buy_price = randint(95, 105)
self.planting_cost = randint(10, 15)
@property
def farmland(self) -> int:
return self.land - FOREST_LAND
@property
def settled_people(self) -> int:
return self.countrymen - self.population_change
def sell_land(self, amount: int) -> None:
assert amount < self.farmland
self.land -= amount
self.rallods += self.land_buy_price * amount
def distribute_rallods(self, distribute: int) -> None:
self.rallods -= distribute
def spend_pollution_control(self, spend: int) -> None:
self.rallods -= spend
def plant(self, sq_to_plant: int) -> None:
self.rallods -= sq_to_plant * self.planting_cost
def print_status(self) -> None:
print(f"\n\nYOU NOW HAVE {self.rallods} RALLODS IN THE TREASURY.")
print(f"{int(self.countrymen)} COUNTRYMEN, ", end="")
if self.foreign_workers > 0:
print(f"{int(self.foreign_workers)} FOREIGN WORKERS, ", end="")
print(f"AND {self.land} SQ. MILES OF LAND.")
print(
f"THIS YEAR INDUSTRY WILL BUY LAND FOR {self.land_buy_price} "
"RALLODS PER SQUARE MILE."
)
print(
f"LAND CURRENTLY COSTS {self.planting_cost} RALLODS "
"PER SQUARE MILE TO PLANT.\n"
)
def handle_deaths(
self, distributed_rallods: int, pollution_control_spendings: int
) -> None:
starved_countrymen = max(
0, int(self.countrymen - distributed_rallods / COST_OF_LIVING)
)
if starved_countrymen > 0:
print(f"{starved_countrymen} COUNTRYMEN DIED OF STARVATION")
self.pollution_deaths = int(random() * (INITIAL_LAND - self.land))
if pollution_control_spendings >= POLLUTION_CONTROL_FACTOR:
self.pollution_deaths = int(
self.pollution_deaths
/ (pollution_control_spendings / POLLUTION_CONTROL_FACTOR)
)
if self.pollution_deaths > 0:
print(
f"{self.pollution_deaths} COUNTRYMEN DIED OF CARBON-MONOXIDE "
f"AND DUST INHALATION"
)
self.died_contrymen = starved_countrymen + self.pollution_deaths
if self.died_contrymen > 0:
funeral_cost = self.died_contrymen * COST_OF_FUNERAL
print(f" YOU WERE FORCED TO SPEND {funeral_cost} RALLODS ON ")
print("FUNERAL EXPENSES.")
self.rallods -= funeral_cost
if self.rallods < 0:
print(" INSUFFICIENT RESERVES TO COVER COST - LAND WAS SOLD")
self.land += int(self.rallods / self.land_buy_price)
self.rallods = 0
self.countrymen -= self.died_contrymen
def handle_tourist_trade(self) -> None:
V1 = int(self.settled_people * 22 + random() * 500)
V2 = int((INITIAL_LAND - self.land) * 15)
tourist_trade_earnings = int(V1 - V2)
print(f" YOU MADE {tourist_trade_earnings} RALLODS FROM TOURIST TRADE.")
if V2 != 0 and not (V1 - V2 >= self.tourism_earnings):
print(" DECREASE BECAUSE ")
reason = randint(0, 10)
if reason <= 2:
print("FISH POPULATION HAS DWINDLED DUE TO WATER POLLUTION.")
if reason <= 4:
print("AIR POLLUTION IS KILLING GAME BIRD POPULATION.")
if reason <= 6:
print("MINERAL BATHS ARE BEING RUINED BY WATER POLLUTION.")
if reason <= 8:
print("UNPLEASANT SMOG IS DISCOURAGING SUN BATHERS.")
if reason <= 10:
print("HOTELS ARE LOOKING SHABBY DUE TO SMOG GRIT.")
# NOTE: The following two lines had a bug in the original game:
self.tourism_earnings = abs(int(V1 - V2))
self.rallods += self.tourism_earnings
def handle_harvest(self, planted_sq: int) -> None:
crop_loss = int((INITIAL_LAND - self.land) * ((random() + 1.5) / 2))
if self.foreign_workers != 0:
print(f"OF {planted_sq} SQ. MILES PLANTED,")
if planted_sq <= crop_loss:
crop_loss = planted_sq
harvested = int(planted_sq - crop_loss)
print(f" YOU HARVESTED {harvested} SQ. MILES OF CROPS.")
unlucky_harvesting_worse = crop_loss - self.crop_loss_last_year
if crop_loss != 0:
print(" (DUE TO ", end="")
if unlucky_harvesting_worse > 2:
print("INCREASED ", end="")
print("AIR AND WATER POLLUTION FROM FOREIGN INDUSTRY.)")
revenue = int((planted_sq - crop_loss) * (self.land_buy_price / 2))
print(f"MAKING {revenue} RALLODS.")
self.crop_loss_last_year = crop_loss
self.rallods += revenue
def handle_foreign_workers(
self,
sm_sell_to_industry: int,
distributed_rallods: int,
polltion_control_spendings: int,
) -> None:
foreign_workers_influx = 0
if sm_sell_to_industry != 0:
foreign_workers_influx = int(
sm_sell_to_industry + (random() * 10) - (random() * 20)
)
if self.foreign_workers <= 0:
foreign_workers_influx = foreign_workers_influx + 20
print(f"{foreign_workers_influx} WORKERS CAME TO THE COUNTRY AND")
surplus_distributed = distributed_rallods / COST_OF_LIVING - self.countrymen
population_change = int(
(surplus_distributed / 10)
+ (polltion_control_spendings / POLLUTION_CONTROL_FACTOR)
- ((INITIAL_LAND - self.land) / 50)
- (self.died_contrymen / 2)
)
print(f"{abs(population_change)} COUNTRYMEN ", end="")
if population_change < 0:
print("LEFT ", end="")
else:
print("CAME TO ", end="")
print("THE ISLAND")
self.countrymen += population_change
self.foreign_workers += int(foreign_workers_influx)
def handle_too_many_deaths(self) -> None:
print(f"\n\n\n{self.died_contrymen} COUNTRYMEN DIED IN ONE YEAR!!!!!")
print("\n\n\nDUE TO THIS EXTREME MISMANAGEMENT, YOU HAVE NOT ONLY")
print("BEEN IMPEACHED AND THROWN OUT OF OFFICE, BUT YOU")
message = randint(0, 10)
if message <= 3:
print("ALSO HAD YOUR LEFT EYE GOUGED OUT!")
if message <= 6:
print("HAVE ALSO GAINED A VERY BAD REPUTATION.")
if message <= 10:
print("HAVE ALSO BEEN DECLARED NATIONAL FINK.")
sys.exit()
def handle_third_died(self) -> None:
print()
print()
print("OVER ONE THIRD OF THE POPULTATION HAS DIED SINCE YOU")
print("WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING)")
print("HATE YOUR GUTS.")
self.end_game()
def handle_money_mismanagement(self) -> None:
print()
print("MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID")
print("NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED")
print("OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE")
print("BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE.")
print("THE CHOICE IS YOURS.")
print("IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER")
print("BEFORE PROCEEDING.")
sys.exit()
def handle_too_many_foreigners(self) -> None:
print("\n\nTHE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER")
print("OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND")
print("TAKEN OVER THE COUNTRY.")
self.end_game()
def end_game(self) -> None:
if random() <= 0.5:
print("YOU HAVE BEEN ASSASSINATED.")
else:
print("YOU HAVE BEEN THROWN OUT OF OFFICE AND ARE NOW")
print("RESIDING IN PRISON.")
sys.exit()
def handle_congratulations(self) -> None:
print("\n\nCONGRATULATIONS!!!!!!!!!!!!!!!!!!")
print(f"YOU HAVE SUCCESFULLY COMPLETED YOUR {YEARS_IN_TERM} YEAR TERM")
print("OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT")
print("NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD")
print("LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT")
print("PLAYS THIS GAME.")
sys.exit()
def print_header() -> None:
print(" " * 34 + "KING")
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
def print_instructions() -> None:
print(
f"""\n\n\nCONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS
DETINU, A SMALL COMMUNIST ISLAND 30 BY 70 MILES LONG. YOUR
JOB IS TO DECIDE UPON THE CONTRY'S BUDGET AND DISTRIBUTE
MONEY TO YOUR COUNTRYMEN FROM THE COMMUNAL TREASURY.
THE MONEY SYSTEM IS RALLODS, AND EACH PERSON NEEDS {COST_OF_LIVING}
RALLODS PER YEAR TO SURVIVE. YOUR COUNTRY'S INCOME COMES
FROM FARM PRODUCE AND TOURISTS VISITING YOUR MAGNIFICENT
FORESTS, HUNTING, FISHING, ETC. HALF YOUR LAND IS FARM LAND
WHICH ALSO HAS AN EXCELLENT MINERAL CONTENT AND MAY BE SOLD
TO FOREIGN INDUSTRY (STRIP MINING) WHO IMPORT AND SUPPORT
THEIR OWN WORKERS. CROPS COST BETWEEN 10 AND 15 RALLODS PER
SQUARE MILE TO PLANT.
YOUR GOAL IS TO COMPLETE YOUR {YEARS_IN_TERM} YEAR TERM OF OFFICE.
GOOD LUCK!"""
)
def ask_how_many_sq_to_plant(state: GameState) -> int:
while True:
sq = ask_int("HOW MANY SQUARE MILES DO YOU WISH TO PLANT? ")
if sq < 0:
continue
elif sq > 2 * state.countrymen:
print(" SORRY, BUT EACH COUNTRYMAN CAN ONLY PLANT 2 SQ. MILES.")
elif sq > state.farmland:
print(
f" SORRY, BUT YOU ONLY HAVE {state.farmland} "
"SQ. MILES OF FARM LAND."
)
elif sq * state.planting_cost > state.rallods:
print(
f" THINK AGAIN. YOU'VE ONLY {state.rallods} RALLODS "
"LEFT IN THE TREASURY."
)
else:
return sq
def ask_pollution_control(state: GameState) -> int:
while True:
rallods = ask_int(
"HOW MANY RALLODS DO YOU WISH TO SPEND ON POLLUTION CONTROL? "
)
if rallods > state.rallods:
print(f" THINK AGAIN. YOU ONLY HAVE {state.rallods} RALLODS REMAINING.")
elif rallods < 0:
continue
else:
return rallods
def ask_sell_to_industry(state: GameState) -> int:
had_first_err = False
first = """(FOREIGN INDUSTRY WILL ONLY BUY FARM LAND BECAUSE
FOREST LAND IS UNECONOMICAL TO STRIP MINE DUE TO TREES,
THICKER TOP SOIL, ETC.)"""
err = f"""*** THINK AGAIN. YOU ONLY HAVE {state.farmland} SQUARE MILES OF FARM LAND."""
while True:
sm = input("HOW MANY SQUARE MILES DO YOU WISH TO SELL TO INDUSTRY? ")
try:
sm_sell = int(sm)
except ValueError:
if not had_first_err:
print(first)
had_first_err = True
print(err)
continue
if sm_sell > state.farmland:
print(err)
elif sm_sell < 0:
continue
else:
return sm_sell
def ask_distribute_rallods(state: GameState) -> int:
while True:
rallods = ask_int(
"HOW MANY RALLODS WILL YOU DISTRIBUTE AMONG YOUR COUNTRYMEN? "
)
if rallods < 0:
continue
elif rallods > state.rallods:
print(
f" THINK AGAIN. YOU'VE ONLY {state.rallods} RALLODS IN THE TREASURY"
)
else:
return rallods
def resume() -> GameState:
while True:
years = ask_int("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED? ")
if years < 0:
sys.exit()
if years >= YEARS_IN_TERM:
print(f" COME ON, YOUR TERM IN OFFICE IS ONLY {YEARS_IN_TERM} YEARS.")
else:
break
treasury = ask_int("HOW MUCH DID YOU HAVE IN THE TREASURY? ")
if treasury < 0:
sys.exit()
countrymen = ask_int("HOW MANY COUNTRYMEN? ")
if countrymen < 0:
sys.exit()
workers = ask_int("HOW MANY WORKERS? ")
if workers < 0:
sys.exit()
while True:
land = ask_int("HOW MANY SQUARE MILES OF LAND? ")
if land < 0:
sys.exit()
if land > INITIAL_LAND:
farm_land = INITIAL_LAND - FOREST_LAND
print(f" COME ON, YOU STARTED WITH {farm_land:,} SQ. MILES OF FARM LAND")
print(f" AND {FOREST_LAND:,} SQ. MILES OF FOREST LAND.")
if land > FOREST_LAND:
break
return GameState(
rallods=treasury,
countrymen=countrymen,
foreign_workers=workers,
years_in_office=years,
)
def main() -> None:
print_header()
want_instructions = input("DO YOU WANT INSTRUCTIONS? ").upper()
if want_instructions == "AGAIN":
state = resume()
else:
state = GameState(
rallods=randint(59000, 61000),
countrymen=randint(490, 510),
planting_cost=randint(10, 15),
)
if want_instructions != "NO":
print_instructions()
while True:
state.set_market_conditions()
state.print_status()
# Users actions
sm_sell_to_industry = ask_sell_to_industry(state)
state.sell_land(sm_sell_to_industry)
distributed_rallods = ask_distribute_rallods(state)
state.distribute_rallods(distributed_rallods)
planted_sq = ask_how_many_sq_to_plant(state)
state.plant(planted_sq)
polltion_control_spendings = ask_pollution_control(state)
state.spend_pollution_control(polltion_control_spendings)
# Run the year
state.handle_deaths(distributed_rallods, polltion_control_spendings)
state.handle_foreign_workers(
sm_sell_to_industry, distributed_rallods, polltion_control_spendings
)
state.handle_harvest(planted_sq)
state.handle_tourist_trade()
if state.died_contrymen > 200:
state.handle_too_many_deaths()
if state.countrymen < 343:
state.handle_third_died()
elif (
state.rallods / 100
) > 5 and state.died_contrymen - state.pollution_deaths >= 2:
state.handle_money_mismanagement()
if state.foreign_workers > state.countrymen:
state.handle_too_many_foreigners()
elif YEARS_IN_TERM - 1 == state.years_in_office:
state.handle_congratulations()
else:
state.years_in_office += 1
state.died_contrymen = 0
if __name__ == "__main__":
main()
+5 -17
View File
@@ -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()
+7 -7
View File
@@ -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):
@@ -1,37 +1,23 @@
import * as readline from 'readline'
#!/usr/bin/env node
// start reusable code
async function input(prompt = "") {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
import { println, input } from '../../00_Common/javascript/common.mjs';
return new Promise((resolve, _) => {
rl.setPrompt(prompt)
// show user the question
rl.prompt()
// listen for user answer,
// callback is triggered as soon as user hits enter key
rl.on('line', answer => {
rl.close()
// resolve the promise, with the input the user entered
resolve(answer)
})
})
}
function println(message = "", align = "left"){
let padColCount = 0
if(align === "center"){
function printAlign(message = "", align = "left") {
// process.stdout.columns is the number of spaces per line in the terminal
const maxWidth = process.stdout.columns
if (align === "center") {
// calculate the amount of spaces required to center the message
// process.stdout.columns is the number of spaces per line in the terminal
padColCount = Math.round(process.stdout.columns / 2 + message.length / 2)
const padColCount = Math.round((process.stdout.columns-message.length)/2);
const padding = padColCount <= 0 ? '' : ' '.repeat(padColCount);
println(padding, message);
} else if (align === "right") {
const padColCount = Math.round(process.stdout.columns-message.length);
const padding = padColCount <= 0 ? '' : ' '.repeat(padColCount);
println(padding, message);
} else {
println(message);
}
console.log(message.padStart(padColCount, " "))
}
// end reusable code
function equalIgnoreCase(correct, provided){
return correct.toString().toLowerCase() === provided.toString().toLowerCase()
@@ -39,8 +25,10 @@ function equalIgnoreCase(correct, provided){
async function evaluateQuestion(question, answerOptions, correctAnswer, correctMessage, wrongMessage){
// ask the user to answer the given question
println(question);
println(answerOptions.map((answer, index) => `${index+1})${answer}`).join(', '));
// this is a blocking wait
const answer = await input(question + "\n" + answerOptions + "\n")
const answer = await input('?')
const isCorrect = equalIgnoreCase(correctAnswer, answer)
println(isCorrect ? correctMessage : wrongMessage)
return isCorrect ? 1 : 0
@@ -48,31 +36,40 @@ async function evaluateQuestion(question, answerOptions, correctAnswer, correctM
async function main(){
let score = 0
println("LITERATURE QUIZ", "center")
println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", "center")
println();println();println()
printAlign("LITERATURE QUIZ", "center")
printAlign("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", "center")
println("\n\n")
println("TEST YOUR KNOWLEDGE OF CHILDREN'S LITERATURE.");
println();
println("THIS IS A MULTIPLE-CHOICE QUIZ.");
println("TYPE A 1, 2, 3, OR 4 AFTER THE QUESTION MARK.");
println();
println("GOOD LUCK!");
println("\n\n");
score += await evaluateQuestion("IN PINOCCHIO, WHAT WAS THE NAME OF THE CAT?",
"1)TIGGER, 2)CICERO, 3)FIGARO, 4)GUIPETTO", 3,
[ "TIGGER", "CICERO", "FIGARO", "GUIPETTO"], 3,
"VERY GOOD! HERE'S ANOTHER.", "SORRY...FIGARO WAS HIS NAME.")
println()
score += await evaluateQuestion("FROM WHOSE GARDEN DID BUGS BUNNY STEAL THE CARROTS?",
"1)MR. NIXON'S, 2)ELMER FUDD'S, 3)CLEM JUDD'S, 4)STROMBOLI'S", 2,
[ "MR. NIXON'S", "ELMER FUDD'S", "CLEM JUDD'S", "STROMBOLI'S" ], 2,
"PRETTY GOOD!", "TOO BAD...IT WAS ELMER FUDD'S GARDEN.")
println()
score += await evaluateQuestion("IN THE WIZARD OF OS, DOROTHY'S DOG WAS NAMED",
"1)CICERO, 2)TRIXIA, 3)KING, 4)TOTO", 4,
[ "CICERO", "TRIXIA", "KING", "TOTO" ], 4,
"YEA! YOU'RE A REAL LITERATURE GIANT.",
"BACK TO THE BOOKS,...TOTO WAS HIS NAME.")
println()
score += await evaluateQuestion("WHO WAS THE FAIR MAIDEN WHO ATE THE POISON APPLE",
"1)SLEEPING BEAUTY, 2)CINDERELLA, 3)SNOW WHITE, 4)WENDY", 3,
[ "SLEEPING BEAUTY", "CINDERELLA", "SNOW WHITE", "WENDY" ], 3,
"GOOD MEMORY!", "OH, COME ON NOW...IT WAS SNOW WHITE.")
println();println()
println("\n")
if(score === 4) {
println("WOW! THAT'S SUPER! YOU REALLY KNOW YOUR NURSERY\n"+
+9 -11
View File
@@ -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)
+20 -22
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
@@ -108,7 +106,7 @@ def main() -> None:
position += length
print(line_text)
print("")
print()
if __name__ == "__main__":
+147 -158
View File
@@ -6,8 +6,9 @@ Lunar landing simulation
Ported by Dave LeCompte
"""
import collections
import math
from dataclasses import dataclass
from typing import Any, NamedTuple
PAGE_WIDTH = 64
@@ -32,7 +33,10 @@ FUEL_RIGHT = FUEL_LEFT + FUEL_WIDTH
BURN_LEFT = FUEL_RIGHT + COLUMN_WIDTH
BURN_RIGHT = BURN_LEFT + BURN_WIDTH
PhysicalState = collections.namedtuple("PhysicalState", ["velocity", "altitude"])
class PhysicalState(NamedTuple):
velocity: float
altitude: float
def print_centered(msg: str) -> None:
@@ -42,29 +46,24 @@ def print_centered(msg: str) -> None:
def print_header(title: str) -> None:
print_centered(title)
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
def add_rjust(line, s, pos):
# adds a new field to a line right justified to end at pos
s = str(s)
slen = len(s)
def add_rjust(line: str, s: Any, pos: int) -> str:
"""Add a new field to a line right justified to end at pos"""
s_str = str(s)
slen = len(s_str)
if len(line) + slen > pos:
new_len = pos - slen
line = line[:new_len]
if len(line) + slen < pos:
spaces = " " * (pos - slen - len(line))
line = line + spaces
return line + s
return line + s_str
def add_ljust(line, s, pos):
# adds a new field to a line left justified starting at pos
def add_ljust(line: str, s: str, pos: int) -> str:
"""Add a new field to a line left justified starting at pos"""
s = str(s)
if len(line) > pos:
line = line[:pos]
@@ -75,32 +74,129 @@ def add_ljust(line, s, pos):
def print_instructions() -> None:
# Somebody had a bad experience with Xerox.
"""Somebody had a bad experience with Xerox."""
print("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR")
print("LANDING CAPSULE.")
print()
print()
print("LANDING CAPSULE.\n\n")
print("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY")
print("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.")
print()
print("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.\n")
def print_intro() -> None:
print("SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN")
print("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.")
print("SET NEW BURN RATE EVERY 10 SECONDS.")
print()
print("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.")
print()
print()
print()
print("GOOD LUCK")
print()
print("SET NEW BURN RATE EVERY 10 SECONDS.\n")
print("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.\n\n\n")
print("GOOD LUCK\n")
def show_landing(sim_clock, capsule):
w = 3600 * capsule.v
def format_line_for_report(
t: Any,
miles: Any,
feet: Any,
velocity: Any,
fuel: Any,
burn_rate: str,
is_header: bool,
) -> str:
line = add_rjust("", t, SECONDS_RIGHT)
line = add_rjust(line, miles, ALT_MI_RIGHT)
line = add_rjust(line, feet, ALT_FT_RIGHT)
line = add_rjust(line, velocity, MPH_RIGHT)
line = add_rjust(line, fuel, FUEL_RIGHT)
if is_header:
line = add_rjust(line, burn_rate, BURN_RIGHT)
else:
line = add_ljust(line, burn_rate, BURN_LEFT)
return line
class SimulationClock:
def __init__(self, elapsed_time: float, time_until_next_prompt: float) -> None:
self.elapsed_time = elapsed_time
self.time_until_next_prompt = time_until_next_prompt
def time_for_prompt(self) -> bool:
return self.time_until_next_prompt < 1e-3
def advance(self, delta_t: float) -> None:
self.elapsed_time += delta_t
self.time_until_next_prompt -= delta_t
@dataclass
class Capsule:
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
def is_out_of_fuel(self) -> bool:
return self.remaining_fuel() < 1e-3
def update_state(
self, sim_clock: SimulationClock, delta_t: float, new_state: PhysicalState
) -> None:
sim_clock.advance(delta_t)
self.m = self.m - delta_t * self.fuel_per_second
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
assert self.fuel_per_second > 0
return self.remaining_fuel() / self.fuel_per_second
def predict_motion(self, delta_t: float) -> PhysicalState:
# Perform an Euler's Method numerical integration of the equations of motion.
q = delta_t * self.fuel_per_second / self.m
# new velocity
new_velocity = (
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.altitude
- self.g * delta_t**2 / 2
- self.velocity * delta_t
+ self.z
* delta_t
* (q / 2 + q**2 / 6 + q**3 / 12 + q**4 / 20 + q**5 / 30)
)
return PhysicalState(altitude=new_altitude, velocity=new_velocity)
def make_state_display_string(self, sim_clock: SimulationClock) -> str:
seconds = sim_clock.elapsed_time
miles = int(self.altitude)
feet = int(5280 * (self.altitude - miles))
velocity = int(3600 * self.velocity)
fuel = int(self.remaining_fuel())
burn_rate = " ? "
return format_line_for_report(
seconds, miles, feet, velocity, fuel, burn_rate, False
)
def prompt_for_burn(self, sim_clock: SimulationClock) -> None:
msg = self.make_state_display_string(sim_clock)
self.fuel_per_second = float(input(msg))
sim_clock.time_until_next_prompt = 10
def show_landing(sim_clock: SimulationClock, capsule: Capsule) -> None:
w = 3600 * capsule.velocity
print(
f"ON MOON AT {sim_clock.elapsed_time:.2f} SECONDS - IMPACT VELOCITY {w:.2f} MPH"
)
@@ -117,121 +213,20 @@ def show_landing(sim_clock, capsule):
end_sim()
def show_out_of_fuel(sim_clock, capsule):
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)
def format_line_for_report(t, miles, feet, velocity, fuel, burn_rate, is_header) -> str:
line = add_rjust("", t, SECONDS_RIGHT)
line = add_rjust(line, miles, ALT_MI_RIGHT)
line = add_rjust(line, feet, ALT_FT_RIGHT)
line = add_rjust(line, velocity, MPH_RIGHT)
line = add_rjust(line, fuel, FUEL_RIGHT)
if is_header:
line = add_rjust(line, burn_rate, BURN_RIGHT)
else:
line = add_ljust(line, burn_rate, BURN_LEFT)
return line
class Capsule:
def __init__(
self,
altitude=120,
velocity=1,
mass_with_fuel=33000,
mass_without_fuel=16500,
g=1e-3,
z=1.8,
):
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 = 0
def remaining_fuel(self):
return self.m - self.n
def is_out_of_fuel(self):
return self.remaining_fuel() < 1e-3
def update_state(self, sim_clock, delta_t, new_state):
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
def fuel_time_remaining(self):
# extrapolates out how many seconds we have at the current fuel burn rate
assert self.fuel_per_second > 0
return self.remaining_fuel() / self.fuel_per_second
def predict_motion(self, delta_t):
# Perform an Euler's Method numerical integration of the equations of motion.
q = delta_t * self.fuel_per_second / self.m
# new velocity
new_velocity = (
self.v
+ 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.g * delta_t**2 / 2
- self.v * delta_t
+ self.z
* delta_t
* (q / 2 + q**2 / 6 + q**3 / 12 + q**4 / 20 + q**5 / 30)
)
return PhysicalState(altitude=new_altitude, velocity=new_velocity)
def make_state_display_string(self, sim_clock) -> str:
seconds = sim_clock.elapsed_time
miles = int(self.a)
feet = int(5280 * (self.a - miles))
velocity = int(3600 * self.v)
fuel = int(self.remaining_fuel())
burn_rate = " ? "
return format_line_for_report(
seconds, miles, feet, velocity, fuel, burn_rate, False
)
def prompt_for_burn(self, sim_clock):
msg = self.make_state_display_string(sim_clock)
self.fuel_per_second = float(input(msg))
sim_clock.time_until_next_prompt = 10
class SimulationClock:
def __init__(self, elapsed_time, time_until_next_prompt):
self.elapsed_time = elapsed_time
self.time_until_next_prompt = time_until_next_prompt
def time_for_prompt(self):
return self.time_until_next_prompt < 1e-3
def advance(self, delta_t):
self.elapsed_time += delta_t
self.time_until_next_prompt -= delta_t
def process_final_tick(delta_t, sim_clock, capsule):
def process_final_tick(
delta_t: float, sim_clock: SimulationClock, capsule: Capsule
) -> None:
# When we extrapolated our position based on our velocity
# and delta_t, we overshot the surface. For better
# accuracy, we will back up and do shorter time advances.
@@ -242,20 +237,20 @@ def process_final_tick(delta_t, sim_clock, capsule):
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)
def handle_flyaway(sim_clock, capsule):
def handle_flyaway(sim_clock: SimulationClock, capsule: Capsule) -> bool:
"""
The user has started flying away from the moon. Since this is a
lunar LANDING simulation, we wait until the capsule's velocity is
@@ -268,11 +263,11 @@ def handle_flyaway(sim_clock, capsule):
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
@@ -284,22 +279,16 @@ def handle_flyaway(sim_clock, capsule):
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
def end_sim():
print()
print()
print()
print("TRY AGAIN??")
print()
print()
print()
def end_sim() -> None:
print("\n\n\nTRY AGAIN??\n\n\n")
def run_simulation():
def run_simulation() -> None:
print()
print(
format_line_for_report("SEC", "MI", "FT", "MPH", "LB FUEL", "BURN RATE", True)
@@ -334,7 +323,7 @@ def run_simulation():
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)
+4 -4
View File
@@ -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:")
+5 -4
View File
@@ -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
+7 -23
View File
@@ -7,45 +7,29 @@ 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):
def is_yes_ish(answer: str) -> bool:
cleaned = answer.strip().upper()
if cleaned == "Y" or cleaned == "YES":
if cleaned in ["Y", "YES"]:
return True
return False
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()
+4 -15
View File
@@ -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()
+10 -10
View File
@@ -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")
+3 -15
View File
@@ -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()
+24 -35
View File
@@ -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__":
+4 -7
View File
@@ -81,7 +81,7 @@ GOOD LUCK. THE FEDERATION IS COUNTING ON YOU.
)
def get_yes_or_no():
def get_yes_or_no() -> bool:
while True:
response = input().upper()
if response == "YES":
@@ -92,7 +92,7 @@ def get_yes_or_no():
print("PLEASE TYPE 'YES' OR 'NO'")
def game_over(is_success):
def game_over(is_success: bool) -> bool:
if is_success:
print("YOU HAVE SUCCESSFULLY COMPLETED YOUR MISSION.")
else:
@@ -103,7 +103,7 @@ def game_over(is_success):
return get_yes_or_no()
def play_game():
def play_game() -> bool:
rom_angle = random.randint(0, 359)
rom_distance = random.randint(100, 300)
rom_angular_velocity = random.randint(10, 30)
@@ -145,10 +145,7 @@ def play_game():
def main() -> None:
print_centered("ORBIT")
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print()
print()
print()
print_centered("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n")
print_instructions()
+132
View File
@@ -0,0 +1,132 @@
PAGE_WIDTH = 64
def print_centered(msg)
spaces = " " * ((PAGE_WIDTH / msg.length).fdiv(2))
puts "#{spaces}#{msg}"
end
def print_instructions
puts "SOMEWHERE ABOVE YOUR PLANET IS A ROMULAN SHIP.
THE SHIP IS IN A CONSTANT POLAR ORBIT. ITS
DISTANCE FROM THE CENTER OF YOUR PLANET IS FROM
10,000 TO 30,000 MILES AND AT ITS PRESENT VELOCITY CAN
CIRCLE YOUR PLANET ONCE EVERY 12 TO 36 HOURS.
UNFORTUNATELY, THEY ARE USING A CLOAKING DEVICE SO
YOU ARE UNABLE TO SEE THEM, BUT WITH A SPECIAL
INSTRUMENT YOU CAN TELL HOW NEAR THEIR SHIP YOUR
PHOTON BOMB EXPLODED. YOU HAVE SEVEN HOURS UNTIL THEY
HAVE BUILT UP SUFFICIENT POWER IN ORDER TO ESCAPE
YOUR PLANET'S GRAVITY.
YOUR PLANET HAS ENOUGH POWER TO FIRE ONE BOMB AN HOUR.
AT THE BEGINNING OF EACH HOUR YOU WILL BE ASKED TO GIVE AN
ANGLE (BETWEEN 0 AND 360) AND A DISTANCE IN UNITS OF
100 MILES (BETWEEN 100 AND 300), AFTER WHICH YOUR BOMB'S
DISTANCE FROM THE ENEMY SHIP WILL BE GIVEN.
AN EXPLOSION WITHIN 5,000 MILES OF THE ROMULAN SHIP
WILL DESTROY IT.
BELOW IS A DIAGRAM TO HELP YOU VISUALIZE YOUR PLIGHT.
90
0000000000000
0000000000000000000
000000 000000
00000 00000
00000 XXXXXXXXXXX 00000
00000 XXXXXXXXXXXXX 00000
0000 XXXXXXXXXXXXXXX 0000
0000 XXXXXXXXXXXXXXXXX 0000
0000 XXXXXXXXXXXXXXXXXXX 0000
180<== 00000 XXXXXXXXXXXXXXXXXXX 00000 ==>0
0000 XXXXXXXXXXXXXXXXXXX 0000
0000 XXXXXXXXXXXXXXXXX 0000
0000 XXXXXXXXXXXXXXX 0000
00000 XXXXXXXXXXXXX 00000
00000 XXXXXXXXXXX 00000
00000 00000
000000 000000
0000000000000000000
0000000000000
270
X - YOUR PLANET
O - THE ORBIT OF THE ROMULAN SHIP
ON THE ABOVE DIAGRAM, THE ROMULAN SHIP IS CIRCLING
COUNTERCLOCKWISE AROUND YOUR PLANET. DON'T FORGET THAT
WITHOUT SUFFICIENT POWER THE ROMULAN SHIP'S ALTITUDE
AND ORBITAL RATE WILL REMAIN CONSTANT.
GOOD LUCK. THE FEDERATION IS COUNTING ON YOU.
"
end
def get_yes_or_no()
while true
response = gets.chomp!.upcase
if response == "YES"
return true
elsif response == "NO"
return false
else
print("PLEASE TYPE 'YES' OR 'NO'")
end
end
end
def game_over(is_success)
if is_success
puts "YOU HAVE SUCCESSFULLY COMPLETED YOUR MISSION."
else
puts "YOU HAVE ALLOWED THE ROMULANS TO ESCAPE."
puts "ANOTHER ROMULAN SHIP HAS GONE INTO ORBIT."
puts "DO YOU WISH TO TRY TO DESTROY IT?"
return get_yes_or_no()
end
end
def play_game
rom_angle = rand(1...360)
rom_distance = rand(100...301)
rom_angular_velocity = rand(10...31)
hour = 0
while hour < 7
hour += 1
puts "\n\n"
puts "THIS IS HOUR #{hour}, AT WHAT ANGLE DO YOU WISH TO SEND"
puts "YOUR PHOTON BOMB?"
bomb_angle = gets.chomp!.to_f
puts "HOW FAR OUT DO YOU WISH TO DETONATE IT?"
bomb_distance = gets.chomp!.to_f
puts "\n\n"
rom_angle = (rom_angle + rom_angular_velocity) % 360
angular_difference = rom_angle - bomb_angle
c = Math.sqrt(rom_distance**2 + bomb_distance**2 - 2 * rom_distance * bomb_distance * Math.cos(angular_difference * Math::PI / 180))
puts "YOUR PHOTON BOMB EXPLODED #{sprintf('%.4f', 5)}*10^2 MILES FROM THE"
puts "ROMULAN SHIP."
if c <= 50
# Destroyed the Romulan
return true
end
end
return false
end
def main
print_centered "ORBIT"
print_instructions()
while true
success = play_game()
again = game_over(success)
if !again
return
end
end
end
if __FILE__ == $0
main
end
+4 -4
View File
@@ -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)
+53 -80
View File
@@ -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__":
+2 -9
View File
@@ -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)
+5 -7
View File
@@ -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
@@ -1,10 +0,0 @@
<html>
<head>
<title>ROCK, SCISSORS, PAPER</title>
<link rel="stylesheet" href="../../00_Utilities/javascript/style_terminal.css" />
</head>
<body>
<pre id="output"></pre>
<script src="rockscissors.js"></script>
</body>
</html>
@@ -1,107 +0,0 @@
// ROCK, SCISSORS, PAPER
//
// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
//
function print(str)
{
document.getElementById("output").appendChild(document.createTextNode(str));
}
function input()
{
var input_element;
var input_str;
return new Promise(function (resolve) {
input_element = document.createElement("INPUT");
print("? ");
input_element.setAttribute("type", "text");
input_element.setAttribute("length", "50");
document.getElementById("output").appendChild(input_element);
input_element.focus();
input_str = undefined;
input_element.addEventListener("keydown", function (event) {
if (event.keyCode == 13) {
input_str = input_element.value;
document.getElementById("output").removeChild(input_element);
print(input_str);
print("\n");
resolve(input_str);
}
});
});
}
function tab(space)
{
var str = "";
while (space-- > 0)
str += " ";
return str;
}
// Main control section
async function main()
{
print(tab(21) + "GAME OF ROCK, SCISSORS, PAPER\n");
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
print("\n");
print("\n");
print("\n");
while (1) {
print("HOW MANY GAMES");
q = parseInt(await input());
if (q >= 11)
print("SORRY, BUT WE AREN'T ALLOWED TO PLAY THAT MANY.\n");
else
break;
}
h = 0; // Human
c = 0; // Computer
for (g = 1; g <= q; g++ ) {
print("\n");
print("GAME NUMBER " + g + "\n");
x = Math.floor(Math.random() * 3 + 1);
while (1) {
print("3=ROCK...2=SCISSORS...1=PAPER\n");
print("1...2...3...WHAT'S YOUR CHOICE");
k = parseInt(await input());
if (k != 1 && k != 2 && k != 3)
print("INVALID.\n");
else
break;
}
print("THIS IS MY CHOICE...");
switch (x) {
case 1:
print("...PAPER\n");
break;
case 2:
print("...SCISSORS\n");
break;
case 3:
print("...ROCK\n");
break;
}
if (x == k) {
print("TIE GAME. NO WINNER.\n");
} else if ((x > k && (k != 1 || x != 3)) || (x == 1 && k == 3)) {
print("WOW! I WIN!!!\n");
c++;
} else {
print("YOU WIN!!!\n");
h++;
}
}
print("\n");
print("HERE IS THE FINAL GAME SCORE:\n");
print("I HAVE WON " + c + " GAME(S).\n");
print("YOU HAVE WON " + h + " GAME(S).\n");
print("AND " + (q - (c + h)) + " GAME(S) ENDED IN A TIE.\n");
print("\n");
print("THANKS FOR PLAYING!!\n");
}
main();
@@ -0,0 +1,117 @@
#!/usr/bin/env node
// ROCK, SCISSORS, PAPER
//
// Converted from BASIC to Javascript by Alexander Wunschik (mojoaxel)
import { println, tab, input } from '../../00_Common/javascript/common.mjs';
let userWins = 0;
let computerWins = 0;
let ties = 0;
// 30 INPUT "HOW MANY GAMES";Q
// 40 IF Q<11 THEN 60
// 50 PRINT "SORRY, BUT WE AREN'T ALLOWED TO PLAY THAT MANY.": GOTO 30
// 60 FOR G=1 TO Q
async function getGameCount() {
let gameCount = await input("HOW MANY GAMES");
if (gameCount > 10) {
println("SORRY, BUT WE AREN'T ALLOWED TO PLAY THAT MANY.");
return await getGameCount();
}
return gameCount;
}
// #90 PRINT "3=ROCK...2=SCISSORS...1=PAPER"
// #100 INPUT "1...2...3...WHAT'S YOUR CHOICE";K
// #110 IF (K-1)*(K-2)*(K-3)<>0 THEN PRINT "INVALID.": GOTO 90
async function getUserInput() {
println("3=ROCK...2=SCISSORS...1=PAPER");
const userChoice = await input("1...2...3...WHAT'S YOUR CHOICE");
if (userChoice < 1 || userChoice > 3) {
println("INVALID.");
return await getUserInput();
}
return userChoice;
}
async function game() {
// 10 PRINT TAB(21);"GAME OF ROCK, SCISSORS, PAPER"
// 20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
// 25 PRINT:PRINT:PRINT
println(tab(21), 'GAME OF ROCK, SCISSORS, PAPER');
println(tab(15), 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY');
println('\n\n');
let gameCount = await getGameCount();
async function playGame(gameNumber) {
// 70 PRINT: PRINT "GAME NUMBER";G
println("\nGAME NUMBER ", gameNumber);
const ROCK = 3;
const SCISSORS = 2;
const PAPER = 1;
const usersChoice = await getUserInput();
// 80 X=INT(RND(1)*3+1)
const computersChoice = Math.floor(Math.random()*3) + 1;
// 120 PRINT "THIS IS MY CHOICE..."
// 130 ON X GOTO 140,150,160
// 140 PRINT "...PAPER": GOTO 170
// 150 PRINT "...SCISSORS": GOTO 170
// 160 PRINT "...ROCK"
println("THIS IS MY CHOICE...",
computersChoice === PAPER ? "...PAPER" :
computersChoice === SCISSORS ? "...SCISSORS" :
"...ROCK");
// 170 IF X=K THEN 250
// 180 IF X>K THEN 230
// 190 IF X=1 THEN 210
// 200 PRINT "YOU WIN!!!":H=H+1: GOTO 260
// 210 IF K<>3 THEN 200
// 220 PRINT "WOW! I WIN!!!":C=C+1:GOTO 260
// 230 IF K<>1 OR X<>3 THEN 220
// 240 GOTO 200
// 250 PRINT "TIE GAME. NO WINNER."
if (computersChoice == usersChoice) {
println("TIE GAME. NO WINNER.");
ties++;
} else if (
(computersChoice == ROCK && usersChoice == SCISSORS) ||
(computersChoice == PAPER && usersChoice == ROCK) ||
(computersChoice == SCISSORS && usersChoice == PAPER)
) {
println("WOW! I WIN!!!");
computerWins++;
} else {
println("YOU WIN!!!");
userWins++;
}
}
for (let gameNumber = 1; gameNumber <= gameCount; gameNumber++) {
await playGame(gameNumber);
// 260 NEXT G
}
// 270 PRINT: PRINT "HERE IS THE FINAL GAME SCORE:"
// 280 PRINT "I HAVE WON";C;"GAME(S)."
// 290 PRINT "YOU HAVE WON";H;"GAME(S)."
// 300 PRINT "AND";Q-(C+H20);"GAME(S) ENDED IN A TIE."
println("\nHERE IS THE FINAL GAME SCORE:");
println(`I HAVE WON ${computerWins} GAME(S).`);
println(`YOU HAVE WON ${userWins} GAME(S).`);
println(`AND ${ties} GAME(S) ENDED IN A TIE.`);
// 310 PRINT: PRINT "THANKS FOR PLAYING!!"
println("\nTHANKS FOR PLAYING!!");
// 320 END
process.exit(0);
}
game();
@@ -6,7 +6,7 @@
import random
def play_game():
def play_game() -> None:
"""Play one round of the game"""
while True:
+4 -4
View File
@@ -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)
+14 -16
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
+101 -145
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,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
-16
View File
@@ -1,16 +0,0 @@
<html>
<head>
<title>SINE WAVE</title>
<link rel="stylesheet" href="../../00_Utilities/javascript/style_terminal.css" />
</head>
<body>
<pre id="output"></pre>
<script>
/* redirect console.log messages to the output-element in the DOM */
window.console = {
log: (text) => document.getElementById("output").innerHTML += text + "<br>"
}
</script>
<script src="sinewave.js"></script>
</body>
</html>
-22
View File
@@ -1,22 +0,0 @@
print(tab(30), "SINE WAVE");
print(tab(15), "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
print("\n\n\n\n");
// REMARKABLE PROGRAM BY DAVID AHL
// Transliterated to Javascript by Les Orchard <me@lmorchard.com>
let toggleWord = true;
for (let step = 0; step < 40; step += 0.25) {
let indent = Math.floor(26 + 25 * Math.sin(step));
print(tab(indent), toggleWord ? "CREATIVE" : "COMPUTING");
toggleWord = !toggleWord;
}
function print(...messages) {
console.log(messages.join(" "));
}
function tab(count) {
return " ".repeat(count);
}
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env node
import { println, tab } from '../../00_Common/javascript/common.mjs';
println(tab(30), "SINE WAVE");
println(tab(15), "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
println("\n".repeat(4));
// REMARKABLE PROGRAM BY DAVID AHL
// Transliterated to Javascript by Les Orchard <me@lmorchard.com>
let toggleWord = true;
for (let step = 0; step < 40; step += 0.25) {
let indent = Math.floor(26 + 25 * Math.sin(step));
println(tab(indent), toggleWord ? "CREATIVE" : "COMPUTING");
toggleWord = !toggleWord;
}
+5 -5
View File
@@ -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):
+8 -7
View File
@@ -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
+15 -16
View File
@@ -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
+8 -10
View File
@@ -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:
+2827 -7
View File
File diff suppressed because one or more lines are too long
+2684 -15
View File
File diff suppressed because one or more lines are too long
+3127 -138
View File
File diff suppressed because one or more lines are too long
+17
View File
@@ -0,0 +1,17 @@
[package]
<<<<<<< HEAD
name = "rust"
=======
name = "stars"
>>>>>>> 3e27c70ca800f5efbe6bc1a7d180211decf55b7d
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
<<<<<<< HEAD
rand = "0.8.5"
=======
rand = "0.8.3"
>>>>>>> 3e27c70ca800f5efbe6bc1a7d180211decf55b7d
+29
View File
@@ -0,0 +1,29 @@
<<<<<<< HEAD
#STARS
From: BASIC Computer Games (1978), edited by David H. Ahl
In this game, the computer selects a random number from 1 to 100
(or any value you set [for MAX_NUM]). You try to guess the number
and the computer gives you clues to tell you how close you're
getting. One star (*) means you're far away from the number; seven
stars (*******) means you're really close. You get 7 guesses.
On the surface this game is very similar to GUESS; however, the
guessing strategy is quite different. See if you can come up with
one or more approaches to finding the mystery number.
Bob Albrecht of People's Computer Company created this game.
## NOTES
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/) by JW Bruce
thanks to Jeff Jetton for his Python port which provide inspiration
=======
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/)
>>>>>>> 3e27c70ca800f5efbe6bc1a7d180211decf55b7d
+236
View File
@@ -0,0 +1,236 @@
<<<<<<< HEAD
//
// Stars
//
// From: BASIC Computer Games (1978), edited by David H. Ahl
//
// In this game, the computer selects a random number from 1 to 100
// (or any value you set [for MAX_NUM]). You try to guess the number
// and the computer gives you clues to tell you how close you're
// getting. One star (*) means you're far away from the number; seven
// stars (*******) means you're really close. You get 7 guesses.
//
// On the surface this game is very similar to GUESS; however, the
// guessing strategy is quite different. See if you can come up with
// one or more approaches to finding the mystery number.
//
// Bob Albrecht of People's Computer Company created this game.
//
// rust port by JW BRUCE 2022
//
// ********************************************************************
//
// Porting Notes (taken for Jeff Jetton's Python version)
//
// The original program never exited--it just kept playing rounds
// over and over. This version asks to continue each time.
//
// Ideas for Modifications
//
// Let the player know how many guesses they have remaining after
// each incorrect guess.
//
// Ask the player to select a skill level at the start of the game,
// which will affect the values of MAX_NUM and MAX_GUESSES.
// For example:
//
// Easy = 8 guesses, 1 to 50
// Medium = 7 guesses, 1 to 100
// Hard = 6 guesses, 1 to 200
//
// *********************************************************************
// I M P O R T S
use std::io;
use std::io::stdin;
//use std::io::{stdin, stdout, Write};
use rand::Rng;
const MAX_NUM: u8 = 100;
const MAX_GUESSES: u8 = 7;
fn main() -> io::Result<()> {
print_header();
if !read_lowercase_input()?.starts_with('n') {
print_rules();
}
loop {
let secret_number : u8 = rand::thread_rng().gen_range(1..101);
let mut guess_count = 0;
let mut player_won: bool = false;
println!("\n\nOK, I am thinking of a number, start guessing.");
while guess_count < MAX_GUESSES && !player_won {
guess_count += 1;
println!("Your guess? ");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
let guess: u8 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
// USE THIS STATEMENT FOR DEBUG PURPOSES
// println!("Guess #{} is {}. secret number is {}",guess_count, guess, secret_number);
if guess == secret_number {
// winner winner chicken dinner
player_won = true;
println!("**************************************************!!!");
println!("You got it in {guess_count} guesses!!!");
} else {
print_stars( guess, secret_number) ;
}
}
// player exhausted their number of guesses and did not win.
if !player_won {
println!("Sorry, that's {guess_count} guesses, number was {secret_number}");
}
println!("\nPlay again (yes or no)?");
if !read_lowercase_input()?.starts_with('y') {
return Ok(());
=======
use rand::Rng;
use std::io;
fn main() {
println!(
"{: >39}\n{: >57}\n\n\n",
"STARS", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
);
// STARS - PEOPLE'S COMPUTER CENTER, MENLO PARK, CA
// A IS LIMIT ON NUMBER, M IS NUMBER OF GUESSES
let a: u32 = 101;
let m: u32 = 7;
let mut need_instrut = String::new();
println!("DO YOU WANT INSTRUCTIONS?");
io::stdin()
.read_line(&mut need_instrut)
.expect("Failed to get input");
if need_instrut[..1].to_ascii_lowercase().eq("y") {
println!("I AM THINKING OF A WHOLE NUMBER FROM 1 TO {}", a - 1);
println!("TRY TO GUESS MY NUMBER. AFTER YOU GUESS, I");
println!("WILL TYPE ONE OR MORE STARS (*). THE MORE");
println!("STARS I TYPE, THE CLOSER YOU ARE TO MY NUMBER.");
println!("ONE STAR (*) MEANS FAR AWAY, SEVEN STARS (*******)");
println!("MEANS REALLY CLOSE! YOU GET {} GUESSES.\n\n", m);
}
loop {
println!("\nOK, I AM THINKING OF A NUMBER, START GUESSING.\n");
let rand_number: i32 = rand::thread_rng().gen_range(1..a) as i32; // generates a random number between 1 and 100
// GUESSING BEGINS, HUMAN GETS M GUESSES
for i in 0..m {
let mut guess = String::new();
println!("YOUR GUESS?");
io::stdin()
.read_line(&mut guess)
.expect("Failed to get input");
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("PLEASE ENTER A NUMBER VALUE.\n");
continue;
}
};
if guess == rand_number {
print!("");
for _i in 0..50 {
print!("*");
}
println!("!!!");
println!("YOU GOT IT IN {} GUESSES!!! LET'S PLAY AGAIN...\n", i + 1);
break;
} else {
match_guess(rand_number - guess);
}
if i == 6 {
println!(
"SORRY, THAT'S {} GUESSES. THE NUMBER WAS {}",
m, rand_number
);
}
>>>>>>> 3e27c70ca800f5efbe6bc1a7d180211decf55b7d
}
}
}
<<<<<<< HEAD
// guess is wrong, so print stars to show how far away they are
fn print_stars( guess: u8, target: u8) {
// choose to use u8 in main, but currently (1.59.0) does not
// have abs() defined for u8. abs() is defined for i16, so
// this provide an opportunity to demonstrate casting in rust
let diff : i16 = ((guess as i16)-(target as i16)).abs();
// Since we only print 1-7 stars, this finite set of choices is
// small enough that we can use rust's match keyword.
// The match "arms" here use the inclusive range notation.
// The exlusive range notation is not an approved feature of
// rust, yet.
match diff {
1..=2 => println!("*******"),
3..=4 => println!("******"),
5..=8 => println!("*****"),
9..=16 => println!("****"),
17..=32 => println!("***"),
33..=64 => println!("**"),
_ => println!("*"),
}
}
//
fn read_lowercase_input() -> io::Result<String> {
let mut input = String::new();
stdin().read_line(&mut input)?;
Ok(input.trim().to_lowercase())
}
// Text to print at the start of the game
fn print_header() {
println!("\n Stars");
println!("Creative-Computing Morristown, New Jersey");
println!("\n\n");
println!("Do you want instructions? ");
}
// Instructions on how to play
fn print_rules() {
println!();
println!("I am thinking of a whole number from 1 to {}", MAX_NUM);
println!("Try to guess my number. After you guess, I");
println!("will type one or more stars (*). The more");
println!("stars I type, the closer you are to my number.");
println!("one star (*) means far away, seven stars (*******)");
println!("means really close! You get {} guesses.", MAX_GUESSES);
}
=======
fn match_guess(diff: i32) {
if diff.abs() >= 64 {
println!("*\n");
} else if diff.abs() >= 32 {
println!("**\n");
} else if diff.abs() >= 16 {
println!("***\n");
} else if diff.abs() >= 8 {
println!("****\n");
} else if diff.abs() >= 4 {
println!("*****\n");
} else if diff.abs() >= 2 {
println!("******\n");
} else {
println!("*******\n");
}
}
>>>>>>> 3e27c70ca800f5efbe6bc1a7d180211decf55b7d
+21 -29
View File
@@ -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,13 +175,12 @@ 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)? ")
# Printing Instruction
if help == "YES" or help == "yes" or help == "Yes":
if help.lower() == "yes":
print_instruction()
# Initialize Game
@@ -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()

Some files were not shown because too many files have changed in this diff Show More