home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: bj.icn
- #
- # Subject: Program to play blackjack game
- #
- # Author: Chris Tenaglia (modified by Richard L. Goerwitz)
- #
- # Date: December 30, 1991
- #
- ###########################################################################
- #
- # Version: 1.7
- #
- ###########################################################################
- #
- # Simple but fun blackjack game. The original version was for an ANSI
- # screen. This version has been modified to work with the UNIX termcap
- # database file.
- #
- ############################################################################
- #
- # Links: itlib
- #
- # Requires: UNIX
- #
- ############################################################################
-
- link itlib
-
- global deck, message, lookup,
- user_money, host_money,
- user_hand, host_hand
-
- procedure main(param)
- local bonus, user_points, host_points
- user_money := integer(param[1]) | 3 ; host_money := user_money
- write(screen("cls"))
- # Most terminals don't do oversize characters like this.
- # write(screen("cls")," ",screen("top"),screen("hinv"),
- # "BLACK JACK",screen("norm"))
- # write(" ",screen("bot"),screen("hinv"),
- # "BLACK JACK",screen("norm"))
- write(screen("high")," ---- BLACK JACK ----",screen("norm"))
- bonus := 0
- repeat
- {
- if not any('y',(map(input(at(1,3) || " " || screen("under") ||
- "Play a game? y/n :"|| screen("norm") || " " ||
- screen("eeol")))[1])) then break
- every writes(at(1,3|4),screen("eeos"))
- display_score()
- deck := shuffle()
- message := ""
- user_hand := [] ; host_hand := []
- put(user_hand,pop(deck)) ; put(host_hand,pop(deck))
- put(user_hand,pop(deck)) ; put(host_hand,pop(deck))
- user_points := first(host_hand[1])
- if user_points > 21 then
- {
- writes(at(1,13),user_points," points. You went over. You lose.")
- user_money -:= 1 ; host_money +:= 1 + bonus ; bonus := 0
- display_score()
- next
- }
- display_host(2)
- host_points := second(user_points)
- if host_points > 21 then
- {
- writes(at(48,22), right(host_points || " points. " ||
- (&host ? tab(find(" ")|0)) || " went over.", 28))
- writes(at(1,13),screen("hiblink"),"You win.",screen("norm"))
- host_money -:= 1 ; user_money +:= 1 + bonus ; bonus := 0
- display_score()
- next
- }
- if host_points = user_points then
- {
- writes(at(1,22),screen("hiblink"),"It's a draw at ",user_points,
- ". The ANTY goes to bonus.",screen("norm"))
- bonus +:= 2 ; host_money -:= 1 ; user_money -:= 1
- display_score()
- next
- }
- writes(at(1,12),user_points," points for user.")
- writes(at(1,14),host_points," points for ",&host ? tab(find(" ")|0))
- if user_points < host_points then
- {
- write(at(1,22),screen("hiblink"),&host ? tab(find(" ")|0)," wins.",
- screen("norm"),screen("eeol"))
- user_money -:= 1 ; host_money +:= 1 + bonus ; bonus := 0
- display_score()
- next
- } else {
- writes(at(1,12),screen("hiblink"),"You win.",screen("norm"),
- screen("eeol"))
- user_money +:= 1 + bonus ; host_money -:= 1 ; bonus := 0
- display_score()
- next
- }
- }
- write(screen("clear"))
- end
-
- #
- # THIS PROCEDURE ALLOWS THE USER TO PLAY AND TAKE HITS
- #
- procedure first(host_card)
- local points
-
- display_user()
- display_host(1)
- points := value(user_hand) # just in case
- writes(at(1,9),"(",points,") ")
- repeat
- if any('hy',map(input(at(1,23) || "Hit ? y/n : " || screen("eeol")))) then
- {
- put(user_hand,pop(deck))
- display_user()
- if (points := value(user_hand)) > 21 then return points
- writes(at(1,9),"(",points,") ")
- } else break
- (points > 0) | (points := value(user_hand))
- writes(at(1,9),"(",points,") ")
- write(at(55,11),right("You stay with "||points,20))
- return points
- end
-
- #
- # THIS SECOND PROCEDURE IS THE HOST PLAYING AGAINST THE USER
- #
- procedure second(ceiling)
- local stop_at, points
-
- static limits
- initial limits := [14,14,15,15,19,16,17,18]
- stop_at := ?limits ; points := 0
- until (points := value(host_hand)) > stop_at do
- {
- if points > ceiling then return points
- writes(at(1,19),"(",points,") ")
- # write(at(1,22),screen("eeol"),&host," will take a hit.",screen("eeol"))
- write(at(1,22),screen("eeol"),&host ? tab(find(" ")|0),
- " will take a hit.",screen("eeol"))
- put(host_hand,pop(deck))
- display_host(2)
- }
- (points > 0) | (points := value(host_hand))
- writes(at(1,19),"(",points,") ")
- return points
- end
-
- #
- # THIS ROUTINE DISPLAYS THE CURRENT SCORE
- #
- procedure display_score()
- writes(screen("nocursor"))
- writes(screen("dim"),at(1,7),"Credits",screen("norm"))
- writes(screen("high"),at(1,8),right(user_money,7),screen("norm"))
- writes(screen("dim"),at(1,17),"Credits",screen("norm"))
- writes(screen("high"),at(1,18),right(host_money,7),screen("norm"))
- end
- #
- # THIS PROCEDURE EVALUATES THE POINTS OF A HAND. IT TRIES TO MAKE THEM
- # AS HIGH AS POSSIBLE WITHOUT GOING OVER 21.
- #
- procedure value(sample)
- local hand, possible, sum, card, i, best_score, gone_over_score, score
-
- hand := copy(sample)
- possible := []
- repeat
- {
- sum := 0
- every card := !hand do sum +:= lookup[card[1]]
- put(possible,sum)
- if not ("A" == (!hand)[1]) then break else
- every i := 1 to *hand do {
- if hand[i][1] == "A" then {
- hand[i][1] := "a"
- break
- }
- }
- }
- best_score := 0
- gone_over_score := 100
- every score := !possible do {
- if score > 21
- then gone_over_score >:= score
- else best_score <:= score
- }
- return (0 ~= best_score) | gone_over_score
- end
-
- #
- # THIS ROUTINE DISPLAYS THE USER HAND AND STATUS
- #
- procedure display_user()
- local x, y, card
-
- writes(screen("nocursor"),at(1,6),screen("hinv"),"USER",screen("norm"))
- x := 10 ; y := 4
- every card := !user_hand do
- {
- display(card,x,y)
- x +:= 7
- }
- end
-
- #
- # THIS ROUTINE DISPLAYS THE HOST HAND AND STATUS
- #
- procedure display_host(flag)
- local x, y, card
-
- writes(screen("nocursor"),at(1,16),screen("hinv"),
- &host ? tab(find(" ")|0),screen("norm"))
- x := 10 ; y := 14 ; /flag := 0
- every card := !host_hand do
- {
- if (flag=1) & (x=10) then card := "XX"
- display(card,x,y)
- x +:= 7
- }
- end
-
- #
- # THIS ROUTINE DISPLAYS A GIVEN CARD AT A GIVEN X,Y SCREEN LOCATION
- #
- procedure display(card,x,y)
- local all, j, shape
-
- all := [] ; j := y
- if find(card[2],"CS") then card := screen("hinv") || card || screen("norm")
- # shape := [at(x,(j+:=1)) || screen("gchar") || "lqqqqqqqk"]
- shape := [at(x,(j+:=1)) || screen("inv") || " " || screen("norm")]
- put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
- " " || card || " " || screen("inv") || " " || screen("norm"))
- put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
- " " || screen("inv") || " " || screen("norm"))
- put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
- " " || screen("inv") || " " || screen("norm"))
- put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
- " " || screen("inv") || " " || screen("norm"))
- # put(shape,at(x,(j+:=1)) || "x x")
- # put(shape,at(x,(j+:=1)) || "x x")
- put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
- " " || card || " " || screen("inv") || " " || screen("norm"))
- # put(shape,at(x,(j+:=1)) || "mqqqqqqqj" || screen("nchar"))
- put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm"))
- put(all,shape)
- x +:= 14
- while shape := pop(all) do every writes(!shape)
- end
-
- #
- # THIS ROUTINE SHUFFLES THE CARD DECK
- #
- procedure shuffle()
- static faces, suits
- local cards, i
- initial {
- &random := map(&clock,":","7") # initial on multiple shuffles
- faces := ["2","3","4","5","6","7","8","9","T","J","Q","K","A"]
- suits := ["D","H","C","S"]
- lookup := table(0)
- every i := 2 to 9 do insert(lookup,string(i),i)
- insert(lookup,"T",10)
- insert(lookup,"J",10)
- insert(lookup,"Q",10)
- insert(lookup,"K",10)
- insert(lookup,"A",11)
- insert(lookup,"a",1)
- }
- cards := []
- every put(cards,!faces || !suits)
- every i := *cards to 2 by -1 do cards[?i] :=: cards[i]
- return cards
- end
-
- #
- # THIS ROUTINE PARSES A STRING WITH RESPECT TO SOME DELIMITER
- #
- procedure parse(line,delims)
- local tokens
-
- static chars
- chars := &cset -- delims
- tokens := []
- line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
- return tokens
- end
-
- #
- # THIS ROUTINE PROMPTS FOR INPUT AND RETURNS A STRING
- #
- procedure input(prompt)
- writes(screen("cursor"),prompt)
- return read()
- end
-
-
- #
- # THIS ROUTINE SETS THE VIDEO OUTPUT ATTRIBUTES FOR VT102 OR LATER
- # COMPATIBLE TERMINALS.
- #
- procedure screen(attr)
- initial if getval("ug"|"mg"|"sg") > 0 then
- er("screen","oops, magic cookie terminal!",34)
- return {
- case attr of
- {
- "cls" : getval("cl")
- "clear": getval("cl")
- # HIGH INTENSITY & INVERSE
- "hinv" : (getval("md") | "") || getval("so")
- "norm" : (getval("se") | "") || (getval("me") | "") || (getval("ue")|"")
- # LOW INTENSITY VIDEO
- "dim" : getval("mh"|"me"|"se")
- "blink": getval("mb"|"md"|"so")
- # HIGH INTENSITY BLINKING
- "hiblink": (getval("md") | "") || getval("mb") | getval("so")
- "under": getval("us"|"md"|"so")
- "high" : getval("md"|"so"|"ul")
- "inv" : getval("so"|"md"|"ul")
- # ERASE TO END OF LINE
- "eeol" : getval("ce")
- # ERASE TO START OF LINE
- "esol" : getval("cb")
- # ERASE TO END OF SCREEN
- "eeos" : getval("cd")
- # MAKE CURSOR INVISIBLE
- "cursor": getval("vi"|"CO") | ""
- # MAKE CURSOR VISIBLE
- "nocursor": getval("ve"|"CF") | ""
- # # START ALTERNATE FONT <- very non-portable
- # "gchar": getval("as") | ""
- # # END ALTERNATE FONT
- # "nchar": getval("ae") | ""
- # "light": return "\e[?5h" # LIGHT COLORED SCREEN
- # "dark" : return "\e[?5l" # DARK COLORED SCREEN
- # "80" : return "\e[?3l" # 80 COLUMNS ON SCREEN
- # "132" : return "\e[?3h" # 132 COLUMNS ON SCREEN
- # "smooth": return "\e[?4h" # SMOOTH SCREEN SCROLLING
- # "jump" : return "\e[?4l" # JUMP SCREEN SCROLLING
- default : er("screen",attr||" is just too weird for most terminals",34)
- } | er("screen","I just can't cope with your terminal.",35)
- }
- end
-
- #
- # THIS ROUTINE SETS THE CURSOR TO A GIVEN X (COL) Y(ROW) SCREEN LOCATION
- #
- procedure at(x,y)
- # return "\e[" || y || ";" || x || "f"
- return igoto(getval("cm"),x,y)
- end
-
-