]> git.bzium.org - embe/choinka.git/blob - choinka.c
Czytamy z /dev/urandom przez read, nie fread
[embe/choinka.git] / choinka.c
1 #include <fcntl.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <term.h>
6 #include <time.h>
7 #include <unistd.h>
8
9 #define A_POGRUBIONY (1 << 0)
10
11 #define KOLOR_BRAK -1
12 #define KOLOR_CZARNY 0
13 #define KOLOR_CZERWONY 1
14 #define KOLOR_ZIELONY 2
15 #define KOLOR_BRAZOWY 3
16 #define KOLOR_NIEBIESKI 4
17 #define KOLOR_MAGENTA 5
18 #define KOLOR_CYJAN 6
19 #define KOLOR_BIALY 7
20
21 typedef struct {
22   int attr;
23   int kolor;
24 } atrybut;
25
26 static atrybut const bombki[] = {
27   {A_POGRUBIONY, KOLOR_CZERWONY},
28   {A_POGRUBIONY, KOLOR_NIEBIESKI},
29   {A_POGRUBIONY, KOLOR_BRAZOWY},
30   {A_POGRUBIONY, KOLOR_MAGENTA},
31   {A_POGRUBIONY, KOLOR_CYJAN},
32   {A_POGRUBIONY, KOLOR_BIALY},
33 };
34 static int const ile_b = sizeof bombki / sizeof *bombki;
35
36 static atrybut const spacja = {0, KOLOR_BRAK};
37 static atrybut const choinka = {0, KOLOR_ZIELONY};
38 static atrybut const podstawa = {0, KOLOR_BRAZOWY};
39 static atrybut const podpis = {A_POGRUBIONY, KOLOR_CZERWONY};
40 static atrybut const gwiazdka = {A_POGRUBIONY, KOLOR_BRAZOWY};
41
42 static void inicjuj_rng()
43 {
44   bool ok = false;
45   unsigned ziarno;
46   int f = open("/dev/urandom", O_RDONLY);
47   if (f != -1) {
48     if (read(f, &ziarno, sizeof ziarno) == sizeof ziarno) {
49       ok = true;
50     }
51     close(f);
52   }
53   if (!ok) {
54     ziarno = time(NULL);
55   }
56   srand(ziarno);
57 }
58
59 static char const rysunek[] =
60 "           *\n"
61 "          /.\\\n"
62 "         /..'\\\n"
63 "         /'.'\\\n"
64 "        /.''.'\\\n"
65 "        /.'.'.\\\n"
66 "       /'.''.'.\\\n"
67 "  jgs  ^^^[_]^^^\n"
68 ;
69
70 static void ustaw(atrybut const* attr)
71 {
72   static atrybut ostatni = {-1, -1};
73   if (ostatni.attr == attr->attr && ostatni.kolor == attr->kolor) return;
74   ostatni = *attr;
75   putp(exit_attribute_mode);
76   if ((attr->attr & A_POGRUBIONY) != 0) {
77     putp(enter_bold_mode);
78   }
79   if (attr->kolor != KOLOR_BRAK) {
80     putp(tparm(set_a_foreground, attr->kolor));
81   }
82 }
83
84 int main()
85 {
86   inicjuj_rng();
87   setupterm(NULL, 1, NULL);
88   atrybut const* kolor = &choinka;
89   for (int i = 0; rysunek[i] != '\0'; i++) {
90     char c = rysunek[i];
91     if (c == '[') kolor = &podstawa;
92     atrybut const* akt = kolor;
93     if (c >= 'a' && c <= 'z') akt = &podpis;
94     if (c == '.') akt = &bombki[rand() % ile_b];
95     if (c == '*') akt = &gwiazdka;
96     if (c == ' ' || c == '\n') akt = &spacja;
97     if (c == ']') kolor = &choinka;
98     ustaw(akt);
99     putchar(c);
100   }
101   putp(exit_attribute_mode);
102   return 0;
103 }