!Blackjack Dealer by Ashok Desai; !To use, put this file in your Inform working directory and write the line; !include "blackjack.inf' immediately after the room object that you want; !your dealer to be located in. At present you may only have one blackjack; !dealer in your game. The dealer's Stickat value can be adjusted to make; !him play more or less recklessly. To insert prizes for winning and forfeits; !for losing, replace the blackjackwin and blackjacklose routines with what; !you would like to happen when the player wins or loses a game, such as paying; !out or giving an object. There is also a routine called Blackjackcost. Normally; !this always returns true, but you can replace it with a routine of your own.; !Blackjackcost is checked before the game starts if there isn't one already in; !progress, and cancels the attempt if it returns false. You should include any; !error messages (i.e. "you don't have enough money to play") with the checking; !routine.; !Declare the globals used by the code. Pack_of_cards holds a; !shuffleable deck of 52 cards, currentcard represents the current; !position in the deck, cardhand and cardace are used when the code; !needs to calculate the best value of a pontoon hand.; array pack_of_cards -->52; Global currentcard = 0; array cardhand --> 2; array cardace --> 2; !The next few routines are lifted or adapted from those written in; !the user manual for Inform. Why change something that works?; [PrintCard n; switch(n%13) { 0: print "Ace"; 1 to 9: print n%13 + 1; 10: print "Jack"; 11: print "Queen"; 12: print "King"; } print " of "; switch(n/13) { 0: print "Hearts"; 1: print "Clubs"; 2: print "Diamonds"; 3: print "Spades"; } ]; !I deleted the part of this routine that writes the exact order of; !all the cards in the deck, but it's otherwise identical.; [ Reorder i j; !Shuffle, using the Dylan Thurston method; for (i=1:i<52:i++) pack_of_cards --> i = i; pack_of_cards-->0 = 0; for (i=1:i<52:i++) { j = random(i+1) - 1; pack_of_cards-->i = pack_of_cards-->j; pack_of_cards-->j = i; } ]; !This routine simply grabs the next card in line, points the deck; !to the next card along, and returns the appropriate value. In; !other words, read this into an attribute when you want to take a; !card off the deck; [getcard x; x = pack_of_cards --> currentcard; currentcard = currentcard + 1; return x; ]; !This routine is called when a player gets a new card. It ; !increments the total for non-ace cards if the new card is not; !an ace, and increments the number of aces if it is. It is !necessary to keep these two values separate so that the code can; !figure out how many aces to convert into 11's.; [addcard x player; !0 means add to the player's hand. 1 means add to the dealer's hand; x = x%13+1; if (x > 10) x = 10; !if it's a picture card, make it worth 10; if (x == 1) cardace-->player = cardace-->player + 1; else cardhand-->player = cardhand-->player + x; ]; !This beauty calculates the exact value of each hand. Basically,; !it takes the total value of all non-ace cards, then goes through; !all the aces checking to see if having this one at 11 would cause; !the player to go bust, if all the others were valued at 1.; [pontoonvalue player x f; x = cardhand-->player; for (f=1:f<=cardace-->player:f++) if (x + 11 + cardace-->player - f <= 21) x = x + 11; else x = x + 1; return x; ]; !This routine ends the game, tidies things up, and rewards the; !player if a reward is on offer.; [endgame winner dealer; if (winner == 0) Blackjack_Win(); else Blackjack_lose(); dealer.gameon = 0; return;]; [blackjack_win; print_ret "The dealer glares at you. ~Beginner's luck,~ he snarls.";]; [blackjack_lose; print_ret "~Sorry friend,~ says the dealer with a smile, ~you lose!~";]; !For some reason, the code cannot access the return value of a replaced function; !directly, so we need to fool it into doing so indirectly with a ghost routine; [blackjack_test; return blackjack_cost();]; [blackjack_cost; return true;]; !And now the dealer himself.; Object -> gambler "gambler" with name "gambler", gameon 0, stick 0, stickat 17, !N.B. stickat is the value at which the Gambler will not risk taking another; !card, unless he knows he has to beat a higher value to win. Set it higher and; !he will go bust more easily. Set it lower, and he will play more carefully but; !will be easier to beat as he will stick at a lower value. The gambler will never; !stick if you have already stuck and his value is less than yours.; description "A man with a deck of cards. (Type and maybe he will tell you how to play!)", !The game's commands must all be spoken to the dealer.; life[c1 c2 f;answer: switch (noun) { !The deal command initialises a new game, if none is in progress; 'deal' : if (self.gameon == 0) {if (blackjack_test() == true) { !First, we initialise the necessary values and tell the dealer; !that the game is on; reorder(); self.gameon = 1; self.stick = 0; for (f=0:f<2:f++) {cardhand-->f = 0; cardace-->f = 0;} !Next, we deal two cards each to both players, and tell them what they are and their totals; c1 = getcard(); c2 = getcard(); addcard(c1,0); addcard(c2,0); print "The gambler deals you the "; printcard (c1); print " and the "; printcard (c2); print ", for a running total of "; print pontoonvalue(0); print "."; c1 = getcard(); c2 = getcard(); addcard(c1,1); addcard (c2,1); print "^To himself, he deals the "; printcard (c1); print " and the "; printcard (c2); print ", for a running total of "; print pontoonvalue(1); print ".^"; !Finally we check to see if either player has Pontoon; if (pontoonvalue(1) == 21) {print "^~Pontoon!~ shouts the dealer triumphantly, ~I win!~^"; endgame(1,self);} else if (pontoonvalue(0) ==21) {print "^You smugly show the gambler your Pontoon hand.^"; endgame(0,self);} return; } else return;} else print_ret "You're halfway through a game, you might as well finish it."; !Now we need to tell the dealer what happens if a player accepts; !a new card, and how it should react.; 'twist', 'hit', 'again', 'another' : if (self.gameon == 1) {c1 = getcard(); addcard (c1,0); !Deal to the player, make sure you're not bust; print "The gambler deals you the "; printcard (c1); print ".";if (pontoonvalue(0) > 21) {print " You have gone bust!^"; endgame(1,self);} else {print " Your current total is "; print pontoonvalue(0); print ".^"; !Check to see if the dealer wants a card, and if he goes bust.; if ((pontoonvalue(1) <= self.stickat || pontoonvalue(1) < pontoonvalue(0)) && self.stick ~= 1) {c1 = getcard(); addcard(c1,1); print "The dealer draws the "; printcard (c1); if (pontoonvalue(1) > 21) {print " and goes bust!^"; endgame(0,self); return;} else {print " for a running total of "; print pontoonvalue(1); print ".";}} else if (self.stick == 0) {self.stick = 1; print "The gambler sticks at "; print pontoonvalue(1); print ".^";} else {print "You need to beat "; print pontoonvalue(1); print ".^";}} !And round off the action, or complain if no game is in progress; return;} else print_ret "There is no game in progress - first."; !Last part now! This is what happens when the player sticks.; 'stick', 'stay', 'stand' : if (self.gameon == 1) { print "You stick at "; print pontoonvalue(0); print ".^"; !We tell the player what value they have stuck upon. Now the; !dealer will continue drawing cards until he either goes bust; !or beats the player's total. Note that if he already stuck, he; !won't be able to do this as the while loop will never trigger.; while (pontoonvalue(1) < pontoonvalue(0) && self.stick ~= 1) {c1 = getcard(); addcard(c1,1); print "The dealer draws the "; printcard(c1); if (pontoonvalue(1) > 21) {print " and goes bust!^"; endgame(0,self); return;} else {print " for a running total of "; print pontoonvalue(1); print ".^";}} print "The gambler sticks at "; print pontoonvalue(1); print ".^"; !This part is technically not necessary, but better safe than; !sorry. It checks to see which player has won. To be honest, if; !it gets to this point in the code then mathematically the dealer; !should already have won, but I put it like this so that people; !could more easily fiddle with the code.; if (pontoonvalue(0) > pontoonvalue (1)) endgame(0,self); else endgame(1,self); return;} else print_ret "There is no game in progress - first."; !You can continue the answer case statement here if you want to; !make the dealer respond to other words too.; };print_ret "The gambler doesn't seem to care for that."; !And, as promised in the description earlier, here the rules of; !the game are briefly explained.; ask : switch (second) { 'rules', 'game', 'pontoon', 'cards', 'play' : print_ret "The gambler smiles, ~This is a very simple game friend, you'll get the hang of it in no time. Just and I'll deal you two cards, and another two for myself. The idea is to get as close to 21 without going over. Face cards like the king, queen and jack are all worth 10 points. The Ace is worth either one or eleven, depending on which would be better for you. Provided you haven't 'gone bust' you can ask me for another card - just - and I can do the same. If you're happy with your score you can instead. Whoever gets closer to 21 wins the hand, if we draw then I win the hand. Oh and to show it's all above board and no cheating is going on, I'll shuffle the cards at the beginning of each hand.~"; };print_ret "The gambler doesn't seem to care for that.";], has animate static;