7979typedef struct cmatrix {
8080 int val ;
8181 bool is_head ;
82+ int color ; // For multi-color mode, each character can have a different color
8283} cmatrix ;
8384
8485/* Global variables */
@@ -92,6 +93,11 @@ int *updates = NULL; /* What does this do again? */
9293#ifndef _WIN32
9394volatile sig_atomic_t signal_status = 0 ; /* Indicates a caught signal */
9495#endif
96+ int * color_array = NULL ; /* Array of color values for multi-color mode */
97+ int num_colors = 0 ; /* Number of colors in current use (0 when not in multi-color mode) */
98+ int original_num_colors = 0 ; /* Remember the original number of colors */
99+ int mcolor = COLOR_GREEN ; /* Current matrix color */
100+ int rainbow = 0 ; /* Flag for rainbow mode */
95101
96102int va_system (char * str , ...) {
97103
@@ -164,7 +170,9 @@ void usage(void) {
164170 printf (" -M [message]: Prints your message in the center of the screen. Overrides -L's default message.\n" );
165171 printf (" -u delay (0 - 10, default 4): Screen update delay\n" );
166172 printf (" -C [color]: Use this color for matrix (default green)\n" );
173+ printf (" Multiple colors can be specified as comma-separated list (e.g. -C red,blue,green)\n" );
167174 printf (" -r: rainbow mode\n" );
175+ printf (" Will use colors from -C if multiple specified, otherwise full rainbow\n" );
168176 printf (" -m: lambda mode\n" );
169177 printf (" -k: Characters change while scrolling. (Works without -o opt.)\n" );
170178 printf (" -t [tty]: Set tty to use\n" );
@@ -189,6 +197,29 @@ void *nmalloc(size_t howmuch) {
189197 return r ;
190198}
191199
200+ /* Parse a color name and return the corresponding COLOR_* constant */
201+ int parse_color (const char * color_name ) {
202+ if (!strcasecmp (color_name , "green" )) {
203+ return COLOR_GREEN ;
204+ } else if (!strcasecmp (color_name , "red" )) {
205+ return COLOR_RED ;
206+ } else if (!strcasecmp (color_name , "blue" )) {
207+ return COLOR_BLUE ;
208+ } else if (!strcasecmp (color_name , "white" )) {
209+ return COLOR_WHITE ;
210+ } else if (!strcasecmp (color_name , "yellow" )) {
211+ return COLOR_YELLOW ;
212+ } else if (!strcasecmp (color_name , "cyan" )) {
213+ return COLOR_CYAN ;
214+ } else if (!strcasecmp (color_name , "magenta" )) {
215+ return COLOR_MAGENTA ;
216+ } else if (!strcasecmp (color_name , "black" )) {
217+ return COLOR_BLACK ;
218+ } else {
219+ return -1 ; /* Invalid color */
220+ }
221+ }
222+
192223/* Initialize the global variables */
193224void var_init () {
194225 int i , j ;
@@ -223,6 +254,7 @@ void var_init() {
223254 for (i = 0 ; i <= LINES ; i ++ ) {
224255 for (j = 0 ; j <= COLS - 1 ; j += 2 ) {
225256 matrix [i ][j ].val = -1 ;
257+ matrix [i ][j ].color = mcolor ; // Initialize with default color
226258 }
227259 }
228260
@@ -310,6 +342,27 @@ void resize_screen(void) {
310342 refresh ();
311343}
312344
345+ /**
346+ * Selects a color for a matrix character based on current global program state.
347+ *
348+ * This function uses GLOBAL STATE variables:
349+ * - num_colors: Number of colors in the custom palette
350+ * - color_array: Array of custom color values
351+ * - rainbow: Flag indicating if rainbow mode is active
352+ * - mcolor: Current default color
353+ *
354+ * @return The selected color value (COLOR_* constant)
355+ */
356+ int select_matrix_color (void ) {
357+ if (num_colors > 0 && color_array != NULL && !rainbow ) {
358+ /* Multi-color mode - select from custom palette */
359+ return color_array [rand () % num_colors ];
360+ } else {
361+ /* Single color mode or no custom palette - use global color */
362+ return mcolor ;
363+ }
364+ }
365+
313366int main (int argc , char * argv []) {
314367 int i , y , z , optchr , keypress ;
315368 int j = 0 ;
@@ -323,8 +376,6 @@ int main(int argc, char *argv[]) {
323376 int random = 0 ;
324377 int update = 4 ;
325378 int highnum = 0 ;
326- int mcolor = COLOR_GREEN ;
327- int rainbow = 0 ;
328379 int lambda = 0 ;
329380 int randnum = 0 ;
330381 int randmin = 0 ;
@@ -356,26 +407,48 @@ int main(int argc, char *argv[]) {
356407 bold = 2 ;
357408 break ;
358409 case 'C' :
359- if (!strcasecmp (optarg , "green" )) {
360- mcolor = COLOR_GREEN ;
361- } else if (!strcasecmp (optarg , "red" )) {
362- mcolor = COLOR_RED ;
363- } else if (!strcasecmp (optarg , "blue" )) {
364- mcolor = COLOR_BLUE ;
365- } else if (!strcasecmp (optarg , "white" )) {
366- mcolor = COLOR_WHITE ;
367- } else if (!strcasecmp (optarg , "yellow" )) {
368- mcolor = COLOR_YELLOW ;
369- } else if (!strcasecmp (optarg , "cyan" )) {
370- mcolor = COLOR_CYAN ;
371- } else if (!strcasecmp (optarg , "magenta" )) {
372- mcolor = COLOR_MAGENTA ;
373- } else if (!strcasecmp (optarg , "black" )) {
374- mcolor = COLOR_BLACK ;
410+ if (strchr (optarg , ',' )) {
411+ /* Multiple colors specified, parse them */
412+ char * colors_copy = strdup (optarg );
413+ if (!colors_copy ) {
414+ c_die ("CMatrix: Out of memory!\n" );
415+ }
416+
417+ /* Count number of colors */
418+ int color_count = 1 ;
419+ for (char * p = colors_copy ; * p ; p ++ ) {
420+ if (* p == ',' ) color_count ++ ;
421+ }
422+
423+ /* Allocate the color array */
424+ color_array = nmalloc (color_count * sizeof (int ));
425+ num_colors = 0 ;
426+
427+ /* Parse each color */
428+ char * token = strtok (colors_copy , "," );
429+ while (token != NULL ) {
430+ int color = parse_color (token );
431+ if (color == -1 ) {
432+ free (colors_copy );
433+ c_die (" Invalid color selection '%s'\n Valid "
434+ "colors are green, red, blue, "
435+ "white, yellow, cyan, magenta and black.\n" , token );
436+ }
437+ color_array [num_colors ++ ] = color ;
438+ token = strtok (NULL , "," );
439+ }
440+ original_num_colors = num_colors ; // Remember the original count
441+ free (colors_copy );
375442 } else {
376- c_die (" Invalid color selection\n Valid "
377- "colors are green, red, blue, "
378- "white, yellow, cyan, magenta " "and black.\n" );
443+ /* Single color specified */
444+ num_colors = 0 ;
445+ color_array = NULL ; /* Ensure color_array is NULL */
446+ mcolor = parse_color (optarg );
447+ if (mcolor == -1 ) {
448+ c_die (" Invalid color selection\n Valid "
449+ "colors are green, red, blue, "
450+ "white, yellow, cyan, magenta and black.\n" );
451+ }
379452 }
380453 break ;
381454 case 'c' :
@@ -618,42 +691,57 @@ if (console) {
618691 case '!' :
619692 mcolor = COLOR_RED ;
620693 rainbow = 0 ;
694+ num_colors = 0 ;
621695 break ;
622696 case '@' :
623697 mcolor = COLOR_GREEN ;
624698 rainbow = 0 ;
699+ num_colors = 0 ;
625700 break ;
626701 case '#' :
627702 mcolor = COLOR_YELLOW ;
628703 rainbow = 0 ;
704+ num_colors = 0 ;
629705 break ;
630706 case '$' :
631707 mcolor = COLOR_BLUE ;
632708 rainbow = 0 ;
709+ num_colors = 0 ;
633710 break ;
634711 case '%' :
635712 mcolor = COLOR_MAGENTA ;
636713 rainbow = 0 ;
714+ num_colors = 0 ;
637715 break ;
638716 case 'r' :
639717 rainbow = 1 ;
718+ if (original_num_colors > 0 ) {
719+ num_colors = original_num_colors ; // Restore original count for rainbow
720+ }
640721 break ;
641722 case 'm' :
642723 lambda = !lambda ;
643724 break ;
644725 case '^' :
645726 mcolor = COLOR_CYAN ;
646727 rainbow = 0 ;
728+ num_colors = 0 ;
647729 break ;
648730 case '&' :
649731 mcolor = COLOR_WHITE ;
650732 rainbow = 0 ;
733+ num_colors = 0 ;
651734 break ;
652735 case 'p' :
653736 case 'P' :
654737 pause = (pause == 0 )?1 :0 ;
655738 break ;
656-
739+ case '+' :
740+ rainbow = 0 ;
741+ if (original_num_colors > 0 ) {
742+ num_colors = original_num_colors ; // Restore multi-color mode
743+ }
744+ break ;
657745 }
658746 }
659747 }
@@ -664,6 +752,7 @@ if (console) {
664752 if (oldstyle ) {
665753 for (i = LINES - 1 ; i >= 1 ; i -- ) {
666754 matrix [i ][j ].val = matrix [i - 1 ][j ].val ;
755+ matrix [i ][j ].color = matrix [i - 1 ][j ].color ;
667756 }
668757 random = (int ) rand () % (randnum + 8 ) + randmin ;
669758
@@ -683,13 +772,15 @@ if (console) {
683772 matrix [0 ][j ].val = 0 ;
684773 } else {
685774 matrix [0 ][j ].val = (int ) rand () % randnum + randmin ;
775+ matrix [0 ][j ].color = select_matrix_color ();
686776 }
687777 spaces [j ] = (int ) rand () % LINES + 1 ;
688778 }
689779 } else if (random > highnum && matrix [1 ][j ].val != 1 ) {
690780 matrix [0 ][j ].val = ' ' ;
691781 } else {
692782 matrix [0 ][j ].val = (int ) rand () % randnum + randmin ;
783+ matrix [0 ][j ].color = select_matrix_color ();
693784 }
694785
695786 } else { /* New style scrolling (default) */
@@ -700,6 +791,10 @@ if (console) {
700791 && matrix [1 ][j ].val == ' ' ) {
701792 length [j ] = (int ) rand () % (LINES - 3 ) + 3 ;
702793 matrix [0 ][j ].val = (int ) rand () % randnum + randmin ;
794+ matrix [0 ][j ].is_head = true;
795+
796+ // Assign a random color to the character head
797+ matrix [0 ][j ].color = select_matrix_color ();
703798
704799 spaces [j ] = (int ) rand () % LINES + 1 ;
705800 }
@@ -740,6 +835,9 @@ if (console) {
740835 matrix [i ][j ].val = (int ) rand () % randnum + randmin ;
741836 matrix [i ][j ].is_head = true;
742837
838+ // Assign a random color to the new character head
839+ matrix [i ][j ].color = select_matrix_color ();
840+
743841 /* If we're at the top of the column and it's reached its
744842 full length (about to start moving down), we do this
745843 to get it moving. This is also how we keep segments not
@@ -794,28 +892,37 @@ if (console) {
794892 }
795893 } else {
796894 if (rainbow ) {
797- int randomColor = rand () % 6 ;
798-
799- switch (randomColor ) {
800- case 0 :
801- mcolor = COLOR_GREEN ;
802- break ;
803- case 1 :
804- mcolor = COLOR_BLUE ;
805- break ;
806- case 2 :
807- mcolor = COLOR_BLACK ;
808- break ;
809- case 3 :
810- mcolor = COLOR_YELLOW ;
811- break ;
812- case 4 :
813- mcolor = COLOR_CYAN ;
814- break ;
815- case 5 :
816- mcolor = COLOR_MAGENTA ;
817- break ;
818- }
895+ if (num_colors > 0 && color_array != NULL ) {
896+ // Rainbow mode with custom color palette
897+ mcolor = color_array [rand () % num_colors ];
898+ } else {
899+ // Standard rainbow mode with predefined colors
900+ int randomColor = rand () % 6 ;
901+
902+ switch (randomColor ) {
903+ case 0 :
904+ mcolor = COLOR_GREEN ;
905+ break ;
906+ case 1 :
907+ mcolor = COLOR_BLUE ;
908+ break ;
909+ case 2 :
910+ mcolor = COLOR_BLACK ;
911+ break ;
912+ case 3 :
913+ mcolor = COLOR_YELLOW ;
914+ break ;
915+ case 4 :
916+ mcolor = COLOR_CYAN ;
917+ break ;
918+ case 5 :
919+ mcolor = COLOR_MAGENTA ;
920+ break ;
921+ }
922+ }
923+ } else if (num_colors > 0 ) {
924+ // Multi-color mode - use stored character colors
925+ mcolor = matrix [i ][j ].color ;
819926 }
820927 attron (COLOR_PAIR (mcolor ));
821928 if (matrix [i ][j ].val == 1 ) {
0 commit comments