# Challenge: Maximum Pixel-art, Minimum Code

It probably shouldn’t compile at all, but Arduino uses -fpermissive which might as well have been called -fabomination.

More about not having a better way to access the logo on ProjectABE’s version of the library.

While it is possible to use getPixel/drawPixel as Pharap pointed out, what you really want to do is to invert your logic: instead of telling something that a pixel needs to be set, your oneliner needs to respond with whether a pixel is set or not. In other words, instead of `drawPixel(5, 10)` you convert `i` into x and y (`x = i % 128` and `y / 8 = (i / 128)`) then use that to set the desired pixel:
`(i % 128 == 5) && ((i / 128) == (10/8)) ? 1 << (10/8) : 0`

The same idea can be applied to multiple points anywhere in the screen. This is probably not the best way to tackle the problem of “Maximum Pixel-art, Minimum Code”.

“Flies on a ”:

``````(<::>(int16_t i){static int16_t t=-1,F;if(t-a.frameCount){if(t==-1){for(int j=0;j<16;++j){F[j]=(21+j)*383^j*479;F[j]=(49+j)*7^j*503;}}t=a.frameCount;for(int j=0;j<16;++j){F[j]+=F[j]-=(F[j]>>15|1)*3;F[j]+=F[j]-=(F[j]>>15|1)*3;}}int r=0;for (int j=0;j<16;++j){if((i&0x7F)==((F[j]>>8)+64)&&(i>>7)==((F[j]>>8)+32)>>3){r|=1<<(((F[j]>>8)+32)&7);}}return r;})(i);
``````
Spoiler 3 Likes

Wow - another nice animation!
I feel this is moving away from the spirit of the challenge of using just “maths formula”… perhaps we should add some rules? e.g. Entries may not create new variables or functions …?

I didn’t mean for that last one to be taken seriously, I was just illustrating my previous point. It might be best/simpler to just have a maximum char count.

Would `#defines` separate from the line be legal in that case?

I’d guess no, since defines can’t be “in place of MAGIC”?

Nice challenge!

Cheat answer first: the pixel layout of video ram gives this formula a pretty good density ``````i
``````

Ancient city:

``````((((i&128)>>4)^(i&8))*31)&(i*191)
``````

I tested on a pico-8 using the following snippet to map bytes 0x0…0x3ff to video – hopefully it comes out the same.

``````cls()pal(1,7)for j=0,7do for x=0,127do for y=0,7do
pset(x,32+j*8+y,(@(x+j*128) & (1<<y)) >> y) end end end
``````
2 Likes
``````    a.sBuffer[i] =
// copy from one column to the right, scrolling the whole screen left
(i%128<127) ? b[i+1] : (
// except the last column, which gets seeded with one pixel on the first frame
a.frameCount == 0 ? (i==511)*32 :
// and calculated from the previous column via Rule 30 afterward
// https://mathworld.wolfram.com/Rule30.html
(
// MSB relies on the LSB of the byte to the southwest
(((((((b[i-1] & 192) >> 6) | ((b[(i+127)%1024] & 1) << 2))        + 7) % 8) < 4) << 7) |
((((( (b[i-1] & 224) >> 5)                                        + 7) % 8) < 4) << 6) |
((((( (b[i-1] & 112) >> 4)                                        + 7) % 8) < 4) << 5) |
((((( (b[i-1] &  56) >> 3)                                        + 7) % 8) < 4) << 4) |
((((( (b[i-1] &  28) >> 2)                                        + 7) % 8) < 4) << 3) |
((((( (b[i-1] &  14) >> 1)                                        + 7) % 8) < 4) << 2) |
((((( (b[i-1] &   7) >> 0)                                        + 7) % 8) < 4) << 1) |
// LSB relies on the MSB of the byte to the northwest
(((((((b[i-1] &   3) << 1) | ((b[(i+1024-129)%1024] & 128) >> 7)) + 7) % 8) < 4) << 0)
// Check for previous generaiton values 1,2,3,4 ---------------->\_____________/
// Put new bits in the correct positions in the current byte ------------------>\____/
)
);
``````

This almost works. Something goes subtly wrong approximately every 9 columns. The output is still nice and chaotic and rule-30-esque, and you can’t even tell once it wraps around so the gaps on the north slope disappear, but those gaps are clear evidence of the problem. 3 Likes

There was a project at some point to create a game with generative art. The method the creator was using was to just have one formula and each sprite was a seed number. They would step through these manually and find results that seemed to be visually distinct or interesting, and then decide what that sprite could be used for.

Checkers:

``````(1<<(c/4+i&7))^(1<<((c/4-i)&7))^-((i/8^i/128)&1)
``````
Spoiler 2 Likes

Looks like this is your thing, Felipe!

1 Like

It’s a good fit for the amount of time I have these days. A:

``````b[i]^"\0p\30|\276\273>>>\273\276|\30\16\0"[(!(c&8)^!(i&128)?i:-i)&0xF]
``````
Spoiler

Needs high framerate emulator/hardware, flashes too much as a gif B:

``````(!(c&8)^!(i&128)?i%16:-i&0xF)["\0p\30|\276\273>>>\273\276|\30\16\0"]
``````
Spoiler

How I’ve been making these strings…  2 Likes

I think it would technically be legal C++ with a `reinterpret_cast` to convert the function address to a `const uint8_t *`, but while it would probably compile and run it would very likely be classed as undefined behaviour.

(Though I must admit, I have no clue what the standard would have to say on the matter, it’s not something I’ve ever needed to look up.)

I wasn’t aware ProjectABE used a different version of the library.

The official Arduboy2 library has exposed the logo image as `Arduboy2Base::arduboy_logo` since July 2020.

Careful, at this rate you’ll be converting people to functional programming. `:P`

Getting the lambda syntax mixed up with another language?

The library wasn’t updated, the logo still wasn’t exposed there.

Looks like the compiler got it mixed up too, then. Of course, if you’re going to go relying on compiler extensions, why bother with an ‘iimmediately invoked’ function when you can just use statement expressions?

``````({static int16_t t=-1,F;if(t-a.frameCount){if(t==-1){for(int j=0;j<16;++j){F[j]=(21+j)*383^j*479;F[j]=(49+j)*7^j*503;}}t=a.frameCount;for(int j=0;j<16;++j){F[j]+=F[j]-=(F[j]>>15|1)*3;F[j]+=F[j]-=(F[j]>>15|1)*3;}}int r=0;for (int j=0;j<16;++j){if((i&0x7F)==((F[j]>>8)+64)&&(i>>7)==((F[j]>>8)+32)>>3){r|=1<<(((F[j]>>8)+32)&7);}} r;});
``````

It shaves off a few characters to say the least.

Unless I misunderstood, alternative operators are part of the standard, not compiler extensions. 1 Like

Got to be honest, I forgot those digraphs existed. Fair enough.
(Not the trigraphs though, I remembered those being deprecated.)

Though surely now you’re just trying to obfuscate things?
The alternative operators use more characters than the ‘proper’ ones.

1 Like

Yeah, there wasn’t much point in trying to codegolf that one so I figured I’d throw in the `<::>` as a little prank.

1 Like

Then consider me pranked.

2 Likes

No time to make an animation, but here’s a really simple single-pixel chequerboard:

``````for(size_t index = 0; index < 1024; ++index)
arduboy.sBuffer[index] = ((index % 2) == 0) ? 0xAA : 0x55;
``````

(Full code in this gist.)

Hideous, badly-written golfed form for character-counting loons:

``````for(int i=0;i<1024;++i)b[i]=i&1?0x55:0xAA;
``````
1 Like

You can further golf the expression into: `170>>(i&1)`