C贸mo particip茅 en IOCCC-'19 (y perd铆). Parte 2: "Simulador NOR"

Esta es la segunda parte de una serie de art铆culos sobre c贸mo particip茅 en IOCCC'19







  1. C贸mo particip茅 en IOCCC-'19 (y perd铆). Parte 1: "Tic-tac-toe"
  2. C贸mo particip茅 en IOCCC-'19 (y perd铆). Parte 2: "Simulador NOR"


Espero que este art铆culo le ayude a analizar el c贸digo o el c贸digo de otra persona despu茅s de un descompilador u ofuscador.



Si a煤n no sabe qu茅 es IOCCC o si desea familiarizarse con una versi贸n m谩s simple del c贸digo ofuscado, le recomiendo pasar a la primera parte.



A todos los dem谩s, les deseo una agradable lectura.



Todas las fuentes se colocan en github , desde donde puede descargarlas e intentar compilarlas.



Datos iniciales



Dado que el c贸digo fuente en forma de texto se puede encontrar en el enlace, mostrar茅 c贸mo se ve el c贸digo gr谩ficamente:







Tradicionalmente, se dan "puntos extra" si el c贸digo tiene un formato no est谩ndar o se parece a alg煤n tipo de imagen. Bueno, supongamos que esto est谩 bien aqu铆.



Pero, 驴qu茅 hace el programa?



Inicializa la pila de gr谩ficos del servidor X, escanea el archivo de configuraci贸n proporcionado, dibuja un circuito el茅ctrico de acuerdo con el archivo e inicia la simulaci贸n, cambiando alternativamente la polaridad en los 4 pines de entrada, usando solo elementos NOR (Not-OR). El renderizado se realiza con el antiguo sombreador de pantalla LCD.



El programa viene con varios archivos de configuraci贸n, a saber:



DIP8-4packnot.txt: un an谩logo aproximado de CMOS 4041 / inversor de cuatro canales







(La imagen se comprime 2 veces para ajustarse a los l铆mites de la decencia. Es realmente divertido que el programa, con un peso de 3,5 KB, genere una serie de im谩genes, que en compresi贸n m谩xima ocupan 10,5 + MB)



DIP8-triplexor.txt: un an谩logo aproximado de CMOS 4030 con entradas combinadas y tres canales / Puerta XOR de tres canales con entradas combinadas







DIP8-fulladder.txt: un an谩logo aproximado de CMOS 4008, pero para dos bits / sumador de 2 bits con una salida de bit de acarreo







Analizando el c贸digo



La tarea m谩s dif铆cil esta vez fue ajustarse al l铆mite de tama帽o del trabajo enviado. No solo el tama帽o del archivo es limitado, sino tambi茅n el n煤mero de "tokens" condicionales: s铆mbolos de operaci贸n, palabras clave de idioma y pares de par茅ntesis. Es para "explotar" esta caracter铆stica del analizador-verificador de tama帽o en el programa que se declara una gran cantidad de definiciones, que reducen los bloques de c贸digo a una sola palabra clave C.



Primero, echemos un vistazo al Makefile para entender c贸mo se ensambla el c贸digo:



#!/usr/bin/env make
PROJECT=prog
CC= gcc
SRC=prog.c
CWARN=-Wall -Wextra -Wno-char-subscripts

CSTD= -std=c99
# Syscalls table
# DS - syscall nanosleep
# DO - syscall open
# DR - syscall read
# DC - syscall close

# X11 structures offsets
# dS - offset of screens in Display
# dR - offset of root in Screen
# dD - offset of root_depth in Screen
# dV - offset of root_visual in Screen
# dG - offset of default_gc in Screen

BITS := $(shell uname -p)

ifeq ($(BITS), x86_64)
    ARCH= -m64
    CDEFINE= -DDS=35 -DDO=2 -DDR=0 -DDC=3 -DdS=232 -DdR=16 -DdD=56 -DdV=64 -DdG=72
else
    ARCH= -m32
    CDEFINE= -DDS=162 -DDO=5 -DDR=3 -DDC=6 -DdS=140 -DdR=8 -DdD=36 -DdV=40 -DdG=44
endif


OPT= -g

CFLAGS= ${CWARN} ${CSTD} ${ARCH} ${CDEFINE} ${OPT}
LDFLAGS= -ldl

RM= rm

all:  ${PROJECT}

${PROJECT}:
	${CC} ${CFLAGS} ${SRC} -o $@ ${LDFLAGS}
clean:
	${RM} -f ${PROJECT}


Como puede ver, este trabajo, al igual que el anterior, utiliza activamente llamadas al sistema para evitar "#include" feos que rompen el patr贸n de la imagen. Recordemos este hecho y preparemos una l铆nea para el preprocesador y el linter:



Despu茅s del preprocesador
gcc -DDS=35 -DDO=2 -DDR=0 -DDC=3 -DdS=232 -DdR=16 -DdD=56 -DdV=64 -DdG=72 prog.c -ldl -E | indent -kr -brf > /tmp/fmt.c


int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

extern void *dlsym(void *, char *);
int x_[616][1220];
extern long syscall(long, ...);
extern void *dlopen(char *, int);
char m[19][20], _n[] =
    "pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
    "D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
    "<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
	|| (m[y][x] != c))
	return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
	|| (_[t][y][x] != c))
	return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x++] = l;
	_[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x--] = l;
	_[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
	_[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
		     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
		     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
		     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
		     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
		     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
		     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
	(char[]) {5, 1}, 
	(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
				   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
				   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
				   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
				   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
				   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
				   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
				   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
				   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
				   38 - 0,
				   4},
	(char[]) {4}, (char[]) {4},
	(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
		  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
		  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
		  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
		  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
		  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
		  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
					       0, 8 + 0 + 0, 21, 12 - 0, 1,
					       31, 9 + 0, 12 - 0, 1,
					       55 - 0 - 0, 21, 12 - 0, 0,
					       32, 9 + 3, 12 - 3, 0,
					       8 + 3 + 3, 21, 12 - 3, 1,
					       31, 9 + 3, 12 - 3, 1,
					       55 - 3 - 3, 21, 12 - 3, 6,
					       14 + 0, 2, 31 + 0, 13, 4,
					       1 - 0, 31 + 0, 16, 7, 3,
					       30 + 3 * 0, 14, 6,
					       12 + 0 * 4, 3, 32 - 0,
					       11 + 0 * 8, 6, 14 + 1, 2,
					       31 + 1, 13, 4, 1 - 1,
					       31 + 1, 16, 7, 3,
					       30 + 3 * 1, 14, 6,
					       12 + 1 * 4, 3, 32 - 1,
					       11 + 1 * 8,
					       4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
	for (int x = 0; x < 64; x++)
	    if (_[t]
		[y][x])
		x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
					32] = _[t][y][x];
}

int main(int a, char *s[]) {
    int h = 127;
    while (h--) {
	_n[h] ^= 28;
	_n[h] -= (_n[h] == 32 ? 32 : 0);
    }
    T = dlopen(_n, 2);
    d = ((void *(*)()) dlsym(T, _n + (1 * 20))) (0);
    w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d,
						(*(long *)
						 ((char
						   *) (*(long *) ((char *)
								  d +
								  232)) +
						  16))



						, 0, 0, 1220, 616, 1, 0,
						0);
    M = ((void *(*)()) dlsym(T, _n + (3 * 20))) (d,
						 (*(long *)
						  ((char
						    *) (*(long *) ((char *)
								   d +
								   232)) +
						   64)),
						 (*(long *)
						  ((char
						    *) (*(long *) ((char *)
								   d +
								   232)) +
						   56)), 2, 0, (char *) x_,
						 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
	char *p = z[i];
	int c = 0;
	while (*p != 4) {
	    switch (*p) {
	    case 0:
		k(i, p[1], p[2], p[3], c);
		p += 4;
		break;
	    case 1:
		r(i, p[1], p[2], p[3], c);
		p += 4;
		break;
	    case 2:
		u(i, p[1], p[2], p[3], c);
		p += 4;
		break;
	    case 3:
		e(i, p[1]
		  , p[2], 0, c);
		p += 3;
		break;
	    case 5:
		p = z[p[1]];
		break;
	    case 6:
		c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
		p += 2;
		break;
	    }
	}
    }
    while (a++) {
	int f = syscall(2, s[1], 0);
	syscall(0, f, m, 380);
	syscall(3, f);
	for (int y = 0; y < 19; y++)
	    for (int x = 0; x < 19; x++)
		if ((x % 14 == 2) && (y % 4 == 3))
		    m[y][x] = 46;
	b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
	b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
	b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
	b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
	for (int i = 0; i < 20; i++)
	    for (int y = 0; y < 19; y++)
		for (int x = 0; x < 19; x++)
		    if (m[y][x] == 62)
			b(0, x + 1, y, m[y][x + 1],
			  !(m[y - 1][x] == 43 ? 1 : 0
			    || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
	for (int y = 0; y < 616; y++)
	    for (int x = 0; x < 1220; x++)
		x_[y][x] = 0;
	for (int y = 0; y < 19; y++)
	    for (int x = 0; x < 19; x++)
		d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
	for (int y = 0; y < 19; y++)
	    for (int x = 0; x < 19; x++)
		if ((x % 14 == 2) && (y % 4 == 3))
		    d_(7, x, y);
	for (int y = 0; y < 616; y++)
	    for (int x = 0; x < 1220; x++) {
		x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
		x_[y][x] += 986895 & (rn *= 16777619);
	    } ((long (*)()) dlsym(T, _n + (4 * 20))) (d, w,
						      (*(long *)
						       ((char
							 *) (*(long
							       *) ((char *)
								   d +
								   232)) +
							72)), M, 0, 0, 0,
						      0, 1220, 616);
	((long (*)()) dlsym(T, _n + (5 * 20))) (d, w);
	((long (*)()) dlsym(T, _n + (6 * 20))) (d);
	syscall(35, &N, &R);
    } return 0;
}




Bueno, cumplimos al menos una de las condiciones de la competencia, el c贸digo despu茅s del preprocesador no se hizo m谩s claro.



Comencemos con lo que puede captar de un vistazo y tratemos de reconstruir la cadena de eventos.



dlsym \ dlopen



Obviamente, para usar las funciones del servidor X y crear una ventana, y luego dibujar algo en ella, el c贸digo debe dirigirse a la biblioteca XLib. El c贸digo contiene funciones dlopen / dlsym que le permiten cargar din谩micamente la biblioteca, pero se alimentan de un l铆o complicado en la entrada:




char _n[] =
    "pu~D--2os" "<<<<<<<<" "<<<DSlyrXuolp}e" "<<<<<<<<"
    "D_ny}hyOuqlpyKurxsk<D_ny" "}hyUq}{y" "<<<<<<<<" "DLihUq}{y" "<<<<<<<<"
    "<<<DQ}lKurxsk" "<<<<<<<<" "<<DZpiot<";
...
T = dlopen(_n, 2);


Demos un paso atr谩s e inspeccionemos el siguiente c贸digo:

int h = 127;
    while (h--) {
	_n[h] ^= 28;
	_n[h] -= (_n[h] == 32 ? 32 : 0);
    }


Aparentemente, transforma la matriz original de alguna manera, lo que nos permite obtener l铆neas legibles. Ejecut茅moslo por separado:



https://onlinegdb.com/SJNM9Og7v :



libX11.so                                                                                                                                                                     
XOpenDisplay                                                                                                                                                                  
XCreateSimpleWindow                                                                                                                                                           
XCreateImage                                                                                                                                                                  
XPutImage                                                                                                                                                                     
XMapWindow                                                                                                                                                                    
XFlush 


Para llamar a funciones tan diferentes en formato en una l铆nea, el c贸digo aprovecha el hecho de que en el lenguaje C est谩ndar (void) significa que no hay par谩metros, y () significa cualquier n煤mero de par谩metros. Solo queda lanzar el vac铆o resultante * al tipo ((long (*) ()) correspondiente y listo:



w = ((long (*)()) dlsym(T, _n + (2 * 20))) (d, (*(long *)((char *) (*(long *)((char *) d + 232)) + 16))


Sabiendo lo que significan estas conversiones, ahora podemos reemplazar este uso inusual de dlsym con cadenas primero:



Despu茅s de reemplazar las l铆neas:
int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

extern void *dlsym(void *, char *);
int x_[616][1220];
extern long syscall(long, ...);
extern void *dlopen(char *, int);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
	|| (m[y][x] != c))
	return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
	|| (_[t][y][x] != c))
	return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x++] = l;
	_[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x--] = l;
	_[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
	_[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
		     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
		     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
		     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
		     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
		     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
		     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
	(char[]) {5, 1}, 
	(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
				   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
				   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
				   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
				   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
				   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
				   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
				   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
				   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
				   38 - 0,
				   4},
	(char[]) {4}, (char[]) {4},
	(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
		  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
		  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
		  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
		  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
		  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
		  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
					       0, 8 + 0 + 0, 21, 12 - 0, 1,
					       31, 9 + 0, 12 - 0, 1,
					       55 - 0 - 0, 21, 12 - 0, 0,
					       32, 9 + 3, 12 - 3, 0,
					       8 + 3 + 3, 21, 12 - 3, 1,
					       31, 9 + 3, 12 - 3, 1,
					       55 - 3 - 3, 21, 12 - 3, 6,
					       14 + 0, 2, 31 + 0, 13, 4,
					       1 - 0, 31 + 0, 16, 7, 3,
					       30 + 3 * 0, 14, 6,
					       12 + 0 * 4, 3, 32 - 0,
					       11 + 0 * 8, 6, 14 + 1, 2,
					       31 + 1, 13, 4, 1 - 1,
					       31 + 1, 16, 7, 3,
					       30 + 3 * 1, 14, 6,
					       12 + 1 * 4, 3, 32 - 1,
					       11 + 1 * 8,
					       4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
	for (int x = 0; x < 64; x++)
	    if (_[t]
		[y][x])
		x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
					32] = _[t][y][x];
}

int main(int a, char *s[]) {
    T = dlopen("libX11.so", 2);
    d = ((void *(*)()) dlsym(T, "XOpenDisplay") (0);
    w = ((long (*)()) dlsym(T, "XCreateSimpleWindow")) (d,
						(*(long *)
						 ((char
						   *) (*(long *) ((char *)
								  d +
								  232)) +
						  16))



						, 0, 0, 1220, 616, 1, 0,
						0);
    M = ((void *(*)()) dlsym(T, "XCreateImage")) (d,
						 (*(long *)
						  ((char
						    *) (*(long *) ((char *)
								   d +
								   232)) +
						   64)),
						 (*(long *)
						  ((char
						    *) (*(long *) ((char *)
								   d +
								   232)) +
						   56)), 2, 0, (char *) x_,
						 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
	char *p = z[i];
	int c = 0;
	while (*p != 4) {
	    switch (*p) {
	    case 0:
		k(i, p[1], p[2], p[3], c);
		p += 4;
		break;
	    case 1:
		r(i, p[1], p[2], p[3], c);
		p += 4;
		break;
	    case 2:
		u(i, p[1], p[2], p[3], c);
		p += 4;
		break;
	    case 3:
		e(i, p[1]
		  , p[2], 0, c);
		p += 3;
		break;
	    case 5:
		p = z[p[1]];
		break;
	    case 6:
		c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
		p += 2;
		break;
	    }
	}
    }
    while (a++) {
	int f = syscall(2, s[1], 0);
	syscall(0, f, m, 380);
	syscall(3, f);
	for (int y = 0; y < 19; y++)
	    for (int x = 0; x < 19; x++)
		if ((x % 14 == 2) && (y % 4 == 3))
		    m[y][x] = 46;
	b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
	b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
	b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
	b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
	for (int i = 0; i < 20; i++)
	    for (int y = 0; y < 19; y++)
		for (int x = 0; x < 19; x++)
		    if (m[y][x] == 62)
			b(0, x + 1, y, m[y][x + 1],
			  !(m[y - 1][x] == 43 ? 1 : 0
			    || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
	for (int y = 0; y < 616; y++)
	    for (int x = 0; x < 1220; x++)
		x_[y][x] = 0;
	for (int y = 0; y < 19; y++)
	    for (int x = 0; x < 19; x++)
		d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
	for (int y = 0; y < 19; y++)
	    for (int x = 0; x < 19; x++)
		if ((x % 14 == 2) && (y % 4 == 3))
		    d_(7, x, y);
	for (int y = 0; y < 616; y++)
	    for (int x = 0; x < 1220; x++) {
		x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
		x_[y][x] += 986895 & (rn *= 16777619);
	    } ((long (*)()) dlsym(T, "XPutImage")) (d, w,
						      (*(long *)
						       ((char
							 *) (*(long
							       *) ((char *)
								   d +
								   232)) +
							72)), M, 0, 0, 0,
						      0, 1220, 616);
	((long (*)()) dlsym(T, "XMapWindow")) (d, w);
	((long (*)()) dlsym(T, "XFlush")) (d);
	syscall(35, &N, &R);
    } return 0;
}




Y luego a las funciones nativas:



Despu茅s de reemplazar con funciones `` nativas '':
#include <X11/Xlib.h>

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int x_[616][1220];
extern long syscall(long, ...);
char m[19][20];
long w, N[2] = { 0, 1 << 29 };
int rn = 2166136261, _[8][40][64] = { 0 };
long R[2];
void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
	|| (m[y][x] != c))
	return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
	|| (_[t][y][x] != c))
	return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x++] = l;
	_[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x--] = l;
	_[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
	_[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
		     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
		     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
		     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
		     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
		     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
		     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
	(char[]) {5, 1}, 
	(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
				   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
				   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
				   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
				   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
				   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
				   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
				   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
				   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
				   38 - 0,
				   4},
	(char[]) {4}, (char[]) {4},
	(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
		  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
		  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
		  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
		  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
		  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
		  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
					       0, 8 + 0 + 0, 21, 12 - 0, 1,
					       31, 9 + 0, 12 - 0, 1,
					       55 - 0 - 0, 21, 12 - 0, 0,
					       32, 9 + 3, 12 - 3, 0,
					       8 + 3 + 3, 21, 12 - 3, 1,
					       31, 9 + 3, 12 - 3, 1,
					       55 - 3 - 3, 21, 12 - 3, 6,
					       14 + 0, 2, 31 + 0, 13, 4,
					       1 - 0, 31 + 0, 16, 7, 3,
					       30 + 3 * 0, 14, 6,
					       12 + 0 * 4, 3, 32 - 0,
					       11 + 0 * 8, 6, 14 + 1, 2,
					       31 + 1, 13, 4, 1 - 1,
					       31 + 1, 16, 7, 3,
					       30 + 3 * 1, 14, 6,
					       12 + 1 * 4, 3, 32 - 1,
					       11 + 1 * 8,
					       4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
	for (int x = 0; x < 64; x++)
	    if (_[t]
		[y][x])
		x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
					32] = _[t][y][x];
}

int main(int a, char *s[]) {
    d = XOpenDisplay(0);
    w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
    M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
	    char *p = z[i];
	    int c = 0;
	    while (*p != 4) {
	        switch (*p) {
	        case 0:
	    	    k(i, p[1], p[2], p[3], c);
	    	    p += 4;
	    	    break;
	        case 1:
	    	    r(i, p[1], p[2], p[3], c);
	    	    p += 4;
	    	    break;
	        case 2:
	    	    u(i, p[1], p[2], p[3], c);
	    	    p += 4;
	    	    break;
	        case 3:
	    	    e(i, p[1]
	    	      , p[2], 0, c);
	    	    p += 3;
	    	    break;
	        case 5:
	    	    p = z[p[1]];
	    	    break;
	        case 6:
	    	    c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
	    	    p += 2;
	    	    break;
	        }
	    }
    }
    while (a++) {
	    int f = syscall(2, s[1], 0);
	    syscall(0, f, m, 380);
	    syscall(3, f);
	    for (int y = 0; y < 19; y++)
	        for (int x = 0; x < 19; x++)
		    if ((x % 14 == 2) && (y % 4 == 3))
		        m[y][x] = 46;
	    b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
	    b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
	    b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
	    b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
	    for (int i = 0; i < 20; i++)
	        for (int y = 0; y < 19; y++)
		    for (int x = 0; x < 19; x++)
		        if (m[y][x] == 62)
			    b(0, x + 1, y, m[y][x + 1],
			    !(m[y - 1][x] == 43 ? 1 : 0
			        || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
	    for (int y = 0; y < 616; y++)
	        for (int x = 0; x < 1220; x++)
		    x_[y][x] = 0;
	    for (int y = 0; y < 19; y++)
	        for (int x = 0; x < 19; x++)
		    d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
	    for (int y = 0; y < 19; y++)
	        for (int x = 0; x < 19; x++)
    		if ((x % 14 == 2) && (y % 4 == 3))
	    	    d_(7, x, y);
    	for (int y = 0; y < 616; y++)
	        for (int x = 0; x < 1220; x++) {
	    	    x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
	    	    x_[y][x] += 986895 & (rn *= 16777619);
	        }
	    XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) +	72)), M, 0, 0, 0, 0, 1220, 616);
	    XMapWindow(d, w);
	    XFlush(d);
	    syscall(35, &N, &R);
    } 
    return 0;
}




Syscalls



Reemplacemos las llamadas al sistema de la misma manera que seguimos en la primera parte:



C贸digo sin llamadas al sistema:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int x_[616][1220];
char m[19][20];
long w;
int rn = 2166136261, _[8][40][64] = { 0 };

void *M, *d, *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
	|| (m[y][x] != c))
	return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
	|| (_[t][y][x] != c))
	return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x++] = l;
	_[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
	_[t][y][x--] = l;
	_[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
	_[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
		     21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
		     63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
		     32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
		     21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
		     36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
		     3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
	(char[]) {5, 1}, 
	(char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
				   0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
				   21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
				   4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
				   5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
				   63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
				   21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
				   0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
				   3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
				   38 - 0,
				   4},
	(char[]) {4}, (char[]) {4},
	(char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
		  21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
		  21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
		  16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
		  2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
		  3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
		  3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
					       0, 8 + 0 + 0, 21, 12 - 0, 1,
					       31, 9 + 0, 12 - 0, 1,
					       55 - 0 - 0, 21, 12 - 0, 0,
					       32, 9 + 3, 12 - 3, 0,
					       8 + 3 + 3, 21, 12 - 3, 1,
					       31, 9 + 3, 12 - 3, 1,
					       55 - 3 - 3, 21, 12 - 3, 6,
					       14 + 0, 2, 31 + 0, 13, 4,
					       1 - 0, 31 + 0, 16, 7, 3,
					       30 + 3 * 0, 14, 6,
					       12 + 0 * 4, 3, 32 - 0,
					       11 + 0 * 8, 6, 14 + 1, 2,
					       31 + 1, 13, 4, 1 - 1,
					       31 + 1, 16, 7, 3,
					       30 + 3 * 1, 14, 6,
					       12 + 1 * 4, 3, 32 - 1,
					       11 + 1 * 8,
					       4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
	for (int x = 0; x < 64; x++)
	    if (_[t]
		[y][x])
		x_[y + q * 16 + p * 16][x + 580 + p * 32 - q *
					32] = _[t][y][x];
}

int main(int a, char *s[]) {
    d = XOpenDisplay(0);
    w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);
    M = XCreateImage(d, (*(long *)((char *) (*(long *) ((char *)d + 232)) + 64)), (*(long *)((char *) (*(long *) ((char *)d + 232)) + 56)), 2, 0, (char *) x_, 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
	    char *p = z[i];
	    int c = 0;
	    while (*p != 4) {
	        switch (*p) {
	        case 0:
	    	    k(i, p[1], p[2], p[3], c);
	    	    p += 4;
	    	    break;
	        case 1:
	    	    r(i, p[1], p[2], p[3], c);
	    	    p += 4;
	    	    break;
	        case 2:
	    	    u(i, p[1], p[2], p[3], c);
	    	    p += 4;
	    	    break;
	        case 3:
	    	    e(i, p[1]
	    	      , p[2], 0, c);
	    	    p += 3;
	    	    break;
	        case 5:
	    	    p = z[p[1]];
	    	    break;
	        case 6:
	    	    c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
	    	    p += 2;
	    	    break;
	        }
	    }
    }
    while (a++) {
	    int f = open(s[1], 0);
	    read(f, m, 380);
	    close(f);
	    
	    
	    for (int y = 0; y < 19; y++)
	        for (int x = 0; x < 19; x++)
		    if ((x % 14 == 2) && (y % 4 == 3))
		        m[y][x] = 46;
	    b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
	    b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
	    b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
	    b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
	    for (int i = 0; i < 20; i++)
	        for (int y = 0; y < 19; y++)
		    for (int x = 0; x < 19; x++)
		        if (m[y][x] == 62)
			    b(0, x + 1, y, m[y][x + 1],
			    !(m[y - 1][x] == 43 ? 1 : 0
			        || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
	    for (int y = 0; y < 616; y++)
	        for (int x = 0; x < 1220; x++)
		    x_[y][x] = 0;
	    for (int y = 0; y < 19; y++)
	        for (int x = 0; x < 19; x++)
		    d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
	    for (int y = 0; y < 19; y++)
	        for (int x = 0; x < 19; x++)
    		if ((x % 14 == 2) && (y % 4 == 3))
	    	    d_(7, x, y);
    	for (int y = 0; y < 616; y++)
	        for (int x = 0; x < 1220; x++) {
	    	    x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
	    	    x_[y][x] += 986895 & (rn *= 16777619);
	        }
	    XPutImage(d, w, (*(long *)((char *) (*(long *) ((char *)d + 232)) +	72)), M, 0, 0, 0, 0, 1220, 616);
	    XMapWindow(d, w);
	    XFlush(d);
	    
	    sleep(1);
    } 
    return 0;
}




XCreateSimpleWindow y compensaciones



Intentemos desmontar la siguiente construcci贸n:



w = XCreateSimpleWindow(d, (*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16)), 0, 0, 1220, 616, 1, 0, 0);


Un mont贸n de conversiones de tipos, que, a primera vista, solo son necesarias para confundir al lector, pero cada conversi贸n aqu铆 tiene su propio prop贸sito, a saber:



d es un puntero a la estructura Display en el contexto Xlib. Tiene un campo de matriz llamado pantallas y para obtener un puntero al primer elemento de esta matriz, debemos contar una cierta cantidad de bytes (x64 - 232) desde el puntero de pantalla hacia adelante. Dado que Display no es char *, entonces con lectura directa habr铆amos calculado en tama帽o de (long *) bytes. Entonces lanzamos d a char * y movemos 232 bytes:



 ((char *)d + 232)


Obtuvimos la posici贸n del primer elemento Screens en la memoria. Convirt谩moslo en un puntero completo y desreferenciamos:



(*(long *) ((char *)d + 232))


Ahora, dentro de la estructura Screens, necesitamos obtener un puntero a la ventana ra铆z, Root. Para hacer esto, alej茅monos de las pantallas 16 bytes y eliminemos la referencia a la construcci贸n:



(*(long *) ((char *) (*(long *) ((char *)d + 232)) + 16))


Esta construcci贸n es utilizada todos los d铆as por los programadores de Xlib, ya que su equivalente de uso com煤n es



RootWindow(Display, DefaultScreen(Display))


De manera similar, reemplazaremos las compensaciones correspondientes en otros lugares para obtener macros m谩s familiares (al mismo tiempo, corregiremos las jambas de sangr铆a):



C贸digo despu茅s de reemplazar compensaciones:

#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int x_[616][1220];
char m[19][20];
int rn = 2166136261, _[8][40][64] = { 0 };

void *T;

Display * display;
Window window;
XImage * image;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
    || (m[y][x] != c))
    return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= 64 || y >= 40 || x < 0 || y < 0) || (_[t][y][x] == l)
        || (_[t][y][x] != c))
        return;
    _[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x++] = l;
        _[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        _[t][y][x--] = l;
        _[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        _[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
    for (int x = 0; x < 64; x++)
        if (_[t][y][x])
            x_[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x];
}

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, 1220, 616, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) x_, 1220, 616, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        int f = open(s[1], 0);
        read(f, m, 380);
        close(f);
        
        
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    m[y][x] = 46;
        b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if (m[y][x] == 62)
                        b(0, x + 1, y, m[y][x + 1],
                            !(m[y - 1][x] == 43 ? 1 : 0
                            || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++)
                x_[y][x] = 0;
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                d_(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    d_(7, x, y);
        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++) {
                x_[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                x_[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, 1220, 616);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}




Datos de imagen



Tenga en cuenta que XCreateImage requiere un puntero al 谩rea de memoria donde se almacenar谩n los datos de p铆xeles. Para nuestra llamada de funci贸n, esta es la variable "x_". Cambie el nombre de pixdata y busque todos los lugares donde se usa:



void d_(int t, int p, int q) {
    for (int y = 0; y < 40; y++)
    for (int x = 0; x < 64; x++)
        if (_[t][y][x])
            pixdata[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x]; // ,      - 
}


    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, 1220, 616, 32, 0); //  


        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++)
                pixdata[y][x] = 0; // "" ,   


        for (int y = 0; y < 616; y++)
            for (int x = 0; x < 1220; x++) { // -   ,     .
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }


A铆slemos el bloque pixdata [..] = 0 en una funci贸n separada e intentemos averiguar qu茅 hace la primera aparici贸n:



    for (int y = 0; y < 40; y++)
    for (int x = 0; x < 64; x++)
        if (_[t][y][x])
            pixdata[y + q * 16 + p * 16][x + 580 + p * 32 - q * 32] = _[t][y][x];


Si observa de cerca la imagen final generada durante la operaci贸n del programa, notar谩 f谩cilmente que 40 y 64 son los tama帽os de un "bloque" separado del cual se construye el circuito.







Por lo tanto, esta funci贸n dibuja un "mosaico" separado en el lienzo de la imagen principal y, a juzgar por la indexaci贸n de la matriz "_", la variable "t" es responsable del 铆ndice de la imagen yp y q - de las coordenadas x e y. Tambi茅n cambiaremos el nombre de "_" a texturas:



El c贸digo en este momento:

#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH *1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + y * 16 + x * 16]
                       [tx + 580 + x * 32 - y * 32] = textures[t][ty][tx];
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

char m[19][20];
int rn = 2166136261;

void *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= 19 || y >= 19 || x < 0 || y < 0) || (m[y][x] == l)
    || (m[y][x] != c))
    return;
    m[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        int f = open(s[1], 0);
        read(f, m, 380);
        close(f);
        
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    m[y][x] = 46;
        b(0, 2, 3, m[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, m[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, m[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, m[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < 19; y++)
                for (int x = 0; x < 19; x++)
                    if (m[y][x] == 62)
                        b(0, x + 1, y, m[y][x + 1],
                            !(m[y - 1][x] == 43 ? 1 : 0
                            || m[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        
        _image_reset();  
        
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                _texture_draw(((m[y][x] >> 4) & 1) << 2 | (m[y][x] & 3), x, y);
                
        for (int y = 0; y < 19; y++)
            for (int x = 0; x < 19; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}




Leyendo el mapa



Separemos las l铆neas open..close en una funci贸n separada, donde el contenido del archivo seleccionado se lee en la variable m (que cambiaremos de nombre a mapdata).

驴Por qu茅 se cuenta el archivo en cada ciclo? Era m谩s corto en t茅rminos de c贸digo y tokens. El proceso de "embestir" el c贸digo tom贸 aproximadamente 4 d铆as para ajustarse a los l铆mites de las reglas. Si lee el archivo solo una vez, se necesitar谩 almacenamiento adicional y alg煤n an谩logo de la funci贸n memcpy.


Funci贸n dedicada _map_read
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        _map_read(s[1]);
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    mapdata[y][x] = 46;
        b(0, 2, 3, mapdata[3][2], a & 1 ? 43 : 45);
        b(0, 2, 7, mapdata[7][2], a & 2 ? 43 : 45);
        b(0, 2, 11, mapdata[11][2], a & 4 ? 43 : 45);
        b(0, 2, 15, mapdata[15][2], a & 8 ? 43 : 45);
        for (int i = 0; i < 20; i++)
            for (int y = 0; y < MAP_HEIGHT; y++)
                for (int x = 0; x < MAP_WIDTH; x++)
                    if (mapdata[y][x] == 62)
                        b(0, x + 1, y, mapdata[y][x + 1],
                            !(mapdata[y - 1][x] == 43 ? 1 : 0
                            || mapdata[y + 1][x] == 43 ? 1 : 0) ? 43 : 45);
        
        _image_reset();  
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((m[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}




Como hemos tocado la variable mapdata, prestemos atenci贸n a las l铆neas y funciones donde cambia - esta es la funci贸n "b", que no tocaremos por ahora, y "main" donde, prestando atenci贸n al contenido de los archivos de configuraci贸n "completos", refactorizaremos:



Despu茅s de refactorizar en mapdata

#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
}

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    b(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    b(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    b(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    b(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    b(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void b(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        _map_read(s[1]);
        _map_wire_inputs();
        _map_wire_counter(a);
        _map_process_gates();
        
        _image_reset();  
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}




Para finalizar el procesamiento del trabajo con "mapdata", debe responder dos preguntas m谩s: 驴qu茅 es la funci贸n "b":



void b(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    b(t, x - 1, y, c, l);
    b(t, x + 1, y, c, l);
    b(t, x, y - 1, c, l);
    b(t, x, y + 1, c, l);
}


Y que pasa en el bloque:



        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);


Funci贸n "b"



Si observa de cerca la funci贸n "b", notar谩 que es dolorosamente similar a la implementaci贸n del algoritmo flood_fill , que coincide con su prop贸sito te贸rico: "inunda" el "cable" con el estado deseado, permitiendo que el frente de onda de la corriente se propague hasta el final del cable. Vamos a cambiarle el nombre y colocarlo en el bloque "listo para producci贸n".



Relleno de inundaci贸n
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int a, char *s[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    while (a++) {
        _map_read(s[1]);
        _map_wire_inputs();
        _map_wire_counter(a);
        _map_process_gates();
        
        _image_reset();  
        
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                _texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        XPutImage(display, window, 
                  DefaultGC(display, DefaultScreen(display)), 
                  image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        XMapWindow(display, window);
        XFlush(display);
        
        sleep(1);
    } 
    return 0;
}




Bloque extra帽o



Ahora queda analizar lo que est谩 sucediendo en la l铆nea:



_texture_draw(((mapdata[y][x] >> 4) & 1) << 2 | (mapdata[y][x] & 3), x, y);


Como ya hemos construido una tabla completa de estados que pueden estar dentro de los datos del mapa, podemos obtener todos los valores de salida del primer par谩metro:

enumeraci贸n En t Resultado
MAPCHAR_WIRE 46 2
MAPCHAR_PLUS 43 3
MAPCHAR_MINUS 45 1
MAPCHAR_NOR 62 6
MAPCHAR_EMPTY 32 0


S铆, es decir, como resultado de esta transformaci贸n, obtenemos el 铆ndice de textura en la matriz de texturas.

Tom贸 un par de horas pensar en el mecanismo de generaci贸n de un conjunto de s铆mbolos legible y asociativamente comprensible en 铆ndices de textura. Escrib铆 los s铆mbolos que podr铆an significar cables y elementos NOR y luego, habiendo pintado sus valores binarios, rode茅 las 谩reas 煤nicas. Adem谩s de la actual, hab铆a una segunda opci贸n con c谩lculos m谩s complejos, pero es m谩s larga, por lo que no se ajusta al l铆mite de tokens.


Genial, nos da la capacidad de aislar otra funci贸n y declarar una enumeraci贸n para cada textura:



Despu茅s de otra refactorizaci贸n:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**<         (ASCII = 32) */
};

/*! \brief    */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**<                    */
    TEXINDEX_MINUS = (1), /**<   " " */
    TEXINDEX_WIRE  = (2), /**<       */
    TEXINDEX_PLUS  = (3), /**<   ""   */
    /**/
    TEXINDEX_NOR   = (6)  /**<   NOR-           */
};

/*! \brief   */
enum program_arguments { 
    ARG_PROGRAM,  /**<    */
    ARG_BLUEPRINT /**<  -   */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief       
 * \param[in] elem  
 * \return   */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief        */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief     */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 0;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        
        
                
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}




Textura # 7



Si observa de cerca la matriz "z", notar谩 que contiene 8 bloques de datos como una constante para el n煤mero de texturas. E incluso tiene dos espacios en las posiciones 4 y 5, al igual que en nuestra enumeraci贸n, lo m谩s probable es que se trate de datos de textura. Sin embargo, contiene 8 im谩genes y s贸lo pudimos "abrir" 7. Sin embargo, si somos lo suficientemente cuidadosos, podemos notar que hay un fragmento de c贸digo que dibuja espec铆ficamente la s茅ptima textura:



        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(7, x, y);


Por la posici贸n, ya puede adivinar qu茅 es, pero comente estas l铆neas y ejecute la aplicaci贸n:



Antes:







Despu茅s:







Ahora sabemos con certeza que esta es la textura del agujero en el tablero y podemos agregarla a la lista de enumeraci贸n renderiz谩ndola en una funci贸n separada:



Todas las texturas ensambladas:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**<         (ASCII = 32) */
};

/*! \brief    */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**<                    */
    TEXINDEX_MINUS = (1), /**<   " " */
    TEXINDEX_WIRE  = (2), /**<       */
    TEXINDEX_PLUS  = (3), /**<   ""   */
    /**/
    TEXINDEX_NOR   = (6), /**<   NOR-           */
    TEXINDEX_HOLE  = (7)  /**<          */
};

/*! \brief   */
enum program_arguments { 
    ARG_PROGRAM,  /**<    */
    ARG_BLUEPRINT /**<  -   */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

static void _texture_draw(int t, int x, int y);

/*! \brief      */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief       
 * \param[in] elem  
 * \return   */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief        */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief     */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief      */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };
int rn = 2166136261;

void *T;

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    _image_create();

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}




Shaders



Los gatos del art铆culo anterior promet铆an sombreadores. Y est谩n aqu铆. 驴Y d贸nde est谩 el c贸digo que se encarga de procesarlos?




        _image_reset();           // 
        _image_compile();       // 
        _image_drill();            // 
        
        for (int y = 0; y < IMAGE_HEIGHT; y++)
            for (int x = 0; x < IMAGE_WIDTH; x++) {
                pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));
                pixdata[y][x] += 986895 & (rn *= 16777619);
            }
        
        _image_draw();  // 


Por el m茅todo de eliminaci贸n, entendemos que el ruido de la pantalla y el efecto del monitor LCD dan estas dos l铆neas. 驴C贸mo trabajan?



Empecemos por el 煤ltimo:



pixdata[y][x] += 986895 & (rn *= 16777619);


A cada p铆xel se le suma el valor 986895 (que en las versiones hexadecimales se parece a 0x0f0f0f), que anteriormente era mediante la operaci贸n bit-AND combinada con el resultado de multiplicar rn por 16777619. Si rn fuera un generador de n煤meros aleatorios, crear铆a un "ruido" granulado en la pantalla dentro de 16 gradaciones para cada canal. Y dado que aparece el ruido, entonces rn es el generador de n煤meros aleatorios. Pero, 驴c贸mo se logra esto?



int rn = 2166136261;


Al comienzo del programa, la variable rn se inicializa con el n煤mero 2166136261. Y en cada iteraci贸n, el p铆xel se multiplica por 16777619. Esto no es m谩s que un generador de n煤meros pseudoaleatorios. Pero en lugar de un generador lineal bien estudiado, se utiliza el algoritmo hash FNV sin un paso XOR, ya que no necesitamos el resultado final.



Queda por ver c贸mo funciona la l铆nea anterior:



pixdata[y][x] &= 14737632 | (31 << ((x % 3) << 3));


Convirtamos el n煤mero 14737632 a formato hexadecimal, ya que estamos trabajando con canales de luz de un byte: 0xe0e0e0. Y ahora, tomando x igual de 0 a 3, realizamos los c谩lculos correspondientes:




0xe0e0e0 | (31 << ((0 % 3) << 3)) = e0e0ff                                                                                                                                                                  
0xe0e0e0 | (31 << ((1 % 3) << 3)) = e0ffe0                                                                                                                                                                        
0xe0e0e0 | (31 << ((2 % 3) << 3)) = ffe0e0 


Si ahora aplicamos estas m谩scaras usando la operaci贸n "&" al color de un p铆xel, obtendremos, respectivamente, los canales R y G, R y B, G y B silenciados, que se ver谩n como el efecto de un monitor LCD:







Separemos en funciones separadas:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**<         (ASCII = 32) */
};

/*! \brief    */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**<                    */
    TEXINDEX_MINUS = (1), /**<   " " */
    TEXINDEX_WIRE  = (2), /**<       */
    TEXINDEX_PLUS  = (3), /**<   ""   */
    /**/
    TEXINDEX_NOR   = (6), /**<   NOR-           */
    TEXINDEX_HOLE  = (7)  /**<          */
};

/*! \brief   */
enum program_arguments { 
    ARG_PROGRAM,  /**<    */
    ARG_BLUEPRINT /**<  -   */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief     */
int random = 2166136261;

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

static void _texture_draw(int t, int x, int y);

/*! \brief      */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief       
 * \param[in] elem  
 * \return   */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief        */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief     */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief      */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief   LCD-  
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief      
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief      */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}

void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}

void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    _image_create();

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                k(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                r(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                u(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                e(i, p[1]
                  , p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}




"E", "k", "r", "u"



Todav铆a hay 4 funciones que no hemos investigado ni cambiado de nombre: estas son "e", "k", "r" y "u". Intentemos inspeccionarlos sin buscar los lugares desde donde se llaman:

void e(int t, int x, int y, int c, int l) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == l) || 
         (textures[t][y][x] != c))
        return;
    textures[t][y][x] = l;
    e(t, x - 1, y, c, l);
    e(t, x + 1, y, c, l);
    e(t, x, y - 1, c, l);
    e(t, x, y + 1, c, l);
}


Obviamente, esta funci贸n se ve y funciona como flood_fill, solo para la matriz de texturas, cambiemos el nombre a _texture_fill.



void k(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x++] = l;
        textures[t][y++][x++] = l;
    }
}

void r(int t, int x, int y, int c, int l) {
    while (c--) {
        textures[t][y][x--] = l;
        textures[t][y++][x--] = l;
    }
}


Las funciones "k" y "r" para cada unidad dada c dibujan dos p铆xeles con el valor de ly se mueven hacia la derecha o izquierda dos p铆xeles y hacia abajo uno; esto significa que estas son funciones para dibujar l铆neas isom茅tricas SW y SE. Cambiemos el nombre a _texture_linesw y _texture_linese.



En este punto, ya puede adivinar que la 煤ltima funci贸n "u" dibuja una l铆nea verticalmente hacia abajo:



void u(int t, int x, int y, int c, int l) {
    while (c--)
        textures[t][y++][x] = l;
}


Cambiemos el nombre a _texture_linedown.

Todas las funciones individuales se han refactorizado:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**<         (ASCII = 32) */
};

/*! \brief    */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**<                    */
    TEXINDEX_MINUS = (1), /**<   " " */
    TEXINDEX_WIRE  = (2), /**<       */
    TEXINDEX_PLUS  = (3), /**<   ""   */
    /**/
    TEXINDEX_NOR   = (6), /**<   NOR-           */
    TEXINDEX_HOLE  = (7)  /**<          */
};

/*! \brief   */
enum program_arguments { 
    ARG_PROGRAM,  /**<    */
    ARG_BLUEPRINT /**<  -   */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief     */
int random = 2166136261;

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

static void _texture_draw(int t, int x, int y);

/*! \brief      */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief       
 * \param[in] elem  
 * \return   */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief        */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief     */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief      */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief   LCD-  
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief      
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief      */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief    
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] source  
 * \param[in] target   */
static void _texture_fill(int t, int x, int y, int source, int target) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == target) || 
         (textures[t][y][x] != source))
        return;
    textures[t][y][x] = target;
    _texture_fill(t, x - 1, y, source, target);
    _texture_fill(t, x + 1, y, source, target);
    _texture_fill(t, x, y - 1, source, target);
    _texture_fill(t, x, y + 1, source, target);
}

/*! \brief      SE
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c     
 * \param[in] color   */
static void _texture_linese(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x++] = color;
        textures[t][y++][x++] = color;
    }
}

/*! \brief      SW
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c     
 * \param[in] color   */
static void _texture_linesw(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x--] = color;
        textures[t][y++][x--] = color;
    }
}

/*! \brief   
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] color   */
static void _texture_linedown(int t, int x, int y, int c, int color) {
    while (c--)
        textures[t][y++][x] = color;
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

char *z[8] = { 
    (char[]) {4}, 
    (char[]) {6, 1 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16, 0, 0,
              21 + 0 * 3 - 0, 16, 1, 63, 21 + 0 * 3 - 0, 16, 2,
              63 * 0, 21 - 0, 4, 2, 31 + 0, 36 - 0, 4, 0 + 1,
              32 - 1, 5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1, 63,
              21 + 1 * 3 - 0, 16, 2, 63 * 1, 21 - 0, 4, 2, 31 + 1,
              36 - 0, 4, 6, 1 * 4 + 0, 3, 31, 8 - 0, 6, 1 * 4 + 2,
              3, 33, 38 - 0, 6, 1 * 4 + 3, 3, 30, 38 - 0, 4},
    (char[]) {5, 1}, 
    (char[]) {6, 0 * 4 + 1, 0 + 0, 32 - 0, 5 - 0, 16,
              0, 0, 21 + 0 * 3 - 0, 16, 1, 63,
              21 + 0 * 3 - 0, 16, 2, 63 * 0, 21 - 0,
              4, 2, 31 + 0, 36 - 0, 4, 0 + 1, 32 - 1,
              5 - 0, 16, 0, 0, 21 + 1 * 3 - 0, 16, 1,
              63, 21 + 1 * 3 - 0, 16, 2, 63 * 1,
              21 - 0, 4, 2, 31 + 1, 36 - 0, 4, 6,
              0 * 4 + 0, 3, 31, 8 - 0, 6, 0 * 4 + 2,
              3, 33, 38 - 0, 6, 0 * 4 + 3, 3, 30,
              38 - 0,
              4},
    (char[]) {4}, 
    (char[]) {4},
    (char[]) {6, 2 * 4 + 1, 0 + 0, 32 - 0, 5 - 3, 16, 0, 0,
              21 + 0 * 3 - 3, 16, 1, 63, 21 + 0 * 3 - 3, 16, 2, 63 * 0,
              21 - 3, 4, 2, 31 + 0, 36 - 3, 4, 0 + 1, 32 - 1, 5 - 3,
              16, 0, 0, 21 + 1 * 3 - 3, 16, 1, 63, 21 + 1 * 3 - 3, 16,
              2, 63 * 1, 21 - 3, 4, 2, 31 + 1, 36 - 3, 4, 6, 2 * 4 + 0,
              3, 31, 8 - 3, 6, 2 * 4 + 2, 3, 33, 38 - 3, 6, 2 * 4 + 3,
              3, 30, 38 - 3, 4}, 
    (char[]) {6, 13, 0, 32, 9 + 0, 12 - 0,
              0, 8 + 0 + 0, 21, 12 - 0, 1,
              31, 9 + 0, 12 - 0, 1,
              55 - 0 - 0, 21, 12 - 0, 0,
              32, 9 + 3, 12 - 3, 0,
              8 + 3 + 3, 21, 12 - 3, 1,
              31, 9 + 3, 12 - 3, 1,
              55 - 3 - 3, 21, 12 - 3, 6,
              14 + 0, 2, 31 + 0, 13, 4,
              1 - 0, 31 + 0, 16, 7, 3,
              30 + 3 * 0, 14, 6,
              12 + 0 * 4, 3, 32 - 0,
              11 + 0 * 8, 6, 14 + 1, 2,
              31 + 1, 13, 4, 1 - 1,
              31 + 1, 16, 7, 3,
              30 + 3 * 1, 14, 6,
              12 + 1 * 4, 3, 32 - 1,
              11 + 1 * 8,
              4}
};

int main(int argc, char * args[]) {
    _image_create();

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                _texture_linese(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                _texture_linesw(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                _texture_linedown(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                _texture_fill(i, p[1], p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}




Gr谩ficos vectoriales



Queda el 煤ltimo paso: averiguar qu茅 est谩 sucediendo en el 煤ltimo caso de interruptor, dejado para m谩s tarde:

    for (int i = 0; i < 8; i++) {
        char *p = z[i];
        int c = 0;
        while (*p != 4) {
            switch (*p) {
            case 0:
                _texture_linese(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 1:
                _texture_linesw(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 2:
                _texture_linedown(i, p[1], p[2], p[3], c);
                p += 4;
                break;
            case 3:
                _texture_fill(i, p[1], p[2], 0, c);
                p += 3;
                break;
            case 5:
                p = z[p[1]];
                break;
            case 6:
                c = _x[p[1] / 4] - 1643277 * (p[1] % 4);
                p += 2;
                break;
            }
        }
    }


Ahora que las funciones tienen nombres nuevos y comprensibles, podemos decir que este bloque de c贸digo interpreta los datos de la matriz "z", y de acuerdo con las instrucciones que contiene (por ejemplo, 0, 5, 5, 8, 2 - "dibuja la l铆nea Sur- Este, de [5,5] 8 p铆xeles de largo en el lado corto con el n煤mero de color 2 ") dibuja el conjunto completo de texturas.

Todo parece estar claro, pero no se not贸 ni una sola indicaci贸n del color en el programa.

c = _x[p[1] / 4] - 1643277 * (p[1] % 4);


S铆, entonces la matriz _x es una paleta, pero en un formato "comprimido" muy extra帽o.

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };


Dado que a煤n no sabemos cu谩ntos colores se utilizan en la paleta (al establecer el color, el 铆ndice es al menos divisible por 4), reformateamos la tabla de datos para dibujar y agrupamos los n煤meros por categor铆as, reemplazando las firmas de instrucci贸n con constantes:

Refactorizaci贸n de la tabla de instrucciones vectoriales
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**<         (ASCII = 32) */
};

/*! \brief    */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**<                    */
    TEXINDEX_MINUS = (1), /**<   " " */
    TEXINDEX_WIRE  = (2), /**<       */
    TEXINDEX_PLUS  = (3), /**<   ""   */
    /**/
    TEXINDEX_NOR   = (6), /**<   NOR-           */
    TEXINDEX_HOLE  = (7)  /**<          */
};

/*! \brief     */
enum textures_instructions {
    TEXVEC_LINESE = (0), /**<  SE                          */
    TEXVEC_LINESW = (1), /**<  SW                          */
    TEXVEC_LINEDW = (2), /**<                          */
    TEXVEC_FILL   = (3), /**<                            */
    TEXVEC_EXIT   = (4), /**<              */
    TEXVEC_REPEAT = (5), /**<     */
    TEXVEC_COLOR  = (6)  /**<                         */
};

/*! \brief   */
enum program_arguments { 
    ARG_PROGRAM,  /**<    */
    ARG_BLUEPRINT /**<  -   */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief     */
int random = 2166136261;

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/*! \brief      */
static const char * vecdata[TEXTURE_COUNT] = { 
    /* TEXINDEX_EMPTY */
    (char[]) { TEXVEC_EXIT }, 
    /* TEXINDEX_MINUS */
    (char[]) { TEXVEC_COLOR,   5,            TEXVEC_LINESE, 32,  5, 16, 
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW,  0, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   4, 
               TEXVEC_FILL,   31, 8,         TEXVEC_COLOR,   6,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   7, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /* TEXINDEX_WIRE */
    (char[]) { TEXVEC_REPEAT,  1 }, 
    /* TEXINDEX_PLUS */
    (char[]) { TEXVEC_COLOR,   1,            TEXVEC_LINESE, 32,  5, 16,
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW, 63, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   0, 
               TEXVEC_FILL,   31,  8,        TEXVEC_COLOR,   2,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   3, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /*   */
    (char[]) { TEXVEC_EXIT }, 
    /*   */
    (char[]) { TEXVEC_EXIT },
    /* TEXINDEX_NOR */
    (char[]) { TEXVEC_COLOR,   9,            TEXVEC_LINESE, 32,  2, 16, 
               TEXVEC_LINESE,  0, 18, 16,    TEXVEC_LINESW, 63, 18, 16, 
               TEXVEC_LINEDW,  0, 18,  4,    TEXVEC_LINEDW, 31, 33,  4, 
               TEXVEC_LINESW, 31,  2, 16,    TEXVEC_LINESE,  0, 21, 16, 
               TEXVEC_LINESW, 63, 21, 16,    TEXVEC_LINEDW, 63, 18,  4, 
               TEXVEC_LINEDW, 32, 33,  4,    TEXVEC_COLOR,   8,
               TEXVEC_FILL,   31,  5,        TEXVEC_COLOR,  10,  
               TEXVEC_FILL,   33, 35,        TEXVEC_COLOR,  11,
               TEXVEC_FILL,   30, 35,        TEXVEC_EXIT }, 
    /* TEXINDEX_HOLE */
    (char[]) { TEXVEC_COLOR,  13,            TEXVEC_LINESE, 32, 9, 12, 
               TEXVEC_LINESE,  8, 21, 12,    TEXVEC_LINESW, 31, 9, 12, 
               TEXVEC_LINESW, 55, 21, 12,    TEXVEC_LINESE, 32, 12, 9, 
               TEXVEC_LINESE, 14, 21,  9,    TEXVEC_LINESW, 31, 12, 9, 
               TEXVEC_LINESW, 49, 21,  9,    TEXVEC_COLOR,  14, 
               TEXVEC_LINEDW, 31, 13,  4,    TEXVEC_LINESW, 31, 16, 7, 
               TEXVEC_FILL,   30, 14,        TEXVEC_COLOR,  12, 
               TEXVEC_FILL,   32, 11,        TEXVEC_COLOR,  15, 
               TEXVEC_LINEDW, 32, 13,  4,    TEXVEC_LINESE, 32, 16, 7, 
               TEXVEC_FILL,   33, 14,        TEXVEC_COLOR,  16, 
               TEXVEC_FILL,   31, 19,        TEXVEC_EXIT }
};

static void _texture_draw(int t, int x, int y);

/*! \brief      */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief       
 * \param[in] elem  
 * \return   */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief        */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief     */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief      */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief   LCD-  
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief      
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief      */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief    
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] source  
 * \param[in] target   */
static void _texture_fill(int t, int x, int y, int source, int target) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == target) || 
         (textures[t][y][x] != source))
        return;
    textures[t][y][x] = target;
    _texture_fill(t, x - 1, y, source, target);
    _texture_fill(t, x + 1, y, source, target);
    _texture_fill(t, x, y - 1, source, target);
    _texture_fill(t, x, y + 1, source, target);
}

/*! \brief      SE
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c     
 * \param[in] color   */
static void _texture_linese(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x++] = color;
        textures[t][y++][x++] = color;
    }
}

/*! \brief      SW
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c     
 * \param[in] color   */
static void _texture_linesw(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x--] = color;
        textures[t][y++][x--] = color;
    }
}

/*! \brief   
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] color   */
static void _texture_linedown(int t, int x, int y, int c, int color) {
    while (c--)
        textures[t][y++][x] = color;
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*    */

int _x[] = { 15117427, 8413248, 5878632, 13027014, 1 };

int main(int argc, char * args[]) {
    _image_create();

    for (int tex = 0; tex < TEXTURE_COUNT; tex++) {
        char * ptr = vecdata[tex];
        int c = 0;
        while (*ptr != TEXVEC_EXIT) {
            switch (*ptr) {
            case TEXVEC_LINESE:
                _texture_linese(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
            case TEXVEC_LINESW:
                _texture_linesw(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
            case TEXVEC_LINEDW:
                _texture_linedown(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
            case TEXVEC_FILL:
                _texture_fill(tex, ptr[1], ptr[2], 0, c);
                ptr += 3;
                break;
            case TEXVEC_REPEAT:
                ptr = vecdata[ptr[1]];
                break;
            case TEXVEC_COLOR:
                c = _x[ptr[1] / 4] - 1643277 * (ptr[1] % 4);
                ptr += 2;
                break;
            }
        }
    }
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}




El n煤mero m谩ximo que se encuentra despu茅s de la instrucci贸n "TEXVEC_COLOR" es 16. Escribamos el c贸digo m谩s simple para obtener la tabla completa:







Ahora, teniendo la paleta descifrada en nuestras manos, podemos reemplazar la funci贸n de su uso y escribir descifrados para los colores en la tabla constante, y al mismo tiempo resaltar la funci贸n de crear texturas:



C贸digo completo despu茅s de la refactorizaci贸n:
#include <X11/Xlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*    */

/*! \brief     */
#define IMAGE_WIDTH (1220)
/*! \brief     */
#define IMAGE_HEIGHT (616)
/*! \brief        */
#define IMAGE_SHIFTX (580)

/*! \brief   */
#define TEXTURE_COUNT (8)
/*! \brief     */
#define TEXTURE_WIDTH (64)
/*! \brief     */
#define TEXTURE_HEIGHT (40)
/*! \brief      */
#define TEXTURE_TOP_WIDTH (64)
/*! \brief      */
#define TEXTURE_TOP_HEIGHT (32)

/*! \brief    */
#define MAP_WIDTH (19)
/*! \brief    */
#define MAP_HEIGHT (19)
/*! \brief    -.      '\n' */
#define MAP_FILEDATA ((MAP_WIDTH + 1) * MAP_HEIGHT)
/*! \brief      NOR- */
#define MAP_ITERATIONS (20)

/*! \brief    - */
enum map_characters {
    MAPCHAR_WIRE  = '.', /**<             (ASCII = 46) */
    MAPCHAR_PLUS  = '+', /**<  ( ) (ASCII = 43) */
    MAPCHAR_MINUS = '-', /**<  ( ) (ASCII = 45) */
    MAPCHAR_NOR   = '>', /**< NOR-       (ASCII = 62) */
    MAPCHAR_EMPTY = ' ', /**<         (ASCII = 32) */
};

/*! \brief    */
enum textures_indexes {
    TEXINDEX_EMPTY = (0), /**<                    */
    TEXINDEX_MINUS = (1), /**<   " " */
    TEXINDEX_WIRE  = (2), /**<       */
    TEXINDEX_PLUS  = (3), /**<   ""   */
    /**/
    TEXINDEX_NOR   = (6), /**<   NOR-           */
    TEXINDEX_HOLE  = (7)  /**<          */
};

/*! \brief     */
enum textures_instructions {
    TEXVEC_LINESE = (0), /**<  SE                          */
    TEXVEC_LINESW = (1), /**<  SW                          */
    TEXVEC_LINEDW = (2), /**<                          */
    TEXVEC_FILL   = (3), /**<                            */
    TEXVEC_EXIT   = (4), /**<              */
    TEXVEC_REPEAT = (5), /**<     */
    TEXVEC_COLOR  = (6)  /**<                         */
};

/*! \brief   */
enum program_arguments { 
    ARG_PROGRAM,  /**<    */
    ARG_BLUEPRINT /**<  -   */
};

/*! \brief    .
 *   int      */
int pixdata[IMAGE_HEIGHT][IMAGE_WIDTH];
/*! \brief  ,    */
int textures[TEXTURE_COUNT][TEXTURE_HEIGHT][TEXTURE_WIDTH] = { 0 };
/*! \brief   . 
 *        '\n' */
char mapdata[MAP_HEIGHT][MAP_WIDTH + 1];
/*! \brief     */
int random = 2166136261;

/*! \brief   Xlib */
Display * display;
/*! \brief    Xlib */
Window window;
/*! \brief      */
XImage * image;

/*! \brief      
 * \note    {001}    ""  {000} */
static const int texturepalette[] = { 
                         /*     鈻佲杹鈻傗杺鈻冣杻鈻勨杽鈻呪枀鈻嗏枂鈻団枃鈻堚枅    */    
    /* - */ 0xe6ac73, 0xcd9966, 0xb48659, 0x9b734c,
    /* -  */ 0x806040, 0x674d33, 0x4e3a26, 0x352719,
    /*            */ 0x59b368, 0x40a05b, 0x278d4e, 0x0e7a41,
    /*              */ 0xc6c6c6, 0xadb3b9, 0x94a0ac, 0x7b8d9f,
    /*             */ 0x000001
};

/*! \brief      */
static const char * vecdata[TEXTURE_COUNT] = { 
    /* TEXINDEX_EMPTY */
    (char[]) { TEXVEC_EXIT }, 
    /* TEXINDEX_MINUS */
    (char[]) { TEXVEC_COLOR,   5,            TEXVEC_LINESE, 32,  5, 16, 
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW,  0, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   4, 
               TEXVEC_FILL,   31, 8,         TEXVEC_COLOR,   6,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   7, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /* TEXINDEX_WIRE */
    (char[]) { TEXVEC_REPEAT,  1 }, 
    /* TEXINDEX_PLUS */
    (char[]) { TEXVEC_COLOR,   1,            TEXVEC_LINESE, 32,  5, 16,
               TEXVEC_LINESE,  0, 21, 16,    TEXVEC_LINESW, 63, 21, 16, 
               TEXVEC_LINEDW, 63, 21,  4,    TEXVEC_LINEDW, 31, 36,  4, 
               TEXVEC_LINESW, 31,  5, 16,    TEXVEC_LINESE,  0, 24, 16, 
               TEXVEC_LINESW, 63, 24, 16,    TEXVEC_LINEDW, 63, 21,  4, 
               TEXVEC_LINEDW, 32, 36,  4,    TEXVEC_COLOR,   0, 
               TEXVEC_FILL,   31,  8,        TEXVEC_COLOR,   2,
               TEXVEC_FILL,   33, 38,        TEXVEC_COLOR,   3, 
               TEXVEC_FILL,   30, 38,        TEXVEC_EXIT },
    /*   */
    (char[]) { TEXVEC_EXIT }, 
    /*   */
    (char[]) { TEXVEC_EXIT },
    /* TEXINDEX_NOR */
    (char[]) { TEXVEC_COLOR,   9,            TEXVEC_LINESE, 32,  2, 16, 
               TEXVEC_LINESE,  0, 18, 16,    TEXVEC_LINESW, 63, 18, 16, 
               TEXVEC_LINEDW,  0, 18,  4,    TEXVEC_LINEDW, 31, 33,  4, 
               TEXVEC_LINESW, 31,  2, 16,    TEXVEC_LINESE,  0, 21, 16, 
               TEXVEC_LINESW, 63, 21, 16,    TEXVEC_LINEDW, 63, 18,  4, 
               TEXVEC_LINEDW, 32, 33,  4,    TEXVEC_COLOR,   8,
               TEXVEC_FILL,   31,  5,        TEXVEC_COLOR,  10,  
               TEXVEC_FILL,   33, 35,        TEXVEC_COLOR,  11,
               TEXVEC_FILL,   30, 35,        TEXVEC_EXIT }, 
    /* TEXINDEX_HOLE */
    (char[]) { TEXVEC_COLOR,  13,            TEXVEC_LINESE, 32, 9, 12, 
               TEXVEC_LINESE,  8, 21, 12,    TEXVEC_LINESW, 31, 9, 12, 
               TEXVEC_LINESW, 55, 21, 12,    TEXVEC_LINESE, 32, 12, 9, 
               TEXVEC_LINESE, 14, 21,  9,    TEXVEC_LINESW, 31, 12, 9, 
               TEXVEC_LINESW, 49, 21,  9,    TEXVEC_COLOR,  14, 
               TEXVEC_LINEDW, 31, 13,  4,    TEXVEC_LINESW, 31, 16, 7, 
               TEXVEC_FILL,   30, 14,        TEXVEC_COLOR,  12, 
               TEXVEC_FILL,   32, 11,        TEXVEC_COLOR,  15, 
               TEXVEC_LINEDW, 32, 13,  4,    TEXVEC_LINESE, 32, 16, 7, 
               TEXVEC_FILL,   33, 14,        TEXVEC_COLOR,  16, 
               TEXVEC_FILL,   31, 19,        TEXVEC_EXIT }
};

static void _texture_draw(int t, int x, int y);

/*! \brief      */
static void _image_create(void) {
    display = XOpenDisplay(0);
    window = XCreateSimpleWindow(display, 
                                 RootWindow(display, DefaultScreen(display)), 
                                 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, 0);
    image = XCreateImage(display, 
                     DefaultVisual(display, DefaultScreen(display)), 
                     DefaultDepth(display, DefaultScreen(display)),
                     2, 0, (char *) pixdata, IMAGE_WIDTH, IMAGE_HEIGHT, 32, 0);
}

/* \brief  ,     */
static void _image_reset(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++)
            pixdata[y][x] = 0;
}

/*! \brief       
 * \param[in] elem  
 * \return   */
static int _map2texture(char elem) {
    return ((elem >> 4) & 1) << 2 | (elem & 3);
}

/*! \brief        */
static void _image_compile(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            _texture_draw(_map2texture(mapdata[y][x]), x, y);
}

/*! \brief     */
static void _image_draw(void) {
    XPutImage(display, window, 
              DefaultGC(display, DefaultScreen(display)), 
              image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    XMapWindow(display, window);
    XFlush(display);
}

/*! \brief      */
static void _image_drill(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if ((x % 14 == 2) && (y % 4 == 3))
                    _texture_draw(TEXINDEX_HOLE, x, y);
}

/*! \brief   LCD-  
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_lcd(int x, int y) {
    pixdata[y][x] &= 0xe0e0e0 | (31 << ((x % 3) << 3));
}

/*! \brief      
 * \param[in] x X- 
 * \param[in] y Y-  */
static void _shader_noise(int x, int y) {
    pixdata[y][x] += 0x0f0f0f & (random *= 16777619);
}

/*! \brief      */
static void _image_postprocess(void) {
    for (int y = 0; y < IMAGE_HEIGHT; y++)
        for (int x = 0; x < IMAGE_WIDTH; x++) {
            _shader_lcd(x, y);
            _shader_noise(x, y);
        }
}

/*! \brief        
 * \param[in] t  
 * \param[in] x X  
 * \param[in] y Y   */
static void _texture_draw(int t, int x, int y) {
    for (int ty = 0; ty < TEXTURE_HEIGHT; ty++)
        for (int tx = 0; tx < TEXTURE_WIDTH; tx++)
            if (textures[t][ty][tx])
                pixdata[ty + 
                        y * (TEXTURE_TOP_HEIGHT / 2) + 
                        x * (TEXTURE_TOP_HEIGHT / 2)]
                       [tx + 
                        IMAGE_SHIFTX + 
                        x * (TEXTURE_TOP_WIDTH / 2) - 
                        y * TEXTURE_TOP_HEIGHT] = textures[t][ty][tx];
}

/*! \brief    
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] source  
 * \param[in] target   */
static void _texture_fill(int t, int x, int y, int source, int target) {
    if ((x >= TEXTURE_WIDTH || y >= TEXTURE_HEIGHT || 
         x < 0 || y < 0) || 
         (textures[t][y][x] == target) || 
         (textures[t][y][x] != source))
        return;
    textures[t][y][x] = target;
    _texture_fill(t, x - 1, y, source, target);
    _texture_fill(t, x + 1, y, source, target);
    _texture_fill(t, x, y - 1, source, target);
    _texture_fill(t, x, y + 1, source, target);
}

/*! \brief      SE
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c     
 * \param[in] color   */
static void _texture_linese(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x++] = color;
        textures[t][y++][x++] = color;
    }
}

/*! \brief      SW
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c     
 * \param[in] color   */
static void _texture_linesw(int t, int x, int y, int c, int color) {
    while (c--) {
        textures[t][y][x--] = color;
        textures[t][y++][x--] = color;
    }
}

/*! \brief   
 * \param[in] t  
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] color   */
static void _texture_linedown(int t, int x, int y, int c, int color) {
    while (c--)
        textures[t][y++][x] = color;
}

/*! \brief   ,    */
static void _textures_create(void) {
    for (int tex = 0; tex < TEXTURE_COUNT; tex++) {
        const char * ptr = vecdata[tex];
        int c = 0;
        while (*ptr != TEXVEC_EXIT) {
            switch (*ptr) {
            case TEXVEC_LINESE:
                _texture_linese(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
                
            case TEXVEC_LINESW:
                _texture_linesw(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
                
            case TEXVEC_LINEDW:
                _texture_linedown(tex, ptr[1], ptr[2], ptr[3], c);
                ptr += 4;
                break;
                
            case TEXVEC_FILL:
                _texture_fill(tex, ptr[1], ptr[2], 0, c);
                ptr += 3;
                break;
                
            case TEXVEC_REPEAT:
                ptr = vecdata[ptr[1]];
                break;
                
            case TEXVEC_COLOR:
                c = texturepalette[ptr[1]];
                ptr += 2;
                break;
            }
        }
    }
}

/*! \brief   -      
 * \param[in] filename  - */
static void _map_read(const char * filename) {
    int f = open(filename, 0);
    read(f, mapdata, MAP_FILEDATA);
    close(f);
}

/*! \brief     -  
 *          */
static void _map_wire_inputs(void) {
    for (int y = 0; y < MAP_HEIGHT; y++)
        for (int x = 0; x < MAP_WIDTH; x++)
            if ((x % 14 == 2) && (y % 4 == 3))
                mapdata[y][x] = MAPCHAR_WIRE;
}

/*! \brief     
 * \param[in] t ,    
 * \param[in] x X- 
 * \param[in] y Y- 
 * \param[in] c  
 * \param[in] l   */
static void _map_fill(int t, int x, int y, int c, int l) {
    if ((x >= MAP_WIDTH || y >= MAP_HEIGHT || 
         x < 0 || y < 0) || (mapdata[y][x] == l)
        || (mapdata[y][x] != c))
        return;
    mapdata[y][x] = l;
    _map_fill(t, x - 1, y, c, l);
    _map_fill(t, x + 1, y, c, l);
    _map_fill(t, x, y - 1, c, l);
    _map_fill(t, x, y + 1, c, l);
}

/*! \brief        
 * .
 * \param[in] counter  */
static void _map_wire_counter(int counter) {
    _map_fill(0, 2, 3,  mapdata[3][2],  counter & 1 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 7,  mapdata[7][2],  counter & 2 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 11, mapdata[11][2], counter & 4 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
    _map_fill(0, 2, 15, mapdata[15][2], counter & 8 ? MAPCHAR_PLUS : MAPCHAR_MINUS);
}

/*! \brief    ()   NOR- */
static void _map_process_gates(void) {       
    for (int i = 0; i < MAP_ITERATIONS; i++)
        for (int y = 0; y < MAP_HEIGHT; y++)
            for (int x = 0; x < MAP_WIDTH; x++)
                if (mapdata[y][x] == MAPCHAR_NOR)
                    _map_fill(0, x + 1, y, mapdata[y][x + 1],
                        !(mapdata[y - 1][x] == MAPCHAR_PLUS ? 1 : 0
                       || mapdata[y + 1][x] == MAPCHAR_PLUS ? 1 : 0) ? 
                            MAPCHAR_PLUS : MAPCHAR_MINUS);
}

int main(int argc, char * args[]) {
    _image_create();
    _textures_create();
    
    unsigned int counter = 1;
    while (counter++) {
        _map_read(args[ARG_BLUEPRINT]);
        _map_wire_inputs();
        _map_wire_counter(counter);
        _map_process_gates();
        
        _image_reset();          
        _image_compile();
        _image_drill();
        _image_postprocess();        
        _image_draw();
        
        sleep(1);
    } 
    return 0;
}




Ep铆logo



Eso es todo.A pesar de que no gan茅 ning煤n premio, fue una experiencia bastante curiosa (el HDD que muri贸 dos d铆as antes del inicio de la aceptaci贸n del trabajo contribuy贸 a esto). Hab铆a algo mal al escribir c贸digo que era lo m谩s ilegible posible y al mismo tiempo absolutamente v谩lido desde el punto de vista del lenguaje. Sin embargo, no se puede decir que no fuera interesante. Cuando una utilidad que cuenta tokens dice que el c贸digo rompe las reglas al exceder el l铆mite en m谩s de 2000 tokens, y no sabes c贸mo acortarlo, eso es un desaf铆o. Cuando el tama帽o del archivo excede los l铆mites y desea agregar alg煤n tipo de efecto gr谩fico, esto es un desaf铆o. Fue dif铆cil acomodar tanta funcionalidad, y m谩s dulce fue leer el resultado de la utilidad, que, despu茅s de varios cientos de correcciones, finalmente dijo que el c贸digo se pod铆a descargar. Recomendar铆a a los lectores que participen en el concurso, aunque solo sea parapara unirte y poner a prueba tu fuerza.



S铆, no otorga premios ni premios, pero sabr谩 que se esconde bajo el sobrenombre de zhestokyshveller en el sitio web del IOCCC.



All Articles