My questions to the community are:
1. Does this script "cheat" in any way? if so how can it be modified to be fair?
2. Is this single deck blackjack? If not how can it be modified to be single deck blackjack?
3. Will anyone with the ability please provide open source gaming code to the community for ALL types of games that involve chance for cash?
It is hard for me as a new person to know who to trust for reliable random card generation. If i make a purchase, how do i know the writer didn't make the code cheat? I know nothing of this language. We MUST have open source gaming codes. Also i would like to note that in the real world of casino's it is not the technology that is the big deal. Anyone can make and buy machines. Anyone can deal cards and roll dice. It is the atmosphere, services, and products that a casino offers that makes it unique. And it is the community that ensures fair gameplay. Casino's that cheat will suffer from no repeat business and the reputation of scum as well as legal ramafications. I think the games odds should be posted in everyplace that has them. This way both the player AND the owner can be sure and honest about what they are doing. I intend to have as close to 99% payback for any games i host as i can get (craps, roulette, blackjack, lotteries, bingo, raffles, and other traditional games have may high payback but not 99% necessarily).
With reliable open source card dealing and dice rolling we can all then focus on the task of having a quality environment to host them in. To provide the highest quality of services and products to our customers while they play on custom machines built from this technology that we can all trust and figure out a way to certify. I would ask for our game gods the good people at Linden to help us with a method of stamping a particular set of code as "Fair Gambling Engine Enabled" or something like that since they are the only people that could tell us if indeed the games we were playing on were what we were being told they are. It is up to us to figure this out in the meantime. I am sure someone will always come up with a way to milk another 5% here and there and commit to being a dishonest person for their 30pieces of silver. But most of us will actually want to have good games on our land so our customers can enjoy legitimate odds and we can all sleep well at night knowing the criminals are hard at work on some new way to steal from us and will quit trying to rig old school scams into this high tech paradise.
I won 20,000L$ in my first month from playing cards at Chilly's Club Extreme. Chilly has some great insight into this issue and I hope he and others can come forward with some solutions that will help all Second Life citizens feel good about L$ gaming here.
I love to gamble. I love to do it even knowng the odds are in the houses favor. The casino will win. But sometimes i do too

I will be posting more code from games like this until we all figure this issue out. So put on the thinking caps and if your ideas involve any "oversight" from any committee or group then let that group be Linden Labs. They are the only entity we will ALL trust. I think we can do this on our own pretty much but some help would not neccessarily be a bad thing. All things must be verifiable.
When this is all done we should all be able to make new and creative "gaming for L$" products that use engine scripts that are fair. This should not put anyone out of business. In fact it will create a whole new genre of credible game makers. First we need to agree on open source code, then have a system that will reward the creators of new innovations to those codes that we can all use. Perhaps a system where we make a fund that buys code from scriptors for public use. This way the scriptors can get paid for legitimate work that has improved existing code and the people can have code that works fair and correctly. I personally will be willing to contribute many L$ to such a fund. Provided they are trustworthy and certified by Linden and keep open books of donations and expenditures of all kinds open to the public. This code could then be distributed in a "no mod" form perhaps.
Please provide positive solution oriented comments to this post and refrain from addressing negative concerns that you offer no solutions for.
This is my first post ever so sorry if the code doesn't go into the neat little box everyone elses does. I have no idea how they do that.
The Code is in 4 parts, they are listed here in this order:
1. Main Blackjack code
2. The Card Texture display code
3. Hit
4. Stand
****************
Main Code
****************
//starts here
key playerkey;
string playername;
float timeout = 120.0;
integer minbet = 1;
integer maxbet = 5;
integer maxpayout = 200;
integer amountbet = 0;
integer amountpaid = 0;
integer inplay = FALSE;
integer playerBJ = FALSE;
integer dealerBJ = FALSE;
integer player1a = FALSE;
integer player5 = FALSE;
integer dealer1a = FALSE;
integer dealer5 = FALSE;
integer bet = 0;
integer playercount = 0;
integer dealercount = 0;
integer playerscore = 0;
integer dealerscore = 0;
integer playeraces = 0;
integer dealeraces = 0;
string command;
string command1;
string command2;
parse(string bulk)
{
list chunks = llParseString2List(bulk, [" "], []);
command = llList2String(chunks, 0);
command1 = llList2String(chunks, 1);
command2 = llList2String(chunks, 2);
//command = llDeleteSubString(command, 0, prefix_length - 1);
}
reset_game()
{
llSetTimerEvent(0.0);
inplay = FALSE;
playerBJ = FALSE;
dealerBJ = FALSE;
player1a = FALSE;
player5 = FALSE;
dealer1a = FALSE;
dealer5 = FALSE;
bet = 0;
playercount = 0;
dealercount = 0;
playerscore = 0;
dealerscore = 0;
playeraces = 0;
dealeraces = 0;
}
integer card_idvalue(integer num) {
integer v;
if (num < 13) {
v = num + 2;
} else {
if (num < 26) {
v = num - 11;
} else {
if (num < 39) {
v = num - 24;
} else {
if (num < 53) {
v = num - 37;
} else {
v = 15;
}
}
}
}
return v;
}
hide_cards()
{
integer cardnum = 1;
do
{
cardnum += 1;
llMessageLinked(cardnum, 0, "Hide", ""

} while (cardnum < 11);
}
deal_card(integer cardnum)
{
integer rand_card;
rand_card = llRound(llFrand(51));
llMessageLinked(llRound(cardnum + 1), 0, "Card " + (string)rand_card, ""

if (cardnum < 6)
{
if (card_idvalue(rand_card) == 14)
{
if (cardnum == 1) {
player1a = TRUE;
}
playerscore += 11;
playeraces += 1;
}
else if (card_idvalue(rand_card) > 10) playerscore += 10;
else playerscore += card_idvalue(rand_card);
if (playerscore == 21)
{
if (cardnum == 2)
{
llWhisper(0, playername + "; Black Jack! Let's see if the dealer can get 21!"

playerBJ = TRUE;
llMessageLinked(7, 0, "Card " + (string)rand_card, ""

if (card_idvalue(rand_card) == 14)
{
dealer1a == TRUE;
dealerscore += 11;
dealeraces += 1;
}
else if (card_idvalue(rand_card) > 10) dealerscore += 10;
else dealerscore += card_idvalue(rand_card);
}
else
{
llWhisper(0, playername + "; You have " + (string)playerscore + "."

}
dealer_play();
return;
}
else if (playerscore > 21)
{
if (playeraces > 0)
{
playeraces -= 1;
playerscore -= 10;
}
else
{
llWhisper(0, playername + "; Sorry, you busted with " + (string)playerscore + ". Better luck next time!"

reset_game();
return;
}
}
playercount += 1;
}
if (cardnum == 5)
{
llWhisper(0, playername + "; You have " + (string)playerscore + " with a 5 card trick! Let's see if the Dealer can beat that!"

player5 = TRUE;
dealer_play();
}
else if (cardnum > 1)
{
llWhisper(0, playername + "; You have " + (string)playerscore + ". 'Hit' or 'Stand'?"

}
if (cardnum == 2)
{
integer rand_card = llRound(llFrand(51));
llMessageLinked(7, 0, "Card " + (string)rand_card, ""

if (card_idvalue(rand_card) == 14)
{
dealer1a == TRUE;
dealerscore += 11;
dealeraces += 1;
}
else if (card_idvalue(rand_card) > 10) dealerscore += 10;
else dealerscore += card_idvalue(rand_card);
llMessageLinked(8, 0, "Card 53", ""

}
}
dealer_play()
{
integer cardnum = 7;
integer rand_card;
do
{
rand_card = llRound(llFrand(51));
llMessageLinked(llRound(cardnum + 1), 0, "Card " + (string)rand_card, ""

if (card_idvalue(rand_card) == 14)
{
dealerscore += 11;
dealeraces += 1;
}
else if (card_idvalue(rand_card) > 10) dealerscore += 10;
else dealerscore += card_idvalue(rand_card);
if ((dealerscore == 21) && (cardnum == 7))
{
dealerBJ = TRUE;
llWhisper(0, playername + "; Dealer has Black Jack!"

dealer_stand();
return;
}
if (dealerscore > 21)
{
if (dealeraces > 0)
{
dealeraces -= 1;
dealerscore -= 10;
}
else
{
dealer_bust();
return;
}
}
if ((dealerscore == 16) && (dealerscore > playerscore)) {
dealer_stand();
return;
}
cardnum += 1;
} while ((cardnum < 11) && (dealerscore < 17));
if (cardnum == 11)
{
dealer5 = TRUE;
llWhisper(0, playername + "; Dealer has " + (string)dealerscore + " with a 5 card trick."

}
dealer_stand();
}
dealer_stand()
{
integer payout;
if (!dealer5) llWhisper(0, playername + "; Dealer has " + (string)dealerscore + "."

if (player5)
{
if (dealer5)
{
if (playerscore > dealerscore)
{
payout = (bet * 2);
llWhisper(0, playername + "; You won $" + (string)payout + "!"

llGiveMoney(playerkey, payout);
amountpaid += payout;
}
else
{
llWhisper(0, playername + "; Sorry, you lost. Better luck next time!"

}
}
else
{
payout = (bet * 2);
llWhisper(0, playername + "; You won $" + (string)payout + "!"

llGiveMoney(playerkey, payout);
amountpaid += payout;
}
}
else if (dealer5)
{
if ((playerBJ) && (player1a))
{
payout = (bet * 3);
llWhisper(0, playername + "; You won $" + (string)payout + "!"

llGiveMoney(playerkey, payout);
amountpaid += payout;
}
else
{
llWhisper(0, playername + "; Sorry, you lost. Better luck next time!"

}
}
else if (playerscore > dealerscore)
{
if (playerBJ) payout = (bet * 3);
else payout = (bet * 2);
llWhisper(0, playername + "; You won $" + (string)payout + "!"

llGiveMoney(playerkey, payout);
amountpaid += payout;
}
else if (playerscore == dealerscore)
{
llGiveMoney(playerkey, bet);
amountpaid += bet;
llWhisper(0, playername + "; You tied with the Dealer! You won $" + (string)bet + "!"

}
else
{
llWhisper(0, playername + "; Sorry, you lost. Better luck next time!"

}
reset_game();
}
dealer_bust()
{
integer payout;
if (playerBJ) payout = (bet * 3);
else payout = (bet * 2);
llWhisper(0, playername + "; The Dealer busted with " + (string)dealerscore + "! You won $" + (string)payout + "!"

llGiveMoney(playerkey, payout);
amountpaid += payout;
reset_game();
}
default
{
on_rez(integer sparam)
{
llResetScript();
}
state_entry()
{
hide_cards();
llListen(0, "", "", ""

llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
}
listen(integer channel, string name, key id, string message)
{
parse(message);
if ((id == playerkey) && (inplay))
{
if (llToLower(message) == "hit"

{
llSetTimerEvent(timeout);
deal_card(llRound(playercount + 1));
}
if (llToLower(message) == "stand"

{
llSetTimerEvent(timeout);
dealer_play();
}
}
if(command == "status" && command1 == "blackjack"

{
llSay(0,"Minimum Bet: " + (string)minbet);
llSay(0,"Maximum Bet: " + (string)maxbet);
llSay(0,"Max Payout: " + (string)maxpayout);
llSay(0,"Time Out: " + (string)timeout);
}
if(!inplay && id == llGetOwner())
{
if(command == "minbet"

{
if((integer)command1 <= maxbet)
{
minbet = (integer)command1;
llSay(0,"Minimum BET set to " + command1);
}
else if((integer)command1 > maxbet)
{
llSay(0,"Minimum Bet must be less than or equal to Maximum Bet"

}
}
else if(command == "maxbet"

{
if((integer)command1 >= minbet)
{
maxbet = (integer)command1;
llSay(0,"Maximum BET set to " + command1);
}
else if((integer)command1 < minbet)
{
llSay(0,"Maximum Bet must be greater than or equal to Minimum Bet"

}
}
else if(command == "maxpayout"

{
maxpayout = (integer)command1;
llSay(0,"Maximum PAYOUT set to " + command1);
}
else if(command == "timeout"

{
timeout = (float)command1;
llSay(0,"Timeout set to " + command1);
}
}
else if(inplay)
{
llSay(0,"Someone is currently playing this game. Please wait until they finish this hand to
change the settings."

}
if(id == llGetOwner() && llToLower(message) == "reset blackjack"

{
llResetScript();
}
}
link_message(integer sender_num, integer num, string str, key id)
{
if ((id == playerkey) && (inplay))
{
if (llToLower(str) == "hit"

{
llSetTimerEvent(timeout);
deal_card(llRound(playercount + 1));
}
if (llToLower(str) == "stand"

{
llSetTimerEvent(timeout);
dealer_play();
}
}
}
money(key giver, integer amount)
{
if (inplay) {
llGiveMoney(giver, amount);
llWhisper(0, "Another game is in play."

return;
}
else if ((amount > maxbet) || (amount < minbet))
{
llGiveMoney(giver, amount);
llWhisper(0, "Min Bet: $" + (string)minbet);
llWhisper(0, "Max Bet: $" + (string)maxbet);
return;
}
else if ((amountpaid > maxpayout) || (amountpaid == maxpayout))
{
llGiveMoney(giver, amount);
llWhisper(0, "This machine is currently down for servicing"

return;
}
amountbet += amount;
hide_cards();
playerkey = giver;
playername = llKey2Name(giver);
inplay = TRUE;
bet = amount;
llWhisper(0, "$" + (string)bet + " bet! Good luck!"

deal_card(1);
deal_card(2);
llSetTimerEvent(timeout);
}
touch_start(integer total_number)
{
if (llDetectedKey(0) == llGetOwner())
{
llWhisper(0, "Total Amount Bet: $" + (string)amountbet);
llWhisper(0, "Total Amount Paid: $" + (string)amountpaid);
}
else
{
llWhisper(0, "Black Jack! Right-Click and 'Pay' to Play!"

}
}
timer()
{
integer refund = bet;
llWhisper(0, "Black Jack has timed out. Please contact the owner for a refund."

reset_game();
llInstantMessage(llGetOwner(), "Black Jack timed out for " + playername + " on a $" + (string)refund + " bet."

}
}
//end main
***********************************************************************
Card texture display code is next (educated guess for what to call it lol, in the object this code is in the card prims and has all the card textures in each object with it).
**********************************************************************
//starts here
integer me;
string card_texture(integer j, integer k) {
string s;
list map1 = ["t","j","q","k","a"];
if (j < 10) {
s = s + (string)j;
} else {
s = s + llList2String(map1, j - 10);
}
list map2 = ["s","h","c","d"];
s = s + llList2String(map2, k - 1);
if (j == 15) {
return "back.jpg";
}
return s + ".jpg";
}
integer card_idvalue(integer num) {
integer v;
if (num < 13) {
v = num + 2;
} else {
if (num < 26) {
v = num - 11;
} else {
if (num < 39) {
v = num - 24;
} else {
if (num < 53) {
v = num - 37;
} else {
v = 15;
}
}
}
}
return v;
}
integer card_idsuit(integer num) {
integer s;
if (num < 13) {
s = 1;
} else {
if (num < 26) {
s = 2;
} else {
if (num < 39) {
s = 3;
} else {
s = 4;
}
}
}
return s;
}
default {
state_entry()
{
llSetTexture("back.jpg", 0);
}
link_message(integer sender_num, integer num, string str, key id)
{
list message = llParseString2List(str, [" "], []);
if (llList2String(message, 0) == "Card"

{
integer num = llList2Integer(message, 1);
llSetTexture(card_texture(card_idvalue(num), card_idsuit(num)), 0);
}
else if (llList2String(message, 0) == "Hide"

{
llSetTexture("clear.jpg", ALL_SIDES);
}
}
listen(integer channel, string name, key id, string message) {
if (llGetOwnerKey(id) == llGetOwner()) {
if (message == "nocards"

llDie();
} else {
if (llGetSubString(message, 0, 3) == "face"

if (me == 53) {
integer num = (integer)(llGetSubString(message,5,-1));
llSetTexture(card_texture(card_idvalue(num), card_idsuit(num)), 0);
}
}
}
}
}
}
//end
*****************************
The Hit Button Prim has this in it:
*****************************
default
{
touch_start(integer total_number)
{
llMessageLinked(1, 0, "HIT", llDetectedKey(0));
}
}
****************************
And finally the Stand Button:
****************************
default
{
touch_start(integer total_number)
{
llMessageLinked(1, 0, "STAND", llDetectedKey(0));
}
}