Naval Clash Game With 16x16 NeoPixel Matrix WS1812B - Random Ships Arrangement

Hello there. I have been testing my random ships set for the Naval Clash Game on a 16 x 16 grid, but after several random generations (6 - 8) the connection between the PC is broken and it stops. Everything works nice in Wokwi. Here is the link: Wokwi - Online ESP32, STM32, Arduino Simulator

In reality, I use another function XY(x, y) because the matrix was built on the factory in a snake fashion (odd and even columns differ so I address them differently), but it seems everything is correct as I tested each LED coords with this new function. I use 3 x AA batteries pack to switch 20 LEDS on at the same time. Maybe it's not enough memory or random seed is over? I would appreciate if you let me know what may have been wrong. Here is the code for the real project:

#include <Adafruit_NeoPixel.h>
#include <Vector.h>
#include <limits.h>

#define PIN    4
#define RGB    4      
#define SIZE   16
#define SHIP   10
#define SLEEP  0
#define SPEED  0

Adafruit_NeoPixel pixels(SIZE * SIZE, PIN);

struct Color {

    byte r;
    byte g;
    byte b;

};

struct Coord {

    byte x;
    byte y;
    
    Color c;

};

struct Deck {

    byte qty;
    byte slot;

};

bool error                 = false;
bool selected              = false;

Coord c;

Coord storage_v[2 * SHIP] = {};
Vector<Coord> v(storage_v, 2 * SHIP);

String direction[SHIP] = {"HOR", "VER", "HOR", "VER", "HOR", "VER",  "HOR", "VER", "HOR", "VER"};
Deck   decks[SHIP]     = {{4, 0}, {3, 0}, {3, 0}, {2, 0}, {2, 0}, {2, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}};
Color  colors[RGB]     = {{UCHAR_MAX / 8, 0, UCHAR_MAX / 8}, {0, UCHAR_MAX / 8, UCHAR_MAX / 8}, {0, 0, UCHAR_MAX / 8}, {0, UCHAR_MAX / 8, UCHAR_MAX / 8}};

void setup() {

    Serial.begin(9600);
    pixels.begin();

    //Clear vectors initialized with zeroes
    v.clear();
    //Clear vectors initialized with zeroes

    //Shuffle decks and colors (primarily for the random set)
    ShuffleColors(decks,  SHIP);
    ShuffleColors(colors, RGB);
    //Shuffle decks and colors (primarily for the random set)


}

//Shuffle decks and their colors (template function)
template<class T>
void ShuffleColors(T arr[], byte limit) {
    
    for (byte i = 0; i < limit; i++) {

        byte n    = random(0, limit);

        auto temp = arr[n];
        arr[n]    = arr[i];
        arr[i]    = temp;

    }

}
//Shuffle decks and their colors (template function) 

//Clear game field (for random set only)
void ClearGameField() {

    for (int i = 0; i < v.size(); i++) {

        pixels.setPixelColor(XY(v[i].y, v[i].x), pixels.Color(0, 0, 0));                               
        pixels.show();

    }

}
//Clear game field (for random set only)

//Check if the ship is not beyond the grid (for random set only)
bool CheckFieldShipBoundary(byte x, byte y, byte decks, String dir, String name) {

    if ((x >= 1 && x <= SIZE) && (y >= 1 && y <= SIZE)) {

        if (dir == "HOR") {

            if (decks - 1 <= SIZE - y) {

                return true;

            } 

            return false;

        } else if (dir == "VER") {

            if (decks - 1 <= SIZE - x) {

                return true;

            } 

            return false;

        }

    }

    return false;

}
//Check if the ship is not beyond the grid (for random set only)

//Check if the ship has got enough space around (for random set only)
bool CheckShipObstacleAround(byte x, byte y, byte decks, String dir, String name) {

    if (dir == "HOR") {

        if ((y - 2 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 2, x - 2)) != 0) ||
            (y - 2 >= 0 && x - 1 >= 0         && pixels.getPixelColor(XY(y - 2, x - 1)) != 0) ||
            (y - 2 >= 0 && x >= 0 && x < SIZE && pixels.getPixelColor(XY(y - 2, x))     != 0)) {

            return false;

        }

        for (byte i = 0; i < decks; i++) {

            byte cx = x - 1;
            byte cy = y - 1 + i;

            if ((cy >= 0 && cy < SIZE && cx - 1 >= 0   && pixels.getPixelColor(XY(cy, cx - 1)) != 0) ||
                (cy >= 0 && cy < SIZE && cx + 1 < SIZE && pixels.getPixelColor(XY(cy, cx + 1)) != 0)) {

                return false;

            }
            
        }

        if ((y + decks - 1 >= 0 && y + decks - 1 < SIZE && x - 2 >= 0         && pixels.getPixelColor(XY(y + decks - 1, x - 2)) != 0) ||
            (y + decks - 1 >= 0 && y + decks - 1 < SIZE && x - 1 >= 0         && pixels.getPixelColor(XY(y + decks - 1, x - 1)) != 0) ||
            (y + decks - 1 >= 0 && y + decks - 1 < SIZE && x >= 0 && x < SIZE && pixels.getPixelColor(XY(y + decks - 1, x))     != 0)) {

            return false;

        }

        return true; 

    } else if (dir == "VER") {

        if ((y - 2 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 2, x - 2)) != 0) ||
            (y - 1 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 1, x - 2)) != 0) ||
            (y >= 0 && y < SIZE && x - 2 >= 0 && pixels.getPixelColor(XY(y, x - 2))     != 0)) {

            return false;

        }

        for (byte i = 0; i < decks; i++) {

            byte cx = x - 1 + i;
            byte cy = y - 1;

            if ((cy - 1 >= 0   && cx >= 0 && cx < SIZE && pixels.getPixelColor(XY(cy - 1, cx)) != 0) ||
                (cy + 1 < SIZE && cx >= 0 && cx < SIZE && pixels.getPixelColor(XY(cy + 1, cx)) != 0)) {

                return false;

            } 

        }

        if ((y - 2 >= 0 && x + decks - 1 >= 0 && x + decks - 1 < SIZE         && pixels.getPixelColor(XY(y - 2, x + decks - 1)) != 0) ||
            (y - 1 >= 0 && x + decks - 1 >= 0 && x + decks - 1 < SIZE         && pixels.getPixelColor(XY(y - 1, x + decks - 1)) != 0) ||
            (y >= 0 && y < SIZE && x + decks - 1 >= 0 && x + decks - 1 < SIZE && pixels.getPixelColor(XY(y,     x + decks - 1)) != 0)) {

            return false;

        }

        return true; 

    }

}
//Check if the ship has got enough space around (for random set only)

//Check if one ship does not overlap another (for random set only)
void ResetShipAfterOverlap(int i, int cx, int cy, String name) {

    for (byte j = 0; j < v.size(); j++) {

        if ((v[j].x == cx) && (v[j].y == cy)) {

            Serial.println("OVERLAPPED " + name + "!");
            delay(SLEEP);
            byte index = i;

            for (byte i = 0; i < index; i++) {

                pixels.setPixelColor(XY(v.back().y, v.back().x), pixels.Color(0, 0, 0));                               
                pixels.show();
                v.pop_back();

            }

            error = true;
            break;

        }

    }

}
//Check if one ship does not overlap another (for random set only)

//Check random ship RGB color (the same number of decks) (for random set only) 
void SetShipRGBColor(byte x, byte y, byte decks, String dir, String name) {

    c.x = x;
    c.y = y;

    for (int i = 0; i < RGB; i++) {

        if (decks == RGB - i) {

            c.c.r = colors[decks-1].r;
            c.c.g = colors[decks-1].g;
            c.c.b = colors[decks-1].b;

        }

    }

    v.push_back(c);

    pixels.setPixelColor(XY(c.y, c.x), pixels.Color(c.c.r, c.c.g, c.c.b));                               
    pixels.show();

}
//Check random ship RGB color (the same number of decks) (for random set only)

//Set a random ship position (for random set only)
void SetHomeShipPosition(byte x, byte y, byte decks, String dir, String name) {

    error = false;

    if ((CheckFieldShipBoundary(x, y, decks, dir, name) == true) && (CheckShipObstacleAround(x, y, decks, dir, name) == true)) {

        if (dir == "HOR") {

            for (byte i = 0; i < decks; i++) {

                byte cx = x - 1;
                byte cy = y - 1 + i;
                
                ResetShipAfterOverlap(i, cx, cy, name);

                if (error == true) {

                    break;

                }

                SetShipRGBColor(cx, cy, decks, dir, name);

            }
            
            if (error == false) {

                Serial.println("OK " + name + "!");
                delay(SLEEP);

            }

        } else if (dir == "VER") {

            for (byte i = 0; i < decks; i++) {

                byte cx = x - 1 + i;
                byte cy = y - 1;

                ResetShipAfterOverlap(i, cx, cy, name);

                if (error == true) {

                    break;

                }

                SetShipRGBColor(cx, cy, decks, dir, name);

            }

            if (error == false) {

                Serial.println("OK " + name + "!");
                delay(SLEEP);

            }

        }

    } else {

        if (CheckFieldShipBoundary(x, y, decks, dir, name) == false) {
         
            error = true;
            Serial.println("NOT ENOUGH SPACE " + name + "!");
            delay(SLEEP);

        } else if (CheckShipObstacleAround(x, y, decks, dir, name) == false) {

            error = true;
            Serial.println("TOO NEARBY " + name + "!");
            delay(SLEEP);

        }

    }

}
//Set a random ship position (for random set only)

//Set a player joystick control
void PlayerJoystickControl() {

    GenerateRandomShipSet();
    delay(SPEED);

}
//Set a player joystick control

//Generate a random multi-colored field with ships (according to the Naval Clash game rules)
void GenerateRandomShipSet() {

    ClearGameField();
    v.clear();

    for (byte i = 0; i < SHIP; i++) {

        randomSeed(micros());

        SetHomeShipPosition(random(1, SIZE + 1), random(1, SIZE + 1), decks[i].qty, direction[random(0, SIZE)], String(i + 1));
        if (error == true) {
            
            i--;

        }

    }

    ShuffleColors(decks,  SHIP);
    ShuffleColors(colors, RGB);

}
//Generate a random multi-colored field with ships (according to the Naval Clash game rules)

void loop() { 

    //randomSeed(micros());
    PlayerJoystickControl();
    delay(5000);

}

byte XY(byte x, byte y) { 

    if (y % 2 == 0) {

        return y * SIZE + x;

    } else {

        return ((y + 1) * SIZE - 1) - x;

    }

} 

Just let me know if I am ran out of memory or random seed is incorrect. It looks like everything is fine, but it interrupts suddenly. Is there anything else that may be wrong? Sometimes it works even for 2 or 3 minutes, but then stops anyway and in Wokwi there are no any mistakes.

You could try to get rid of the strings and use C strings instead. It’s more code you would need to write but it should be more stable.

Can you describe the circuit ? Hopefully you don’t power the leds directly from the arduino pins…

Your wokwi code and your posted code are different.

Your code sets up the game board, then erases it, then repeats.

One way to eliminate "not enough space" is to not allow attempts at placing ships closer than their length.

Why do you not look at your IDE error report?

Sketch uses 8650 bytes (28%) of program storage space. Maximum is 30720 bytes.
Global variables use 484 bytes (23%) of dynamic memory, leaving 1564 bytes for local variables. Maximum is 2048 bytes.

What is your question?

It won't include memory allocated dynamically when the code runs on the Uno:

  • At least 768 bytes for the Neopixel library which is almost 40% of the available
  • The Vector type may allocate memory dynamically also. Each time the .push() and .pop() methods are used, dynamic memory is probably allocated or freed up, and may be fragmenting the heap, leading to running out of memory.

Thank you all for your replies. For now it's been working just fine. It does not interrupt when I put randomSeed() function inside for loop. I just need random at each step because ships collisions happen and I need to get back to make a new position for the ship. In Wokwi it was different, though.

The problem was that the program stopped because a new random seed couldn't be generated. It was always the same in a loop and another ship position was the same as well. I observed this issue in Wokwi too.

I've been told that it's not a good idea to keep calling randomSeed() like that. You should call randomSeed() one time only, maybe in setup(), and give it some genuinely random value such as reading a floating analog input pin or timing a human pressing a button.

By the way

can be shortened to

if (error)

because it's already a Boolean. Comparing a Boolean value with true has no effect. (true == true) is true and (false == true) is false :wink:

PaulRB, thank you for this advice. Actually I know that, but use only when I am not sure what value may come with a shortened condition so that to check that something came at all (I mean when several different values may come with it and I don't know which one it was) . It's rather a professional way of dealing with that. I am not a professional yet. What is more, it may end up with a mistake as well, so I prefer to be precise most of the time.

P.S. I have updated the code. Now it works properly and it's possible to choose a random field with a joystick, just in case if it still matters. You can find it below:

#include <Adafruit_NeoPixel.h>
#include <Vector.h>
#include <limits.h>

#define PIN    4
#define RGB    4      
#define SIZE   16
#define SHIP   10
#define MOVE   512
#define SLEEP  0
#define SPEED  0

#define XJ1  A0
#define YJ1  A1
#define SW1  A2

Adafruit_NeoPixel pixels(SIZE * SIZE, PIN);

struct Color {

    int r;
    int g;
    int b;

};

struct Coord {

    int x;
    int y;
    
    Color c;

};

struct Deck {

    int qty;
    int slot;

};

bool error                 = false;
bool selected              = false;

Coord c;

Coord storage_v[2 * SHIP] = {};
Vector<Coord> v(storage_v, 2 * SHIP);

String direction[SHIP] = {"HOR", "VER", "HOR", "VER", "HOR", "VER",  "HOR", "VER", "HOR", "VER"};
Deck   decks[SHIP]     = {{4, 0}, {3, 0}, {3, 0}, {2, 0}, {2, 0}, {2, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}};
Color  colors[RGB]     = {{UCHAR_MAX, UCHAR_MAX / 2, 0}, {0, UCHAR_MAX, 0}, {UCHAR_MAX , 0, 0}, {UCHAR_MAX / 2, 0, UCHAR_MAX}};

void setup() {

    Serial.begin(9600);
    pixels.begin();

    //Link joystick
    pinMode(XJ1, INPUT);
    pinMode(YJ1, INPUT);
    pinMode(SW1, INPUT);
    //Link joystick

    pixels.setBrightness(5);

    //Clear vectors initialized with zeroes
    v.clear();
    //Clear vectors initialized with zeroes

    //Shuffle decks and colors (primarily for the random set)
    ShuffleColors(decks,  SHIP);
    ShuffleColors(colors, RGB);
    //Shuffle decks and colors (primarily for the random set)


}

//Shuffle decks and their colors (template function)
template<class T>
void ShuffleColors(T arr[], int limit) {
    
    for (int i = 0; i < limit; i++) {

        int n    = random(0, limit);

        auto temp = arr[n];
        arr[n]    = arr[i];
        arr[i]    = temp;

    }

}
//Shuffle decks and their colors (template function) 

//Clear game field (for random set only)
void ClearGameField() {

    for (int i = 0; i < v.size(); i++) {

        pixels.setPixelColor(XY(v[i].y, v[i].x), pixels.Color(0, 0, 0));                               
        pixels.show();

    }

}
//Clear game field (for random set only)

//Check if the ship is not beyond the grid (for random set only)
bool CheckFieldShipBoundary(int x, int y, int decks, String dir, String name) {

    if ((x >= 1 && x <= SIZE) && (y >= 1 && y <= SIZE)) {

        if (dir == "HOR") {

            if (decks - 1 <= SIZE - y) {

                return true;

            } 

            return false;

        } else if (dir == "VER") {

            if (decks - 1 <= SIZE - x) {

                return true;

            } 

            return false;

        }

    }

    return false;

}
//Check if the ship is not beyond the grid (for random set only)

//Check if the ship has got enough space around (for random set only)
bool CheckShipObstacleAround(int x, int y, int decks, String dir, String name) {

    if (dir == "HOR") {

        if ((y - 2 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 2, x - 2)) != 0) ||
            (y - 2 >= 0 && x - 1 >= 0         && pixels.getPixelColor(XY(y - 2, x - 1)) != 0) ||
            (y - 2 >= 0 && x >= 0 && x < SIZE && pixels.getPixelColor(XY(y - 2, x))     != 0)) {

            return false;

        }

        for (int i = 0; i < decks; i++) {

            int cx = x - 1;
            int cy = y - 1 + i;

            if ((cy >= 0 && cy < SIZE && cx - 1 >= 0   && pixels.getPixelColor(XY(cy, cx - 1)) != 0) ||
                (cy >= 0 && cy < SIZE && cx + 1 < SIZE && pixels.getPixelColor(XY(cy, cx + 1)) != 0)) {

                return false;

            }
            
        }

        if ((y + decks - 1 >= 0 && y + decks - 1 < SIZE && x - 2 >= 0         && pixels.getPixelColor(XY(y + decks - 1, x - 2)) != 0) ||
            (y + decks - 1 >= 0 && y + decks - 1 < SIZE && x - 1 >= 0         && pixels.getPixelColor(XY(y + decks - 1, x - 1)) != 0) ||
            (y + decks - 1 >= 0 && y + decks - 1 < SIZE && x >= 0 && x < SIZE && pixels.getPixelColor(XY(y + decks - 1, x))     != 0)) {

            return false;

        }

        return true; 

    } else if (dir == "VER") {

        if ((y - 2 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 2, x - 2)) != 0) ||
            (y - 1 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 1, x - 2)) != 0) ||
            (y >= 0 && y < SIZE && x - 2 >= 0 && pixels.getPixelColor(XY(y, x - 2))     != 0)) {

            return false;

        }

        for (int i = 0; i < decks; i++) {

            int cx = x - 1 + i;
            int cy = y - 1;

            if ((cy - 1 >= 0   && cx >= 0 && cx < SIZE && pixels.getPixelColor(XY(cy - 1, cx)) != 0) ||
                (cy + 1 < SIZE && cx >= 0 && cx < SIZE && pixels.getPixelColor(XY(cy + 1, cx)) != 0)) {

                return false;

            } 

        }

        if ((y - 2 >= 0 && x + decks - 1 >= 0 && x + decks - 1 < SIZE         && pixels.getPixelColor(XY(y - 2, x + decks - 1)) != 0) ||
            (y - 1 >= 0 && x + decks - 1 >= 0 && x + decks - 1 < SIZE         && pixels.getPixelColor(XY(y - 1, x + decks - 1)) != 0) ||
            (y >= 0 && y < SIZE && x + decks - 1 >= 0 && x + decks - 1 < SIZE && pixels.getPixelColor(XY(y,     x + decks - 1)) != 0)) {

            return false;

        }

        return true; 

    }

}
//Check if the ship has got enough space around (for random set only)

//Check if one ship does not overlap another (for random set only)
void ResetShipAfterOverlap(int i, int cx, int cy, String name) {

    for (int j = 0; j < v.size(); j++) {

        if ((v[j].x == cx) && (v[j].y == cy)) {

            Serial.println("OVERLAPPED " + name + "!");
            delay(SLEEP);
            int index = i;

            for (int i = 0; i < index; i++) {

                pixels.setPixelColor(XY(v.back().y, v.back().x), pixels.Color(0, 0, 0));                               
                pixels.show();
                v.pop_back();

            }

            error = true;
            break;

        }

    }

}
//Check if one ship does not overlap another (for random set only)

//Check random ship RGB color (the same number of decks) (for random set only) 
void SetShipRGBColor(int x, int y, int decks, String dir, String name) {

    c.x = x;
    c.y = y;

    for (int i = 0; i < RGB; i++) {

        if (decks == RGB - i) {

            c.c.r = colors[decks-1].r;
            c.c.g = colors[decks-1].g;
            c.c.b = colors[decks-1].b;

        }

    }

    v.push_back(c);

    pixels.setPixelColor(XY(c.y, c.x), pixels.Color(c.c.r, c.c.g, c.c.b));                               
    pixels.show();

}
//Check random ship RGB color (the same number of decks) (for random set only)

//Set a random ship position (for random set only)
void SetHomeShipPosition(int x, int y, int decks, String dir, String name) {

    error = false;

    if ((CheckFieldShipBoundary(x, y, decks, dir, name) == true) && (CheckShipObstacleAround(x, y, decks, dir, name) == true)) {

        if (dir == "HOR") {

            for (int i = 0; i < decks; i++) {

                int cx = x - 1;
                int cy = y - 1 + i;
                
                ResetShipAfterOverlap(i, cx, cy, name);

                if (error == true) {

                    break;

                }

                SetShipRGBColor(cx, cy, decks, dir, name);

            }
            
            if (error == false) {

                Serial.println("OK " + name + "!");
                delay(SLEEP);

            }

        } else if (dir == "VER") {

            for (int i = 0; i < decks; i++) {

                int cx = x - 1 + i;
                int cy = y - 1;

                ResetShipAfterOverlap(i, cx, cy, name);

                if (error == true) {

                    break;

                }

                SetShipRGBColor(cx, cy, decks, dir, name);

            }

            if (error == false) {

                Serial.println("OK " + name + "!");
                delay(SLEEP);

            }

        }

    } else {

        if (CheckFieldShipBoundary(x, y, decks, dir, name) == false) {
         
            error = true;
            Serial.println("NOT ENOUGH SPACE " + name + "!");
            delay(SLEEP);

        } else if (CheckShipObstacleAround(x, y, decks, dir, name) == false) {

            error = true;
            Serial.println("TOO NEARBY " + name + "!");
            delay(SLEEP);

        }

    }

}
//Set a random ship position (for random set only)

//Player joystick control
void PlayerJoystickControl() {

    int x = analogRead(A1);
    int y = analogRead(A0);

    if (x == 2 * MOVE - 1 && y == MOVE) { //LEFT

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("LEFT");
        selected = false;

    } else if (x == 0 && y == MOVE) { //RIGHT

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("RIGHT");
        selected = false;
        
    } else if (y == 2 * MOVE - 1 && x == MOVE) { //DOWN

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("DOWN");
        selected = false;

    } else if (y == 0 && x == MOVE) { //UP

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("UP");
        selected = false;

    }

}
//Player joystick control

//Generate a random multi-colored field with ships (according to the Naval Clash game rules)
void GenerateRandomShipSet() {

    if (selected == false) {

        ClearGameField();
        v.clear();

        for (int i = 0; i < SHIP; i++) {

            randomSeed(micros() + analogRead(A0) + analogRead(A1));

            SetHomeShipPosition(random(1, SIZE + 1), random(1, SIZE + 1), decks[i].qty, direction[random(0, SIZE)], String(i + 1));
            if (error == true) {
                
                //if (i >= 0) {
                
                    i--;
                    Serial.print("INDEX => ");
                    Serial.println(i);

                //}

            }

        }

        ShuffleColors(decks,  SHIP);
        ShuffleColors(colors, RGB);

        selected = true;

    }

}
//Generate a random multi-colored field with ships (according to the Naval Clash game rules)

void loop() { 

    PlayerJoystickControl();

}

int XY(int x, int y) { 

    if (y % 2 == 0) {

        return y * SIZE + x;

    } else {

        return ((y + 1) * SIZE - 1) - x;

    }

}

The code in post #1 AND the code in wokwi (they are different) did nothing more than "place ships, erase them, and repeat indefinitely."

As mentioned in post #9, randomSeed(); should be called one time to give a "random" starting point (one of 1024). I understand your hoping for a more random set of values, but that will never happen with a computer - which are very non-random. Save the clock cycles and call randomSeed() one time only.

Your code in Post #10 does not even start when used with your configuration in Post #1. You need to show updates to the hardware and the software when you make changes. (it sets up the ships when any joystick direction is selected)

What did you change that fixed the problem?

There are only 1024 possible seeds for random? Oh, wait, you mean if you use analogRead() from a floating pin as the seed?

This could be increased:

void setup() {
  ...
  unsigned long seed = analogRead(A0);
  seed = seed << 10 | analogRead(A0);
  seed = seed << 10 | analogRead(A0);
  randomSeed(seed);
  ...
}

Yes, I neglected to add that to my response, using one randomSeed(analogRead(A0)); not adding complexity to the impossible.

Shifting 1024 bits a pseudorandom number of times does nothing to increase 1024 bit pseudorandomness. It's like the Ceasar cypher of shifting their alphabet.

void setup() {
  Serial.begin(115200);
  char m[] = { "+mr+rlv+bsfd+^kkld+obsbK" };
  for (int i = 0; i < strlen(m) + 1; i++)
    Serial.write(m[strlen(m) - i] + 3); // shift by three
  Serial.println();
}
void loop() {}

Using "Lava Lamps" is closest approximation of random.