############################################################################ # # File: hr.icn # # Subject: Program to play horse-race game # # Author: Chris Tenaglia # # Date: August 14, 1996 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program implements a horse-race game. # ############################################################################ # # Links: random # ############################################################################ link random global horse1, horse2, horse3, # horses are global players, money, bets, # player info is global vectors, leg1, leg2, leg3, # track parameters front, back, y1 , y2, y3, # horse parameters pos1, pos2, pos3, # more horse parameters oops1, oops2, oops3 # accident flags procedure main() local winner banner() if ready() == "no" then stop("Game Over.") # ask if ready players := get_players() # get player name list money := table(100) # everyone starts w/$100 randomize() repeat { if ready() == "no" then break writes("\e[2J\e[H") # clear old junk off screen repeat # choose 3 fresh horses { horse1 := get_horse() # get first horse list horse2 := get_horse() # get second horse list horse3 := get_horse() # get third horse list if horse1[1] == horse2[1] | # disallow duplicates horse2[1] == horse3[1] | # because a horse can't horse3[1] == horse1[1] then next # race against himself break # continue... } bets := get_bet() # bets initially 0 winner := race() # race the horses, get winner pay(winner) # pay winner(s) if any } done() end # # # ask if ready to play the game, return yes or no # procedure ready() local answer static pass,sh initial { pass := 0 # initialize pass counter sh := "\e[1;7m \e[0;1;33;44m" # initialize a shadow for box } if (pass +:= 1) = 1 then { writes("\e[0;1;33;44m\e[2J\e[H") write(" +----------------------------------------------------------+") write(" | WELCOME TO ICON PARK VIRTUAL RACE TRACK |",sh) write(" | |",sh) write(" | The following game allow one or more players to bet on |",sh) write(" | three Cyberspace steeds that will run on an ANSI VT100 |",sh) write(" | dirt track. Of course the bets are Cyberspace dollars, |",sh) write(" | which have no real world value. We use only the oldest |",sh) write(" | escape sequences to condition the track surface, which |",sh) write(" | may not appeal to TEK crowds, and I'm sure some fans |",sh) write(" | will hurl curses. C'est la vie! |",sh) write(" | |",sh) write(" +----------------------------------------------------------+",sh) write(" \e[1;7m \e[0;1;33;44m") write("") write(" Are we ready to enter our names, and begin?") answer := map(input("Enter yes or no:")) if answer[1] == "n" then return "no" else return "yes" } end # # get the names of the players # procedure get_players() local counter, people, who people := [] counter := 1 write("\nEnter Player Names. Enter blank when done.") repeat { (who := input(" Player #" || counter || ":")) | break if trim(who) == "" then break put(people,who) counter +:= 1 } if *people < 1 then stop("Not enough players. Need at least one.") return people end # # # build a horse list structure # procedure get_horse() local odds, pic, tmp static stable,photos initial { photos := [pick1(),pick2(),pick3(), pick4(),pick5(),pick6()] stable := ["Incredible Hash", "Random Number", "Floppy Crash", "RAM Dump", "Programmers Nightmare", "Spaghetti Code", "Infinite Loop", "User Blues", "See Plus Plus", "Press Any Key", "Paradigm Shift", "Adricks' Abend", "Client Server", "Network Storm", "Mr. Cobol", "Forgotten Password", "Hackers' Byte", "Chad Hollerith", "ASCII Question", "EBCDIC Object", "Recursive Instance", "RunTime Error"] } name := ?stable # pick a horse name odds := 1 + real((?30)/real(10.0)) # calculate the odds tmp := ?photos # choose a photo file pic := [name,odds] every put(pic,!tmp) return pic end # # # obtain bets from the players # procedure get_bet() local items, person, summation, wager (&features == "MS-DOS") | writes("\e[?25h") bets := table(0) summation := 0 every person := !players do { if money[person] <= 0 then next summation +:= money[person] write("\e[2J\e[H",person,", enter your bet. You have $",money[person],"\n") write("1. ",left(horse1[1],32)," odds = ",horse1[2]," : 1") write("2. ",left(horse2[1],32)," \" = ",horse2[2]," : 1") write("3. ",left(horse3[1],32)," \" = ",horse3[2]," : 1") write("\n (enter 5 on 2 for $5 on ",horse2[1],")\n") wager := trim(map(input("Your decision : "))) if wager == "" then next if wager == "q" then done() items := parse(wager,' ') if not(numeric(items[1])) | not(numeric(items[3])) then { input("\7Wager Improperly Entered. No wager made. Press RETURN") next } if (*items ~= 3) | (items[2] ~== "on") | (items[1] > money[person]) | (1 > items[3] > 3) then { input("\7Wager Improperly Entered. No wager made. Press RETURN") next } bets[person] := wager money[person] -:= parse(wager,' ')[1] } if summation = 0 then { write("\e[2J\e[HICON PARK CYBER RACE TRACK BIDS YOU ADIEU\n") write("It looks you'all lost all your money here today.") write("Take it easy now. Better luck next time") stop("Game Over") } input("Done Entering Wagers. Press RETURN to Continue.") end # # # determine the victor and pay out winnings. if there is a tie # then nothing gets payed out (bets are refunded) # procedure pay(victor) local check, i, msg, nag, odds, pair, player, prize, test local wager, winner, winnings, y (&features == "MS-DOS") | writes("\e[?25h") # turn on cursor again winner := case victor of { 1 : horse1 2 : horse2 3 : horse3 default : ["tie"] } if victor = 4 then { writes(at(12,14),"All The Steeds Fell Down! Too many injuries!\7") wait(1) writes(at(12,14),"The judges are coming to a decision....") wait(2) writes(at(12,14),"All bets will be refunded. Sorry.......") check := sort(bets,1) every pair := !check do { name := pair[1] wager := pair[2] odds := winner[2] prize := parse(bets[name],' ')[1] money[name] +:= integer(prize) } test := map(input(at(13,1) || "Press RETURN to Continue.")) if test[1] == "q" then done() return } if winner[1] == "tie" then { writes(at(12,14),"It was a photo finish!\7") wait(1) writes(at(12,14),"The judges are coming to a decision....") wait(2) writes(at(12,14),"All bets will be refunded. Sorry.......") check := sort(bets,1) every pair := !check do { name := pair[1] wager := pair[2] odds := winner[2] prize := parse(bets[name],' ')[1] money[name] +:= integer(prize) } test := map(input(at(13,1) || "Press RETURN to Continue.")) if test[1] == "q" then done() return } else { writes(at(12,14),winner[1]," WINS! ") writes(at(victor+21,1),"\e[1;5;33;44m",victor," : ",left(winner[1],32),"\e[0;1;33;44m") wait(2) writes(at(12,14),"And now for a closeup of the winner....") wait(3) y := 4 writes(at((y+:=1),40),"+",repl("-",35),"+") every i := 3 to *winner do writes(at((y+:=1),40),"|",left(winner[i],35),"|") writes(at(y,40),"+",repl("-",35),"+") } check := sort(bets,1) every pair := !check do { name := pair[1] wager := pair[2] nag := parse(wager,' ')[3] if nag = victor then { odds := winner[2] prize := odds * parse(bets[name],' ')[1] money[name] +:= integer(prize) } } test := map(input(at(13,1) || "Press RETURN to Continue.")) if test[1] == "q" then { # # evaluate results from todays races # write("\e[2J\e[HICON PARK CYBER RACE TRACK BIDS YOU ADIEU\n") write(" We all started with $100. And now for the results...\n") every player := !players do { winnings := money[player] if winnings < 100 then msg := "Looks like you lost some $ today." if winnings = 0 then msg := "Lost all your money today." if winnings = 100 then msg := "Looks like you broke even today." if winnings > 100 then msg := "Looks like a winner. Stop at the IRS window please!" if winnings > 300 then msg := "Wow! The IRS agent will escort you to his office." write("OK ",player,", you have $",winnings," left. ",msg) } } end # # # run the race and return the winning horse # (1, 2, or 3) # procedure race() local diamx, diamy, finish, inc1, inc2, inc3, platform, result vectors := draw_track() # # set up starting positions # pos1 := 1 pos2 := 1 pos3 := 1 # # select lanes to run in # y1 := 5 y2 := 7 y3 := 9 # # set up for the legs of the race, 3 normal + 3 accidentsal # leg1 := 1 leg2 := 1 leg3 := 1 # # set up accident multipliers # oops1 := 1 oops2 := 1 oops3 := 1 # # designate vector milestones, marking legs of the race # diamx := 68 diamy := 10 finish := 146 # # design horse bodies from different vantage points # front := list(6) front[1] := "#^" front[2] := "V" front[3] := "#' " front[4] := "_X " front[5] := "X" front[6] := "_X " back := list(6) back[1] := " `#" back[2] := "/" back[3] := "^#" back[4] := " X_" back[5] := "X" back[6] := " X_" # # display the starting positions and fire the gun to begin! # (&features == "MS-DOS") | writes("\e[?25l") # deactivate cursor writes(at(5,1),back[1],1,front[1]) # horse 1 writes(at(22,6),left(horse1[1],32)," / ",horse1[2]," : 1 / ") writes(at(7,1),back[1],2,front[1]) # horse 2 writes(at(23,6),left(horse2[1],32)," / ",horse2[2]," : 1 / ") writes(at(9,1),back[1],3,front[1]) # horse 3 writes(at(24,6),left(horse3[1],32)," / ",horse3[2]," : 1 / ") writes(at(12,14),"ON YOUR MARK... GET SET...") wait(1) writes("\7",at(12,14),"AND THEY'RE OFF! ") # # run the race # repeat { case &features of { "VMS" : delay(500) # delay 10,000/sec VMS "UNIX": delay(50) # delay 1,000/sec UNIX default : platform := &features # not on DOS icon 8.5 } inc1 := ?3-1 * oops1 if oops1 = 1 then pos1 +:= inc1 inc2 := ?3-1 * oops2 if oops2 = 1 then pos2 +:= inc2 inc3 := ?3-1 * oops3 if oops3 = 1 then pos3 +:= inc3 if (pos1 >= 68) & (leg1 = 1) then leg1 := 2 if (pos2 >= 68) & (leg2 = 1) then leg2 := 2 if (pos3 >= 68) & (leg3 = 1) then leg3 := 2 if (pos1 > 78) & (leg1 = 2) then leg1 := 3 if (pos2 > 78) & (leg2 = 2) then leg2 := 3 if (pos3 > 78) & (leg3 = 2) then leg3 := 3 if (78 >= pos1 >= 68) then y1 +:= inc1 if (78 >= pos2 >= 68) then y2 +:= inc2 if (78 >= pos3 >= 68) then y3 +:= inc3 if y1 > 15 then y1 := 15 if y2 > 17 then y2 := 17 if y3 > 19 then y3 := 19 result := accident() display() if result = 0 then return 4 if (pos1 >= finish) & (pos2 < finish) & (pos3 < finish) then return 1 if (pos2 >= finish) & (pos1 < finish) & (pos3 < finish) then return 2 if (pos3 >= finish) & (pos1 < finish) & (pos2 < finish) then return 3 if (pos1 >= finish) & (pos2 >= finish) | (pos2 >= finish) & (pos3 >= finish) | (pos3 >= finish) & (pos1 >= finish) then return 0 } end # # # display the horses at different legs of the race # procedure display() static oldy1,oldy2,oldy3,blanks initial { oldy1 := 5 oldy2 := 7 oldy3 := 9 blanks:= " " } if leg1 = 2 then { writes(at(5,68),blanks) writes(at(oldy1,68),blanks) if y1 < 12 then { writes(at(y1,68)," ",back[2]," ") writes(at(y1+1,68)," 1 ") writes(at(y1+2,68)," ",front[2]," ") } oldy1 := y1 } else { writes(at(y1,vectors[pos1]),back[leg1],1,front[leg1]) } if leg2 = 2 then { writes(at(7,68),blanks) writes(at(oldy2,68),blanks) if y2 < 14 then { writes(at(y2,69)," ",back[2]," ") writes(at(y2+1,69)," 2 ") writes(at(y2+2,69)," ",front[2]," ") } oldy2 := y2 } else { writes(at(y2,vectors[pos2]),back[leg2],2,front[leg2]) } if leg3 = 2 then { writes(at(9,68),blanks) writes(at(oldy3,68),blanks) if y3 < 16 then { writes(at(y3,70)," ",back[2]," ") writes(at(y3+1,70)," 3 ") writes(at(y3+2,70)," ",front[2]," ") } oldy3 := y3 } else { writes(at(y3,vectors[pos3]),back[leg3],3,front[leg3]) } end # # simulate rare freakish accidents # procedure accident() if (?2000 = 111) & (leg1 ~= 2) then { oops1 := 0 leg1 +:= 3 write(at(13,1),"\7OH NO! ",horse1[1]," fell down!") } if (?2000 = 111) & (leg2 ~= 2) then { oops2 := 0 leg2 +:= 3 write(at(13,1),"\7OH NO! ",horse2[1]," fell down!") } if (?2000 = 111) & (leg3 ~= 2) then { oops3 := 0 leg3 +:= 3 write(at(13,1),"\7OH NO! ",horse3[1]," fell down!") } if oops1+oops2+oops3 = 0 then return 0 return 1 end # # # return a list of track x positions # procedure draw_track() local i, offset static pavement initial pavement := copy(mktrack()) offset := [] every i := 1 to 68 do put(offset,i) every i := 1 to 10 do put(offset,72) every i := 68 to 1 by -1 do put(offset,i) offset |||:= [1,1,1,1,1] writes("\e[0;1;33;44m\e[2J\e[H") every i := 1 to *pavement do writes(at(i,1),pavement[i]) return offset end # # generate racing track # procedure mktrack() local track track := [] put(track," WELCOME TO ICON PARK CYBER STEED RACE TRACK") put(track,"") put(track,"___________________________________________________________________________") put(track," \\") put(track,"`#1#^ \\") put(track," \\") put(track,"`#2#^ \\") put(track," |") put(track,"`#3#^ |") put(track,"_________________________________________________________________ |") put(track," \\ |") put(track,"Commentator: | |") put(track," | |") put(track,"_________________________________________________________________/ |") put(track," |") put(track," |") put(track," /") put(track," /") put(track," /") put(track," /") put(track,"__________________________________________________________________________/") put(track,"1 :") put(track,"2 :") put(track,"3 :") return track end # # final wrapup procedure, summarize winnings # procedure done() local msg, player, winnings write("\e[2J\e[HICON PARK CYBER RACE TRACK BIDS YOU ADIEU\n") write(" We all started with $100. And now for the results...\n") every player := !players do { winnings := money[player] if winnings < 100 then msg := "\nLooks like you lost some $ today.\n" if winnings = 100 then msg := "\nLooks like you broke even today.\n" if winnings > 100 then msg := "\nLooks like a winner. Stop at the IRS window please!\n" write("OK ",player,", you have $",winnings," left. ",msg) } stop("Game Over.") end # # # generate horse 1 portraite # procedure pick1() local pferd pferd := [] put(pferd,"") put(pferd," /\\") put(pferd," |||/ \\") put(pferd," / \\\\") put(pferd," / \\\\\\\\") put(pferd," / o \\\\\\\\\\\\") put(pferd," / \\\\\\\\\\\\") put(pferd," / \\\\\\\\\\\\\\") put(pferd," / \\\\\\\\\\\\") put(pferd," O /-----\\ \\\\\\\\\\___") put(pferd," \\/|_/ \\") put(pferd," \\") put(pferd," \\") put(pferd," \\") return pferd end # # generate horse 2 portraite # procedure pick2() local pferd pferd := [] put(pferd,"") put(pferd," /\\") put(pferd," |||/ \\") put(pferd," / \\\\") put(pferd," / / \\\\\\\\") put(pferd," / O \\\\\\\\") put(pferd," / \\\\\\\\") put(pferd," / \\\\\\\\") put(pferd," / \\\\\\\\") put(pferd," o /----\\\\ \\\\\\\\\\___") put(pferd," \\/|_/ \\\\") put(pferd," \\\\\\") put(pferd," \\") put(pferd," \\") put(pferd,"") return pferd end # # generate horse 3 portraite # procedure pick3() local pferd pferd := [] put(pferd," \\/ ") put(pferd," \\ /||| ") put(pferd," \\ / ") put(pferd," \\\\ / ") put(pferd," \\\\\\ o / ") put(pferd," \\\\\\\\ / ") put(pferd," \\\\\\\\\\ / ") put(pferd," \\\\\\\\\\ / ") put(pferd," ___\\\\\\\\ \\\\-----/ O") put(pferd," \\\\ /_|/\\ ") put(pferd," \\ ") put(pferd," \\ ") put(pferd," \\ ") put(pferd,"") return pferd end # # # generate horse 4 portraite # procedure pick4() local pferd pferd := [] put(pferd," \\/ ") put(pferd," \\\\//||| ") put(pferd," \\\\ / ") put(pferd," \\\\\\ / / ") put(pferd," \\\\\\ O / ") put(pferd," \\\\\\ / ") put(pferd," \\\\\\ / ") put(pferd," \\\\\\ /") put(pferd," ___\\\\\\ \\----/ o") put(pferd," \\\\ /_|/\\ ") put(pferd," \\\\ ") put(pferd," \\ ") put(pferd," \\ ") put(pferd,"") return pferd end # # generate horse 5 portraite # procedure pick5() local pferd pferd := [] put(pferd," /\\ /\\") put(pferd," | ||||| |") put(pferd," | ||| |") put(pferd," | || |\\") put(pferd," | | \\") put(pferd," | 0 0 | |\\") put(pferd," | | |\\") put(pferd," | | |\\") put(pferd," | | |\\") put(pferd," | | |") put(pferd," | o o |\\") put(pferd," \\ ____ / \\") put(pferd," \\______/ \\") put(pferd,"") return pferd end # # generate horse 6 portraite # procedure pick6() local pferd pferd := [] put(pferd," \\/ \\/ ") put(pferd," | ||||| | ") put(pferd," | ||| | ") put(pferd," \\| || | ") put(pferd," \\ | | ") put(pferd," \\| | 0 0 | ") put(pferd," \\| | | ") put(pferd," \\| | | ") put(pferd," \\| | | ") put(pferd," | | | ") put(pferd," \\| o o | ") put(pferd," \\ / ____ \\") put(pferd," \\ /______\\ ") put(pferd,"") return pferd end procedure banner() write("\e[0;1;33;44m\e[2J\e[H") write("###############################################################################") write(" ") write(" **** * * **** ***** **** **** ***** ***** ***** **** ") write(" * * * * * * * * * * * * * * ") write(" * * **** *** **** *** * *** *** * * ") write(" * * * * * * * * * * * * * ") write(" **** * **** ***** * * **** * ***** ***** **** ") write(" ") write(" **** * **** *** * * **** ") write(" * * * * * * ** * * ") write(" **** ***** * * * * * * *** ") write(" * * * * * * * ** * * ") write(" * * * * **** *** * * **** ") write(" ") write(" \e[1;5m by tenaglia\e[0;1;33;44m") write(" ") write("###############################################################################") wait(3) end # # # move cursor to specified screen position # procedure at(row,column) return "\e[" || row || ";" || column || "f" end # # procedure to wait n seconds # procedure wait(n) local now, secs secs := &clock[-2:0] + n if secs > 60 then secs -:= 60 repeat { now := &clock[-2:0] if now = secs then break } return end # # this procedure prompts for an input string # procedure input(prompt) writes(prompt) return read() end # # parse a string into a list with respect to a 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