#define SNOWFLAKE \ " _ 8* @ \n"\ " . O __ _| |_ __ ' * ' \n"\ " * /'v /\\_ + _/\\ v`\\ o \n"\ " > x \\ _| |_ / x < \n"\ " .0 __`./\\ _^_ /\\.'__ @ .: ' \n"\ " _\\ \\__/ /\\ v /\\ \\__/ /_ \n"\ "' |_ + __ < > < > __ + _| 0. \n"\ " /_/ \\ \\/_^_\\/ / \\_\\ . \n"\ " . @ .'\\/ _ v _ \\/`. * 8 \n"\ " > x / _| |_ \\ x < @ .\n"\ " . : \\.^_\\/_ + _\\/_^./ Oo * \n"\ " ' |_| \n"\ /* this software is she12ware * .o '. @ o. */ #define PAYPLAN "!!!PLEASE DONATE TO SDF.ORG!!!" #define DID_PAY 0 #define VERSION 1.0 #include #include #include #include #include #ifdef __unix__ #include #define DECXY struct winsize win; #define GETXY ioctl(STDIN_FILENO,TIOCGWINSZ,&win)!=-1 #define GETXV win.ws_col #define GETYV win.ws_row #define ENVXV "COLUMNS" #define ENVYV "LINES" #define SEEDR srandom(time(NULL)) #define GETRA 32+random()%(126-32+1) #define GETRC(S) S[random()%strlen(S)] #define GETRN(B,F) B+random()%F #define CLEAR printf("\x1B[H\x1B[2J") #define SLEEP(T) usleep(T) #else #include #define DECXY CONSOLE_SCREEN_BUFFER_INFO win #define GETXY GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&win) #define GETXV win.srWindow.Right-win.srWindow.Left+1 #define GETYV win.srWindow.Bottom-win.srWindow.Top+1 #define ENVXV "COLS" #define ENVYV "ROWS" #define SEEDR srand(time(NULL)) #define RANDM rand() #define GETRA 32+rand()%(126-32+1) #define GETRC(S) S[rand()%strlen(S)] #define GETRN(B,F) B+rand()%F #define CLEAR system("cls") #define SLEEP(T) sleep(T/1000000) #endif char *init_string(char,long); char **init_strings(char,long,long); void read_strings(char*,char**,long,long); int main(int argc,char **argv){ int c,s; int cascade=0; int debug=0; int frame=0; int increase=0; int maximize=0; int randomize=0; int tail=0; int upwards=0; int wide=0; long h,w,x; long length; long density=750; long height=10; long iterations=-1; long swing=0; long timeout=140000; long width=53; char bg=' '; char *background=NULL; char *charset=NULL; char *frameset="--||+"; char *framebar_top; char *framebar_bot; char *intro="It'Snowtime!"; char *overlay=DID_PAY?NULL:PAYPLAN; char *snow=".*'.'*:oOO008@****...@"; char **buf; char **top; char **bot; while((c=getopt(argc,argv,"b:c:d:Df:Fh:i:Io:LRs:St:Tw:WUX"))!=-1) switch(c){ case'b':if(strlen(optarg)>1) background=optarg; else bg=*optarg;break; case'c':snow=optarg;break; case'd':density=strtol(optarg,NULL,0);break; case'f':frameset=optarg;break; case'h':height=strtol(optarg,NULL,0);break; case'i':iterations=strtol(optarg,NULL,0);break; case'o':overlay=optarg;break; case's':swing=strtol(optarg,NULL,0);break; case't':timeout=strtol(optarg,NULL,0);break; case'w':width=strtol(optarg,NULL,0);break; case'D':debug=1;break; case'F':frame=1;break; case'I':increase=1;break; case'L':cascade=1;break; case'R':cascade=2;break; case'S':randomize=1;break; case'T':tail=1;break; case'U':upwards=1;break; case'W':wide=1;break; case'X':maximize=1;break; default:printf("\n%s\nusage: %s [b:c:d:Df:Fh:i:Io:LRs:St:Tw:WUX]\n" "\t-b [c*].....set background character, string or file\n" "\t-c .........set flake charset string\n" "\t-d ........set background density\n" "\t-f [c]...set framebar characters: [corner]\n" "\t-h ........set height\n" "\t-i ........set iterations\n" "\t-o .........set overlay string or file\n" "\t-s ........set flake swing range\n" "\t-t ........set timeout in microseconds\n" "\t-w ........set width\n" "\n" "\t-D.............show debug information\n" "\t-F.............draw frame\n" "\t-I.............increase density each iteration\n" "\t-L.............cascade to left\n" "\t-R.............cascade to right\n" "\t-S.............random parameters\n" "\t-T.............flakes draw tails\n" "\t-U.............flakes go upwards\n" "\t-W.............full width flakes\n" "\t-X.............maximize to current terminal size\n" ,SNOWFLAKE,*argv); return 1; } SEEDR; /* get terminal window size .8o .@ : o*. */ if(maximize){ DECXY; if(GETXY){ width=GETXV; height=GETYV; height-=debug*(5+strlen(snow)/width)+1; }else if(getenv(ENVXV)&&getenv(ENVYV)){ width=strtol(getenv(ENVXV),NULL,0); height=strtol(getenv(ENVYV),NULL,0); height-=debug*(5+strlen(snow)/width)+1; } } height=height>0?height:1; width=width>0?width:1; /* randomize parameters .0 : .*:. .' O' 0 */ if(randomize){ height=GETRN(1,height); width=GETRN(1,width); randomize=GETRN(1,10*height); bg=GETRA; background="/dev/urandom"; density=GETRN(10,randomize+10*height); swing=GETRN(0,height); timeout=GETRN(35000,900000-35000); increase=GETRN(0,2); cascade=GETRN(0,3); tail=GETRN(0,2); upwards=GETRN(0,2); wide=GETRN(0,2); frame=GETRN(0,2); frameset=init_string('\0',5); if(frame&&!frameset)return 1; for(w=0;w<5;w++) frameset[w]=GETRA; snow=init_string('\0',randomize); if(!snow)return 1; for(w=0;w2&&width>2){ framebar_top=init_string(frameset[0],width); framebar_bot=init_string(frameset[1],width); if(!framebar_top||!framebar_bot)return 1; if(frameset[4]) framebar_top[0] =framebar_bot[0] =framebar_top[width-1] =framebar_bot[width-1] =frameset[4]; height-=2; width-=2; }else frame=0; } /* create background '*8 '. o . .* 0 */ bot=init_strings(bg,height,width); if(!bot)return 1; if(background) read_strings(background,bot,height,width); /* create snowerlay . * O.o. * .'* o */ top=init_strings(bg,height,width); if(!top)return 1; if(overlay) read_strings(overlay,top,height,width); /* create charset * ' * . O :. o0 8 */ charset=init_string('\0',density+strlen(snow)+2); if(!charset)return 1; memset(charset,bg,density); strcat(charset,snow); /* create buffer . 'o . *8 O * ' @. :*/ length=(cascade?width+height:width)+swing; buf=init_strings(bg,height,length); if(!buf)return 1; if(debug){ x=length/2-strlen(intro)/2; if(x>=0) memcpy(buf[height/2]+x,intro,strlen(intro)); } /* start of output . * * . . O. @' */ while(iterations>-1?iterations--:iterations!=0){ CLEAR; if(debug){ if(frame)putchar(' '); for(w=1;w<=width;w++) putchar(w%5?',':'|'); putchar('\n'); } if(frame)puts(framebar_top); /* snow row by row ' 8 . . @ *o * .*/ for(c=h=0;hheight) c=GETRN(1,height); } if(cascade) x=cascade+upwards==2?height-h:h; else x=0; /* snow flake by flake . @8 @* . 8 */ for(w=c+x;wx?density/x:1:0; charset+=increase; } /* shift rows .O :'@ :. * 8 */ if(upwards){ for(h=0;h1) &&buf[c][w]!=bg &&buf[c][w]!=buf[GETRN(x,height/2)][w]) buf[h][w]=buf[c][w]; else if(w==0) buf[h][w]=GETRC(charset); else for(buf[h][w]=GETRC(charset); buf[h][w]==buf[h][w-1] &&buf[h][w]!=bg&&density>1; buf[h][w]=GETRC(charset)) ; SLEEP(timeout); } return 0; } /* allocate and fill char array * .0 * oO .*/ char *init_string(char bg,long width){ char *str=NULL; str=malloc(width+1); if(!str)return NULL; memset(str,'\0',width+1); memset(str,bg,width); return str; } /* allocate and fill 2D char array .o '* .@ */ char **init_strings(char bg,long height,long width){ long h; char **strs=NULL; strs=malloc(height*sizeof(*strs)); if(!strs)return NULL; for(h=0;h126)break; strs[h][w]=c; } if(in)free(input); }