mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 07:10:42 -08:00
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!");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user