mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-29 14:15:08 -08:00
Merge branch 'coding-horror:main' into 48_High_IQ_Python
This commit is contained in:
2
01_Acey_Ducey/d/.gitignore
vendored
Normal file
2
01_Acey_Ducey/d/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.exe
|
||||
*.obj
|
||||
29
01_Acey_Ducey/d/README.md
Normal file
29
01_Acey_Ducey/d/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html)
|
||||
|
||||
Converted to [D](https://dlang.org/) by [Bastiaan Veelo](https://github.com/veelo).
|
||||
|
||||
Two versions are supplied that are functionally equivalent, but differ in source layout:
|
||||
|
||||
<dl>
|
||||
<dt><tt>aceyducey_literal.d</tt></dt>
|
||||
<dd>A largely literal transcription of the original Basic source. All unnecessary uglyness is preserved.</dd>
|
||||
<dt><tt>aceyducey.d</tt></dt>
|
||||
<dd>An idiomatic D refactoring of the original, with a focus on increasing the readability and robustness.
|
||||
Memory-safety <A href="https://dlang.org/spec/memory-safe-d.html">is ensured by the language</a>, thanks to the
|
||||
<tt>@safe</tt> annotation.</dd>
|
||||
</dl>
|
||||
|
||||
## Running the code
|
||||
|
||||
Assuming the reference [dmd](https://dlang.org/download.html#dmd) compiler:
|
||||
```shell
|
||||
dmd -run aceyducey.d
|
||||
```
|
||||
|
||||
[Other compilers](https://dlang.org/download.html) also exist.
|
||||
|
||||
Note that there are compiler switches related to memory-safety (`-preview=dip25` and `-preview=dip1000`) that are not
|
||||
used here because they are unnecessary in this case. What these do is to make the analysis more thorough, so that with
|
||||
them some code that needed to be `@system` can then be inferred to be in fact `@safe`. [Code that compiles without
|
||||
these switches is just as safe as when compiled with them]
|
||||
(https://forum.dlang.org/post/dftgjalswvwfjpyushgn@forum.dlang.org).
|
||||
131
01_Acey_Ducey/d/aceyducey.d
Normal file
131
01_Acey_Ducey/d/aceyducey.d
Normal file
@@ -0,0 +1,131 @@
|
||||
@safe: // Make @safe the default for this file, enforcing memory-safety.
|
||||
|
||||
void main()
|
||||
{
|
||||
import std.stdio : write, writeln;
|
||||
import std.string : center, toUpper, wrap;
|
||||
import std.exception : ifThrown;
|
||||
|
||||
enum width = 80;
|
||||
writeln(center("Acey Ducey Card Game", width));
|
||||
writeln(center("(After Creative Computing Morristown, New Jersey)\n", width));
|
||||
writeln(wrap("Acey-Ducey is played in the following manner: The dealer (computer) deals two cards face up. " ~
|
||||
"You have an option to bet or not bet depending on whether or not you feel the third card will " ~
|
||||
"have a value between the first two. If you do not want to bet, input a 0.", width));
|
||||
|
||||
enum Hand {low, middle, high}
|
||||
Card[Hand.max + 1] cards; // Three cards.
|
||||
bool play = true;
|
||||
|
||||
while (play)
|
||||
{
|
||||
int cash = 100;
|
||||
while (cash > 0)
|
||||
{
|
||||
writeln("\nYou now have ", cash, " dollars.");
|
||||
int bet = 0;
|
||||
while (bet <= 0)
|
||||
{
|
||||
do // Draw new cards, until the first card has a smaller value than the last card.
|
||||
{
|
||||
foreach (ref card; cards)
|
||||
card.drawNew;
|
||||
} while (cards[Hand.low] >= cards[Hand.high]);
|
||||
writeln("Here are your next two cards:\n", cards[Hand.low], "\n", cards[Hand.high]);
|
||||
|
||||
int askBet() // A nested function.
|
||||
{
|
||||
import std.conv : to;
|
||||
|
||||
write("\nWhat is your bet? ");
|
||||
int answer = readString.to!int.
|
||||
ifThrown!Exception(askBet); // Try again when answer does not convert to int.
|
||||
if (answer <= cash)
|
||||
return answer;
|
||||
writeln("Sorry, my friend, but you bet too much.\nYou have only ", cash, " dollars to bet.");
|
||||
return askBet; // Recurse: Ask again.
|
||||
}
|
||||
bet = askBet;
|
||||
if (bet <= 0) // Negative bets are interpreted as 0.
|
||||
writeln("CHICKEN!!");
|
||||
} // bet is now > 0.
|
||||
|
||||
writeln(cards[Hand.middle]);
|
||||
if (cards[Hand.low] < cards[Hand.middle] && cards[Hand.middle] < cards[Hand.high])
|
||||
{
|
||||
writeln("YOU WIN!!!");
|
||||
cash += bet;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln("Sorry, you lose.");
|
||||
cash -= bet;
|
||||
if (cash <= 0)
|
||||
{
|
||||
writeln("\n\nSorry, friend, but you blew your wad.");
|
||||
write("\n\nTry again (Yes or No)? ");
|
||||
play = readString.toUpper == "YES";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln("O.K., hope you had fun!");
|
||||
}
|
||||
|
||||
struct Card
|
||||
{
|
||||
int value = 2;
|
||||
alias value this; // Enables Card to stand in as an int, so that cards can be compared as ints.
|
||||
|
||||
invariant
|
||||
{
|
||||
assert(2 <= value && value <= 14); // Ensure cards always have a valid value.
|
||||
}
|
||||
|
||||
/// Adopt a new value.
|
||||
void drawNew()
|
||||
{
|
||||
import std.random : uniform;
|
||||
|
||||
value = uniform!("[]", int, int)(2, 14); // A random int between inclusive bounds.
|
||||
}
|
||||
|
||||
/// Called for implicit conversion to string.
|
||||
string toString() const pure
|
||||
{
|
||||
import std.conv : text;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case 11: return "Jack";
|
||||
case 12: return "Queen";
|
||||
case 13: return "King";
|
||||
case 14: return "Ace";
|
||||
default: return text(" ", value); // Basic prepends a space.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a string from standard input, stripping newline and other enclosing whitespace.
|
||||
string readString() nothrow
|
||||
{
|
||||
import std.string : strip;
|
||||
|
||||
try
|
||||
return trustedReadln.strip;
|
||||
catch (Exception) // readln throws on I/O and Unicode errors, which we handle here.
|
||||
return "";
|
||||
}
|
||||
|
||||
/** An @trusted wrapper around readln.
|
||||
*
|
||||
* This is the only function that formally requires manual review for memory-safety.
|
||||
* [Arguably readln should be safe already](https://forum.dlang.org/post/rab398$1up$1@digitalmars.com)
|
||||
* which would remove the need to have any @trusted code in this program.
|
||||
*/
|
||||
string trustedReadln() @trusted
|
||||
{
|
||||
import std.stdio : readln;
|
||||
|
||||
return readln;
|
||||
}
|
||||
104
01_Acey_Ducey/d/aceyducey_literal.d
Normal file
104
01_Acey_Ducey/d/aceyducey_literal.d
Normal file
@@ -0,0 +1,104 @@
|
||||
void main()
|
||||
{
|
||||
import std;
|
||||
|
||||
L10: writef("%26s", ' '); writeln("ACEY DUCEY CARD GAME");
|
||||
L20: writef("%15s", ' '); writeln("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
|
||||
L21: writeln;
|
||||
L22: writeln;
|
||||
L30: writeln("ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER ");
|
||||
L40: writeln("THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP");
|
||||
L50: writeln("YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING");
|
||||
L60: writeln("ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE");
|
||||
L70: writeln("A VALUE BETWEEN THE FIRST TWO.");
|
||||
L80: writeln("IF YOU DO NOT WANT TO BET, INPUT A 0");
|
||||
L100: int N=100;
|
||||
L110: int Q=100, M;
|
||||
L120: writeln("YOU NOW HAVE ",Q," DOLLARS.");
|
||||
L130: writeln;
|
||||
L140: goto L260;
|
||||
L210: Q=Q+M;
|
||||
L220: goto L120;
|
||||
L240: Q=Q-M;
|
||||
L250: goto L120;
|
||||
L260: writeln("HERE ARE YOUR NEXT TWO CARDS: ");
|
||||
L270: auto A=to!int(14*uniform01)+2;
|
||||
L280: if (A<2) goto L270;
|
||||
L290: if (A>14) goto L270;
|
||||
L300: auto B=to!int(14*uniform01)+2;
|
||||
L310: if (B<2) goto L300;
|
||||
L320: if (B>14) goto L300;
|
||||
L330: if (A>=B) goto L270;
|
||||
L350: if (A<11) goto L400;
|
||||
L360: if (A==11) goto L420;
|
||||
L370: if (A==12) goto L440;
|
||||
L380: if (A==13) goto L460;
|
||||
L390: if (A==14) goto L480;
|
||||
L400: writefln("%2d", A);
|
||||
L410: goto L500;
|
||||
L420: writeln("JACK");
|
||||
L430: goto L500;
|
||||
L440: writeln("QUEEN");
|
||||
L450: goto L500;
|
||||
L460: writeln("KING");
|
||||
L470: goto L500;
|
||||
L480: writeln("ACE");
|
||||
L500: if (B<11) goto L550;
|
||||
L510: if (B==11) goto L570;
|
||||
L520: if (B==12) goto L590;
|
||||
L530: if (B==13) goto L610;
|
||||
L540: if (B==14) goto L630;
|
||||
L550: writefln("%2d", B);
|
||||
L560: goto L650;
|
||||
L570: writeln("JACK");
|
||||
L580: goto L650;
|
||||
L590: writeln("QUEEN");
|
||||
L600: goto L650;
|
||||
L610: writeln("KING");
|
||||
L620: goto L650;
|
||||
L630: writeln("ACE");
|
||||
L640: writeln;
|
||||
L650: writeln;
|
||||
L660: write("WHAT IS YOUR BET? "); M = stdin.readln.strip.to!int;
|
||||
L670: if (M!=0) goto L680;
|
||||
L675: writeln("CHICKEN!!");
|
||||
L676: writeln;
|
||||
L677: goto L260;
|
||||
L680: if (M<=Q) goto L730;
|
||||
L690: writeln("SORRY, MY FRIEND, BUT YOU BET TOO MUCH.");
|
||||
L700: writeln("YOU HAVE ONLY ",Q," DOLLARS TO BET.");
|
||||
L710: goto L650;
|
||||
L730: auto C=to!int(14*uniform01)+2;
|
||||
L740: if (C<2) goto L730;
|
||||
L750: if (C>14) goto L730;
|
||||
L760: if (C<11) goto L810;
|
||||
L770: if (C==11) goto L830;
|
||||
L780: if (C==12) goto L850;
|
||||
L790: if (C==13) goto L870;
|
||||
L800: if (C==14) goto L890;
|
||||
L810: writeln(C);
|
||||
L820: goto L910;
|
||||
L830: writeln("JACK");
|
||||
L840: goto L910;
|
||||
L850: writeln("QUEEN");
|
||||
L860: goto L910;
|
||||
L870: writeln("KING");
|
||||
L880: goto L910;
|
||||
L890: writeln( "ACE");
|
||||
L900: writeln;
|
||||
L910: if (C>A) goto L930;
|
||||
L920: goto L970;
|
||||
L930: if (C>=B) goto L970;
|
||||
L950: writeln("YOU WIN!!!");
|
||||
L960: goto L210;
|
||||
L970: writeln("SORRY, YOU LOSE");
|
||||
L980: if (M<Q) goto L240;
|
||||
L990: writeln;
|
||||
L1000: writeln;
|
||||
L1010: writeln("SORRY, FRIEND, BUT YOU BLEW YOUR WAD.");
|
||||
L1015: writeln;writeln;
|
||||
L1020: write("TRY AGAIN (YES OR NO)? "); auto AS=stdin.readln;
|
||||
L1025: writeln;writeln;
|
||||
L1030: if (AS.strip.toUpper=="YES") goto L110;
|
||||
L1040: writeln("O.K., HOPE YOU HAD FUN!");
|
||||
}
|
||||
@@ -12,3 +12,7 @@ As published in Basic Computer Games (1978):
|
||||
|
||||
Downloaded from Vintage Basic at
|
||||
http://www.vintage-basic.net/games.html
|
||||
|
||||
---
|
||||
|
||||
**2022-01-04:** patched original source in [#400](https://github.com/coding-horror/basic-computer-games/pull/400) to fix a minor bug where a generated maze may be missing an exit, particularly at small maze sizes.
|
||||
|
||||
156
21_Calendar/python/calendar.py
Normal file
156
21_Calendar/python/calendar.py
Normal file
@@ -0,0 +1,156 @@
|
||||
########################################################
|
||||
# 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.
|
||||
#
|
||||
########################################################
|
||||
|
||||
def parse_input():
|
||||
"""
|
||||
function to parse input for weekday and leap year boolean
|
||||
"""
|
||||
|
||||
days_mapping = {
|
||||
"sunday": 0,
|
||||
"monday": -1,
|
||||
"tuesday": -2,
|
||||
"wednesday": -3,
|
||||
"thursday": -4,
|
||||
"friday": -5,
|
||||
"saturday": -6
|
||||
}
|
||||
|
||||
day = 0
|
||||
leap_day = False
|
||||
|
||||
correct_day_input = False
|
||||
while not correct_day_input:
|
||||
weekday = input("INSERT THE STARTING DAY OF THE WEEK OF THE YEAR:")
|
||||
|
||||
for day_k in days_mapping.keys():
|
||||
if weekday.lower() in day_k:
|
||||
day = days_mapping[day_k]
|
||||
correct_day_input = True
|
||||
break
|
||||
|
||||
while True:
|
||||
leap = input("IS IT A LEAP YEAR?:")
|
||||
|
||||
if 'y' in leap.lower():
|
||||
leap_day = True
|
||||
break
|
||||
|
||||
if 'n' in leap.lower():
|
||||
leap_day = False
|
||||
break
|
||||
|
||||
return day, leap_day
|
||||
|
||||
|
||||
def calendar(weekday, leap_year):
|
||||
"""
|
||||
function to print a year's calendar.
|
||||
|
||||
input:
|
||||
_weekday_: int - the initial day of the week (0=SUN, -1=MON, -2=TUES...)
|
||||
_leap_year_: bool - indicates if the year is a leap year
|
||||
"""
|
||||
months_days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||
days = 'S M T W T F S\n'
|
||||
sep = "*" * 59
|
||||
years_day = 365
|
||||
d = weekday
|
||||
|
||||
if leap_year:
|
||||
months_days[2] = 29
|
||||
years_day = 366
|
||||
|
||||
months_names = [" JANUARY ",
|
||||
" FEBRUARY",
|
||||
" MARCH ",
|
||||
" APRIL ",
|
||||
" MAY ",
|
||||
" JUNE ",
|
||||
" JULY ",
|
||||
" AUGUST ",
|
||||
"SEPTEMBER",
|
||||
" OCTOBER ",
|
||||
" NOVEMBER",
|
||||
" DECEMBER"]
|
||||
|
||||
days_count = 0 # S in the original program
|
||||
|
||||
# main loop
|
||||
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))
|
||||
print(days)
|
||||
print(sep)
|
||||
|
||||
for w in range(1, 7):
|
||||
print("\n")
|
||||
for g in range(1, 8):
|
||||
d += 1
|
||||
d2 = d - days_count
|
||||
|
||||
if d2 > months_days[n]:
|
||||
break
|
||||
|
||||
if d2 <= 0:
|
||||
print("{}".format(' '), end=' ')
|
||||
elif d2 < 10:
|
||||
print(" {}".format(d2), end=' ')
|
||||
else:
|
||||
print("{}".format(d2), end=' ')
|
||||
print()
|
||||
|
||||
if d2 >= months_days[n]:
|
||||
break
|
||||
|
||||
if d2 > months_days[n]:
|
||||
d -= g
|
||||
|
||||
print("\n")
|
||||
|
||||
print("\n")
|
||||
|
||||
|
||||
def main():
|
||||
print(" "*32 + "CALENDAR")
|
||||
print(" "*15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
|
||||
print("\n"*11)
|
||||
|
||||
day, leap_year = parse_input()
|
||||
calendar(day, leap_year)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
########################################################
|
||||
#
|
||||
########################################################
|
||||
#
|
||||
# Porting notes:
|
||||
#
|
||||
# It has been added an input at the beginning of the
|
||||
# program so the user can specify the first day of the
|
||||
# week of the year and if the year is leap or not.
|
||||
#
|
||||
########################################################
|
||||
69
25_Chief/perl/chief.pl
Normal file
69
25_Chief/perl/chief.pl
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
print ' ' x 30 . "CHIEF\n";
|
||||
print ' ' x 15 . "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n";
|
||||
print "\n\n\n";
|
||||
|
||||
print "I AM CHIEF NUMBERS FREEK, THE GREAT INDIAN MATH GOD.\n";
|
||||
print "ARE YOU READY TO TAKE THE TEST YOU CALLED ME OUT FOR?\n";
|
||||
|
||||
chomp( my $A = uc <STDIN> );
|
||||
print "SHUT UP, PALE FACE WITH WISE TONGUE.\n" unless ( $A eq 'YES' );
|
||||
|
||||
print " TAKE A NUMBER AND ADD 3. DIVIDE THIS NUMBER BY 5 AND\n";
|
||||
print "MULTIPLY BY 8. DIVIDE BY 5 AND ADD THE SAME. SUBTRACT 1.\n";
|
||||
print " WHAT DO YOU HAVE?\n";
|
||||
|
||||
chomp( my $B = <STDIN> );
|
||||
my $C = ( $B + 1 - 5 ) * 5 / 8 * 5 - 3;
|
||||
|
||||
print "I BET YOUR NUMBER WAS $C. AM I RIGHT?\n";
|
||||
|
||||
chomp( my $D = uc <STDIN> );
|
||||
if ( $D eq 'YES' ) {
|
||||
print "BYE!!!\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
print "WHAT WAS YOUR ORIGINAL NUMBER?\n";
|
||||
|
||||
chomp( my $K = <STDIN> );
|
||||
my $F = $K + 3;
|
||||
my $G = $F / 5;
|
||||
my $H = $G * 8;
|
||||
my $I = $H / 5 + 5;
|
||||
my $J = $I - 1;
|
||||
|
||||
print "SO YOU THINK YOU'RE SO SMART, EH?\n";
|
||||
print "NOW WATCH.\n";
|
||||
print "$K PLUS 3 EQUALS $F. THIS DIVIDED BY 5 EQUALS $G;\n";
|
||||
print "THIS TIMES 8 EQUALS $H. IF WE DIVIDE BY 5 AND ADD 5,\n";
|
||||
print "WE GET $I , WHICH, MINUS 1, EQUALS $J.\n";
|
||||
print "NOW DO YOU BELIEVE ME?\n";
|
||||
|
||||
chomp( my $Z = uc <STDIN> );
|
||||
if ( $Z eq 'YES' ) {
|
||||
print "BYE!!!\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
print "YOU HAVE MADE ME MAD!!!\n";
|
||||
print "THERE MUST BE A GREAT LIGHTNING BOLT!\n\n\n";
|
||||
|
||||
for my $i ( reverse 22 .. 30 ) {
|
||||
print ' ' x $i . "X X\n";
|
||||
}
|
||||
print ' ' x 21 . "X XXX\n";
|
||||
print ' ' x 20 . "X X\n";
|
||||
print ' ' x 19 . "XX X\n";
|
||||
for my $i ( reverse 13 .. 20 ) {
|
||||
print ' ' x $i . "X X\n";
|
||||
}
|
||||
print ' ' x 12 . "XX\n";
|
||||
print ' ' x 11 . "X\n";
|
||||
print ' ' x 10 . "*\n";
|
||||
print "\n#########################\n\n";
|
||||
print "I HOPE YOU BELIEVE ME NOW, FOR YOUR SAKE!!\n";
|
||||
57
31_Depth_Charge/ruby/.gitignore
vendored
Normal file
57
31_Depth_Charge/ruby/.gitignore
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# Package Shell Specific Things
|
||||
|
||||
## Build Process
|
||||
|
||||
/build
|
||||
|
||||
## Transient files
|
||||
|
||||
/src/input
|
||||
/src/output
|
||||
/src/log
|
||||
/drop
|
||||
|
||||
# Programming Languages
|
||||
|
||||
## Java
|
||||
/src/java/**/*.class
|
||||
|
||||
## Rakudo / Perl6
|
||||
/src/**/.precomp
|
||||
|
||||
## PHP
|
||||
/vendor/
|
||||
|
||||
## Python
|
||||
*.swp
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.egg-info
|
||||
/dist
|
||||
|
||||
## Ruby
|
||||
*.gem
|
||||
.bundle
|
||||
|
||||
# Editors
|
||||
|
||||
## Dia
|
||||
*.dia.autosave
|
||||
|
||||
## Emacs
|
||||
\#*\#
|
||||
.\#*
|
||||
|
||||
|
||||
## Vi / Vim
|
||||
*.swp
|
||||
|
||||
# Filesystem Artifacts
|
||||
|
||||
## Mac
|
||||
|
||||
.DS_Store
|
||||
|
||||
## NFS
|
||||
|
||||
.nfs*
|
||||
@@ -13,7 +13,6 @@ class DepthCharge
|
||||
break if ! get_input_another_game()
|
||||
end
|
||||
|
||||
# 420 PRINT "OK. HOPE YOU ENJOYED YOURSELF." : GOTO 600
|
||||
printf("OK. HOPE YOU ENJOYED YOURSELF.\n")
|
||||
end
|
||||
|
||||
@@ -51,7 +50,7 @@ class DepthCharge
|
||||
|
||||
the_input = Integer(value) rescue nil
|
||||
|
||||
if the_input == nil || the_input < 0
|
||||
if the_input == nil || the_input < 1
|
||||
printf("PLEASE ENTER A POSITIVE NUMBER\n\n")
|
||||
next
|
||||
|
||||
@@ -61,25 +60,7 @@ class DepthCharge
|
||||
end
|
||||
end
|
||||
|
||||
def get_search_area_dimension
|
||||
# 20 INPUT "DIMENSION OF SEARCH AREA";G: PRINT
|
||||
@search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ")
|
||||
# 30 N=INT(LOG(G)/LOG(2))+1
|
||||
|
||||
@num_tries = Integer(
|
||||
Math.log(@search_area_dimension)/Math.log(2)
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
def print_instructions
|
||||
# 40 PRINT "YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER"
|
||||
# 50 PRINT "AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR"
|
||||
# 60 PRINT "MISSION IS TO DESTROY IT. YOU HAVE";N;"SHOTS."
|
||||
# 70 PRINT "SPECIFY DEPTH CHARGE EXPLOSION POINT WITH A"
|
||||
# 80 PRINT "TRIO OF NUMBERS -- THE FIRST TWO ARE THE"
|
||||
# 90 PRINT "SURFACE COORDINATES; THE THIRD IS THE DEPTH."
|
||||
# 100 PRINT : PRINT "GOOD LUCK !": PRINT
|
||||
printf( <<~INSTRUCTIONS
|
||||
YOU ARE THE CAPTAIN OF THE DESTROYER USS COMPUTER
|
||||
AN ENEMY SUB HAS BEEN CAUSING YOU TROUBLE. YOUR
|
||||
@@ -110,19 +91,21 @@ GOOD LUCK !
|
||||
end
|
||||
|
||||
def setup_game
|
||||
get_search_area_dimension()
|
||||
@search_area_dimension = get_input_positive_integer("DIMENSION OF SEARCH AREA: ")
|
||||
|
||||
@num_tries = Integer(
|
||||
Math.log(@search_area_dimension)/Math.log(2) + 1
|
||||
)
|
||||
setup_enemy()
|
||||
end
|
||||
|
||||
def setup_enemy
|
||||
# 110 A=INT(G*RND(1)) : B=INT(G*RND(1)) : C=INT(G*RND(1))
|
||||
@enemy_x = rand(1..@search_area_dimension)
|
||||
@enemy_y = rand(1..@search_area_dimension)
|
||||
@enemy_z = rand(1..@search_area_dimension)
|
||||
end
|
||||
end
|
||||
|
||||
def game_loop
|
||||
# 120 FOR D=1 TO N : PRINT : PRINT "TRIAL #";D; : INPUT X,Y,Z
|
||||
for @trial in 1..@num_tries do
|
||||
output_game_status()
|
||||
|
||||
@@ -130,7 +113,6 @@ GOOD LUCK !
|
||||
@shot_y = get_input_positive_integer("Y: ")
|
||||
@shot_z = get_input_positive_integer("Z: ")
|
||||
|
||||
# 130 IF ABS(X-A)+ABS(Y-B)+ABS(Z-C)=0 THEN 300
|
||||
if (
|
||||
(@enemy_x - @shot_x).abs \
|
||||
+ (@enemy_y - @shot_y).abs \
|
||||
@@ -140,7 +122,6 @@ GOOD LUCK !
|
||||
you_win()
|
||||
return
|
||||
else
|
||||
# 140 GOSUB 500 : PRINT : NEXT D
|
||||
missed_shot()
|
||||
end
|
||||
end
|
||||
@@ -156,54 +137,41 @@ GOOD LUCK !
|
||||
printf("TRIAL \#%d\n", @trial)
|
||||
end
|
||||
def you_win
|
||||
printf("B O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial )
|
||||
printf("\nB O O M ! ! YOU FOUND IT IN %d TRIES!\n\n", @trial )
|
||||
end
|
||||
def missed_shot
|
||||
missed_directions = []
|
||||
|
||||
# 530 IF X>A THEN PRINT "EAST";
|
||||
# 540 IF X<A THEN PRINT "WEST";
|
||||
if @shot_x > @enemy_x
|
||||
missed_directions.push('TOO FAR EAST')
|
||||
elsif @shot_x < @enemy_x
|
||||
missed_directions.push('TOO FAR WEST')
|
||||
end
|
||||
|
||||
# 510 IF Y>B THEN PRINT "NORTH";
|
||||
# 520 IF Y<B THEN PRINT "SOUTH";
|
||||
if @shot_y > @enemy_y
|
||||
missed_directions.push('TOO FAR NORTH')
|
||||
elsif @shot_y < @enemy_y
|
||||
missed_directions.push('TOO FAR SOUTH')
|
||||
end
|
||||
|
||||
# 560 IF Z>C THEN PRINT " TOO LOW."
|
||||
# 570 IF Z<C THEN PRINT " TOO HIGH."
|
||||
# 580 IF Z=C THEN PRINT " DEPTH OK."
|
||||
if @shot_z > @enemy_z
|
||||
missed_directions.push('TOO DEEP')
|
||||
elsif @shot_z < @enemy_z
|
||||
missed_directions.push('TOO SHALLOW')
|
||||
end
|
||||
|
||||
# 500 PRINT "SONAR REPORTS SHOT WAS ";
|
||||
printf("SONAR REPORTS SHOT WAS: \n")
|
||||
printf("%s\n", "\t" + missed_directions.join("\n\t"))
|
||||
# 550 IF Y<>B OR X<>A THEN PRINT " AND";
|
||||
# 590 RETURN
|
||||
end
|
||||
|
||||
def you_lose
|
||||
# You took too long!
|
||||
printf("YOU HAVE BEEN TORPEDOED! ABANDON SHIP!\n")
|
||||
printf("THE SUBMARINE WAS AT %d %d %d\n", @enemy_x, @enemy_y, @enemy_z)
|
||||
|
||||
end
|
||||
|
||||
def get_input_another_game
|
||||
# 400 PRINT : PRINT: INPUT "ANOTHER GAME (Y OR N)";A$
|
||||
return get_input_y_or_n("ANOTHER GAME (Y OR N): ")
|
||||
# 410 IF A$="Y" THEN 100
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ sub game_play {
|
||||
if ($choice == 0) {
|
||||
until ($marbles == 0) {
|
||||
|
||||
my $computer_choice = &computer_select($marbles,$turn);
|
||||
my $computer_choice = &computer_select($marbles,$turn,$player_total);
|
||||
$marbles = $marbles - $computer_choice;
|
||||
$computer_total = $computer_total + $computer_choice;
|
||||
print "MY TOTAL IS $computer_total\n";
|
||||
@@ -52,7 +52,7 @@ sub game_play {
|
||||
|
||||
if ($marbles == 0) {&determine_winner($computer_total,$player_total)};
|
||||
|
||||
my $computer_choice = &computer_select($marbles,$turn);
|
||||
my $computer_choice = &computer_select($marbles,$turn,$player_total);
|
||||
$marbles = $marbles - $computer_choice;
|
||||
$computer_total = $computer_total + $computer_choice;
|
||||
print "MY TOTAL IS $computer_total\n";
|
||||
@@ -114,6 +114,7 @@ sub player_select {
|
||||
sub computer_select {
|
||||
my $marbles = shift;
|
||||
my $turn = shift;
|
||||
my $player_total = shift;
|
||||
my $num = 2;
|
||||
my $validity = "invalid";
|
||||
if ($turn == 0) {
|
||||
@@ -122,14 +123,24 @@ sub computer_select {
|
||||
else {
|
||||
until ($validity eq "valid") {
|
||||
my $R=$marbles-6*int(($marbles/6));
|
||||
if ($marbles < 4.2) {
|
||||
|
||||
if (int($player_total/2) == $player_total/2) {
|
||||
if ($R < 1.5 || $R > 5.3) {
|
||||
$num = 1;
|
||||
}
|
||||
else {
|
||||
$num = $R - 1;
|
||||
}
|
||||
}
|
||||
|
||||
elsif ($marbles < 4.2) {
|
||||
$num = $marbles;
|
||||
}
|
||||
if ($R > 3.4) {
|
||||
elsif ($R > 3.4) {
|
||||
if ($R < 4.7 || $R > 3.5) {
|
||||
$num = 4;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
$num = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,17 +142,32 @@ def game_over():
|
||||
print('')
|
||||
|
||||
def computer_turn():
|
||||
global marbles_in_middle
|
||||
global computer_marbles
|
||||
global marbles_in_middle
|
||||
global computer_marbles
|
||||
global human_marbles
|
||||
|
||||
print("It's the computer's turn ...")
|
||||
max_choice = min(4, marbles_in_middle)
|
||||
marbles_to_take=0
|
||||
|
||||
# choose at random
|
||||
n = random.randint(1, max_choice)
|
||||
print(f'Computer takes {marbles_str(n)} ...')
|
||||
marbles_in_middle -= n
|
||||
computer_marbles += n
|
||||
print("It's the computer's turn ...")
|
||||
r = marbles_in_middle - 6 * int((marbles_in_middle/6)) #line 500
|
||||
|
||||
if int(human_marbles/2) == human_marbles/2: #line 510
|
||||
if r < 1.5 or r > 5.3: #lines 710 and 720
|
||||
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
|
||||
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
|
||||
|
||||
def play_game():
|
||||
global marbles_in_middle
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
### King
|
||||
## King
|
||||
|
||||
This is one of the most comprehensive, difficult, and interesting games. (If you’ve never played one of these games, start with HAMMURABI.)
|
||||
|
||||
@@ -8,7 +8,9 @@ The money system is Rollods; each person needs 100 Rallods per year to survive.
|
||||
|
||||
The author of this program is James A. Storer who wrote it while a student at Lexington High School.
|
||||
|
||||
## Bugs
|
||||
⚠️ This game includes references to suicide or self-harm.
|
||||
|
||||
### Bugs
|
||||
|
||||
Implementers should be aware that this game contains at least one bug.
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ import kotlin.random.Random
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
lateinit var gameState: GameState
|
||||
const val INCLUDE_BUGS_FROM_ORIGINAL = false
|
||||
const val KEEP_ORIGINAL_BUGS = false
|
||||
const val KEEP_ORIGINAL_SUICIDE_REFERENCE = false
|
||||
|
||||
val rnd: Double get() = Random.nextDouble()
|
||||
fun tab(i: Int) = " ".repeat(i)
|
||||
@@ -19,29 +20,25 @@ fun main() {
|
||||
}
|
||||
?: throw EndOfInputException()
|
||||
|
||||
try {
|
||||
with(gameState) {
|
||||
while(currentYear < yearsRequired) {
|
||||
recalculateLandCost()
|
||||
displayStatus()
|
||||
inputLandSale()
|
||||
performLandSale()
|
||||
inputWelfare()
|
||||
performWelfare()
|
||||
inputPlantingArea()
|
||||
performPlanting()
|
||||
inputPollutionControl()
|
||||
if (zeroInput()) {
|
||||
displayExitMessage()
|
||||
exitProcess(0)
|
||||
}
|
||||
simulateOneYear()
|
||||
currentYear ++
|
||||
with(gameState) {
|
||||
do {
|
||||
recalculateLandCost()
|
||||
displayStatus()
|
||||
inputLandSale()
|
||||
performLandSale()
|
||||
inputWelfare()
|
||||
performWelfare()
|
||||
inputPlantingArea()
|
||||
performPlanting()
|
||||
inputPollutionControl()
|
||||
if (zeroInput()) {
|
||||
displayExitMessage()
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
win(gameState.yearsRequired)
|
||||
} catch (e: GameEndingException) {
|
||||
e.displayConsequences()
|
||||
val yearResult = simulateOneYear().also {
|
||||
it.displayConsequences()
|
||||
}
|
||||
} while (yearResult == YearOutcome.ContinueNextYear)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +51,8 @@ private fun header() {
|
||||
}
|
||||
|
||||
fun instructions(yearsRequired: Int) {
|
||||
println("""
|
||||
println(
|
||||
"""
|
||||
|
||||
|
||||
CONGRATULATIONS! YOU'VE JUST BEEN ELECTED PREMIER OF SETATS
|
||||
@@ -80,10 +78,7 @@ fun loadOldGame(): GameState = GameState().apply {
|
||||
do {
|
||||
var retry = false
|
||||
print("HOW MANY YEARS HAD YOU BEEN IN OFFICE WHEN INTERRUPTED? ")
|
||||
currentYear = numberInput()
|
||||
|
||||
if (currentYear <= 0)
|
||||
throw GameEndingException.DataEntryValidation()
|
||||
currentYear = validatedInput { it > 0 }
|
||||
|
||||
if (currentYear >= yearsRequired) {
|
||||
println(" COME ON, YOUR TERM IN OFFICE IS ONLY $yearsRequired YEARS.")
|
||||
@@ -92,21 +87,19 @@ fun loadOldGame(): GameState = GameState().apply {
|
||||
} while (retry)
|
||||
|
||||
print("HOW MUCH DID YOU HAVE IN THE TREASURY? ")
|
||||
rallods = numberInput()
|
||||
if (rallods < 0)
|
||||
throw GameEndingException.DataEntryValidation()
|
||||
rallods = validatedInput { it >= 0 }
|
||||
|
||||
print("HOW MANY COUNTRYMEN? ")
|
||||
countrymen = validatedInput { it >= 0 }
|
||||
|
||||
print("HOW MANY WORKERS? ")
|
||||
foreignWorkers = numberInput()
|
||||
if (foreignWorkers < 0)
|
||||
throw GameEndingException.DataEntryValidation()
|
||||
foreignWorkers = validatedInput { it >= 0 }
|
||||
|
||||
do {
|
||||
var retry = false
|
||||
print("HOW MANY SQUARE MILES OF LAND? ")
|
||||
landArea = numberInput()
|
||||
if (landArea<0)
|
||||
throw GameEndingException.DataEntryValidation()
|
||||
landArea = validatedInput { it >= 0 }
|
||||
|
||||
if (landArea > 2000 || landArea <= 1000) {
|
||||
println(" COME ON, YOU STARTED WITH 1000 SQ. MILES OF FARM LAND")
|
||||
println(" AND 10,000 SQ. MILES OF FOREST LAND.")
|
||||
@@ -118,11 +111,13 @@ fun loadOldGame(): GameState = GameState().apply {
|
||||
|
||||
|
||||
/**
|
||||
* All exceptions which indicate the premature ending of the game, due
|
||||
* to mismanagement, starvation, revolution, or mis-entry of a game state.
|
||||
* Possible outcomes for a year.
|
||||
*/
|
||||
sealed class GameEndingException : Throwable() {
|
||||
abstract fun displayConsequences()
|
||||
sealed class YearOutcome {
|
||||
|
||||
open fun displayConsequences() {
|
||||
// Default display nothing
|
||||
}
|
||||
|
||||
fun finalFate() {
|
||||
if (rnd < .5) {
|
||||
@@ -135,7 +130,28 @@ sealed class GameEndingException : Throwable() {
|
||||
println()
|
||||
}
|
||||
|
||||
class ExtremeMismanagement(private val death: Int) : GameEndingException() {
|
||||
object ContinueNextYear : YearOutcome()
|
||||
|
||||
class Win(val yearsRequired: Int) : YearOutcome() {
|
||||
override fun displayConsequences() {
|
||||
// The misspelling of "successfully" is in the original code.
|
||||
println(
|
||||
"""
|
||||
|
||||
CONGRATULATIONS!!!!!!!!!!!!!!!!!!
|
||||
YOU HAVE SUCCESFULLY COMPLETED YOUR $yearsRequired YEAR TERM
|
||||
OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT
|
||||
NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD
|
||||
LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT
|
||||
PLAYS THIS GAME.
|
||||
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ExtremeMismanagement(private val death: Int) : YearOutcome() {
|
||||
override fun displayConsequences() {
|
||||
println()
|
||||
println("$death COUNTRYMEN DIED IN ONE YEAR!!!!!")
|
||||
@@ -151,74 +167,68 @@ sealed class GameEndingException : Throwable() {
|
||||
}
|
||||
}
|
||||
|
||||
class TooManyPeopleDead : GameEndingException() {
|
||||
object TooManyPeopleDead : YearOutcome() {
|
||||
// The mistyping of "population" is in the original game.
|
||||
override fun displayConsequences() {
|
||||
println("""
|
||||
println(
|
||||
"""
|
||||
|
||||
|
||||
OVER ONE THIRD OF THE POPULTATION HAS DIED SINCE YOU
|
||||
WERE ELECTED TO OFFICE. THE PEOPLE (REMAINING)
|
||||
HATE YOUR GUTS.
|
||||
""".trimIndent())
|
||||
""".trimIndent()
|
||||
)
|
||||
finalFate()
|
||||
}
|
||||
}
|
||||
|
||||
class AntiImmigrationRevolution : GameEndingException() {
|
||||
object AntiImmigrationRevolution : YearOutcome() {
|
||||
override fun displayConsequences() {
|
||||
println("""
|
||||
println(
|
||||
"""
|
||||
THE NUMBER OF FOREIGN WORKERS HAS EXCEEDED THE NUMBER
|
||||
OF COUNTRYMEN. AS A MINORITY, THEY HAVE REVOLTED AND
|
||||
TAKEN OVER THE COUNTRY.
|
||||
""".trimIndent())
|
||||
""".trimIndent()
|
||||
)
|
||||
finalFate()
|
||||
}
|
||||
}
|
||||
|
||||
class StarvationWithFullTreasury : GameEndingException() {
|
||||
object StarvationWithFullTreasury : YearOutcome() {
|
||||
override fun displayConsequences() {
|
||||
println("""
|
||||
MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID
|
||||
NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED
|
||||
OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE
|
||||
BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE.
|
||||
THE CHOICE IS YOURS.
|
||||
IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER
|
||||
BEFORE PROCEEDING.
|
||||
""".trimIndent())
|
||||
println(
|
||||
if (KEEP_ORIGINAL_SUICIDE_REFERENCE) {
|
||||
"""
|
||||
MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID
|
||||
NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED
|
||||
OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE
|
||||
BEEN FORCED TO EITHER RESIGN OR COMMIT SUICIDE.
|
||||
THE CHOICE IS YOURS.
|
||||
IF YOU CHOOSE THE LATTER, PLEASE TURN OFF YOUR COMPUTER
|
||||
BEFORE PROCEEDING.
|
||||
""".trimIndent()
|
||||
} else {
|
||||
"""
|
||||
MONEY WAS LEFT OVER IN THE TREASURY WHICH YOU DID
|
||||
NOT SPEND. AS A RESULT, SOME OF YOUR COUNTRYMEN DIED
|
||||
OF STARVATION. THE PUBLIC IS ENRAGED AND YOU HAVE
|
||||
BEEN FORCED TO RESIGN.
|
||||
PLEASE TURN OFF YOUR COMPUTER AND SURRENDER IT TO
|
||||
THE NEAREST POLICE STATION.
|
||||
""".trimIndent()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class DataEntryValidation : GameEndingException() {
|
||||
override fun displayConsequences() {
|
||||
// no action
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun win(yearsRequired: Int) {
|
||||
// The misspelling of "successfully" is in the original code.
|
||||
println("""
|
||||
|
||||
CONGRATULATIONS!!!!!!!!!!!!!!!!!!
|
||||
YOU HAVE SUCCESFULLY COMPLETED YOUR $yearsRequired YEAR TERM
|
||||
OF OFFICE. YOU WERE, OF COURSE, EXTREMELY LUCKY, BUT
|
||||
NEVERTHELESS, IT'S QUITE AN ACHIEVEMENT. GOODBYE AND GOOD
|
||||
LUCK - YOU'LL PROBABLY NEED IT IF YOU'RE THE TYPE THAT
|
||||
PLAYS THIS GAME.
|
||||
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
/**
|
||||
* Record data, allow data input, and process the simulation for the game.
|
||||
*/
|
||||
class GameState(val yearsRequired: Int = 8) {
|
||||
|
||||
/**
|
||||
* The current year. Years start with zero, but we never
|
||||
* output the current year.
|
||||
@@ -240,8 +250,8 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
private var tourists = 0
|
||||
|
||||
private var moneySpentOnPollutionControl = 0
|
||||
private var moneySpentOnPlanting = 0
|
||||
|
||||
private var moneySpentOnPlanting = 0
|
||||
/**
|
||||
* Current stock of rallods.
|
||||
* Player starts with between 59000 and 61000 rallods, but
|
||||
@@ -252,10 +262,10 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
|
||||
/**
|
||||
* Population.
|
||||
* Initial population is about to 500.
|
||||
* Initial population is about 500.
|
||||
* 75% of the time it's between 495 and 505.
|
||||
*/
|
||||
private var countrymen = (500 + (10 * rnd) - (10 * rnd)).toInt()
|
||||
var countrymen = (500 + (10 * rnd) - (10 * rnd)).toInt()
|
||||
|
||||
/**
|
||||
* Land sale price is evenly between 95 and 104 rallods per
|
||||
@@ -265,8 +275,8 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
private var landPrice = (10 * rnd + 95).toInt()
|
||||
|
||||
private var plantingArea = 0
|
||||
private var welfareThisYear = 0
|
||||
|
||||
private var welfareThisYear = 0
|
||||
/**
|
||||
* Land area in square miles. Arable land is 1000 square miles less.
|
||||
* Almost all calculations use landArea-1000 because only arable
|
||||
@@ -339,7 +349,6 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
rallods -= welfareThisYear
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ask how much land we want to sell. Immediately get the money.
|
||||
* The player has to do the calculations to work out how much
|
||||
@@ -362,6 +371,7 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
} while (sellThisYear < 0 || sellThisYear > landArea - 1000)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Input the value of `welfareThisYear`
|
||||
*/
|
||||
@@ -444,7 +454,7 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
plantingArea == 0 &&
|
||||
moneySpentOnPollutionControl == 0
|
||||
|
||||
fun simulateOneYear() {
|
||||
fun simulateOneYear(): YearOutcome {
|
||||
rallods -= moneySpentOnPollutionControl
|
||||
val rallodsAfterPollutionControl = rallods
|
||||
|
||||
@@ -460,7 +470,7 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
https://github.com/coding-horror/basic-computer-games/blob/main/53_King/king.bas#:~:text=1105%20IF%20I/100%3C50%20THEN%201700
|
||||
*/
|
||||
if (welfareThisYear / 100.0 < 50)
|
||||
throw GameEndingException.TooManyPeopleDead()
|
||||
return YearOutcome.TooManyPeopleDead
|
||||
|
||||
starvationDeaths = (countrymen - (welfareThisYear / 100.0)).toInt()
|
||||
println("$starvationDeaths COUNTRYMEN DIED OF STARVATION")
|
||||
@@ -568,33 +578,37 @@ class GameState(val yearsRequired: Int = 8) {
|
||||
|
||||
https://github.com/coding-horror/basic-computer-games/blob/main/53_King/king.bas#:~:text=1450%20V3%3DINT,INT(A%2BV3)
|
||||
*/
|
||||
if (INCLUDE_BUGS_FROM_ORIGINAL) {
|
||||
if (KEEP_ORIGINAL_BUGS) {
|
||||
tourists += rallods
|
||||
} else {
|
||||
tourists = abs(v1 - v2)
|
||||
}
|
||||
rallods += tourists
|
||||
|
||||
if (death > 200)
|
||||
throw GameEndingException.ExtremeMismanagement(death)
|
||||
if (countrymen < 343)
|
||||
throw GameEndingException.TooManyPeopleDead()
|
||||
if (rallodsAfterPollutionControl / 100 > 5 && death - pollutionDeaths >= 2)
|
||||
throw GameEndingException.StarvationWithFullTreasury()
|
||||
if (foreignWorkers > countrymen)
|
||||
throw GameEndingException.AntiImmigrationRevolution()
|
||||
return if (death > 200)
|
||||
YearOutcome.ExtremeMismanagement(death)
|
||||
else if (countrymen < 343)
|
||||
YearOutcome.TooManyPeopleDead
|
||||
else if (rallodsAfterPollutionControl / 100 > 5 && death - pollutionDeaths >= 2)
|
||||
YearOutcome.StarvationWithFullTreasury
|
||||
else if (foreignWorkers > countrymen)
|
||||
YearOutcome.AntiImmigrationRevolution
|
||||
else {
|
||||
if (currentYear++ > yearsRequired)
|
||||
YearOutcome.Win(yearsRequired)
|
||||
else
|
||||
YearOutcome.ContinueNextYear
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun numberInput() = try {
|
||||
readLine()?.toInt() ?: throw EndOfInputException()
|
||||
} catch (r: NumberFormatException) {
|
||||
0
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DataEntryValidationException : Throwable()
|
||||
private fun validatedInput(predicate : (Int)->Boolean) =
|
||||
numberInput().apply { if (!predicate(this)) throw DataEntryValidationException() }
|
||||
|
||||
@@ -4,6 +4,8 @@ In this game, you are given by the computer a revolver loaded with one bullet an
|
||||
|
||||
Tom Adametx wrote this program while a student at Curtis Jr. High School in Sudbury, Massachusetts.
|
||||
|
||||
⚠️ This game includes EXPLICT references to suicide, and should not be included in most distributions, especially considering the extreme simplicity of the program.
|
||||
|
||||
---
|
||||
|
||||
As published in Basic Computer Games (1978):
|
||||
|
||||
@@ -1,60 +1,95 @@
|
||||
// WAR
|
||||
//
|
||||
// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
|
||||
// Original conversion from BASIC to Javascript by Oscar Toledo G. (nanochess)
|
||||
//
|
||||
|
||||
function print(str)
|
||||
{
|
||||
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)
|
||||
function tab(space) {
|
||||
let str = "";
|
||||
while (space-- > 0) {
|
||||
str += " ";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
var a = [, "S-2","H-2","C-2","D-2","S-3","H-3","C-3","D-3",
|
||||
"S-4","H-4","C-4","D-4","S-5","H-5","C-5","D-5",
|
||||
"S-6","H-6","C-6","D-6","S-7","H-7","C-7","D-7",
|
||||
"S-8","H-8","C-8","D-8","S-9","H-9","C-9","D-9",
|
||||
"S-10","H-10","C-10","D-10","S-J","H-J","C-J","D-J",
|
||||
"S-Q","H-Q","C-Q","D-Q","S-K","H-K","C-K","D-K",
|
||||
"S-A","H-A","C-A","D-A"];
|
||||
function input() {
|
||||
return new Promise(function (resolve) {
|
||||
const input_element = document.createElement("INPUT");
|
||||
|
||||
var l = [];
|
||||
print("? ");
|
||||
input_element.setAttribute("type", "text");
|
||||
input_element.setAttribute("length", "50");
|
||||
document.getElementById("output").appendChild(input_element);
|
||||
input_element.focus();
|
||||
input_element.addEventListener("keydown", function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
const input_str = input_element.value;
|
||||
document.getElementById("output").removeChild(input_element);
|
||||
print(input_str);
|
||||
print("\n");
|
||||
resolve(input_str);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Main control section
|
||||
async function main()
|
||||
{
|
||||
async function askYesOrNo(question) {
|
||||
while (1) {
|
||||
print(question);
|
||||
const str = await input();
|
||||
if (str == "YES") {
|
||||
return true;
|
||||
}
|
||||
else if (str == "NO") {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
print("YES OR NO, PLEASE. ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function askAboutInstructions() {
|
||||
const playerWantsInstructions = await askYesOrNo("DO YOU WANT DIRECTIONS");
|
||||
if (playerWantsInstructions) {
|
||||
print("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD\n");
|
||||
print("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO\n");
|
||||
print("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n");
|
||||
}
|
||||
print("\n");
|
||||
print("\n");
|
||||
}
|
||||
|
||||
function createGameDeck(cards, gameSize) {
|
||||
const deck = [];
|
||||
const deckSize = cards.length;
|
||||
for (let j = 0; j < gameSize; j++) {
|
||||
let card;
|
||||
|
||||
// Compute a new card index until we find one that isn't already in the new deck
|
||||
do {
|
||||
card = Math.floor(deckSize * Math.random());
|
||||
} while (deck.includes(card));
|
||||
deck.push(card);
|
||||
}
|
||||
return deck;
|
||||
}
|
||||
|
||||
function computeCardValue(cardIndex) {
|
||||
return Math.floor(cardIndex / 4);
|
||||
}
|
||||
|
||||
function printGameOver(playerScore, computerScore) {
|
||||
print("\n");
|
||||
print("\n");
|
||||
print(`WE HAVE RUN OUT OF CARDS. FINAL SCORE: YOU: ${playerScore} THE COMPUTER: ${computerScore}\n`);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
function printTitle() {
|
||||
print(tab(33) + "WAR\n");
|
||||
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
|
||||
print("\n");
|
||||
@@ -62,72 +97,65 @@ async function main()
|
||||
print("\n");
|
||||
print("THIS IS THE CARD GAME OF WAR. EACH CARD IS GIVEN BY SUIT-#\n");
|
||||
print("AS S-7 FOR SPADE 7. ");
|
||||
while (1) {
|
||||
print("DO YOU WANT DIRECTIONS");
|
||||
str = await input();
|
||||
if (str == "YES") {
|
||||
print("THE COMPUTER GIVES YOU AND IT A 'CARD'. THE HIGHER CARD\n");
|
||||
print("(NUMERICALLY) WINS. THE GAME ENDS WHEN YOU CHOOSE NOT TO\n");
|
||||
print("CONTINUE OR WHEN YOU HAVE FINISHED THE PACK.\n");
|
||||
break;
|
||||
}
|
||||
if (str == "NO")
|
||||
break;
|
||||
print("YES OR NO, PLEASE. ");
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
function printCards(playerCard, computerCard) {
|
||||
print("\n");
|
||||
print(`YOU: ${playerCard}\tCOMPUTER: ${computerCard}\n`);
|
||||
}
|
||||
|
||||
const cards = [
|
||||
"S-2", "H-2", "C-2", "D-2",
|
||||
"S-3", "H-3", "C-3", "D-3",
|
||||
"S-4", "H-4", "C-4", "D-4",
|
||||
"S-5", "H-5", "C-5", "D-5",
|
||||
"S-6", "H-6", "C-6", "D-6",
|
||||
"S-7", "H-7", "C-7", "D-7",
|
||||
"S-8", "H-8", "C-8", "D-8",
|
||||
"S-9", "H-9", "C-9", "D-9",
|
||||
"S-10", "H-10", "C-10", "D-10",
|
||||
"S-J", "H-J", "C-J", "D-J",
|
||||
"S-Q", "H-Q", "C-Q", "D-Q",
|
||||
"S-K", "H-K", "C-K", "D-K",
|
||||
"S-A", "H-A", "C-A", "D-A"
|
||||
];
|
||||
|
||||
// Main control section
|
||||
async function main() {
|
||||
printTitle();
|
||||
await askAboutInstructions();
|
||||
|
||||
a1 = 0;
|
||||
b1 = 0;
|
||||
p = 0;
|
||||
let computerScore = 0;
|
||||
let playerScore = 0;
|
||||
|
||||
// Generate a random deck
|
||||
for (j = 1; j <= 52; j++) {
|
||||
do {
|
||||
l[j] = Math.floor(52 * Math.random()) + 1;
|
||||
for (k = 1; k < j; k++) {
|
||||
if (l[k] == l[j]) // Already in deck?
|
||||
break;
|
||||
}
|
||||
} while (j != 1 && k < j) ;
|
||||
}
|
||||
l[j] = 0; // Mark the end of the deck
|
||||
const gameSize = cards.length; // Number of cards to shuffle into the game deck. Can be <= cards.length.
|
||||
const deck = createGameDeck(cards, gameSize);
|
||||
let shouldContinuePlaying = true;
|
||||
|
||||
while (1) {
|
||||
m1 = l[++p]; // Take a card
|
||||
m2 = l[++p]; // Take a card
|
||||
print("\n");
|
||||
print("YOU: " + a[m1] + "\tCOMPUTER: " + a[m2] + "\n");
|
||||
n1 = Math.floor((m1 - 0.5) / 4);
|
||||
n2 = Math.floor((m2 - 0.5) / 4);
|
||||
if (n1 < n2) {
|
||||
a1++;
|
||||
print("THE COMPUTER WINS!!! YOU HAVE " + b1 + " AND THE COMPUTER HAS " + a1 + "\n");
|
||||
} else if (n1 > n2) {
|
||||
b1++;
|
||||
print("YOU WIN. YOU HAVE " + b1 + " AND THE COMPUTER HAS " + a1 + "\n");
|
||||
while (deck.length > 0 && shouldContinuePlaying) {
|
||||
const playerCard = deck.shift(); // Take a card
|
||||
const computerCard = deck.shift(); // Take a card
|
||||
printCards(cards[playerCard], cards[computerCard]);
|
||||
|
||||
const playerCardValue = computeCardValue(playerCard);
|
||||
const computerCardValue = computeCardValue(computerCard);
|
||||
if (playerCardValue < computerCardValue) {
|
||||
computerScore++;
|
||||
print("THE COMPUTER WINS!!! YOU HAVE " + playerScore + " AND THE COMPUTER HAS " + computerScore + "\n");
|
||||
} else if (playerCardValue > computerCardValue) {
|
||||
playerScore++;
|
||||
print("YOU WIN. YOU HAVE " + playerScore + " AND THE COMPUTER HAS " + computerScore + "\n");
|
||||
} else {
|
||||
print("TIE. NO SCORE CHANGE.\n");
|
||||
}
|
||||
if (l[p + 1] == 0) {
|
||||
print("\n");
|
||||
print("\n");
|
||||
print("WE HAVE RUN OUT OF CARDS. FINAL SCORE: YOU: " + b1 + " THE COMPUTER: " + a1 + "\n");
|
||||
print("\n");
|
||||
break;
|
||||
|
||||
if (deck.length === 0) {
|
||||
printGameOver(playerScore, computerScore);
|
||||
}
|
||||
while (1) {
|
||||
print("DO YOU WANT TO CONTINUE");
|
||||
str = await input();
|
||||
if (str == "YES")
|
||||
break;
|
||||
if (str == "NO")
|
||||
break;
|
||||
print("YES OR NO, PLEASE. ");
|
||||
else {
|
||||
shouldContinuePlaying = await askYesOrNo("DO YOU WANT TO CONTINUE");
|
||||
}
|
||||
if (str == "NO")
|
||||
break;
|
||||
}
|
||||
print("THANKS FOR PLAYING. IT WAS FUN.\n");
|
||||
print("\n");
|
||||
|
||||
Reference in New Issue
Block a user