pipesx (5071B)
1 #!/usr/bin/env 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 COLORS=(31 32 33 34 35 36 37) 33 34 # default values 35 N=1 36 T=() 37 I=0.05 38 P=25 39 R=$((W * H / 4)) 40 41 HELP="Usage: $(basename $0) [OPTIONS] 42 Animated pipes.sh terminal screensaver at an angle. 43 44 Options: 45 46 -n [1-] number of pipes. (Default: $N) 47 -t [0-$((${#SETS[@]} - 1))] types of pipes, can be used more than once. (Default: $T) 48 -i [float] piping interval or maze generation interval. (Default: $I) 49 -P [0-100] probability of a turning pipe or of \\ in maze generation. (Default: $P) 50 -r [LIMIT] reset after x characters, 0 if no limit. (Default: $R) 51 -R random starting point. 52 -C no color. 53 -X maze generation. 54 -h this help message. 55 -v print version number. 56 " 57 58 while getopts "n:t:i:P:r:RCXhv" arg; do 59 case $arg in 60 n) 61 ((N = OPTARG > 0 ? OPTARG : N)) 62 ;; 63 t) 64 T+=($(((OPTARG >= 0 && OPTARG < ${#SETS[@]}) ? OPTARG : T))) 65 ;; 66 i) 67 I=$OPTARG 68 ;; 69 P) 70 ((P = (OPTARG >= 0 && OPTARG <= 100) ? OPTARG : P)) 71 ;; 72 r) 73 ((R = OPTARG >= 0 ? OPTARG : R)) 74 ;; 75 R) 76 RNDSTART=1 77 ;; 78 C) 79 NOCOLOR=1 80 ;; 81 X) 82 MAZE=1 83 ;; 84 h) 85 echo -e "$HELP" 86 exit 0 87 ;; 88 v) 89 echo "$(basename -- "$0") $VERSION" 90 exit 0 91 esac 92 done 93 94 # set to default values if not by options 95 ((${#T[@]})) || T=(0) 96 97 do_exit() { 98 # Show cursor and echo stdin 99 echo -ne "\e[?25h" 100 stty echo 101 clear 102 exit 0 103 } 104 trap do_exit INT TERM 105 106 # No echo stdin and hide the cursor 107 stty -echo 108 echo -ne "\e[?25l" 109 110 # maze geneartion 111 while [[ $MAZE ]] && clear; do 112 [[ $NOCOLOR ]] || echo -ne "\e[1;${COLORS[${#COLORS[@]} * RANDOM / M]}m" 113 for ((i = 0; i < W * H; i++ )); do 114 echo -ne ${SETS[T]:100 * RANDOM / M < P:1} 115 done 116 read -t $I -n 1 && [[ $REPLY =~ q|Q ]] && do_exit 117 done 118 119 # initialze values 120 for ((n = 0; n < N; n++)); do 121 ((X[n] = RNDSTART ? (W + 2) * RANDOM / M : W / 2)) 122 ((Y[n] = RNDSTART ? (H + 2) * RANDOM / M : H / 2)) 123 D[n]=$((4 * RANDOM / M)) 124 C[n]=${COLORS[${#COLORS[@]} * RANDOM / M]} 125 t[n]=${T[${#T[@]} * RANDOM / M]} 126 done 127 128 clear 129 while :; do 130 for ((n = 0; n < N; n++, CC = 0)); do 131 x=${X[n]} y=${Y[n]} 132 d=${D[n]} c=${C[n]} 133 134 # calculate new direction `d` 135 # 1 0 136 # \/ 4 directions 0 to 3 137 # /\ 138 # 2 3 139 # valid directions: d: dd', d' is the new direction 140 # d 141 # 0: / 00 \ 01 03 142 # / / /\ 143 # 1: / 10 \ 11 12 144 # \ \ /\ 145 # 2: \/ 21 / 22 / 23 146 # / \ 147 # 3: \/ 30 \ 32 \ 33 148 # / \ 149 ((d = (100 * RANDOM / M) < P ? ((d + 1) + 2 * (RANDOM % 2)) % 4 : d)) 150 ((e = (d + 1) % 4)) 151 152 # calculate new position 153 # d' x' y' 154 # 0: x+1 y-1 155 # 1: x-1 y-1 156 # 2: x-1 y+1 157 # 3: x+1 y+1 158 ((xn = e < 2 ? x + 1 : x - 1)) 159 ((yn = d < 2 ? y - 1 : y + 1)) 160 161 # adjust position and change color? 162 ((d < 2 && y == 0)) && ((yn--, CC=1)) 163 ((e > 1 && x == 0)) && ((xn--, CC=1)) 164 ((d > 1 && y == H)) && ((yn++, CC=1)) 165 ((e < 2 && x == W)) && ((xn++, CC=1)) 166 ((CC)) && c=${COLORS[${#COLORS[@]} * RANDOM / M]} 167 ((CC)) && t[n]=${T[${#T[@]} * RANDOM / M]} 168 169 # warp pipe 170 ((xn = (xn + W + 1) % (W + 1))) 171 ((yn = (yn + H + 1) % (H + 1))) 172 173 # calculate position in terminal 174 # d' xt yt 175 # 0: x' y'+1 176 # 1: x'+1 y'+1 177 # 2: x'+1 y' 178 # 3: x' y' 179 ((xt = e < 2 ? xn : xn + 1)) 180 ((yt = d < 2 ? yn + 1 : yn)) 181 182 echo -ne "\e[${yt};${xt}H" 183 [[ $NOCOLOR ]] || echo -ne "\e[1;${c}m" 184 echo -n "${SETS[t[n]]:d%2:1}" 185 186 X[n]=$xn Y[n]=$yn 187 D[n]=$d C[n]=$c 188 done 189 read -t $I -n 1 && [[ $REPLY =~ q|Q ]] && do_exit 190 ((R)) && ((r += N, r >= R)) && r=0 && clear 191 done 192 193 do_exit