Every Picture In The Universe - the useless (?) app
category: offtopic [glöplog]
Main menu scroller from The Electra demo released in 1991:
Quote:
ELECTRA PRESENT THEIR FIRST DEMO.EACH PLANET IS ONE DEMOSCREEN SO USE THE CURSOR KEYS AND SPACE TO WATCH THEM! YOU CAN ENTER THE SHOP WINDOW MODE IF YOU PRESS 'RETURN'. SINCE NOBODY KNOWS WHO WE ARE WE WILL INTRODUCE OURSELVES.WE ARE A SWEDISH FOUR MEMBER CREW ... ICARUZ ... KASPER ... ABEL ... AND STIGELS.INTRO AND MENU CODED BY ICARUZ WHO ALSO PUT THIS FUCKIN' DEMO TOGETHER.THE REASON WE DID THIS DEMO ON ONE MEG IS OBVIOUS... WE WANTED TO! WE HAVE A SPECIAL GREETING AND FUCKING GREETING SCREEN,SO WE WON'T BORE YOU WITH THAT NOW.IN CASE SOMEBODY IS INTERESTED,THIS ENTIRE DEMO IS CODED WITH THE NEW ELECTRA TECHNIQUE THAT WE INVENTED ONE YEAR AGO.THIS DEMO IS THE FIRST PROOF OF THAT IT REALLY WORKS! WE WILL FOR THE FIRST TIME EVER EXPLAIN THIS REVOLUTIONARY TECHNIQUE FOR THE REST OF THE WORLD.HMMMMM.... THINK LIKE THIS,EVERY PIECE OF CODE,WHAT EVER IT IS A GAME,A CALCULATE PROGRAM OR A DEMO IT JUST CONTAINS OF BINARY DIGITS.SO IF YOU CALCULATE ALL POSSIBLE COMBINATIONS OF ALL BINARY DIGITS IN ONE OR HALF MEG AND SAVE THEM TO DISK,THERE IS,IN ALL THOSE COMBINATONS,A SUPER GAME WITH SUPER GRAPHIX AND SUPER MUZEXX AND SUPER CODING.SO YOU JUST HAVE TO DO SOME SEARCHING TO FIND THE DEMO OR GAME YOU LIKE! BRILLIANT ISN'T IT !!! WE'VE GOT A COUPLE OF HUNDRED THOUSAND DISKS AROUND US,ALL WITH DIFFERENT VERSIONS OF THIS MENU SCREEN.THIS WAS THE BEST ONE.I THINK IT WAS DISK NUMBER NINEHUNDRED THOUSAND OR SOMETHING LIKE THAT,AND IT HAS FOUR THOUSAND LINES IN THE SOURCE TEXT.THE WORST SCREEN WAS THE TUBE.WE HAD TO MAKE SEVENTYSIX MILLION DISKS BEFORE WE FOUND A VERSION THAT WAS ACCEPTABLE.WELL,THAT'S LIFE... THE REASON FOR THE LONG WAIT BEFORE THE MENU SCREEN IS DECRUNCHED IS THAT WE WOULD RUN OUT OF MEMORY DURING SOME SCREENS IF WE DIDN'T USE THAT TECHNIQUE.NOT ALL OF THE SCREENS IN THIS DEMO ARE USING ONE MEG,BUT WE DECIDED TO MAKE THE ENTIRE DEMO A ONE MEG DEMO AFTER ALL,SINCE WE'RE SO LAZY.WELL,AS I WROTE EARLIER,MEMORY IS RUNNING OUT AND THE DEMO MUST BE RELEASED TOMORROW SO I'VE GOT TO WRAP HERE... I HOPE WE MANAGE TO PUT THIS DEMO TOGETHER DURING THIS NIGHT HERE IN TYNNELSO... KEEP ON HACKING... ...AND ALWAYS REMEMBER... ...ELECTRA RULES
>infinite monkey thread
It was the best of times, It was the blurst of times‽ You stupid monkey!
It was the best of times, It was the blurst of times‽ You stupid monkey!
When you check the intros generated by the automatical intro generator, you also have to take care that the "intro" does not format your harddisk or install a virus on your system...
I'd suggest to hook into dosbox and monitor the execution from outside, perform some automated unit tests (is the video memory filled to some degree after some time, are we still in mode 13h, does the program quit on ESC, and so on). Only programs that pass those test can be saved as candidates. Also keep track of programs that were already rejected or ensure that you won't omit a program or check a program twice, then you can spend your nights generating intro candidates for approval for when you wake up :)
somebody remembers "god or not"? It was one of those hotornot parody sited and did exactly the same. produce a random picture in a certain resolution...
aka a noise generator =)
aka a noise generator =)
also
I guess we all forgot to mention this
This one is worth mentioning as well.
I think we should take all the avatars on pouet and try running them.
Quote:
xTr1m: minus the necessary bits needed for mode13 setup, esc-check and programm exit
could bring 16b down to 2^96, approximately 10^30
with an automated validation process, maybe we're onto something
yes, and using gpgpu and distributed computing would definitely help. anyway, hardest part would be to implement an automated validator. how can a machine decide if something is looking nice (puls) or not (just random rectangles of pixels) ?
I just gave this a go, and with a huge amount of tweaking & removing unnecessary crap got a 32b intro generator down to just 2^20 combinations. So I generated them all, and sat down to find the ultimate 32b. Got about half way, fell asleep and lost my place, and now the doctor says I need glasses and i've developed serious epilepsy after watching a long string of strobers. You know what, this is a fucking dumb idea.
How about getting a basic AI program to look at this? You could give it some base code (enter 13h, quit on escape) then tell it to look for visual output, and then patterns and smooth motion in the output. Vary the code it uses genetically and it might find something at least watchable?
How about getting a basic AI program to look at this? You could give it some base code (enter 13h, quit on escape) then tell it to look for visual output, and then patterns and smooth motion in the output. Vary the code it uses genetically and it might find something at least watchable?
I think we should seriously try to code a 16b intro generator. The program should meet at least the following restrictions:
- The opcodes should be restricted to .286 for the sake of simplicity.
- All intros should start with push 0a000h; pop es; move al, 13h; int 10h.
- CS, DS, ES, SS must not be changed.
- No data must be written to a segment other than CS, DS, ES, SS.
- Calling DOS interrupts (INT 20h, INT 21h) should be forbidden (to prevent the intro from deleting files or formatting the harddisk).
- ... I think that's all?
- The opcodes should be restricted to .286 for the sake of simplicity.
- All intros should start with push 0a000h; pop es; move al, 13h; int 10h.
- CS, DS, ES, SS must not be changed.
- No data must be written to a segment other than CS, DS, ES, SS.
- Calling DOS interrupts (INT 20h, INT 21h) should be forbidden (to prevent the intro from deleting files or formatting the harddisk).
- ... I think that's all?
psonice: I will try something like that.
question is... how good can you expect a 32 byte intro to be?
I wouldn't go full 24-bit if I were to render every image in the world. 2x2 isn't much either - if you settle with 8-bit grayscale there's just 2^32 combinations (we're excluding the file header here)
With one image rendered every second, that will take 136 years. I just tested on my server, and it could write (to disk) 100k images in 5 seconds. At that speed, you're done in 12 hours. With 2x2.
But, again - luck also matters here. You don't necessarily need to run through every combination to get a nasty porn image. It could happen on the first render, or the 100th.
With one image rendered every second, that will take 136 years. I just tested on my server, and it could write (to disk) 100k images in 5 seconds. At that speed, you're done in 12 hours. With 2x2.
But, again - luck also matters here. You don't necessarily need to run through every combination to get a nasty porn image. It could happen on the first render, or the 100th.
So we got to the point where democoders are so lazy they're looking for programs to write their demos... :D
The idea of this program is to set the colors of every pixel in a 256x256 rectangle. There are 10 variables, two of them are the coordinates, three of them are the RGB values. In each iteration (for each pixel) a list of functions is evaluated. Each function computes a value for a variable. These values are assigned (so the color of the pixel can be changed this way). The user can mutate the list of functions by pressing 1, and he/she can mutate the functions themselves by pressing 2 (which will mutate the currently selected function to an increasing degree) or 3 (which will select a random function and slightly mutate it).
The program actually does work, it will generate changing images if you press the keys 1, 2, 3 several times, but for some reason it ceases to produce new images after some iteration.
Maybe somebody can improve this program. Here is the code.
main.cpp
window.cpp
window.h
The program actually does work, it will generate changing images if you press the keys 1, 2, 3 several times, but for some reason it ceases to produce new images after some iteration.
Maybe somebody can improve this program. Here is the code.
main.cpp
Code:
//#define DEBUG
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include "window.h"
GLint winWidth = 256, winHeight = 256;
Window win;
int OPENGL_XRES = winWidth;
int OPENGL_YRES = winHeight;
int OPENGL_FULLSCREEN = false;
int keyDown [256];
const int numProgs = 10;
int variable [numProgs];
class Operator
{
public:
unsigned char opcode;
Operator *param [2];
unsigned char constant;
Operator ()
{
}
Operator (char _opcode)
{
opcode = _opcode;
}
void setParam (int n, Operator *program)
{
param [n] = program;
}
void setConstant (int c)
{
constant = c;
}
unsigned char evaluate ()
{
int i;
#ifdef DEBUG
if (opcode == 'v')
printf ("v%d ", constant);
else
printf ("%c ", opcode);
#endif
switch (opcode)
{
case '+': return param [0]->evaluate () + param [1]->evaluate ();
case '-': return param [0]->evaluate () - param [1]->evaluate ();
case '*': return param [0]->evaluate () * param [1]->evaluate ();
case '/': i = param [1]->evaluate (); if (!i) return 0; else return param [0]->evaluate () / i;
case '&': return param [0]->evaluate () & param [1]->evaluate ();
case '|': return param [0]->evaluate () | param [1]->evaluate ();
case '^': return param [0]->evaluate () ^ param [1]->evaluate ();
case 's': return (int) sin ((double) param [0]->evaluate ());
case 'c': return (int) cos ((double) param [0]->evaluate ());
// case 'p': for (i = param [1]->evaluate (), j = param [0]->evaluate (), k = 1; i; i--, k *= j); return k;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return variable [opcode - '0'];
case 'v':
return constant;
default:
return 0;
}
}
unsigned char randomOperation ()
{
int i = rand () % 9;
switch (i)
{
case 0: return '+';
case 1: return '-';
case 2: return '*';
case 3: return '/';
case 4: return '&';
case 5: return '|';
case 6: return '^';
case 7: return 's';
case 8: return 'c';
// case 9: return 'p';
default: return 'n';
}
}
void assign (bool canBeValue)
{
if (!canBeValue || rand () % 2)
{
opcode = randomOperation ();
param [0] = new Operator ();
param [1] = new Operator ();
param [0]->assign (true);
switch (opcode)
{
case 's':
case 'c':
param [1]->opcode = 'n';
break;
default:
param [1]->assign (true);
break;
}
}
else if (!(rand () % 3))
opcode = '0' + rand () % numProgs;
else
{
opcode = 'v';
constant = rand () % 256;
}
}
void mutate (int ugliness)
{
Operator *ptr;
bool t;
for (ugliness++; ugliness; ugliness--)
{
ptr = this;
for (t = false; !t; )
{
#ifdef DEBUG
printf ("mutating operator %c\n", ptr->opcode);
getch ();
#endif
if (rand () % 3 && ptr->opcode != 'v' && ptr->opcode != 'n' && (ptr->opcode < '0' || ptr->opcode > '9'))
ptr = ptr->param [rand () % 2];
else
{
ptr->assign (false);
t = true;
}
}
}
}
};
Operator *program [numProgs];
class Listing
{
public:
int progNum;
Listing *next;
Listing ()
{
}
Listing (int _progNum)
{
progNum = _progNum;
}
void mutate ()
{
int i;
Listing *l, *m;
l = this;
for (i = rand () % 255 + 1; i; i--)
l = l->next;
m = new Listing (rand () % (numProgs - 2) + 2);
m->next = l->next;
l->next = m;
if (!(rand () % 5) && l->next != this)
{
m = l->next;
l->next = l->next->next;
delete m;
}
}
};
Listing *listing;
Listing *listingPointer;
int selected;
void initPrograms ()
{
int i;
srand (GetTickCount ());
for (i = 0; i < numProgs; i++)
{
program [i] = new Operator ();
program [i]->assign (false);
}
program [2]->opcode = '+';
program [2]->param [0] = new Operator ();
program [2]->param [0]->opcode = '2';
program [2]->param [1] = new Operator ();
program [2]->param [1]->opcode = 'v';
program [2]->param [1]->constant = '1';
program [3]->opcode = '0';
program [4]->opcode = 'v';
program [4]->constant = 0;
#ifdef DEBUG
for (i = 0; i < numProgs; i++)
{
printf ("testing program %d\n", i);
getch ();
program [i]->evaluate ();
printf ("\n");
getch ();
}
#endif
listing = new Listing (2);
listing->next = new Listing (3);
listing->next->next = new Listing (4);
listing->next->next->next = listing;
listingPointer = listing;
variable [0] = 0;
variable [1] = 0;
for (i = 2; i < numProgs; i++)
variable [i] = rand () % 256;
selected = rand () % 3 + 2;
}
bool keyPressed [3];
int ugliness = 0;
void displayFcn ()
{
for (variable [1] = 0; variable [1] < winHeight; variable [1]++)
for (variable [0] = 0; variable [0] < winWidth; variable [0]++)
{
#ifndef DEBUG
glColor3f (variable [2] / 256.0f, variable [3] / 256.0f, variable [4] / 256.0f);
glBegin (GL_LINES);
glVertex2i (variable [0], variable [1]);
glVertex2i (variable [0], variable [1] + 1);
glEnd ();
if (!keyDown ['1']) keyPressed [0] = false;
if (!keyDown ['2']) keyPressed [1] = false;
if (!keyDown ['3']) keyPressed [2] = false;
if (keyDown ['1'] && !keyPressed [0])
{
keyPressed [0] = true;
listing->mutate ();
}
if (keyDown ['1'] && !keyPressed [0]
|| (keyDown ['2'] && !keyPressed [1]))
{
ugliness++;
program [selected]->mutate (ugliness);
}
if (keyDown ['2'] && !keyPressed [1])
keyPressed [1] = true;
if (keyDown ['3'] && !keyPressed [2])
{
ugliness = 0;
keyPressed [2] = true;
program [rand () % numProgs]->mutate (ugliness);
selected = rand () % 3 + 2;
program [selected]->mutate (ugliness);
}
#endif
do
{
#ifdef DEBUG
printf ("progNum: %d\n", listingPointer->progNum);
getch ();
#endif
variable [listingPointer->progNum] = program [listingPointer->progNum]->evaluate ();
#ifdef DEBUG
printf ("\n");
getch ();
#endif
listingPointer = listingPointer->next;
} while (listingPointer != listing);
#ifdef DEBUG
printf ("POSX: %d, POSY: %d, R: %d, G: %d, B: %d\n", variable [0], variable [1], variable [2], variable [3], variable [4]);
getch ();
#endif
}
#ifdef DEBUG
program [selected]->mutate ();
#endif
}
#ifdef DEBUG
int main ()
{
initPrograms ();
while (true)
displayFcn ();
}
#endif
#ifndef DEBUG
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR cmd, int n)
{
MSG msg = { 0 };
bool done = false;
int tickCount = 0, tickCountLastMouthChange = 0;
if (!win.create ("Assisted Learning"))
return 0;
initPrograms ();
glEnable (GL_POINT_SMOOTH);
glHint (GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable (GL_LINE_SMOOTH);
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
glClearColor (1, 1, 1, 1);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (0.0, winWidth, 0.0, winHeight);
int startTime = GetTickCount ();
while (!done && !GetAsyncKeyState (VK_ESCAPE))
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
done = true;
else
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
else
{
if (GetTickCount () - startTime > 5000)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
startTime = GetTickCount ();
}
displayFcn ();
SwapBuffers (win.getDC());
}
}
return 1;
}
#endif
window.cpp
Code:
#include "window.h"
Window::Window ()
{
}
Window::~Window ()
{
}
bool Window::create (char *title)
{
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
DWORD dwStyle = WS_OVERLAPPEDWINDOW;
WNDCLASS wc;
hInstance = GetModuleHandle (NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
if (!RegisterClass (&wc))
return false;
RtlZeroMemory (&screenSettings, sizeof (screenSettings));
p.nSize = sizeof (PIXELFORMATDESCRIPTOR);
p.nVersion = 1;
p.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
p.iPixelType = PFD_TYPE_RGBA;
p.cColorBits = 32;
p.cDepthBits = 16;
p.iLayerType = PFD_MAIN_PLANE;
RtlZeroMemory (&screenSettings, sizeof (screenSettings));
screenSettings.dmSize = sizeof (screenSettings);
screenSettings.dmPelsWidth = OPENGL_XRES;
screenSettings.dmPelsHeight = OPENGL_YRES;
screenSettings.dmBitsPerPel = 32;
screenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (OPENGL_FULLSCREEN)
{
DEVMODE dmScreenSettings;
memset (&dmScreenSettings, 0, sizeof (dmScreenSettings));
dmScreenSettings.dmSize = sizeof (dmScreenSettings);
dmScreenSettings.dmPelsWidth = OPENGL_XRES;
dmScreenSettings.dmPelsHeight = OPENGL_YRES;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
return false;
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
}
hwnd = CreateWindowEx (dwExStyle, "OpenGL", title, dwStyle, 0, 0, OPENGL_XRES, OPENGL_YRES, NULL, NULL, hInstance, NULL);
hdc = GetDC (hwnd);
pixelformat = ChoosePixelFormat (hdc, &p);
SetPixelFormat (hdc, pixelformat, &p);
hrc = wglCreateContext (hdc);
wglMakeCurrent (hdc, hrc);
if (OPENGL_FULLSCREEN)
ShowCursor (false);
else
ShowCursor (true);
ShowWindow (hwnd, SW_SHOW);
SetForegroundWindow (hwnd);
SetFocus (hwnd);
return true;
}
void Window::shut()
{
ChangeDisplaySettings (NULL, 0);
ReleaseDC (hwnd, hdc);
DestroyWindow (hwnd);
}
HDC Window::getDC()
{
return hdc;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
break;
case WM_KEYDOWN:
if ((wParam >= 0) && (wParam <= 255))
{
keyDown [wParam] = TRUE;
return 0;
}
break;
case WM_KEYUP:
if ((wParam >= 0) && (wParam <= 255))
{
keyDown [wParam] = FALSE;
return 0;
}
break;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam);
}
window.h
Code:
#ifndef _WINDOW_H_
#define _WINDOW_H_
#include <windows.h>
extern int OPENGL_XRES;
extern int OPENGL_YRES;
extern int OPENGL_FULLSCREEN;
extern int keyDown [256];
class Window
{
public:
Window ();
~Window ();
bool create (char *title);
void shut ();
HDC getDC ();
private:
HWND hwnd;
HDC hdc;
HGLRC hrc;
PIXELFORMATDESCRIPTOR p;
int pixelformat;
DEVMODE screenSettings;
HINSTANCE hInstance;
};
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
#endif
Here are some images this program created:
wtf, ever heard of file uploading?
@Adok : thanks for sharing code. If i understand what you have done : it works like pixel shaders, were scripts you would change over the time.
I think this is the kind of program that would benefit of being written in something much more high level like SDL or C#/winforms (maybe there is other solutions/languages but they are the only ones I know).
That would result in less lines of code (especially for the gui) and would make the "make changes/try them" process easier. C/C++ and Win32 is nice, but for things that you want to try quickly and for which you are not sure of what it would become later, there is better solution (that's my opinion)
Also using multithreading here would certainly be great (something you can do easily in C# 4.0 / TPL)
I think this is the kind of program that would benefit of being written in something much more high level like SDL or C#/winforms (maybe there is other solutions/languages but they are the only ones I know).
That would result in less lines of code (especially for the gui) and would make the "make changes/try them" process easier. C/C++ and Win32 is nice, but for things that you want to try quickly and for which you are not sure of what it would become later, there is better solution (that's my opinion)
Also using multithreading here would certainly be great (something you can do easily in C# 4.0 / TPL)
also : i dont have any C/C++ compiler here and not time to install and configure one for the moment. can you upload binaries somewhere?
Yes, it is like pixel shader. I will upload an .exe.
Here it is:
http://www.hugi.scene.org/adok/miscellaneous/gpgl.zip
But don't be disappointed: usually most of the images don't look too fancy.
http://www.hugi.scene.org/adok/miscellaneous/gpgl.zip
But don't be disappointed: usually most of the images don't look too fancy.
Interestingly, my program gives much better results on this PC now than on the netbook on which I developed it. Here are two screenshots:
thanks. ok now i understand that each window in your screenshot is in fact a different process. so my remark about multi-threading now feel a little bit worthless.