📄 horserace.sh
字号:
#!/bin/bash# horserace.sh: Very simple horserace simulation.# Author: Stefano Palmeri# Used with permission.################################################################# Goals of the script:# playing with escape sequences and terminal colors.## Exercise:# Edit the script to make it run less randomly,#+ set up a fake betting shop . . . # Um . . . um . . . it's starting to remind me of a movie . . .## The script gives each horse a random handicap.# The odds are calculated upon horse handicap#+ and are expressed in European(?) style.# E.g., odds=3.75 means that if you bet $1 and win,#+ you receive $3.75.# # The script has been tested with a GNU/Linux OS,#+ using xterm and rxvt, and konsole.# On a machine with an AMD 900 MHz processor,#+ the average race time is 75 seconds. # On faster computers the race time would be lower.# So, if you want more suspense, reset the USLEEP_ARG variable.## Script by Stefano Palmeri.################################################################E_RUNERR=65# Check if md5sum and bc are installed. if ! which bc &> /dev/null; then echo bc is not installed. echo "Can\'t run . . . " exit $E_RUNERRfiif ! which md5sum &> /dev/null; then echo md5sum is not installed. echo "Can\'t run . . . " exit $E_RUNERRfi# Set the following variable to slow down script execution.# It will be passed as the argument for usleep (man usleep) #+ and is expressed in microseconds (500000 = half a second).USLEEP_ARG=0 # Clean up the temp directory, restore terminal cursor and #+ terminal colors -- if script interrupted by Ctl-C.trap 'echo -en "\E[?25h"; echo -en "\E[0m"; stty echo;\tput cup 20 0; rm -fr $HORSE_RACE_TMP_DIR' TERM EXIT# See the chapter on debugging for an explanation of 'trap.'# Set a unique (paranoid) name for the temp directory the script needs.HORSE_RACE_TMP_DIR=$HOME/.horserace-`date +%s`-`head -c10 /dev/urandom \| md5sum | head -c30`# Create the temp directory and move right in.mkdir $HORSE_RACE_TMP_DIRcd $HORSE_RACE_TMP_DIR# This function moves the cursor to line $1 column $2 and then prints $3.# E.g.: "move_and_echo 5 10 linux" is equivalent to#+ "tput cup 4 9; echo linux", but with one command instead of two.# Note: "tput cup" defines 0 0 the upper left angle of the terminal,#+ echo defines 1 1 the upper left angle of the terminal.move_and_echo() { echo -ne "\E[${1};${2}H""$3" }# Function to generate a pseudo-random number between 1 and 9. random_1_9 (){ head -c10 /dev/urandom | md5sum | tr -d [a-z] | tr -d 0 | cut -c1 }# Two functions that simulate "movement," when drawing the horses. draw_horse_one() { echo -n " "//$MOVE_HORSE//}draw_horse_two(){ echo -n " "\\\\$MOVE_HORSE\\\\ } # Define current terminal dimension.N_COLS=`tput cols`N_LINES=`tput lines`# Need at least a 20-LINES X 80-COLUMNS terminal. Check it.if [ $N_COLS -lt 80 ] || [ $N_LINES -lt 20 ]; then echo "`basename $0` needs a 80-cols X 20-lines terminal." echo "Your terminal is ${N_COLS}-cols X ${N_LINES}-lines." exit $E_RUNERRfi# Start drawing the race field.# Need a string of 80 chars. See below.BLANK80=`seq -s "" 100 | head -c80`clear# Set foreground and background colors to white.echo -ne '\E[37;47m'# Move the cursor on the upper left angle of the terminal.tput cup 0 0 # Draw six white lines.for n in `seq 5`; do echo $BLANK80 # Use the 80 chars string to colorize the terminal.done# Sets foreground color to black. echo -ne '\E[30m'move_and_echo 3 1 "START 1" move_and_echo 3 75 FINISHmove_and_echo 1 5 "|"move_and_echo 1 80 "|"move_and_echo 2 5 "|"move_and_echo 2 80 "|"move_and_echo 4 5 "| 2"move_and_echo 4 80 "|"move_and_echo 5 5 "V 3"move_and_echo 5 80 "V"# Set foreground color to red. echo -ne '\E[31m'# Some ASCII art.move_and_echo 1 8 "..@@@..@@@@@...@@@@@.@...@..@@@@..."move_and_echo 2 8 ".@...@...@.......@...@...@.@......."move_and_echo 3 8 ".@@@@@...@.......@...@@@@@.@@@@...."move_and_echo 4 8 ".@...@...@.......@...@...@.@......."move_and_echo 5 8 ".@...@...@.......@...@...@..@@@@..."move_and_echo 1 43 "@@@@...@@@...@@@@..@@@@..@@@@."move_and_echo 2 43 "@...@.@...@.@.....@.....@....."move_and_echo 3 43 "@@@@..@@@@@.@.....@@@@...@@@.."move_and_echo 4 43 "@..@..@...@.@.....@.........@."move_and_echo 5 43 "@...@.@...@..@@@@..@@@@.@@@@.."# Set foreground and background colors to green.echo -ne '\E[32;42m'# Draw eleven green lines.tput cup 5 0for n in `seq 11`; do echo $BLANK80done# Set foreground color to black. echo -ne '\E[30m'tput cup 5 0# Draw the fences. echo "++++++++++++++++++++++++++++++++++++++\++++++++++++++++++++++++++++++++++++++++++"tput cup 15 0echo "++++++++++++++++++++++++++++++++++++++\++++++++++++++++++++++++++++++++++++++++++"# Set foreground and background colors to white.echo -ne '\E[37;47m'# Draw three white lines.for n in `seq 3`; do echo $BLANK80done# Set foreground color to black.echo -ne '\E[30m'# Create 9 files to stores handicaps.for n in `seq 10 7 68`; do touch $ndone # Set the first type of "horse" the script will draw.HORSE_TYPE=2# Create position-file and odds-file for every "horse".#+ In these files, store the current position of the horse,#+ the type and the odds.for HN in `seq 9`; do touch horse_${HN}_position touch odds_${HN} echo \-1 > horse_${HN}_position echo $HORSE_TYPE >> horse_${HN}_position # Define a random handicap for horse. HANDICAP=`random_1_9` # Check if the random_1_9 function returned a good value. while ! echo $HANDICAP | grep [1-9] &> /dev/null; do HANDICAP=`random_1_9` done # Define last handicap position for horse. LHP=`expr $HANDICAP \* 7 + 3` for FILE in `seq 10 7 $LHP`; do echo $HN >> $FILE done # Calculate odds. case $HANDICAP in 1) ODDS=`echo $HANDICAP \* 0.25 + 1.25 | bc` echo $ODDS > odds_${HN} ;; 2 | 3) ODDS=`echo $HANDICAP \* 0.40 + 1.25 | bc` echo $ODDS > odds_${HN} ;; 4 | 5 | 6) ODDS=`echo $HANDICAP \* 0.55 + 1.25 | bc` echo $ODDS > odds_${HN} ;; 7 | 8) ODDS=`echo $HANDICAP \* 0.75 + 1.25 | bc` echo $ODDS > odds_${HN} ;; 9) ODDS=`echo $HANDICAP \* 0.90 + 1.25 | bc` echo $ODDS > odds_${HN} esacdone# Print odds.print_odds() {tput cup 6 0echo -ne '\E[30;42m'for HN in `seq 9`; do echo "#$HN odds->" `cat odds_${HN}`done}# Draw the horses at starting line.draw_horses() {tput cup 6 0echo -ne '\E[30;42m'for HN in `seq 9`; do echo /\\$HN/\\" "done}print_oddsecho -ne '\E[47m'# Wait for a enter key press to start the race.# The escape sequence '\E[?25l' disables the cursor.tput cup 17 0echo -e '\E[?25l'Press [enter] key to start the race...read -s# Disable normal echoing in the terminal.# This avoids key presses that might "contaminate" the screen#+ during the race. stty -echo# --------------------------------------------------------# Start the race.draw_horsesecho -ne '\E[37;47m'move_and_echo 18 1 $BLANK80echo -ne '\E[30m'move_and_echo 18 1 Starting...sleep 1# Set the column of the finish line.WINNING_POS=74# Define the time the race started.START_TIME=`date +%s`# COL variable needed by following "while" construct.COL=0 while [ $COL -lt $WINNING_POS ]; do MOVE_HORSE=0 # Check if the random_1_9 function has returned a good value. while ! echo $MOVE_HORSE | grep [1-9] &> /dev/null; do MOVE_HORSE=`random_1_9` done # Define old type and position of the "randomized horse". HORSE_TYPE=`cat horse_${MOVE_HORSE}_position | tail -n 1` COL=$(expr `cat horse_${MOVE_HORSE}_position | head -n 1`) ADD_POS=1 # Check if the current position is an handicap position. if seq 10 7 68 | grep -w $COL &> /dev/null; then if grep -w $MOVE_HORSE $COL &> /dev/null; then ADD_POS=0 grep -v -w $MOVE_HORSE $COL > ${COL}_new rm -f $COL mv -f ${COL}_new $COL else ADD_POS=1 fi else ADD_POS=1 fi COL=`expr $COL + $ADD_POS` echo $COL > horse_${MOVE_HORSE}_position # Store new position. # Choose the type of horse to draw. case $HORSE_TYPE in 1) HORSE_TYPE=2; DRAW_HORSE=draw_horse_two ;; 2) HORSE_TYPE=1; DRAW_HORSE=draw_horse_one esac echo $HORSE_TYPE >> horse_${MOVE_HORSE}_position # Store current type. # Set foreground color to black and background to green. echo -ne '\E[30;42m' # Move the cursor to new horse position. tput cup `expr $MOVE_HORSE + 5` \ `cat horse_${MOVE_HORSE}_position | head -n 1` # Draw the horse. $DRAW_HORSE usleep $USLEEP_ARG # When all horses have gone beyond field line 15, reprint odds. touch fieldline15 if [ $COL = 15 ]; then echo $MOVE_HORSE >> fieldline15 fi if [ `wc -l fieldline15 | cut -f1 -d " "` = 9 ]; then print_odds : > fieldline15 fi # Define the leading horse. HIGHEST_POS=`cat *position | sort -n | tail -1` # Set background color to white. echo -ne '\E[47m' tput cup 17 0 echo -n Current leader: `grep -w $HIGHEST_POS *position | cut -c7`\ " "done # Define the time the race finished.FINISH_TIME=`date +%s`# Set background color to green and enable blinking text.echo -ne '\E[30;42m'echo -en '\E[5m'# Make the winning horse blink.tput cup `expr $MOVE_HORSE + 5` \`cat horse_${MOVE_HORSE}_position | head -n 1`$DRAW_HORSE# Disable blinking text.echo -en '\E[25m'# Set foreground and background color to white.echo -ne '\E[37;47m'move_and_echo 18 1 $BLANK80# Set foreground color to black.echo -ne '\E[30m'# Make winner blink.tput cup 17 0echo -e "\E[5mWINNER: $MOVE_HORSE\E[25m"" Odds: `cat odds_${MOVE_HORSE}`"\" Race time: `expr $FINISH_TIME - $START_TIME` secs"# Restore cursor and old colors.echo -en "\E[?25h"echo -en "\E[0m"# Restore echoing.stty echo# Remove race temp directory.rm -rf $HORSE_RACE_TMP_DIRtput cup 19 0exit 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -