mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 07:10:42 -08:00
550 lines
16 KiB
JavaScript
550 lines
16 KiB
JavaScript
// BLACKJACK
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
var da = [];
|
|
|
|
var pa = [];
|
|
var qa = [];
|
|
var ca = [];
|
|
var ta = [];
|
|
var sa = [];
|
|
var ba = [];
|
|
var za = [];
|
|
var ra = [];
|
|
|
|
var ds = "N A 2 3 4 5 6 7N 8 9 10 J Q K";
|
|
var is = "H,S,D,/,"
|
|
|
|
var q;
|
|
var aa;
|
|
var ab;
|
|
var ac;
|
|
var h;
|
|
var h1;
|
|
|
|
function af(q) {
|
|
return q >= 22 ? q - 11 : q;
|
|
}
|
|
|
|
function reshuffle()
|
|
{
|
|
print("RESHUFFLING\n");
|
|
for (; d >= 1; d--)
|
|
ca[--c] = da[d];
|
|
for (c1 = 52; c1 >= c; c1--) {
|
|
c2 = Math.floor(Math.random() * (c1 - c + 1)) + c;
|
|
c3 = ca[c2];
|
|
ca[c2] = ca[c1];
|
|
ca[c1] = c3;
|
|
}
|
|
}
|
|
|
|
// Subroutine to get a card.
|
|
function get_card()
|
|
{
|
|
if (c >= 51)
|
|
reshuffle();
|
|
return ca[c++];
|
|
}
|
|
|
|
// Card printing subroutine
|
|
function card_print(x)
|
|
{
|
|
print(ds.substr(3 * x - 3, 3) + " ");
|
|
}
|
|
|
|
// Alternate card printing subroutine
|
|
function alt_card_print(x)
|
|
{
|
|
print(" " + ds.substr(3 * x - 2, 2) + " ");
|
|
}
|
|
|
|
// Subroutine to add card 'which' to total 'q'
|
|
function add_card(which)
|
|
{
|
|
x1 = which;
|
|
if (x1 > 10)
|
|
x1 = 10;
|
|
q1 = q + x1;
|
|
if (q < 11) {
|
|
if (which <= 1) {
|
|
q += 11;
|
|
return;
|
|
}
|
|
if (q1 >= 11)
|
|
q = q1 + 11;
|
|
else
|
|
q = q1;
|
|
return;
|
|
}
|
|
if (q <= 21 && q1 > 21)
|
|
q = q1 + 1;
|
|
else
|
|
q = q1;
|
|
if (q >= 33)
|
|
q = -1;
|
|
}
|
|
|
|
// Subroutine to evaluate hand 'which'. Total is put into
|
|
// qa[which]. Totals have the following meaning:
|
|
// 2-10...hard 2-10
|
|
// 11-21...soft 11-21
|
|
// 22-32...hard 11-21
|
|
// 33+....busted
|
|
function evaluate_hand(which)
|
|
{
|
|
q = 0;
|
|
for (q2 = 1; q2 <= ra[which]; q2++) {
|
|
add_card(pa[i][q2]);
|
|
}
|
|
qa[which] = q;
|
|
}
|
|
|
|
// Subroutine to add a card to row i
|
|
function add_card_to_row(i, x) {
|
|
ra[i]++;
|
|
pa[i][ra[i]] = x;
|
|
q = qa[i];
|
|
add_card(x);
|
|
qa[i] = q;
|
|
if (q < 0) {
|
|
print("...BUSTED\n");
|
|
discard_row(i);
|
|
}
|
|
}
|
|
|
|
// Subroutine to discard row i
|
|
function discard_row(i) {
|
|
while (ra[i]) {
|
|
d++;
|
|
da[d] = pa[i][ra[i]];
|
|
ra[i]--;
|
|
}
|
|
}
|
|
|
|
// Prints total of hand i
|
|
function print_total(i) {
|
|
print("\n");
|
|
aa = qa[i];
|
|
total_aa();
|
|
print("TOTAL IS " + aa + "\n");
|
|
}
|
|
|
|
function total_aa()
|
|
{
|
|
if (aa >= 22)
|
|
aa -= 11;
|
|
}
|
|
|
|
function total_ab()
|
|
{
|
|
if (ab >= 22)
|
|
ab -= 11;
|
|
}
|
|
|
|
function total_ac()
|
|
{
|
|
if (ac >= 22)
|
|
ac -= 11;
|
|
}
|
|
|
|
function process_input(str)
|
|
{
|
|
str = str.substr(0, 1);
|
|
for (h = 1; h <= h1; h += 2) {
|
|
if (str == is.substr(h - 1, 1))
|
|
break;
|
|
}
|
|
if (h <= h1) {
|
|
h = (h + 1) / 2;
|
|
return 0;
|
|
}
|
|
print("TYPE " + is.substr(0, h1 - 1) + " OR " + is.substr(h1 - 1, 2) + " PLEASE");
|
|
return 1;
|
|
}
|
|
|
|
// Main program
|
|
async function main()
|
|
{
|
|
print(tab(31) + "BLACK JACK\n");
|
|
print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
|
|
print("\n");
|
|
print("\n");
|
|
print("\n");
|
|
// --pa[i][j] IS THE JTH CARD IN HAND I, qa[i] IS TOTAL OF HAND I
|
|
// --C IS THE DECK BEING DEALT FROM, D IS THE DISCARD PILE,
|
|
// --ta[i] IS THE TOTAL FOR PLAYER I, sa[i] IS THE TOTAL THIS HAND FOR
|
|
// --PLAYER I, ba[i] IS TH BET FOR HAND I
|
|
// --ra[i] IS THE LENGTH OF pa[I,*]
|
|
|
|
// --Program starts here
|
|
// --Initialize
|
|
for (i = 1; i <= 15; i++)
|
|
pa[i] = [];
|
|
for (i = 1; i <= 13; i++)
|
|
for (j = 4 * i - 3; j <= 4 * i; j++)
|
|
da[j] = i;
|
|
d = 52;
|
|
c = 53;
|
|
print("DO YOU WANT INSTRUCTIONS");
|
|
str = await input();
|
|
if (str.toUpperCase().substr(0, 1) != "N") {
|
|
print("THIS IS THE GAME OF 21. AS MANY AS 7 PLAYERS MAY PLAY THE\n");
|
|
print("GAME. ON EACH DEAL, BETS WILL BE ASKED FOR, AND THE\n");
|
|
print("PLAYERS' BETS SHOULD BE TYPED IN. THE CARDS WILL THEN BE\n");
|
|
print("DEALT, AND EACH PLAYER IN TURN PLAYS HIS HAND. THE\n");
|
|
print("FIRST RESPONSE SHOULD BE EITHER 'D', INDICATING THAT THE\n");
|
|
print("PLAYER IS DOUBLING DOWN, 'S', INDICATING THAT HE IS\n");
|
|
print("STANDING, 'H', INDICATING HE WANTS ANOTHER CARD, OR '/',\n");
|
|
print("INDICATING THAT HE WANTS TO SPLIT HIS CARDS. AFTER THE\n");
|
|
print("INITIAL RESPONSE, ALL FURTHER RESPONSES SHOULD BE 'S' OR\n");
|
|
print("'H', UNLESS THE CARDS WERE SPLIT, IN WHICH CASE DOUBLING\n");
|
|
print("DOWN IS AGAIN PERMITTED. IN ORDER TO COLLECT FOR\n");
|
|
print("BLACKJACK, THE INITIAL RESPONSE SHOULD BE 'S'.\n");
|
|
}
|
|
while (1) {
|
|
print("NUMBER OF PLAYERS");
|
|
n = parseInt(await input());
|
|
print("\n");
|
|
if (n < 1 || n > 7)
|
|
continue;
|
|
else
|
|
break;
|
|
}
|
|
for (i = 1; i <= 8; i++)
|
|
ta[i] = 0;
|
|
d1 = n + 1;
|
|
while (1) {
|
|
if (2 * d1 + c >= 52) {
|
|
reshuffle();
|
|
}
|
|
if (c == 2)
|
|
c--;
|
|
for (i = 1; i <= n; i++)
|
|
za[i] = 0;
|
|
for (i = 1; i <= 15; i++)
|
|
ba[i] = 0;
|
|
for (i = 1; i <= 15; i++)
|
|
qa[i] = 0;
|
|
for (i = 1; i <= 7; i++)
|
|
sa[i] = 0;
|
|
for (i = 1; i <= 15; i++)
|
|
ra[i] = 0;
|
|
print("BETS:\n");
|
|
for (i = 1; i <= n; i++) {
|
|
do {
|
|
print("#" + i + " ");
|
|
za[i] = parseFloat(await input());
|
|
} while (za[i] <= 0 || za[i] > 500) ;
|
|
}
|
|
for (i = 1; i <= n; i++)
|
|
ba[i] = za[i];
|
|
print("PLAYER");
|
|
for (i = 1; i <= n; i++) {
|
|
print(" " + i + " ");
|
|
}
|
|
print("DEALER\n");
|
|
for (j = 1; j <= 2; j++) {
|
|
print(tab(5));
|
|
for (i = 1; i <= d1; i++) {
|
|
pa[i][j] = get_card();
|
|
if (j == 1 || i <= n)
|
|
alt_card_print(pa[i][j]);
|
|
}
|
|
print("\n");
|
|
}
|
|
for (i = 1; i <= d1; i++)
|
|
ra[i] = 2;
|
|
// --Test for insurance
|
|
if (pa[d1][1] <= 1) {
|
|
print("ANY INSURANCE");
|
|
str = await input();
|
|
if (str.substr(0, 1) == "Y") {
|
|
print("INSURANCE BETS\n");
|
|
for (i = 1; i <= n; i++) {
|
|
do {
|
|
print("#" + i + " ");
|
|
za[i] = parseFloat(await input());
|
|
} while (za[i] < 0 || za[i] > ba[i] / 2) ;
|
|
}
|
|
for (i = 1; i <= n; i++)
|
|
sa[i] = za[i] * ((pa[d1][2] >= 10 ? 3 : 0) - 1);
|
|
}
|
|
}
|
|
// --Test for dealer blackjack
|
|
l1 = 1;
|
|
l2 = 1;
|
|
if (pa[d1][1] == 1 && pa[d1][2] > 9) {
|
|
l1 = 0;
|
|
l2 = 0;
|
|
}
|
|
if (pa[d1][2] == 1 && pa[d1][1] > 9) {
|
|
l1 = 0;
|
|
l2 = 0;
|
|
}
|
|
if (l1 == 0 && l2 == 0) {
|
|
print("\n");
|
|
print("DEALER HAS A" + ds.substr(3 * pa[d1][2] - 3, 3) + " IN THE HOLE FOR BLACKJACK\n");
|
|
for (i = 1; i <= d1; i++)
|
|
evaluate_hand(i);
|
|
} else {
|
|
// --No dealer blackjack
|
|
if (pa[d1][1] <= 1 || pa[d1][1] >= 10) {
|
|
print("\n");
|
|
print("NO DEALER BLACKJACK.\n");
|
|
}
|
|
// --Now play the hands
|
|
for (i = 1; i <= n; i++) {
|
|
print("PLAYER " + i + " ");
|
|
h1 = 7;
|
|
do {
|
|
str = await input();
|
|
} while (process_input(str)) ;
|
|
if (h == 1) { // Player wants to be hit
|
|
evaluate_hand(i);
|
|
h1 = 3;
|
|
x = get_card();
|
|
print("RECEIVED A");
|
|
card_print(x);
|
|
add_card_to_row(i, x);
|
|
if (q > 0)
|
|
print_total(i);
|
|
} else if (h == 2) { // Player wants to stand
|
|
evaluate_hand(i);
|
|
if (qa[i] == 21) {
|
|
print("BLACKJACK\n");
|
|
sa[i] = sa[i] + 1.5 * ba[i];
|
|
ba[i] = 0;
|
|
discard_row(i);
|
|
} else {
|
|
print_total(i);
|
|
}
|
|
} else if (h == 3) { // Player wants to double down
|
|
evaluate_hand(i);
|
|
h1 = 3;
|
|
h = 1;
|
|
while (1) {
|
|
if (h == 1) { // Hit
|
|
x = get_card();
|
|
print("RECEIVED A");
|
|
card_print(x);
|
|
add_card_to_row(i, x);
|
|
if (q < 0)
|
|
break;
|
|
print("HIT");
|
|
} else if (h == 2) { // Stand
|
|
print_total(i);
|
|
break;
|
|
}
|
|
do {
|
|
str = await input();
|
|
} while (process_input(str)) ;
|
|
h1 = 3;
|
|
}
|
|
} else if (h == 4) { // Player wants to split
|
|
l1 = pa[i][1];
|
|
if (l1 > 10)
|
|
l1 = 10;
|
|
l2 = pa[i][2];
|
|
if (l2 > 10)
|
|
l2 = 10;
|
|
if (l1 != l2) {
|
|
print("SPLITTING NOT ALLOWED.\n");
|
|
i--;
|
|
continue;
|
|
}
|
|
// --Play out split
|
|
i1 = i + d1;
|
|
ra[i1] = 2;
|
|
pa[i1][1] = pa[i1][2];
|
|
ba[i + d1] = ba[i];
|
|
x = get_card();
|
|
print("FIRST HAND RECEIVES A");
|
|
card_print(x);
|
|
pa[i][2] = x;
|
|
evaluate_hand(i);
|
|
print("\n");
|
|
x = get_card();
|
|
print("SECOND HAND RECEIVES A");
|
|
i = i1;
|
|
card_print(x);
|
|
pa[i][2] = x;
|
|
evaluate_hand(i);
|
|
print("\n");
|
|
i = i1 - d1;
|
|
if (pa[i][1] != 1) {
|
|
// --Now play the two hands
|
|
do {
|
|
|
|
print("HAND " + (i > d1 ? 2 : 1) + " ");
|
|
h1 = 5;
|
|
while (1) {
|
|
do {
|
|
str = await input();
|
|
} while (process_input(str)) ;
|
|
h1 = 3;
|
|
if (h == 1) { // Hit
|
|
x = get_card();
|
|
print("RECEIVED A");
|
|
card_print(x);
|
|
add_card_to_row(i, x);
|
|
if (q < 0)
|
|
break;
|
|
print("HIT");
|
|
} else if (h == 2) { // Stand
|
|
print_total(i);
|
|
break;
|
|
} else { // Double
|
|
x = get_card();
|
|
ba[i] *= 2;
|
|
print("RECEIVED A");
|
|
card_print(x);
|
|
add_card_to_row(i, x);
|
|
if (q > 0)
|
|
print_total(i);
|
|
break;
|
|
}
|
|
}
|
|
i += d1;
|
|
} while (i == i1) ;
|
|
i = i1 - d1;
|
|
}
|
|
}
|
|
}
|
|
// --Test for playing dealer's hand
|
|
evaluate_hand(i);
|
|
for (i = 1; i <= n; i++) {
|
|
if (ra[i] > 0 || ra[i + d1] > 0)
|
|
break;
|
|
}
|
|
if (i > n) {
|
|
print("DEALER HAD A");
|
|
x = pa[d1][2];
|
|
card_print(x);
|
|
print(" CONCEALED.\n");
|
|
} else {
|
|
print("DEALER HAS A" + ds.substr(3 * pa[d1][2] - 3, 3) + " CONCEALED ");
|
|
i = d1;
|
|
aa = qa[i];
|
|
total_aa();
|
|
print("FOR A TOTAL OF " + aa + "\n");
|
|
if (aa <= 16) {
|
|
print("DRAWS");
|
|
do {
|
|
|
|
x = get_card();
|
|
alt_card_print(x);
|
|
add_card_to_row(i, x);
|
|
aa = q;
|
|
total_aa();
|
|
} while (q > 0 && aa < 17) ;
|
|
if (q < 0) {
|
|
qa[i] = q + 0.5;
|
|
} else {
|
|
qa[i] = q;
|
|
}
|
|
if (q >= 0) {
|
|
aa = q;
|
|
total_aa();
|
|
print("---TOTAL IS " + aa + "\n");
|
|
}
|
|
}
|
|
print("\n");
|
|
}
|
|
}
|
|
// --TALLY THE RESULT
|
|
str = "LOSES PUSHES WINS "
|
|
print("\n");
|
|
for (i = 1; i <= n; i++) {
|
|
aa = qa[i]
|
|
total_aa();
|
|
ab = qa[i + d1];
|
|
total_ab();
|
|
ac = qa[d1];
|
|
total_ac();
|
|
signaaac = aa - ac;
|
|
if (signaaac) {
|
|
if (signaaac < 0)
|
|
signaaac = -1;
|
|
else
|
|
signaaac = 1;
|
|
}
|
|
signabac = ab - ac;
|
|
if (signabac) {
|
|
if (signabac < 0)
|
|
signabac = -1;
|
|
else
|
|
signabac = 1;
|
|
}
|
|
sa[i] = sa[i] + ba[i] * signaaac + ba[i + d1] * signabac;
|
|
ba[i + d1] = 0;
|
|
print("PLAYER " + i + " ");
|
|
signsai = sa[i];
|
|
if (signsai) {
|
|
if (signsai < 0)
|
|
signsai = -1;
|
|
else
|
|
signsai = 1;
|
|
}
|
|
print(str.substr(signsai * 6 + 6, 6) + " ");
|
|
if (sa[i] == 0)
|
|
print(" ");
|
|
else
|
|
print(" " + Math.abs(sa[i]) + " ");
|
|
ta[i] = ta[i] + sa[i];
|
|
print("TOTAL= " + ta[i] + "\n");
|
|
discard_row(i);
|
|
ta[d1] = ta[d1] - sa[i];
|
|
i += d1;
|
|
discard_row(i);
|
|
i -= d1;
|
|
}
|
|
print("DEALER'S TOTAL= " + ta[d1] + "\n");
|
|
print("\n");
|
|
discard_row(i);
|
|
}
|
|
}
|
|
|
|
main();
|