LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Christmas card 2022 (https://www.linuxquestions.org/questions/programming-9/christmas-card-2022-a-4175717023/)

teckk 09-22-2022 07:18 AM

Christmas card 2022
 
This years Christmas card for LQ members.
https://www.linuxquestions.org/quest...lq-2022-38875/

hazel 09-22-2022 07:55 AM

Very nice! I like it better though at a speed of 150. You can see the movements more clearly. And shouldn't it be only Rudolph with a red nose?;)

teckk 09-22-2022 08:02 AM

Yes, tried to keep the code as small as possible. You can add stuff to that forever. Put christmas trees on the ground, individualize the reindeer, at some point you just stop and say that's good enough.

I thought about giving each reindeer a distro name, and have the reindeer snort awk and sed. I did one like that, but the code gets so big. And I wanted that in one file with no headers.

teckk 10-09-2022 01:16 PM

Welcome. Just playing with ncurses to learn how it works. So that I can do other things with it.

jmccue 10-16-2022 03:15 PM

Very Nice!

aragorn2101 11-05-2022 02:55 AM

Thank you very much teckk.
Very nice!
Merry Christmas.

:)

GazL 11-05-2022 11:27 AM

Yes, this is really cool. Thank you. :)

Structurally, I'd suggest moving the screen drawing code into its own function, and in the main loop testing for c=='q' or KEY_RESIZE before calling the drawing function. That always seems to work best for me.

Also, if I may suggest,
const * const distro[] = { "Slackware", ... } would be cleaner than that distro[25][25] you're using.

Anyway, loved it.


P.S. just giving Rudolph a red nose is an easy fix: pass i to draw_reindeer() and if it's zero, it's rudolph.

teckk 11-06-2022 08:37 AM

Ok thanks a lot. I'll look at that more.
That was a first/second attempt at using ncurses/curses.

teckk 11-06-2022 09:10 AM

mytest.c
Code:

#include <stdio.h>

int main()
{
    //1
    char distro1[5][10] = {
        "Slackware", "Arch", "Debian", "Fedora", "OpenBSD"
    };
   
    int num1 = sizeof(distro1) / sizeof(distro1[0]);
    printf("%s%d\n", "sizeof distro1=", num1);
    printf("%s%s\n", "distro1[0]=", distro1[0]);
   
    //2
    const *const distro2[] = {
        "Slackware", "Arch", "Debian", "Fedora", "OpenBSD"
    };
   
    int num2 = sizeof(distro2) / sizeof(distro2[0]);
    printf("%s%d\n", "sizeof distro2=", num2);
    printf("%s%s\n", "distro2[0]=", distro2[0]);

    return 0;
}

//gcc mytest.c -o mytest


GazL 11-06-2022 11:08 AM

Oops, yep, that's my fault. I should have been more explicit. should be:
char const * const distro[] = { ...

Code:

#include <stdio.h>

int main()
{
    //1
    char distro1[5][10] = {
        "Slackware", "Arch", "Debian", "Fedora", "OpenBSD"
    };
   
    size_t  num1 = sizeof distro1  / sizeof distro1[0];
    printf("%s%zd\n", "sizeof distro1=", num1);
    printf("%s%s\n", "distro1[0]=", distro1[0]);
   
    //2
    char const *const distro2[] = {
        "Slackware", "Arch", "Debian", "Fedora", "OpenBSD"
    };
   
    size_t  num2 = sizeof distro2 / sizeof distro2[0];
    printf("%s%zd\n", "sizeof distro2=", num2);
    printf("%s%s\n", "distro2[0]=", distro2[0]);

    return 0;
}


camorri 11-06-2022 12:10 PM

Thank-you Teckk.

GazL 11-08-2022 01:35 PM

For fun, I had a little play with your code over the last couple of evenings. I've attached what I came up with.

Keys 1-9 set the number of Reindeer in the team.
's' toggles the snowfall
'g' toggles the ground (with very basic collision detection for the gifts — they won't stack).

I reworked draw_string() to be a little more efficient than drawing one char at a time in a loop, and reworked much of the snow and gift drop routines. I split the drawing/presentation from the movement logic. Been a while since I've done anything with ncurses, was a useful refresher. :)

teckk 11-08-2022 02:23 PM

Oh yes, that's excellent.

Here. play with this if you want. I found several different code trees on the net over time for ncurses/curses, altered them, put them together. One c file again.

Penguin express, Or, whatever you wish.

ctrain3.c
Code:

/**
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 **/
 
#include <ctype.h>
#include <curses.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

//Make the engine and coal car
#define EngHEIGHT        10
#define EngFUNNEL        7
#define EngPATTERNS        6

#define EngSTR1  "      ====        ________                ___________ "
#define EngSTR2  "  _D _|  |_______/        \\__I_I_____===__|__Mint___| "
#define EngSTR3  "  |(_)......  S\\________/ |  |    .  =|___ ___|  "
#define EngSTR4  "  /    |  .  u  |  |    |  |    .    ||_| |_||  "
#define EngSTR5  "  | .....|..... s  |__......Slackware..... | [___] |  "
#define EngSTR6  "  | ________.___e_____|_______________.____| Arch  |  "
#define EngSTR7  "  |/ |  |---------I_____I--[][][]----D    |=======|  "

#define EngWHL11 " _/ =| o |=/~~\\  /~~\\  /~~\\  /~~\\ ____Y____________|__ "
#define EngWHL12 "/|/~\\|___|=    ||    ||    ||    |_____/~\\___/        "
#define EngWHL13 "  \\_/      \\0=====0=====0=====0_/      \\_/            "

#define EngWHL21 " _/ =| o |=/~~\\  /~~\\  /~~\\  /~~\\ ____Y____________|__ "
#define EngWHL22 "/|/~\\|___|=O=====O=====O=====O  |_____/~\\___/        "
#define EngWHL23 "  \\_/      \\__/  \\__/  \\__/  \\__/      \\_/            "

#define EngWHL31 " _/ =| o |=/O=====O=====O=====O \\ ____Y____________|__ "
#define EngWHL32 "/|/~\\|___|=    ||    ||    ||    |_____/~\\___/        "
#define EngWHL33 "  \\_/      \\__/  \\__/  \\__/  \\__/      \\_/            "

#define EngWHL41 " _/ =| o |=/~O=====O=====O=====O\\ ____Y____________|__ "
#define EngWHL42 "/|/~\\|___|=    ||    ||    ||    |_____/~\\___/        "
#define EngWHL43 "  \\_/      \\__/  \\__/  \\__/  \\__/      \\_/            "

#define EngWHL51 " _/ =| o |=/~~\\  /~~\\  /~~\\  /~~\\ ____Y____________|__ "
#define EngWHL52 "/|/~\\|___|=  O=====O=====O=====O|_____/~\\___/        "
#define EngWHL53 "  \\_/      \\__/  \\__/  \\__/  \\__/      \\_/            "

#define EngWHL61 " _/ =| o |=/~~\\  /~~\\  /~~\\  /~~\\ ____Y____________|__ "
#define EngWHL62 "/|/~\\|___|=    ||    ||    ||    |_____/~\\___/        "
#define EngWHL63 "  \\_/      \\_O=====O=====O=====O/      \\_/            "

#define EngDEL  "                                                      "

#define COAL01 "                              "
#define COAL02 "                              "
#define COAL03 "    ______Redhat_____        "
#define COAL04 "  _|                \\Bodhi_  "
#define COAL05 "  |    Penguin express.    |  "
#define COAL06 "  | ...................... |  "
#define COAL07 "  |________________________|_ "
#define COAL08 "o_|__________________________| "
#define COAL09 "  \\__Fedora__|  |__Ubuntu_/  "
#define COAL10 "    \\_/  \\_/    \\_/  \\_/ "

#define COALDEL "                              "
#define LOGOFUNNEL          4

void add_smoke(int y, int x);
int add_Eng(int x);
int add_sl(int x);
int my_mvaddstr(int y, int x, char *str);

int NUMBER    = -1;
int SIGNAL    = 1;
int LOGO      = 0;

int my_mvaddstr(int y, int x, char *str) {
    for ( ; x < 0; ++x, ++str)
        if (*str == '\0')  return ERR;
    for ( ; *str != '\0'; ++str, ++x)
        if (mvaddch(y, x, *str) == ERR)  return ERR;
    return OK;
}

int add_sl(int x) {
    if (NUMBER < 0)
        NUMBER = 2;

    int y;
    y = LINES / 2 - 3;
   
    add_smoke(y - 1, x + LOGOFUNNEL);
    return OK;
}

int add_Eng(int x) {
    static char *Eng[EngPATTERNS][EngHEIGHT + 1]
        = {{EngSTR1, EngSTR2, EngSTR3, EngSTR4, EngSTR5, EngSTR6, EngSTR7,
            EngWHL11, EngWHL12, EngWHL13, EngDEL},
          {EngSTR1, EngSTR2, EngSTR3, EngSTR4, EngSTR5, EngSTR6, EngSTR7,
            EngWHL21, EngWHL22, EngWHL23, EngDEL},
          {EngSTR1, EngSTR2, EngSTR3, EngSTR4, EngSTR5, EngSTR6, EngSTR7,
            EngWHL31, EngWHL32, EngWHL33, EngDEL},
          {EngSTR1, EngSTR2, EngSTR3, EngSTR4, EngSTR5, EngSTR6, EngSTR7,
            EngWHL41, EngWHL42, EngWHL43, EngDEL},
          {EngSTR1, EngSTR2, EngSTR3, EngSTR4, EngSTR5, EngSTR6, EngSTR7,
            EngWHL51, EngWHL52, EngWHL53, EngDEL},
          {EngSTR1, EngSTR2, EngSTR3, EngSTR4, EngSTR5, EngSTR6, EngSTR7,
            EngWHL61, EngWHL62, EngWHL63, EngDEL}};
    static char *coal[EngHEIGHT + 1]
        = {COAL01, COAL02, COAL03, COAL04, COAL05,
          COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL};

    if (NUMBER < 0)
        NUMBER = 1;

    int y, i, j, dy = 0;
    int EngLENGTH = 54 + 29*NUMBER;

    if (x < - EngLENGTH)  return ERR;
    y = LINES / 2 - 5;

    for (i = 0; i <= EngHEIGHT; ++i) {
        my_mvaddstr(y + i, x, Eng[(EngLENGTH + x) % EngPATTERNS][i]);
        for (j = 1; j <= NUMBER; ++j)
            my_mvaddstr(y + i + dy*j, x + 24 + 29*j, coal[i]);
    }

    add_smoke(y - 1, x + EngFUNNEL);
    return OK;
}

void add_smoke(int y, int x)
#define SMOKEPTNS        16
{
    static struct smokes {
        int y, x;
        int ptrn, kind;
    } S[1000];
   
    static int sum = 0;
    //Smoke puffs
    static char *Smoke[2][SMOKEPTNS]   
        = {{"()", "( )", "(  )", "(  )", "(  )",
            "(  )" , "( )"  , "( )"  , "()"  , "()"  ,
            "O"    , "O"    , "0"    , "o"    , "o"  ,
            " "                                          },
          {"@@", "@@@", "Debian", "Gentoo", "@@@@",
            "@@@" , "@@@"  , "@@"  , "@@"  , "@@"  ,
            "@"    , "@"    , "@"    , "@"    , "@"  ,
            " "                                          }};
    static char *Eraser[SMOKEPTNS]
        =  {"    ", "      ", "      ", "      ", "    ",
            "    " , "  "  , "  "  , "  "  , "  "  ,
            " "    , " "    , " "    , " "    , " "  ,
            " "                                          };
    static int dy[SMOKEPTNS] = { 2,  1, 1, 1, 0, 0, 0, 0, 0, 0,
                                0,  0, 0, 0, 0, 0            };
    static int dx[SMOKEPTNS] = {-2, -1, 0, 1, 1, 1, 1, 1, 2, 2,
                                2,  2, 2, 3, 3, 3            };
    int i;

    //Smoke frequency
    if (x % 3 == 0) {
        for (i = 0; i < sum; ++i) {
            my_mvaddstr(S[i].y, S[i].x, Eraser[S[i].ptrn]);
            S[i].y    -= dy[S[i].ptrn];
            S[i].x    += dx[S[i].ptrn];
            S[i].ptrn += (S[i].ptrn < SMOKEPTNS - 2) ? 1 : 0;
            my_mvaddstr(S[i].y, S[i].x, Smoke[S[i].kind][S[i].ptrn]);
        }
        my_mvaddstr(y, x, Smoke[sum % 2][0]);
        S[sum].y = y;    S[sum].x = x;
        S[sum].ptrn = 0; S[sum].kind = sum % 2;
        sum ++;
    }
}

int main(int argc, char *argv[])
{
    int x;
    int base_usleep = 100000; //Animation speed
    initscr();

    if (SIGNAL) signal(SIGINT, SIG_IGN);
        noecho();
        curs_set(0);
        nodelay(stdscr, TRUE);
        leaveok(stdscr, TRUE);
        scrollok(stdscr, FALSE);
   
    for (x = COLS - 1; ; --x) {
        if (LOGO == 1) {
            if (add_sl(x) == ERR) break;
        } else {
            if (add_Eng(x) == ERR) break;
        }
        getch();
        refresh();
        usleep(base_usleep);
    }
    mvcur(0, COLS - 1, LINES - 1, 0);
    endwin();

    return (EXIT_SUCCESS);
}

Code:

gcc -O3 -Wall ctrain3.c -o ctrain3 -lncurses

Keith Hedger 11-22-2022 03:03 PM

tis the season to be jolly and other things ending in olly!

Keith Hedger 11-23-2022 07:05 AM

1 Attachment(s)
Just a little tweak, snow drifts side to side, added "LFS" to gifts.


All times are GMT -5. The time now is 11:00 AM.