pipesx (5086B)
1 #!/bin/bash 2 # Animated pipes.sh terminal screensaver at an angle. 3 # Copyright (C) 2013, 2014 by Yu-Jie Lin 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 # 23 # Website: https://github.com/livibetter/pipesX.sh 24 25 VERSION=0.1.0 26 27 W=$(tput cols) H=$(tput lines) 28 # maximal random value + 1 29 M=32768 30 31 SETS=('╱╲' '/\') 32 #SETS=('|-' '') 33 COLORS=(31 32 33 34 35 36 37) 34 35 # default values 36 N=1 37 T=() 38 I=0.05 39 P=25 40 R=$((W * H / 4)) 41 42 HELP="Usage: $(basename $0) [OPTIONS] 43 Animated pipes.sh terminal screensaver at an angle. 44 45 Options: 46 47 -n [1-] number of pipes. (Default: $N) 48 -t [0-$((${#SETS[@]} - 1))] types of pipes, can be used more than once. (Default: $T) 49 -i [float] piping interval or maze generation interval. (Default: $I) 50 -P [0-100] probability of a turning pipe or of \\ in maze generation. (Default: $P) 51 -r [LIMIT] reset after x characters, 0 if no limit. (Default: $R) 52 -R random starting point. 53 -C no color. 54 -X maze generation. 55 -h this help message. 56 -v print version number. 57 " 58 59 while getopts "n:t:i:P:r:RCXhv" arg; do 60 case $arg in 61 n) 62 ((N = OPTARG > 0 ? OPTARG : N)) 63 ;; 64 t) 65 T+=($(((OPTARG >= 0 && OPTARG < ${#SETS[@]}) ? OPTARG : T))) 66 ;; 67 i) 68 I=$OPTARG 69 ;; 70 P) 71 ((P = (OPTARG >= 0 && OPTARG <= 100) ? OPTARG : P)) 72 ;; 73 r) 74 ((R = OPTARG >= 0 ? OPTARG : R)) 75 ;; 76 R) 77 RNDSTART=1 78 ;; 79 C) 80 NOCOLOR=1 81 ;; 82 X) 83 MAZE=1 84 ;; 85 h) 86 echo -e "$HELP" 87 exit 0 88 ;; 89 v) 90 echo "$(basename -- "$0") $VERSION" 91 exit 0 92 esac 93 done 94 95 # set to default values if not by options 96 ((${#T[@]})) || T=(0) 97 98 do_exit() { 99 # Show cursor and echo stdin 100 echo -ne "\e[?25h" 101 stty echo 102 clear 103 exit 0 104 } 105 trap do_exit INT TERM 106 107 # No echo stdin and hide the cursor 108 stty -echo 109 echo -ne "\e[?25l" 110 111 # maze geneartion 112 while [[ $MAZE ]] && clear; do 113 [[ $NOCOLOR ]] || echo -ne "\e[1;${COLORS[${#COLORS[@]} * RANDOM / M]}m" 114 for ((i = 0; i < W * H; i++ )); do 115 echo -ne ${SETS[T]:100 * RANDOM / M < P:1} 116 done 117 read -t $I -n 1 && [[ $REPLY =~ q|Q ]] && do_exit 118 done 119 120 # initialze values 121 for ((n = 0; n < N; n++)); do 122 ((X[n] = RNDSTART ? (W + 2) * RANDOM / M : W / 2)) 123 ((Y[n] = RNDSTART ? (H + 2) * RANDOM / M : H / 2)) 124 D[n]=$((4 * RANDOM / M)) 125 C[n]=${COLORS[${#COLORS[@]} * RANDOM / M]} 126 t[n]=${T[${#T[@]} * RANDOM / M]} 127 done 128 129 clear 130 while :; do 131 for ((n = 0; n < N; n++, CC = 0)); do 132 x=${X[n]} y=${Y[n]} 133 d=${D[n]} c=${C[n]} 134 135 # calculate new direction `d` 136 # 1 0 137 # \/ 4 directions 0 to 3 138 # /\ 139 # 2 3 140 # valid directions: d: dd', d' is the new direction 141 # d 142 # 0: / 00 \ 01 03 143 # / / /\ 144 # 1: / 10 \ 11 12 145 # \ \ /\ 146 # 2: \/ 21 / 22 / 23 147 # / \ 148 # 3: \/ 30 \ 32 \ 33 149 # / \ 150 ((d = (100 * RANDOM / M) < P ? ((d + 1) + 2 * (RANDOM % 2)) % 4 : d)) 151 ((e = (d + 1) % 4)) 152 153 # calculate new position 154 # d' x' y' 155 # 0: x+1 y-1 156 # 1: x-1 y-1 157 # 2: x-1 y+1 158 # 3: x+1 y+1 159 ((xn = e < 2 ? x + 1 : x - 1)) 160 ((yn = d < 2 ? y - 1 : y + 1)) 161 162 # adjust position and change color? 163 ((d < 2 && y == 0)) && ((yn--, CC=1)) 164 ((e > 1 && x == 0)) && ((xn--, CC=1)) 165 ((d > 1 && y == H)) && ((yn++, CC=1)) 166 ((e < 2 && x == W)) && ((xn++, CC=1)) 167 ((CC)) && c=${COLORS[${#COLORS[@]} * RANDOM / M]} 168 ((CC)) && t[n]=${T[${#T[@]} * RANDOM / M]} 169 170 # warp pipe 171 ((xn = (xn + W + 1) % (W + 1))) 172 ((yn = (yn + H + 1) % (H + 1))) 173 174 # calculate position in terminal 175 # d' xt yt 176 # 0: x' y'+1 177 # 1: x'+1 y'+1 178 # 2: x'+1 y' 179 # 3: x' y' 180 ((xt = e < 2 ? xn : xn + 1)) 181 ((yt = d < 2 ? yn + 1 : yn)) 182 183 echo -ne "\e[${yt};${xt}H" 184 [[ $NOCOLOR ]] || echo -ne "\e[1;${c}m" 185 echo -n "${SETS[t[n]]:d%2:1}" 186 187 X[n]=$xn Y[n]=$yn 188 D[n]=$d C[n]=$c 189 done 190 read -t $I -n 1 && [[ $REPLY =~ q|Q ]] && do_exit 191 ((R)) && ((r += N, r >= R)) && r=0 && clear 192 done 193 194 do_exit