News Uni Dev Res Blag

Sebbles

2010/11/19 - 13:54

Finished writing this sometime around september

sebbles.cpp

/* sebbles.cpp - nibbles clone in C++
 * Copyright (C) 2010  ed <irc.rizon.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, please refer to the following URL:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */

#include <cstdlib>   //derp
#include <stdio.h>   //I/O
#include <unistd.h>  //sleep
#include <termios.h> //linebuf
#include <string.h>  //strcpy
#include <time.h>    //rand

int dir;       //urdl
int cx, cy;    //char
int ax, ay;    //apple
char **sekai;  //map
char **mander; //worm
const int W = 86;   //width
const int H = 40;   //height
const int N = 1000; //maxlen
const int S = 5;    //startlen

void pc(char c)
{
    putc(c, stdout);
}

void set(int y, int x, char c)
{
    x *= 2;
    if (c != sekai[y][x])
    {
        sekai[y][x] = c;
        if (y != cy || x != cx)
        {
            printf("%c[%d;%dH",
                27, y+1, x+1);
        }
        pc(c);
        cx = x+1;
        cy = y;
    }
}

void clr()
{
    printf("%c[2J",   27);    //clr
    printf("%c[H",    27);    //home
    printf("%c[?%dl", 27, H); //hide
    for (int y = 1; y < H-1; y++)
    for (int x = 1; x < W-1; x++)
    sekai[y][x] = ' ';

    // Draw walls
    for (int a = 0; a < H; a++)
    {
        sekai[a][  0] = '|';
        sekai[a][W-1] = '|';
    }
    for (int a = 0; a < W; a++)
    {
        sekai[  0][a] = '-';
        sekai[H-1][a] = '-';
    }

    // Draw snake
    for (int a = 0; a < N; a++)
    {
        if (mander[a][0] >= 0)
        {
            sekai[mander[a][0]]
                 [mander[a][1]] =
                 (a==0? '@':'#');
	        }
    }
    cx = -1;
    cy = -1;
}

void echo()
{
    for (int y = 0; y < H; y++)
    {
        for (int x = 0; x < W; x++)
        {
            pc(sekai[y][x]);
            pc(' ');
        }
        pc('\n');
    }
}

void derp()
{
    clr();
    strcpy(sekai[12]+32, "G A M E   O V E R");
    echo();
}

void mkApple()
{
    while (true)
    {
        bool ok = true;
        ax = 1 + rand() % (W-2);
        ay = 1 + rand() % (H-2);
        for (int a = 0; a < N; a++)
        {
            if (mander[a][0] < 0)
            {
                break;
            }
            if (ay == mander[a][0] ||
                ax == mander[a][1])
            {
                ok = false;
                break;
            }
        }
        if (ok) break;
    }
}

bool poll()
{
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return (FD_ISSET(0, &fds));
}

int main(int argc, char **argv)
{
    srand(time(NULL));

    // DISABLE STDIN BUFFERING
    termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
    setbuf(stdin, NULL);

    // INITIATE BUFFER
    sekai = (char **)malloc(H*sizeof(int));
    for (int a = 0; a < H; a++)
    {
        sekai[a] = (char*)malloc((W+1)*sizeof(char));
    }

    // INITIALIZE MANDER
    mander = (char **)malloc(N*sizeof(char*));
    for (int a = 0; a < N; a++)
    {
        mander[a] = (char*)malloc(2*sizeof(char));
        mander[a][0] = -1; //y
        mander[a][1] = -1; //x
    }

    // START WORM
    for (int a = 0; a < S; a++)
    {
        mander[a][0] = 12;
        mander[a][1] = 15;
    }
    dir = 1;      //right
    clr();        //make
    mkApple();    //put
    echo();       //paint

    while (true)
    {
        usleep(50000);
        if (poll())
        {
            char c;
            scanf("%c",&c);
            if (c=='w' && dir != 2) dir=0;
            if (c=='s' && dir != 0) dir=2;
            if (c=='d' && dir != 3) dir=1;
            if (c=='a' && dir != 1) dir=3;
        }

        int basey = mander[0][0];
        int basex = mander[0][1];

        // Apple?
        if (basey == ay &&
            basex == ax)
        {
            mkApple();
            for (int a = 0; a < N; a++)
            {
                if (mander[a][0]<0)
                {
                    for (int b = a; b < a+3; b++)
                    {
                        mander[b][0] = mander[b-1][0];
                        mander[b][1] = mander[b-1][1];
                    }
                    break;
                }
            }
        }
        if (dir == 0) basey--;
        if (dir == 2) basey++;
        if (dir == 1) basex++;
        if (dir == 3) basex--;

        // Redraw mander
        for (int a = 0; a < N; a++)
        {
            if (mander[a][0] < 0) {
            	break;
            }
            int newy = mander[a][0];
            int newx = mander[a][1];
            mander[a][0] = basey;
            mander[a][1] = basex;
            basey = newy;
            basex = newx;
        }

        // Check for collisions (walls)
        if (mander[0][0] < 1 ||
            mander[0][1] < 1 ||
            mander[0][0] > H-2 ||
            mander[0][1] > W-2)
        {
            derp(); return 0;
        }

        // Check for collisions (self)
        if (mander[0][0] != mander[1][0] ||
            mander[0][1] != mander[1][1])
        {
            // ...if snake has extended
            for (int a = 2; a < N; a++)
            {
                if (mander[a][0] < 0) {
                    break;
                }
                if (mander[0][0] == mander[a][0] &&
                    mander[0][1] == mander[a][1])
                {
                    //derp(); return 0;
                }
            }
        }

        // Update console
        set(mander[0][0], mander[0][1], '@');
        set(mander[1][0], mander[1][1], 'O');
        set(basey, basex, ' ');
        set(ay, ax, '+');
        cy = H;
        
        printf("%c[%dH", 27, H);
        fflush(stdout);
    }

    // ECHO BUFFER
    return 0;
}

Copyright © 2010 Ed Edland