Wtf-rate my code



  • Hi there, a year or so ago I saw myself orced to learn C using the most horrible compiler ever, now, I don't remember exactly what was it -I think it was some obscure/broken Borland C++ compiler- but it featured some C++ features and some others not, at least I could use // coments, but still the thing was weird, for example, it didn't like you to store input directly on an element of an array of some structures using scanf, so the following for example would throw an error:

    i=1;
    scanf(" %c", myarray[i].mychar);

    while this would compile/run just fine:

    scanf(" %c", myarray[1].mychar);

    But enough justifying, the reason of me summoning you here, is that I've recently stumbled upon a dark piece of code I made back then, I commited the sin of friggin' writing a Pacman "clone" on that compiler, but as I started writing the thing, I started to stumble upon some of it's limitations, and some other times I jsut got stuck on debugging some things that now look really stupid to me, but at the time were like trying to walk trhu a brick wall.
    So now what I would like you to do, is kill some of your spare time and look at this piece of crap, and tell me, what do you think is the worse piece of all the code.

    Note: yup, all comments and functions are named in spanish, some comments -about 1/3- are "angry comments" left behind when I couldn't make something work right and I just invented some workaound, I'm not sure if you would need me to at least translate the comments so you can have an idea of what each piece of code is supposed to be doing, but as the path of the smaller effort is to leave the code 'as is' I will not translate them unless I'm asked.
    I know it looks long, but anyway, I hope you have appetite for some spaghetti. 

    Without further ado, Teh Code:

    /*------------------------------------------------------------------------*/
    /*-----------------------------------PACOMAN------------------------------*/
    /*------------------------------------------------------------------------*/

    #include <string.h>
    #include <conio.h>
    #include <stdio.h>
    #include <dos.h>
    #include <stdlib.h>


    /* CONSTANTES SIMBOLICAS*/
    /* VERSION */
    #define PACOVER "v0.5a"
    #define COMPATIVERSION 'a' //a:casa //b:notebook hp //->necesario puesto que el ASCII de las notebooks hp aparentemente difiere de el de la maquina de mi casa en algunos caracteres

    	   /* SONIDO */
    //#define CONWAKA 1 //hace *wakawakawaka* cuando se mueve?
    //#define CONTWEET 1 //hace *tweet* cuando come un fantasma?
    //#define CONMUSICAMUERTE //hace priiiiibuuukacua


    /* SIMBOLOS DEL MAPA */
    #define PVAI 185 //¹:185 pared vertical abierta a la izquierda
    #define PVER 186 //º:186 pared vertical
    #define ECSD 187 //»:187 esquina cerrada superior derecha
    #define ECID 188 //¼:188 esquina cerrada inferior derecha
    #define ECSI 201 //É:201 esquina cerrada superior izquierda
    #define ECII 200 //È:200 esquina cerrada inferior izquierda
    #define TINV 202 //Ê:202 T abierta invertida
    #define TCOM 203 //Ë:203 T abierta
    #define PVAD 204 //Ì:204 pared vertical abierta a la derecha
    #define PHZN 205 //Í:205 pared horizontal
    #define CRUZ 206 //Î:206 + (cruz abierta)
    #define SPFN 126 //~:126 spawn fantasma <-requiere un espacio vacio arriba //cuenta como pared //SOLO PUEDE HABER UNO POR MAPA
    #define PACO 2 //:2 paco /spawn paco //SOLO PUEDE HABER UNO EN EL MAPA

    #if COMPATIVERSION=='a' //si estamos en modo compatibilidad con la pc de mi casa
    #define PAST 250 //ú:250 pastilla
    #define SPAS 155 //›:155 super pastilla
    #define FANT 169 //©:169 fantasma
    #elif COMPATIVERSION=='b' //si estamos en modo compatibilidad con las notebooks hp
    #define PAST 249 //ù:249 pastilla
    #define SPAS 236 //ì:236 super pastilla
    #define FANT 234 //ê:234 fantasma
    #endif

    /* TIPOS DE DATOS */

    struct ente{
    char q; //su simbolo
    int x; //su posicion en x
    int y; //su posicion en y
    int dir; //la direccion en la que se mueve //0 no se mueve
    int vel; //la velocidad a la que se mueve //0 no se mueve
    int def_vel; //la velocidad estandar del ente
    int dopa_vel; //la velocidad del ente cuando el paco esta dopado
    int def_color; //su color normal
    int color; //el color que posee actualmente
    int dopa_color; //su color cuando el paco esta dopado
    };


    /* CONSTANTES GLOBALES */

    const int POS_INI_X=1; //comienzo del mapa en x
    const int POS_INI_Y=3; //comienzo del mapa en y

    const int PAREDES[12]={PVAI, PVER, ECSD, ECID, ECSI, ECII, TINV, TCOM, PVAD, PHZN, CRUZ, SPFN}; //todos los caracteres que no son caminables

    enum DIRECCIONES{QUIETO=0,ARR,IZQ,ABA,DER}; //las 4 posibles direcciones de movimiento
    const int MAX_DIR=DER;
    enum VELOCIDADES{ NORMAL=1,RAPIDO}; //las posibles velocidades (es valida la direccion QUIETO como velocidad 0)
    const int MAX_VEL=RAPIDO;

    const char MOV_AR='w';
    const char MOV_IZ='a';
    const char MOV_AB='s';
    const char MOV_DE='d';
    const char SALIR='k';
    const char PAUSA='p';

    enum ERRORES{PSNF=0,FSNF,PANF,SPANF,MFDG,FMNE}; //los distintos codigos de error

    const int ANCHOMAPA=22; //1 espacio extra para el caracter de fin de cadena
    const int ALTOMAPA=21; //OjO, el mapa no debe tener mas de 20 de altura o no entra en la pantalla todo

    const int MAXFANTASMAS=4; //la maxima cantidad de fantasmas simultaneos //nota, no puede ser mayor a (MAX_FANT_COLOR-MIN_FANT_COLOR)

    const int MAX_VEL_FANT=NORMAL; //la maxima velocidad posible para los fantasmas
    const int MIN_FANT_COLOR=GREEN; //el color mas bajo asignable a un fantasma
    const int MAX_FANT_COLOR=DARKGRAY; //el color mas alto asignable a un fantasma
    const int FANT_DOPA_COLOR=LIGHTBLUE+BLINK; //el color de los fantasmas cuando el paco esta dopado

    const int PACO_DEF_COLOR=YELLOW; //el color normal del paco
    const int PACO_DOPA_COLOR=YELLOW; //el color dopado del paco
    const int PACO_DEF_DIR=ARR; //direccion en la que comienza moviendoce el paco
    const int PACO_DEF_VEL=NORMAL; //velocidad estandar del paco //nota: dado mi estilo vago de programacion, el paco no deberia tener una velocidad mayor a 1, de lo contrarios pueden darse errores con las verificaciones de coliciones con los fantasmas, los fantasmas por otro lado pueden ser tan rapidos como se quiera.

    const int COLOR_TEXTO=WHITE;
    const int COLOR_MAPA=RED;
    const int COLOR_PASTILLAS=YELLOW;
    const int COLOR_PUNTAJE_OBT=CYAN;

    const int PUNTAJE_PASTILLA=1;
    const int PUNTAJE_SUP_PAST=10;
    const int PUNTAJE_FANTASMA=100;

    const int LAPSO_ENTRE_FANTASMAS=13; //el tiempo en segundos entre que sale un fatasma y el siguiente
    const int DURACION_DOPA=30; //duracion de la superpastilla en segundos
    const int DEF_VIDAS=1; //vidas con las que comienza la partida el jugador
    const int HSFPS=75; //la cantidad de centesimas de segundo a esperar antes del siguiente cuadro

    const char CHARNULO=' ';

    #ifdef CONWAKA //faa, fanatico de la performance :P
    const int FREC_DOPADO=100; //default:100
    const int MIN_FREC_WAKA=300; //default:300
    const int MAX_FREC_WAKA=600; //default:600
    const int MIN_INTER_WAKA=600; //default:600
    const int MAX_INTER_WAKA=1200; //default:1200
    int g_sonando=0; //es constante, pero ni ganas de hacer otro ifdef-endif
    int g_suena_mueve=0; //para que solo suene si se esta moviendo el paco
    #endif

    /* VARIABLES GLOBALES */
    int g_puntaje=0; //puntaje del jugador
    int g_vidas=DEF_VIDAS; //vidas del jugador
    int g_killing_spree=0; //bonus por cantidad de fantasmas comidos en una misma sesion de dopaje //aumenta el puntaje que entrega comerse a un fantasma
    int g_pastillas=0; //la cantidad de pastillas que faltan comer
    int g_super_pastillas=0;
    int g_cant_fant=0; //la cantidad de fantasmas que hay dando vuelta

    int g_fin_del_juego=0; //cuando sea !=0 terminar  el juego
    int g_dopado=0; //para saber si hay activa una superpastilla

    struct time g_t_com_dopa; //comienzo del dopaje
    struct time g_t_com_juego; //comienzo del juego

    int g_color_fantasma_muerto=-1; //soy un limado (no, no voy a explicar para que es esto, es bastante autoexplicativo, mira en el main sino) //nota: esto sirve solo porque no puede haber 2 fantasmas con el mismo color

    char pastillas[ALTOMAPA][ANCHOMAPA];
    char MAPA001[ALTOMAPA][ANCHOMAPA]={ //el mapa cargado, si bien no es constante me resulta comodo ponerlo en mayuscula
    /**/" ",/**/ "ÉÍÍÍÍÍ» ÉÍÍÍÍÍ»", //NOTA, el agregado de una linea vacia al comienzo es por el bug raro que aparecio al separar las pastillas en otra capa, el porque del bug me sigue eludiendo
    "º21111ÈÍÍÍÍÍÍͼ11112º",
    "º1ÉÍ»11111111111ÉÍ»1º",
    "º1º ÈÍÍÍÍ»1ÉÍÍÍͼ º1º",
    "º1ÈËÍËÍÍͼ1ÈÍÍÍËÍ˼1º",
    "º11Èͼ111121111Èͼ11º",
    "È»11111ÉÍÍ~ÍÍ»11111ɼ",
    " ÈÍÍÍ»1ÈÍÍÍÍͼ1ÉÍÍͼ ",
    " Éͼ111111111ÈÍ» ",
    " Éͼ111ÉÍ»1ÉÍ»111ÈÍ» ",
    "ɼ111ÉÍÎ͹1ÌÍÎÍ»111È»",
    "º11Éͼ º º1º º ÈÍ»11º",
    "º1ɼ º º1º º È»1º",
    "º1ÌÍÍÍÍÊ͹1ÌÍÊÍÍÍ͹1º",
    "º1º º1º º1º",
    "º1º º1º º1º",
    "º1ÈÍ» Éͼ1ÈÍ» Éͼ1º",
    "º111ÈÍͼ1111ÈÍͼ111º",
    "ÈÍ»211111ÉÍ»111112Éͼ",
    " ÈÍÍÍÍÍͼ ÈÍÍÍÍÍͼ ",};


    /*PROTOTIPO DE FUNCIONES */

    void muestra_titulo(); //limpia la pantalla y muestra el titulo del juego
    void muestra_mapa(); //imprime el mapa en pantalla
    void muestra_pastillas(); //actualiza las pastillas
    void muestra_puntaje_y_vidas(); //muestra las vidas y el puntaje del jugador denajo del mapa
    void muestra_instrucciones(); //muestra las teclas de manejo al fondo de la pantalla
    void muestra_ente(struct ente); //dibuja al ente que se le pasa en su posicion correspondiente y con su correspondiente color

    struct ente buscar_ente(char); //busca un cierto caracter en el mapa y lo devuelve como ente
    int buscar_spawn_paco(struct ente&); //busca el caracter de spawn del paco
    int buscar_spawn_fantasma(struct ente&); //busca el caracter de spawn de fantasmas
    void buscar_pastillas(); //busca las pastillas, las convierte al caracter segun la version y las carga en el arreglo (limpiando el mapa), guardando la cantidad ademas, obvio

    void crear_paco(struct ente &paco, struct ente spawn); //crea al ente paco en la posicion dada por su ente spawn
    void crear_fant(struct ente &fant, int&, struct ente spawn); //crea un ente fantasma arriba de la puerta o punto de spawn de fantasma

    void recibir_input(struct ente&); //recibe input desde el teclado y lo interpreta
    void modif_dir_ente(int nuevadir,struct ente&); //modifica la direccion del ente dado
    void mover_ente(struct ente&,struct ente otto); //mueve a un ente en la direccion dada y con su velocidad propia (si es posible) /nota: el chocarse contra una pared termina el movimiento hasta el siguiente cuadro //verifica la coliciones con el ente "otto" //nota: uso "otto" porque "aux" ya era otra cosa en la funcion, y "dummy" tom‚ por costumbre que sea un ente vacio, asi que este ente auxiliar generico se lama "otto"
    int valid_mov(struct ente, struct ente otto); //verifica que sea valido mover al ente/ devuelve la cantidad de espacios que se movera en la direccion dada //verfica las coliciones con el ente "otto"

    void comer_pastilla(int x, int y); //elimina la pastilla del mapa en la posicion dada, suma el puntaje y llama a la funcion que comienza el dopaje en caso de que haya sido una super pastilla

    void err(int); //maneja los errores del programa

    /* MAIN */

    int main()
    {
    gettime(&g_t_com_juego);
    /* CONSTANTES LOCALES DE MAIN*/

    /* VARIABLES LOCALES DE MAIN*/

    int i=0,j=0; //indices genericos

    #ifdef CONWAKA //se, ya lime con esto, asi que la hago completa
    int sonando; //para alternar el sonido producido..
    #endif

    struct ente punto_spawn_paco;
    struct ente punto_spawn_fantasma;
    struct ente paco;
    struct ente fantasmas[MAXFANTASMAS];
    struct ente dummy; dummy.q=CHARNULO; dummy.x=0; dummy.y=0; //ver para que lo uso en la funcion de movimiento, validacion de movimiento y entonces coliciones

    int ult_color_fant=MIN_FANT_COLOR; //el color asignado al ultimo fantasma que fue creado
    int imprimir_puntaje=0;

    struct time t_com_bucle; //variable para buclear mientras que el usuario realice un input
    struct time t_ultimo_fant; //cuando se cre¢ el ultimo fantasma
    struct time t_aux;
    //int t_hudif=0;
    int t_sedif=0;

    /* INICIO DEL PROGRAMA */

    srand(time(0)); //inicializa el generador de numeros aleatorios

    muestra_titulo(); //muestra *PACOMAN vX.X*
    if(buscar_spawn_paco(punto_spawn_paco)) {err(PSNF); return PSNF; }
    if(buscar_spawn_fantasma(punto_spawn_fantasma)) {err(FSNF); return FSNF; }
    buscar_pastillas(); if(!g_pastillas) {err(PANF); return PANF; }
    if(MAXFANTASMAS > MAX_FANT_COLOR-MIN_FANT_COLOR) {err(MFDG); return MFDG; }
    crear_paco(paco, punto_spawn_paco);
    crear_fant(fantasmas[g_cant_fant],ult_color_fant,punto_spawn_fantasma);
    gettime(&t_ultimo_fant); /* creamos un fantasma si ya es hora */
    do
    {
    gettime(&t_aux);
    t_sedif=t_aux.ti_sec-g_t_com_dopa.ti_sec;
    (t_sedif<0)?t_sedif=-t_sedif:1;
    if(t_sedif>=DURACION_DOPA)
    {
    g_dopado=0;
    g_killing_spree=0;
    }
    if(g_cant_fant<MAXFANTASMAS && !g_dopado) //solo se crean fantasmas si no se llego al maximo y si el paco no esta dopado, para evitar que "campee"
    {
    gettime(&t_aux);
    t_sedif=t_aux.ti_sec-t_ultimo_fant.ti_sec;
    (t_sedif<0)?t_sedif=-t_sedif:1;
    if(t_sedif>=LAPSO_ENTRE_FANTASMAS)
    {
    crear_fant(fantasmas[g_cant_fant],ult_color_fant,punto_spawn_fantasma);
    gettime(&t_ultimo_fant);
    }
    }
    muestra_titulo();
    muestra_mapa();
    muestra_pastillas();
    muestra_ente(paco);
    for (i=0;i<g_cant_fant;i++)
    muestra_ente(fantasmas[i]);
    muestra_puntaje_y_vidas();
    muestra_instrucciones();
    if(imprimir_puntaje)
    {
    textcolor(COLOR_PUNTAJE_OBT);
    gotoxy(POS_INI_X+paco.y,POS_INI_Y+paco.x);
    cprintf("%d!!",PUNTAJE_FANTASMA*g_killing_spree);
    #ifdef CONTWEET
    printf("\a\a\a");
    #endif
    textcolor(WHITE);
    imprimir_puntaje=0;
    }
    gettime(&t_com_bucle);
    // gotoxy(1,13); printf("\n%d %d",paco.x,paco.y); //que muestre la posicion para debuggear mas facil
    do //bucle para input/espera a siguiente cuadro para no actualizar muchas veces por segundo que queda feo
    {
    #ifdef CONWAKA
    if (g_suena_mueve)
    {
    if(!g_dopado)
    if(g_sonando>MIN_INTER_WAKA){sound(MIN_FREC_WAKA); g_sonando++; if(g_sonando>MAX_INTER_WAKA)g_sonando=0;}//wakawakawakawaka..
    else{sound(MAX_FREC_WAKA); g_sonando++;}
    else sound(FREC_DOPADO);
    }
    #endif
    recibir_input(paco);
    gettime(&t_aux);
    /*t_hudif=t_aux.ti_hund-t_com_bucle.ti_hund;
    (t_hudif<0)?t_hudif=-t_hudif:1;*/
    t_sedif=t_aux.ti_sec-t_com_bucle.ti_sec;
    (t_sedif<0)?t_sedif=-t_sedif:1;
    }while(/*t_hudif<HSFPS&&*/t_sedif<1);
    mover_ente(paco, dummy); //mando a dummy porque no tengo nada que pasarle, las coliciones del paco con los fantasmas se verfican al mover los fantasmas nomas
    for (i=0;i<g_cant_fant;i++)
    {
    mover_ente(fantasmas[i], paco);
    if(g_color_fantasma_muerto!=-1) //elimina al fantasma muerto, muestra y suma puntaje y usa el intervalo de tiempo para crear otro fantasma
    {
    i=-1;
    do
    {
    i++;
    }while(fantasmas[i].color!=g_color_fantasma_muerto /*&& i<g_cant_fant*/); //por alguna razon si le agrego la condicion que dej‚ comentada no anda
    if(fantasmas[i].color!=g_color_fantasma_muerto) {err(FMNE); return FMNE;} //porlas
    for(j=i;j<g_cant_fant-1;j++) //mueve todos los fantasmas que estan despues del muerto para eliminarlo
    {
    fantasmas[j]=fantasmas[j+1];
    }
    g_cant_fant--;
    fantasmas[g_cant_fant].color=WHITE; //simplemente un color ilegal para fantasmas, para que no quede tanta basura (paranoia?)
    g_killing_spree++;
    g_puntaje+=PUNTAJE_FANTASMA*g_killing_spree;
    g_color_fantasma_muerto=-1;
    gettime(&t_ultimo_fant);
    imprimir_puntaje=1;
    }
    }
    }while(!g_fin_del_juego);

    #ifdef CONWAKA
    nosound(); //detiene el wakawaka
    #endif

    #ifdef CONMUSICAMUERTE
    if(g_fin_del_juego==2)
    {
    for(i=500;i>100;i--)
    {
    sound(i);
    delay(5);
    }
    nosound();
    sound(700);
    delay(300);
    nosound();
    sound(700);
    delay(300);
    nosound();
    }
    #endif

    muestra_titulo();
    muestra_mapa();
    muestra_pastillas();
    // muestra_ente(paco);
    for (i=0;i<g_cant_fant;i++)
    muestra_ente(fantasmas[i]);
    muestra_puntaje_y_vidas();
    switch (g_fin_del_juego)
    {
    case 1: printf("\nGANASTE!!"); break;
    case 2: printf("\nperdiste.. y bueh.."); break;
    case 3: printf("\naah, cobarde, no lograste terminar la partida"); break;
    }

    while(!kbhit());
    return 0;

    /* FIN DEL PROGRAMA */

    }

    /* DEFINICION DE FUNCIONES */

    void mover_ente(struct ente &pj, struct ente otto) //MUEVE AL ENTE EN LA DIRECCION DADA SEGUN SU VELOCIDAD Y SEGUN SEA POSIBLE. CONTROLA EL MOVIMIENTO DE LOS FANTASMAS, EL WAKAWAKA, Y NO ME ACUERDO SI ALGO MAS /nota: esta funcion tb quedo demasiado grande creo
    {
    int cant=0, dir=0, ban=0;
    char aux=CHARNULO;
    if(pj.dir>QUIETO && pj.vel>QUIETO)
    {
    cant=valid_mov(pj, otto);
    if (cant>0)
    {
    switch (pj.dir)
    {
    case ARR: pj.x-=cant; break;
    case ABA: pj.x+=cant; break;
    case IZQ: pj.y-=cant; break;
    case DER: pj.y+=cant; break;
    }
    }
    }
    if(pj.q==(char)FANT) /* controla el movimiento de los fanasmas.. tengo que pensar algo menos frutal.. quizas que sigan al paco.. nose..*/
    {
    switch (pj.dir)
    {
    case ARR: aux=MAPA001[pj.x-1][pj.y]; break;
    case ABA: aux=MAPA001[pj.x+1][pj.y]; break;
    case IZQ: aux=MAPA001[pj.x][pj.y-1]; break;
    case DER: aux=MAPA001[pj.x][pj.y+1]; break;
    }
    if(cant<pj.vel || aux!=CHARNULO)
    {
    dir=pj.dir;
    do
    {
    pj.dir=rand()%MAX_DIR +1;
    switch (pj.dir)
    {
    case ARR: aux=MAPA001[pj.x-1][pj.y]; break;
    case ABA: aux=MAPA001[pj.x+1][pj.y]; break;
    case IZQ: aux=MAPA001[pj.x][pj.y-1]; break;
    case DER: aux=MAPA001[pj.x][pj.y+1]; break;
    }
    }while(pj.dir==dir && aux!=CHARNULO);
    }
    }
    #ifdef CONWAKA
    if(pj.q==(char)PACO)
    if(cant>0)
    g_suena_mueve=1;
    else
    {
    nosound(); //solo debe sonar si se esta moviendo el paco
    g_suena_mueve=0;
    }
    #endif
    return;
    }

    int valid_mov(struct ente pj, struct ente otto) //DEVUELVE CUANTOS CUADROS SE PUEDE MOVER EN LA DIRECCION DADA SIN CHOCARSE /CALCULA LAS COLICIONES DE SER NECESARIO/nota: es un monstro esta funcion ahora
    {
    char aux;
    int i=0, cant=0, ban=0;
    int x=pj.x, y=pj.y;
    if(pj.q==(char)FANT && otto.q==(char)PACO)
    if(x==otto.x && y==otto.y)
    if(!g_dopado)
    {
    g_vidas--;
    /* TERMINAR RONDA*/
    if(g_vidas==0) g_fin_del_juego=2; //cuando lo termine posta (cuando implemente varias rondas) esto ya no iria aca
    return 0; //si colisionaron ahi sin moverse devuelve cero
    }
    else
    {
    g_color_fantasma_muerto=pj.color;
    }
    do
    {
    i++;
    switch (pj.dir)
    {
    case ARR: x=pj.x-i; break;
    case ABA: x=pj.x+i; break;
    case IZQ: y=pj.y-i; break;
    case DER: y=pj.y+i; break;
    }
    aux=MAPA001[x][y];
    if(aux!=CHARNULO) //un ente solo puede caminar a traves de espacio vacio (o pastillas, pero est n en otra matriz)
    ban=1;
    else
    {
    cant=i;
    if((pj.q==(char)PACO) && (pastillas[x][y]!=CHARNULO))
    comer_pastilla(x,y);
    if(pj.q==(char)FANT && otto.q==(char)PACO)
    if(x==otto.x && y==otto.y)
    if(!g_dopado)
    {
    g_vidas--;
    /* To Do: TERMINAR RONDA*/
    if(g_vidas==0) g_fin_del_juego=2; //cuando lo termine posta (cuando implemente varias rondas) esto ya no iria aca
    return 0; //para que salga sin hacer nada mas
    }
    else
    {
    g_color_fantasma_muerto=pj.color;
    }
    }
    }while(i<pj.vel && ban==0);
    return (cant);
    }

    void comer_pastilla(int x, int y) //se come una pastilla y hace lo que tenga que hacer
    {
    switch (pastillas[x][y])
    {
    case (char)PAST: g_puntaje+=PUNTAJE_PASTILLA; g_pastillas--; break;
    case (char)SPAS: g_puntaje+=PUNTAJE_SUP_PAST; g_super_pastillas--; gettime(&g_t_com_dopa); g_dopado=1; /* DOPAJE!! */ break;
    }
    pastillas[x][y]=CHARNULO;
    if (g_pastillas==0 && g_super_pastillas==0) g_fin_del_juego=1;
    return;
    }

    void recibir_input(struct ente &paco) //verfica si se ha pulsado una tecla y realiza la accion que corresponda
    {
    int tecla;
    if(kbhit())
    {
    tecla=getch();
    if (tecla==MOV_AR||tecla==MOV_IZ||tecla==MOV_AB||tecla==MOV_DE)
    modif_dir_ente(tecla, paco);
    else
    if (tecla==PAUSA)
    /*p*/;
    else
    if (tecla==SALIR)
    g_fin_del_juego=3;
    }
    return;
    }

    void modif_dir_ente(int nuevadir, struct ente &pj) //cambia la direccion del ente por la dada
    {
    char aux=CHARNULO;
    int dirant=pj.dir;
    switch (nuevadir)
    {
    case MOV_AR: pj.dir=ARR; break;
    case MOV_AB: pj.dir=ABA; break;
    case MOV_IZ: pj.dir=IZQ; break;
    case MOV_DE: pj.dir=DER; break;
    }
    switch (pj.dir)
    {
    case ARR: aux=MAPA001[pj.x-1][pj.y]; break;
    case ABA: aux=MAPA001[pj.x+1][pj.y]; break;
    case IZQ: aux=MAPA001[pj.x][pj.y-1]; break;
    case DER: aux=MAPA001[pj.x][pj.y+1]; break;
    }
    if (aux!=CHARNULO) pj.dir=dirant;
    return;
    }

    struct ente buscar_ente(char coso) /* DEVUELVE UN ENTE CON EL CARACTER BUSCADO EN SU POSICION (soy malo con las descripciones..)*/
    {
    struct ente esto;
    int i=0, j=0;
    for(i=0;i<ALTOMAPA;i++)
    for(j=0;j<ANCHOMAPA;j++)
    if(MAPA001[i][j]==coso)
    {
    esto.q=coso;
    esto.x=i;
    esto.y=j;
    esto.dir=QUIETO;
    esto.vel=esto.def_vel=QUIETO;
    esto.dopa_color=esto.color=esto.def_color=WHITE;
    return esto;
    }
    esto.q='0';
    return esto;
    }

    int buscar_spawn_paco(struct ente &paco) /* BUSCA EL PUNTO DE SPAWN DEL PACO */
    {
    paco=buscar_ente((char)PACO);
    if (paco.q=='0') return 1;
    else
    {
    MAPA001[paco.x][paco.y]=CHARNULO; // quita el simbolo de spawn del mapa
    return 0;
    }
    }

    int buscar_spawn_fantasma(struct ente &fant) /* BUSCA EL PUNTO DE SPAWN DE LOS FANTASMAS */
    {
    fant=buscar_ente((char)SPFN);
    if (fant.q=='0') return 1;
    else return 0;
    }

    void buscar_pastillas() /* BUSCA TODAS LAS PASTILLAS EN EL MAPA Y LAS CARGA */
    {
    int i=0,j=0;
    char aux=CHARNULO;
    for(i=0;i<=ALTOMAPA;i++)
    for(j=0;j<ANCHOMAPA;j++)
    {
    switch(MAPA001[i][j])
    {
    case '1': pastillas[i][j]=(char)PAST;
    g_pastillas++;
    MAPA001[i][j]=CHARNULO;
    break;
    case '2': pastillas[i][j]=(char)SPAS;
    g_super_pastillas++;
    MAPA001[i][j]=CHARNULO;
    break;
    default: pastillas[i][j]=CHARNULO;
    break;
    }
    }
    return;
    }

    void crear_fant(struct ente &fantasma, int& color, struct ente spawn) /*CREA E INICIALIZA A UN FANTASMA*/
    {
    char aux=MAPA001[spawn.x-1][spawn.y];
    if (g_cant_fant<MAXFANTASMAS)
    if(aux==CHARNULO)
    {
    fantasma.q=(char)FANT;
    fantasma.x=spawn.x-1; //osea que lo crea una posicion arriba de el punto de spawn
    fantasma.y=spawn.y;
    fantasma.dir=rand()%4 +1; //sin el +1 podria dar 0, que es quieto
    fantasma.vel=fantasma.def_vel=rand()%MAX_VEL_FANT +1; //sin el +1 podria dar 0, que es el quieto
    color++;
    fantasma.color=fantasma.def_color=color;
    fantasma.dopa_color=FANT_DOPA_COLOR;
    g_cant_fant++;
    }
    //else /*no se pudo crear el fantasma debido a que el espacio sobre el punto de spawn estaba ocupado */
    //else /*no se pudo crear el fantasma debido a que ya se ha llegado al maximo de fantasmas*/
    return;
    }

    void crear_paco(struct ente &paco, struct ente spawn) /*CREA E INICIALIZA AL PACO*/
    {
    paco.q=(char)PACO;
    paco.x=spawn.x;
    paco.y=spawn.y;
    paco.dir=PACO_DEF_DIR;
    paco.vel=paco.def_vel=PACO_DEF_VEL;
    paco.color=paco.def_color=PACO_DEF_COLOR;
    paco.dopa_color=PACO_DOPA_COLOR;
    return;
    }


    void err(int horror) /* MANEJA LOS ERROES DEL PROGRAMA */
    {
    clrscr();
    switch(horror)
    {
    case PSNF: printf("\n\nERROR %d: no se encontro el punto de spawn del paco en el mapa",PSNF); break;
    case FSNF: printf("\n\nERROR %d: no se encontro el punto de spawn del fantasma en el mapa",FSNF); break;
    case PANF: printf("\n\nERROR %d: no se encontro ninguna pastilla en el mapa",PANF); break;
    case SPANF: printf("\n\nERROR %d: no se encontro ninguna superpastilla en el mapa",SPANF); break;
    case MFDG: printf("\n\nERROR %d: el maximo de fantasmas existentes es mayor a la cantidad de colores posibles",MFDG); break;
    case FMNE: printf("\n\nERROR %d: sucedio fruta al tratar de matar un fantasma",FMNE); break;
    }
    getche();
    return;
    }

    void muestra_titulo() /* LIMPIA LA PANTALLA Y MUESTRA EL TITULO */
    {
    textbackground(BLACK);
    textcolor(WHITE);
    clrscr();
    textbackground(BLUE);
    textcolor(YELLOW);
    //gotoxy(20,1); cprintf("*******************************");
    gotoxy(22,2); cprintf("****** ******");
    //gotoxy(20,3); cprintf("*******************************");
    textcolor(YELLOW + BLINK);
    gotoxy(29,2); cprintf("PACOMAN %s",PACOVER);
    gotoxy(POS_INI_X,POS_INI_Y);//deja el cursor en un lugar comodo para continuar con el juego
    textbackground(BLACK); //deja el fondo estandar
    textcolor(WHITE); //deja la fuente estandar
    return;
    }

    void muestra_mapa() /* MUESTRA EL MAPA EN PANTALLA */
    {
    textcolor(COLOR_MAPA);
    gotoxy(POS_INI_X,POS_INI_Y);
    int i=0, j=0;
    for(i=0;i<ALTOMAPA;i++)
    {
    for(j=0;j<ANCHOMAPA;j++)
    {
    cprintf("%c",MAPA001[i][j]);
    }
    printf("\n");
    }
    textcolor(WHITE);
    return;
    }

    void muestra_pastillas() /* MUESTRA LAS PASTILLAS EN PANTALLA */
    {
    textcolor(COLOR_PASTILLAS);
    int i=0, j=0;
    for(i=0;i<ALTOMAPA;i++)
    {
    for(j=0;j<ANCHOMAPA;j++)
    {
    if(pastillas[i][j]!=CHARNULO) //PORUQE ENTRA SI ES FALSO?!?!?
    {
    gotoxy(POS_INI_X+j,POS_INI_Y+i);
    cprintf("%c",pastillas[i][j]);
    }
    }
    }
    textcolor(WHITE);
    return;
    }

    void muestra_puntaje_y_vidas()
    {
    textcolor(COLOR_TEXTO);
    gotoxy(POS_INI_X,POS_INI_Y+ALTOMAPA); //justo debajo del mapa
    printf("PUNTAJE: %d\t\tVIDAS: %d", g_puntaje, g_vidas);
    textcolor(WHITE);
    return;
    }

    void muestra_instrucciones()
    {
    textcolor(COLOR_TEXTO);
    gotoxy(POS_INI_X,POS_INI_Y+ALTOMAPA+1); //debajo del puntaje
    cprintf("Movimiento: Arriba:\'%c\' Izquierda:'\%c' Abajo:\'%c\' Derecha\'%c\' Salir:\'%c\'", MOV_AR, MOV_IZ, MOV_AB, MOV_DE, SALIR/*, PAUSA*/);
    textcolor(WHITE);
    return;
    }

    void muestra_ente(struct ente pj) /* MUESTRA AL ENTE DADO EN SU POSICION Y CON SU COLOR */
    {
    if(g_dopado)
    textcolor(pj.dopa_color);
    else
    textcolor(pj.color); //el color adecuado para el ente
    gotoxy(POS_INI_X+pj.y,POS_INI_Y+pj.x); //en las posicion adecuada dentro del mapa //nota:las x y las y cambiadas porque ni ganas de modificar todo el resto del codigo
    cprintf("%c",pj.q);
    textcolor(WHITE); // para continuar tranquilo con el resto del programa
    return;
    }

    /*Teh end*/

    BTW, I will not accept a "TRWTF is that all the code is in spanish" type of answer.

    PS: yeah, I realize I'm "redrawing" everything on the screen and that it actually has a performance hit in some not-so-old computers (I remember a sort of matrix-effect happening when executed full screen on a hp notebook with a 1GHz proccessor). Plus the game runs at a solid 1 FPS, nice uh? 



  • Holy crap!

    I've just spent the last 5 minutes reading this again and, not only I have noticed some stuff that I didn't remember, but I actually now hope that no one in the forums knows spanish or I¡ll be really embarrassed :S:S



  • OK I'm a little drunk atm but:

    Bar TRWTF of it being in spanish, I would initially just say add some whitespace. The extra return characters do help logically break up code and make it a lot more readable.

    secondly I dislike things like paco.vel=paco.def_vel=PACO_DEF_VEL;

    much easier to read:

    paco.vel = PACO_DEF_VEL;

    paco.def_vel = PACO_DEF_VEL;

    yes in theory it should compile/run better, but you shoud be able to rely on the compiler to optimise such code.

    Secondy, since I can't really be too arsed to completely go over the code why the hell does two members of a struct/class have to be set to the same value? Although i'm guessing def == default.

    With your comments some can be put before the code (particularly before functions). Much mre readble, I initially browsed through and thought there are no comments, then saw them afterwards.

    Code like (t_sedif<0)?t_sedif=-t_sedif:1; is more readable as

    (t_sedif < 0) ? t_sedif = -t_sedif : 1;

    The whitespace helps alot.

     

    Just remember readabilty is one of the most important thing when it comes to code.



  • More drunken rants:

    ok things like:

    //gotoxy(20,1); cprintf("*******************************");
    gotoxy(22,2); cprintf("******                   ******");
    //gotoxy(20,3); cprintf("*******************************");
     

    is not good unless you give a reason to coment out such code

    AND with tools availabe to us these days such as intellisence i always try to use names such as default over def



  • @Hitsuji said:

    *burp* 

     

    lmao, maybe you should be sleeping rather than reading TDWTF?

    anyway, 'def' is for 'deault', I assign it to 2 different vars because one is the one that I use when I have to make the pacoman move, and the other is the default speed, you see, there's also another speed, the speed when the pacoman is high on pills.

    I usually use withspce an comments properly, but the damn blue screen and yellow letters had me a bit crazy at the moment I guess.

    those commented printf's were for .. displaying the title of the game I think, it makes sense if you compile/run this thing. Also if you open it in some old DOS based C/C++ compiler -like the one I used- the code atually looks pretier.-

    ps: intellisece?! BLUE SCREEN AND YELLOW LETTERS MATE!

    ps2: idk why I yelled, I hope you tell me the worse WTF you can find there when you wake up fresh. Anyway, thanks.-



  • And this post because HTML view is now disabled when posting apparently.

    Particularly with c++ or c if i was initialising a set of variables at once or even just setting then i would try to align the operators, again for readiblity, such as instead of:

        fantasma.q=(char)FANT;
        fantasma.x=spawn.x-1; //osea que lo crea una posicion arriba de el punto de spawn
        fantasma.y=spawn.y;
        fantasma.dir=rand()%4 +1; //sin el +1 podria dar 0, que es quieto
        fantasma.vel=fantasma.def_vel=rand()%MAX_VEL_FANT +1; //sin el +1 podria dar 0, que es el quieto
        color++;
        fantasma.color=fantasma.def_color=color;
        fantasma.dopa_color=FANT_DOPA_COLOR;
    

    I always prefer:

    color++; fantasma.q = (char) FANT; fantasma.x = spawn.x - 1; //osea que lo crea una posicion arriba de el punto de spawn fantasma.y = spawn.y; fantasma.dir = (rand() % 4) + 1; //sin el +1 podria dar 0, que es quieto fantasma.vel = (rand() % MAX_VEL_FANT) + 1; fantasma.def_vel = (rand() % MAX_VEL_FANT) + 1; //sin el +1 podria dar 0, que es el quieto fantasma.color = color; fantasma.def_color = color; fantasma.dopa_color = FANT_DOPA_COLOR;


  • mhmh yup, I guess that's more readable that's quite easier to read, but still, the original code was not wtf-worthy.- 



  • FUCK.  Sites like pastebin will let you throw up large sections of code and they have syntax highlighting so you don't need to make a 5 page post into the thread. 



  •  I wasn't really sure how to post it, ifupload the .cpp file into rpidshare or what, I would normally use a spoiler tag, but I don't think this forum has them?



  • there, If there were a magic/ninja way to edit my first post, I would delete all that code and simply point to this:

     

    PASTEBIN PASTEBIN PASTEBIN 



  • @ZippoLag said:

    there, If there were a magic/ninja way to edit my first post, I would delete all that code and simply point to this:

     

    PASTEBIN PASTEBIN PASTEBIN 

    It's cool, just keep it in mind for future reference.  I'm not going to pore over half a dozen pages of code with no syntax highlighting.  If your code snippet is longer than a dozen or so lines, consider linking to an external source. 



  • @ZippoLag said:

    #ifdef CONWAKA
    nosound(); //detiene el wakawaka
    #endif

    That gave me a much-needed laugh for the day, thanks :)

    -cw

     



  • @morbiuswilters said:

    It's cool, just keep it in mind for future reference.  I'm not going to pore over half a dozen pages of code with no syntax highlighting.  If your code snippet is longer than a dozen or so lines, consider linking to an external source. 

     

    Noted for the future. 

     

    @CodeWhisperer said:

    @ZippoLag said:

    #ifdef CONWAKA
    nosound(); //detiene el wakawaka
    #endif

    That gave me a much-needed laugh for the day, thanks :)

    -cw

     

    there are one or two purposedly humoristic lines around the code, I'm glad you found that one -tho it's actually functional code-.

    This afternoon or tomorrow I'll try and translate th whole thing -code & comments- so this post can actually be understood by someone, I of course will limit myself to the lineal translation and not remove/add any wtfish code.

     



  • alrighty then, I've translated the comments in case anyone wishes to see it.

    HERE

    ps: I DO NOT CLAIM MY PACOMAN TO BE BETTER THAN THE ORIGINAL PACMAN. Just in case anyone was thinking I'm morphing into some kind of spetate. 



  • You're using deprecated headers. Should be:

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>

     



  • @antred said:

    You're using deprecated headers. Should be:

    #include <cstring>
    #include <cstdio>
    #include <cstdlib> 

    It looks to me like he wrote this in C, which means he used the correct headers. 



  • Oh ....yeah, you're right ... my bad.



  • Discourse touched me in a no-no place

    @antred said:

    (TRWTF is that anyone would still use stone-age C in 2008 :P ... )
    Are you volunteering to re-write the Linux Kernel then?



  •  Hmmm, how did you manage to quote that 3 hours later when I deleted it pretty much 2 minutes after I made my post?? :p

     

    Anyway yeah sorry, I should have read the whole thread before making a comment. 



  • @antred said:

     Hmmm, how did you manage to quote that 3 hours later when I deleted it pretty much 2 minutes after I made my post?? :p

    Welcome to the Internet, where once you say something you cannot unsay it.  Enjoy your stay here. 


  • Discourse touched me in a no-no place

    @antred said:

    how did you manage to quote that 3 hours later when I deleted it pretty much 2 minutes after I made my post?? :p

    Welcome to email subscription. Hope you enjoyed your stay.

     Back on topic (or more likely this is going off topic...)

    You didn't answer my question.

    More to the point, why did you feel the need to remove that bit of your comment after posting it?



  • @antred said:

     Hmmm, how did you manage to quote that 3 hours later when I deleted it pretty much 2 minutes after I made my post?? :p

    Anyway yeah sorry, I should have read the whole thread before making a comment. 

    Because then you would have realized that C isn't a stone-age language?



  •  Why not use curses library for redrawing the screen?

     ** Disclaimer: did not read all of the post. Did not read code. Doe not know what code  does. Just read the flickering screen :)



  •  Oh and you are making pacman all over, are you going to release/distribute it?



  • @PJH said:

    More to the point, why did you feel the need to remove that bit of your comment after posting it?
     

     

    Because I re-read his post and noticed he said he was basically forced to revert to old C-style because of the antique compiler he used. 

      



  • @bstorer said:

    Because then you would have realized that C isn't a stone-age language?
     

     

    No, I don't think I would have "realized" that. IMO C is a relic of the past and should be avoided where ever possible. Of course I'm aware that sometimes it just can't be avoided. 



  • @antred said:

    @bstorer said:

    Because then you would have realized that C isn't a stone-age language?
     

     

    No, I don't think I would have "realized" that. IMO C is a relic of the past and should be avoided where ever possible. Of course I'm aware that sometimes it just can't be avoided. 

    Thank god that nobody values your opinion, then. Calling C a relic of the past is to call the hammer a relic of the past because you have a cordless drill and some screws. Now, I'm not crazy enough to advocate C for every project big or small, but -- You know what? Yes I am. I, bstorer, hereby advocate the use of C for any project, big or small.

    Seriously, though, I'm going to go out on a limb and guess that your fear of C stems from an inability to write robust, quality code in C. Just because Java takes care of the memory for you doesn't make it a better language. Looking down your nose at C comes from a distinct lack of understanding of what C tried to do, because it fills its niche more completely than perhaps any other programming language.



  • Why are you getting so defensive? I didn't insult your momma or something like that. I merely stated my opinion about C. Oh, and btw. I don't like Java either so I'm afraid you're not going to put me in that drawer.

    I think I'm quite capable of writing relatively robust and efficient code in C should I ever have to, but I find it much easier in a more modern language like C++.



  • @antred said:

    Why are you getting so defensive? I didn't insult your momma or something like that. I merely stated my opinion about C.

    My mother is a C compiler, you insensitive clod!

    I'm not getting defensive in the least. I just hate that some young lad might someday wander across this page and be swayed by your terribly foolish opinion regarding C. Won't you please think of the children?

    @antred said:
    Oh, and btw. I don't like Java either so I'm afraid you're not going to put me in that drawer.

    That's a better drawer than the one you're about to put yourself into. Oh, I can hardly wait! Let's just jump right to it:

    @antred said:
    but I find it much easier in a more modern language like C++.

    BWAHAHAHAHA! You crack me up, pal. "I prefer a modern, 23-year-old language over that antiquated, 30-year-old one!" Man, that's funny!

    What?! You were serious? What exactly makes you think C++ is even remotely modern in any way, shape or form?



  • @bstorer said:

    BWAHAHAHAHA! You crack me up, pal. "I prefer a modern, 23-year-old language over that antiquated, 30-year-old one!" Man, that's funny!

    What?! You were serious? What exactly makes you think C++ is even remotely modern in any way, shape or form?

     

     Is the actual age of either language really decisive? I think compared to C, C++ rates as quite modern. Just the mere fact that objects have their destructors invoked on them when they go out of scope makes me think of C++ as a hugely more productive language than C. How do you employ the RAII idiom without destructors? Coding without RAII is a huge pain in the rear, if you ask me. Doubly so if you do threading (no scoped locks without RAII), or if you're used to having shared_ptr do the reference counting for you.

    Also, note that I didn't call C++ modern per se ... I just called it more modern than C, and I won't retreat from that assertion. I'm fully aware that other languages out there offer features that C++ is lacking, and that compared to some of them, C++ may look like a dinosaur. The difference, however, is that unlike with C++ vs C, they often do not have the potential to replace the older language in its area of use.

    If you have to do low-level coding close to the hardware and performane is of great importance to you, you very often will have to resort to C/C++ or other compiled languages.

     



  • Let's take this out of order to better highlight how little sense you're demonstrating.
    @antred said:

    If you have to do low-level coding close to the hardware and performane is of great importance to you, you very often will have to resort to C/C++ or other compiled languages.
    Nice try with lumping C and C++ as the same thing, but they're fundamentally different, which we'll get to in time. Further, just because coding close to the hardware is of importance doesn't mean that any old compiled language will do. Even ignoring the fact that any language can be compiled or interpreted, have fun trying to do systems programming in, say, Fortran-77. In other words, compiled ≠ low-level.
    @antred said:

    Also, note that I didn't call C++ modern per se ... I just called it more modern than C, and I won't retreat from that assertion. I'm fully aware that other languages out there offer features that C++ is lacking, and that compared to some of them, C++ may look like a dinosaur.

    C++ is a dinosaur. And what's worse, it's more of a dinosaur than C, because nothing beats C in C's niche.
    @antred said:
    The difference, however, is that unlike with C++ vs C, they often do not have the potential to replace the older language in its area of use.
    Good, you said it again. Now, let's highlight how silly this is:
    @antred said:
    I think compared to C, C++ rates as quite modern. Just the mere fact that objects have their destructors invoked on them when they go out of scope makes me think of C++ as a hugely more productive language than C. How do you employ the RAII idiom without destructors? Coding without RAII is a huge pain in the rear, if you ask me. Doubly so if you do threading (no scoped locks without RAII), or if you're used to having shared_ptr do the reference counting for you.
    RAII and destructors and shared_ptrs with reference counting! And you want to talk about C++ as a systems language? You can't have it both ways. Either C++ is a systems language, in which case you're using little more than C gives you in exchange for a lot more hassle, or you're using it as a high-level language, at which point it is the very king of the dinosaurs.
    @antred said:
    Is the actual age of either language really decisive?
    No, not really. LISP and Smalltalk are both far older than C++, but both are far more modern. Hell, Objective C is only 3 years younger than C++ and does right many of the things C++ does wrong.



  • @bstorer said:

    Nice try with lumping C and C++ as the same thing, but they're fundamentally different, which we'll get to in time. Further, just because coding close to the hardware is of importance doesn't mean that any old compiled language will do. Even ignoring the fact that any language can be compiled or interpreted, have fun trying to do systems programming in, say, Fortran-77. In other words, compiled ≠ low-level.

    Okay, maybe I should have dropped "or other compiled languages". I think it was quite obvious that I meant "other compiled languages that deliver similarily efficient code", so that means compiled Tcl/Perl/Python/whatever is out of the question, should there be such a thing for the respective language.

    @bstorer said:

    C++ is a dinosaur. And what's worse, it's more of a dinosaur than C, because nothing beats C in C's niche.

    C++ beats C just fine in just about any conceivable role, and probably in some inconceivable roles, too. What can you do in C that you [i]can't[/i] do in C++? If there's something that C does better than C++ I'd sure like to know what it is! IMO the only reason to use C as a systems language is if there is no decent C++ compiler available for your target platform.

    @bstorer said:

    RAII and destructors and shared_ptrs with reference counting! And you want to talk about C++ as a systems language? You can't have it both ways. Either C++ is a systems language, in which case you're using little more than C gives you in exchange for a lot more hassle, or you're using it as a high-level language, at which point it is the very king of the dinosaurs.

     So what exactly is it that makes use of RAII impractical when using C++ as a system language?

     @bstorer said:

    No, not really. LISP and Smalltalk are both far older than C++, but both are far more modern. Hell, Objective C is only 3 years younger than C++ and does right many of the things C++ does wrong

     Unfortunately I can't comment on that, as I have only very superficial experience with Lisp and Smalltalk and none with Objective C.


  • Discourse touched me in a no-no place

    @antred said:

    C++ beats C just fine in just about any conceivable role,

    Linux kernel, Linux drivers?

    Unless you plan on single handedly plan on doing the rewrite? For all of them.

    @antred said:

    What can you do in C that you can't do in C++?

    Assume the value of sizeof('a'). Use variables called 'new' and 'template'. Use malloc() without warnings. Use goto over initialisations. Be lax in using others' header files by having them defining int foo() and you later declaring it as int foo(<arguements>)

    Apply to the kernel argument above.

    @antred said:

    If there's something that C does better than C++ I'd sure like to know what it is!

    You either run Windows, or have no interest/knowledge in how your Linux system is actually programmed.

     

    On a more salient note - what (apart from ignorance) stops you using OOP in C? It's been going on in the Linux kernel for ages.

    <flame>After all, C++ is just syntatic sugar for OOP in C..... </flame>



  • @antred said:

    Okay, maybe I should have dropped "or other compiled languages". I think it was quite obvious that I meant "other compiled languages that deliver similarily efficient code", so that means compiled Tcl/Perl/Python/whatever is out of the question, should there be such a thing for the respective language.
    Again, still not true. The quality of the compiler has little to do with the language itself. Any language can be compiled down to the same, best code for an algorithm; that's a corollary of the Church-Turing Thesis.
    @antred said:
    C++ beats C just fine in just about any conceivable role, and probably in some inconceivable roles, too.
    This is patently untrue. C++ is a horrible collision of a systems language with a high-level language. For example, sure C++ stole the implicit type conversions from C, but it's horribly at odds with its increased type-checking.
    @antred said:
    What can you do in C that you can't do in C++? If there's something that C does better than C++ I'd sure like to know what it is!
    Well, for starters, compiler optimization is much more effective in C. It's not a coincidence that for a long time C++ compilers simply did their best to interpret the C++ down into C, which could then be optimized. But more importantly, flip the question around: what can you do in C++ that you can't do in C? And don't you dare say OOP, because you'll just embarrass yourself.
    @antred said:
    IMO the only reason to use C as a systems language is if there is no decent C++ compiler available for your target platform.
    Again, good thing your opinion doesn't matter, because it's wrong.
    @antred said:

     So what exactly is it that makes use of RAII impractical when using C++ as a system language?

    The overhead. Do you think destructors come for free? For that matter, do you think C++'s class system comes for free?
    @antred said:

     Unfortunately I can't comment on that, as I have only very superficial experience with Lisp and Smalltalk and none with Objective C.

    A lack of knowledge hasn't stopped you with regards to C.



  • I have a tingling sensation that you were sarcastic, but oh well...

    @PJH said:

    Assume the value of sizeof('a').

    One. Of course, it's equal to sizeof(int) in C, but how's that an argument in C's favour?

    @PJH said:

    Use variables called 'new' and 'template'.

    That's just silly.

    @PJH said:

    Use malloc() without warnings. Use goto over initialisations. Be lax in using
    others' header files by having them defining int foo() and you later declaring
    it as int foo(<arguements>)

    Aaaand,.. How exactly is any of these a good thing?



  • @bstorer said:

    This is patently untrue. C++ is a horrible collision of a systems language with a high-level language. For example, sure C++ stole the implicit type conversions from C, but it's horribly at odds with its increased type-checking.

    I see stronger type checking as an advantage rather than as a weakness.

    @bstorer said:

    Well, for starters, compiler optimization is much more effective in C. It's not a coincidence that for a long time C++ compilers simply did their best to interpret the C++ down into C, which could then be optimized.
     

    Welcome to 2008!  Today's C++ compiles are every bit as good as optimizing code as C compilers.

    @bstorer said:

    But more importantly, flip the question around: what can you do in C++ that you can't do in C? And don't you dare say OOP, because you'll just embarrass yourself.

    Well,  RAII for example, something that is completely impossible in C. And I can use templates to write generic code cleanly. Sure, this comes at a cost, but writing the same codes for x different types in C isn't free either. And since you mentioned it, yes in fact the ability to use OOP/polymorphism can come in quite handy. Please don't tell me you find emulting polymorphism using integer type id's and function pointers more elegant ...

    @bstorer said:

    Again, good thing your opinion doesn't matter, because it's wrong.

    I've endured your little pot shots for quite a while now, but I'm really starting to find your your anal retentive debating tactics a bit childish, to be honest. Let me know if you're interested in continuing this discussion in a civil tone because otherwise I guess we may just as well call it quits.

     @bstorer said:

    The overhead. Do you think destructors come for free? For that matter, do you think C++'s class system comes for free?

    The overhead is absolutely minimal. And I mean minimal as in not even worth mentioning; far far outweighed by the benefits. The company I work for successfully uses C++ to write real-time operating systems for drives with responsiveness requirements in the range of microseconds (our last product series used plain old C, but we've since migrated to C++ as high-quality C++ compilers have become available for the hardware we're targeting). Granted, you have to be aware of what features of the language come at what cost, but other than that we can do the same things we did in C in C++, at no loss in efficiency and with less hassle.

    @bstorer said:

    A lack of knowledge hasn't stopped you with regards to C.
     

    Yeah, whatever. 



  • @antred said:

    I've endured your little pot shots for quite a while now, but I'm really starting to find your your anal retentive debating tactics a bit childish, to be honest. Let me know if you're interested in continuing this discussion in a civil tone because otherwise I guess we may just as well call it quits.
     

    Oh man bstorer! This guy went all slyadams on you! 



  • @PJH said:

    Linux kernel, Linux drivers?

    I think that's covered by "sometimes it's just impossible to avoid C". I'd hope that next time someone writes a popular operating system, they won't do it in C.

    @PJH said:

    Assume the value of sizeof('a'). Use variables called 'new' and 'template'. Use malloc() without warnings. Use goto over initialisations. Be lax in using others' header files by having them defining int foo() and you later declaring it as int foo(<arguements>)

    I don't see how ANY of those up the score for C in the C vs C++ battle.

    @PJH said:

    You either run Windows, or have no interest/knowledge in how your Linux system is actually programmed.

    Don't avoid the question, answer it! 

    @PJH said:

    On a more salient note - what (apart from ignorance) stops you using OOP in C? It's been going on in the Linux kernel for ages.

    Nothing. But why not just use the built-in polymorphism offered by C++ rather than rolling your own? The C++ compiler will very likely do a better job of it than you.


  • @antred said:

    I see stronger type checking as an advantage rather than as a weakness.
    And you don't find it at odds with the implicit type conversion? Perhaps you've seen this example before, but let's check it out anyway:

    [bstorer@localhost cpp]$ g++ --version
    g++ (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
    Copyright (C) 2006 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    [bstorer@localhost cpp]$ cat barf.cpp
    #include <iostream>
    
    void foo(const std::string & x) { std::cout << x << std::endl;}
    int main()
    {
      foo(false);
      return 0;
    }
    [bstorer@localhost cpp]$ g++ -Wall barf.cpp -o barf.out
    [bstorer@localhost cpp]$ ./barf.out
    terminate called after throwing an instance of 'std::logic_error'
      what():  basic_string::_S_construct NULL not valid
    Aborted
    
    Hooray, strong typing!

    @antred said:

    Welcome to 2008!  Today's C++ compiles are every bit as good as optimizing code as C compilers.
    Oh, good! Nice of you guys to catch up.
    @antred said:
    Well,  RAII for example, something that is completely impossible in C.
    Depending on how you define it, it's potentially impossible in C++, seeing as destructors can't throw exceptions reliably. But if you really must have RAII, Samba's talloc probably does a lot of what you want. Also, while we're on the subject, do you really love RAII all that much? What happens when your spiffy RAII-powered object is added to a std::vector? Do you copy it every time, lest it go out of scope and be destroyed? Or do you create it on the heap anyway, which just makes the RAII method a waste of time?
    @antred said:
    And I can use templates to write generic code cleanly.
    Ah, templates... We can discuss them later if you'd really like. But for now, did you see <a href="http://forums.thedailywtf.com/forums/p/8109/152677.aspx#152677"my beautiful template code to kill a compiler?
    @antred said:
    And since you mentioned it, yes in fact the ability to use OOP/polymorphism can come in quite handy. Please don't tell me you find emulting polymorphism using integer type id's and function pointers more elegant ...
    No, but I often find that full-blown polymorphism isn't really as necessary as one might think.
    @antred said:
    I've endured your little pot shots for quite a while now, but I'm really starting to find your your anal retentive debating tactics a bit childish, to be honest. Let me know if you're interested in continuing this discussion in a civil tone because otherwise I guess we may just as well call it quits.
    Well, you've just now offered something worth discussing, so let's see what happens.
    @antred said:
    Granted, you have to be aware of what features of the language come at what cost, but other than that we can do the same things we did in C in C++, at no loss in efficiency and with less hassle.
    I'm interested in what features of the language you use such that you get "less hassle". In my experience, nothing in C++ comes with less hassle.



  • @antred said:

    I think that's covered by "sometimes it's just impossible to avoid C".
    But why? Surely anything in C can be improved by writing it in C++!



  • @bstorer said:

    And you don't find it at odds with the implicit type conversion? Perhaps you've seen this example before, but let's check it out anyway [...]


    Well, yeah the system is obviously not foolproof ...  you're always going to be able to find ways to 'outsmart' the compiler.Still, on the whole, strong type checking is a good thing IMO.

    @bstorer said:
    Oh, good! Nice of you guys to catch up.


    :p

    @bstorer said:
    Also, while we're on the subject, do you really love RAII all that much? What happens when your spiffy RAII-powered object is added to a std::vector? Do you copy it every time, lest it go out of scope and be destroyed? Or do you create it on the heap anyway, which just makes the RAII method a waste of time?


    Yes, I do love RAII that much because I like to offload as much work as possible to the compiler. I use little RAII guard classes all over my code to ensure execution of any code that must be run on leaving a block. Example:

    void lockMutexDoStuffAndUnlockMutex( Mutex& theMutex )
    {
        class ScopedLock
        {
        private:
            Mutex& m_theMutex;

        public:

            explicit ScopedLock( Mutex& theMutex ) : m_theMutex( theMutex ) { theMutex.lock(); }

            ~ScopedLock() { m_theMutex.unlock(); }

        };

        // use RAII to make sure the mutex is unlocked, regardless of where and how we exit from this block
        const ScopedLock sl( theMutex );

        // do stuff ...
        if ( mayRaiseException() == true )
        {
            return;
        }



        // do some more stuff
        blabla();

    }

    Rather than worry about all the various ways the function can be left (early return, exception, late return) I just create my little RAII guard on the stack and let the compiler handle it.

    The second major tool that RAII offers me are reference-counted pointers ... either boost::shared_ptr and boost::weak_ptr or ACE::Strong_Bound_Ptr and ACE::Weak_Bound_Ptr. If you're worried that these implementations may be too inefficient, which from my personal experience they're absolutely not, you can even write your own. It's not a trivial task but it's certainly doable. Using implicit reference counting certainly makes for much more robust code and greatly decreases the chance of resource leaks. I barely ever invoke operator delete manually anymore.

    @bstorer said:
    Ah, templates... We can discuss them later if you'd really like.


    What reservations do you have against templates? I'm aware that they can lead to code bloat if used unwisely but then any feature can have negative repercussions if used thoughtlessly. In the hands of  a competent programmer, templates are an enormously useful tool IMO.

    @bstorer said:
    But for now, did you see to kill a compiler?


    Sorry, I'm not following.

    @bstorer said:
    No, but I often find that full-blown polymorphism isn't really as necessary as one might think.


    Well, full-blown polymorphism is never really necessary in the sense that you can't do without it, as I'm sure virtually any problem that can be solved through the use of polymorphism can also be solved without it in one way or another. That said, in many situations, polymorphism seems JUST right ... to me anyway, so I'm very thankful the language provides me with that option.



  • @antred said:

    Yes, I do love RAII that much because I like to offload as much work as possible to the compiler. I use little RAII guard classes all over my code to ensure execution of any code that must be run on leaving a block.
    Do you use exceptions? Because RAII mixes very poorly with exceptions. The reason is that you can't throw an exception while unwinding the stack due to another exception. Which means that destructors can't do anything which may throw an exception. It's little things like this that start to chip away at the usefulness of RAII.
    @antred said:
    @bstorer said:
    But for now, did you see to kill a compiler?


    Sorry, I'm not following.
    I hate Community Server. It ate the text inside my link. Anyway, it should have said:

    But for now, did you see my code to kill a compiler?
    This highlights one of my great dislikes about C++'s templates -- they're just pretty C preprocessor macros, but with the added "bonus" of being entwined in the type system. @antred said:
    The second major tool that RAII offers me are reference-counted pointers ... either boost::shared_ptr and boost::weak_ptr or ACE::Strong_Bound_Ptr and ACE::Weak_Bound_Ptr.
    I'm not familiar with all of these implementations, but reference-counting pointers are pretty much all susceptible to reference loops. Ignoring that annoying little issue, what happens if I want to store a bunch of objects in, say, a std::vector which are stored in smart pointers? Now I'm working with std::vector<smart_pointer<some_type> >, which sort of kills any attempt at abstraction, doesn't it?


  • @bstorer said:

    Do you use exceptions? Because RAII mixes very poorly with exceptions. The reason is that you can't throw an exception while unwinding the stack due to another exception. Which means that destructors can't do anything which may throw an exception. It's little things like this that start to chip away at the usefulness of RAII.

    Yeah, I use exceptions. The fact that d'tors must not allow exceptions to propagate outwards is a limitation of course, albeit one that I don't find too much of a problem in practice. If I intend to use a RAII guard to ensure execution of a piece of code I just design that piece of code to never throw. Granted, if you're using a lot of library functions and you don't know if / what they might throw you got problem.

    @bstorer said:

    I hate Community Server. It ate the text inside my link. Anyway, it should have said:
    But for now, did you see my code to kill a compiler?
    This highlights one of my great dislikes about C++'s templates -- they're just pretty C preprocessor macros, but with the added "bonus" of being entwined in the type system.

    Well, unlike macros they're type-safe. Yeah yeah I know, your std::string example says otherwise but I can honestly say I've NEVER encountered such a problem in a real-life scenario. 

    @bstorer said:

    I'm not familiar with all of these implementations, but reference-counting pointers are pretty much all susceptible to reference loops.

    weak_ptr is used to break circular references.

    @bstorer said:

    Ignoring that annoying little issue, what happens if I want to store a bunch of objects in, say, a std::vector which are stored in smart pointers? Now I'm working with std::vector<smart_pointer<some_type> >, which sort of kills any attempt at abstraction, doesn't it?

    Not sure what you're getting at. 




  • Oh boy, I should've read this thread earlier. I just spent 10 minutes laughing, as Spanish is my native language. By the way, wouldn't this be the Borland Turbo C compiler by chance??? I do remember having some major WTFs with that...


Log in to reply