mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-07-01 18:44:33 -07:00
Merge branch 'main' of https://github.com/coding-horror/basic-computer-games into main
This commit is contained in:
@@ -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();
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)? ")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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] = []
|
||||
|
||||
|
||||
@@ -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
@@ -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")
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
]
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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__":
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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__":
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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? ")
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
+35
-38
@@ -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"+
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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:")
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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__":
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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__":
|
||||
|
||||
@@ -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 +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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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):
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because one or more lines are too long
+2684
-15
File diff suppressed because one or more lines are too long
+3127
-138
File diff suppressed because one or more lines are too long
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user