/*
 *  Mine Field v1.7 by Steve Lee ® 1992,93.  All Rights Reserved.
 *
 *  This source code is released on 11-17-92 as Freeware.
 *
 *  Thanx.  Also, if you do decide to improve upon this game, please
 *  remember to include my name somewhere as the original author and
 *  please upload the new version to:
 *
 *  Key 880 (503)-524-0670 -- Epsilon World HeadQuarters
 *
 *  Thanx.  Also look for my latest online game: Global Dominance.
 *
 *  I can be reached at Usenet/Internet: link@cryo.rain.com
 *
 *           _   _   _      _ _
 *          /(  (_) /(  _  /(/(
 *         /_/  /( /  \/( / /_/
 *        / \__/ // /\  // _ \
 *        \___/\/ \/  \/ \/ \/ (Link) of Epsilon.  "Quality demos
 *                                                  from non-Euro's."
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define ESC 27
#define CR 13
#define Flag 213
#define Player 1 /* asc '1' is smiley face */

void SetColor(int, int, int);
void ClearScreen(void), Normal(void), Locate(int, int), SetColors(int, int);
void SetForeColor(int), SetBackColor(int), PrintAt(int, int, char *);
void ReadFile(char *);
int PrintMines(int, int);
void PrintScore(int);
void ShowMap(int, int), Redraw(void), ClearText(void);
int HighScore(char *,char *,int);
void MakeScores(void);
void BreakFunction(int);

int map[62][18];
int max_x = 61;
int max_y = 17;
int start_x = 3;
int start_y = 1;
int max_mines = 50;
int max_flags = 20;
char VER[10] = "1.7\0";

int main(int argc, char *argv[])
{
    char _input;
    char *FirstName = argv[1];
    char *LastName = argv[2];
    char *Ansi = "on";
    char Firstname[15];
    char Lastname[15];
    int x = 30, y = 8;
    int x2, y2;
    int score = 1;
    int a, b, i;
    int Text = 0;
    int path = 0;
    int num_mines;
    int num_flags;
    long percent = 0;
    long percent_old = -1;
    int board = 0;
    char buf[100];

    signal(SIGINT, BreakFunction);

    ERR:

    if(argc < 2)
        {
        printf("\n\r\n\r");
        SetColor(1,2,3);
        printf(" Mine Field v%s by Steve Lee ", &VER[0]);
        SetColor(1,3,0);
        printf("\n\r------------------------------");
        SetColor(0,1,0);
        printf("\n\r(C)1992, All Rights Reserved");
        SetColor(0,2,0);
        printf("\n\r\n\rSpecial thanx to Steven Frank and Ben Schaeffer");
        printf("\n\r\n\rThis program is freely distributable, but not modifiable.");
        printf("\n\r");
        SetColor(0,1,0);
        printf("\n\rUsage:");
        Normal();
        printf(" Mine_Field <FirstName> [LastName] <Color|Mono>");
        printf("\n\r\n\r FALCON users should use: Mine_Field «FULLNAME» «ANSI»«Color»«Mono»\n\r");
        SetColor(0,1,0);
        printf("\n\r       on/off refers to ANSI capabilities of the current user.");
        printf("\n\r       A CTRL-C will terminate the program at any time.");
        printf("\n\r       DO NOT send any arguments within quotes!!!");
        printf("\n\r\n\r");
        return(0);
        }

    strncpy(Ansi, argv[argc-1], 5);

    if(strncmp(Ansi, "Mono", 4) == 0)
        {
        printf("\n\r\n\rANSI required! Come back when you get a REAL term program! :)");
        printf("\n\r\n\r");
        return(0);
        }

    if(argc == 3)
        strncpy(LastName, "!\0", 2);

    srand(time(NULL));

    Beginning:

    ClearScreen();
    Normal();
    ReadFile("doors:mine/intro.ansi");
    SetColor(1,7,0);
    Locate(73,4);
    printf("%s",&VER[0]);
    Locate(49,19);
    Normal();

    Again:

    _input = getchar();

    if(_input == 'q')
        {
        Normal();
        printf("\n\rMayby next time, %s...\n\r\n\r", FirstName);
        return(0);
        }
    if(_input == 'p')
        goto New;
    if(_input == CR)
        goto New;
    if(_input == 'i')
        goto Instructions;
    if(_input == 'b')
        {
        board++;
        Locate(43,19);
        SetColor(1,6,0);
        if(board == 3)
            board = 0;
        if(board == 0)
            printf("normal        ");
        if(board == 1)
            printf("red lines     ");
        if(board == 2)
            printf("checkered blue");
        }
    goto Again;


/* begin game */

    New:

    ClearScreen();
    max_x = 61;
    max_y = 17;
    num_mines = max_mines;
    num_flags = max_flags;
    percent = 0;
    percent_old = -1;

    for(a = 0;a <= max_y;a++)
        {
        for(b = 0;b <= max_x;b++)
            {
            map[b][a] = 0;
            }
        }

    if(board == 0)
        ReadFile("doors:mine/board.0");
    if(board == 1)
        ReadFile("doors:mine/board.1");
    if(board == 2)
        ReadFile("doors:mine/board.2");
    Locate(75,12);
    SetColor(1,7,0);
    printf("%s",&VER[0]);
    Normal();

/* initialize map */

    for(b = num_mines;b != 0; b--)
        {
        Random:
        x2 = rand() % max_x + 1;
        y2 = rand() % max_y + 1;
        if(x2 == x)
            if(y2 == y)
                goto Random;
        if(x2 == max_x)
            goto Random;
        if(y2 == max_y)
            goto Random;
        if(map[x2][y2] != 0)
            goto Random;
        map[x2][y2] = 2;
        }
    a = 0;
    SetColor(1,6,0);
    for(b = 1;b <= num_flags; b++)
        {
        Random2:
        x2 = rand() % max_x + 1;
        y2 = rand() % max_y + 1;
        if(x2 == x)
            if(y2 == y)
                goto Random2;
        if(x2 == max_x)
            goto Random2;
        if(y2 == max_y)
            goto Random2;
        if(map[x2][y2] != 0)
            goto Random2;
        map[x2][y2] = 3;
        Locate(x2+3,y2+1);
        printf("%c",Flag);
        }
    max_x--;
    max_y--;
    map[x][y] = 1;

/* get keypad moves */

    Game:

    if(percent >= 10)
        {
        if(num_flags == 0)
            {
            ClearText();
            Locate(1,20);
            Normal();
            printf("Alright, here comes a new field!  Press RETURN.");
            while(_input != CR)
                {
                _input = getchar();
                }
            path = 0;
            score = score + 100;
            max_mines += 5;
            if(max_mines > 100)
                max_mines = 100;
            max_flags += 2;
            if(max_flags > 50)
                max_flags = 50;
            goto New;
            }
        }
    Locate(x+start_x,y+start_y);
    SetColor(1,2,0);
    printf("%c",Player);
    PrintScore(score);
    PrintMines(x,y);
    _input = getchar();
    Locate(x+start_x,y+start_y);
    printf(" ");

    Locate(1,20);
    percent = ((path * 100) / (max_x * max_y));
    if(percent != percent_old)
        {
        Locate(76,20);
        SetColor(1,7,0);
        printf("%ld%%", percent);
        percent_old = percent;
        }

    if(_input == 'q')
        {
        Locate(1,20);
        Normal();
        printf("Are you SURE (y/N) ? ");
        _input = getchar();
        if(_input == 'y')
            return(0);
        Locate(1,20);
        printf("                    ");
        goto Game;
        }
    if(_input == 'r')
        {
        ClearScreen();
        if(board == 0)
            ReadFile("doors:mine/board.0");
        if(board == 1)
            ReadFile("doors:mine/board.1");
        if(board == 2)
            ReadFile("doors:mine/board.2");
        Locate(75,12);
        SetColor(1,7,0);
        printf("%s",&VER[0]);
        Redraw();
        goto Game;
        }
    if(_input == '8')
        {
        y--;
        if(y == 0)
            y = 1;
        goto Check;
        }
    if(_input == '2')
        {
        y++;
        if(y == max_y+1)
            y = max_y;
        goto Check;
        }
    if(_input == '4')
        {
        x--;
        if(x == 0)
            x = 1;
        goto Check;
        }
    if(_input == '6')
        {
        x++;
        if(x == max_x+1)
            x = max_x;
        goto Check;
        }
    if(_input == '7')
        {
        x--;
        y--;
        if(x == 0)
            x = 1;
        if(y == 0)
            y = 1;
        goto Check;
        }
    if(_input == '9')
        {
        x++;
        y--;
        if(x == max_x+1)
            x = max_x;
        if(y == 0)
            y = 1;
        goto Check;
        }
    if(_input == '1')
        {
        x--;
        y++;
        if(x == 0)
            x = 1;
        if(y == max_y+1)
            y = max_y;
        goto Check;
        }
    if(_input == '3')
        {
        x++;
        y++;
        if(x == max_x+1)
            x = max_x;
        if(y == max_y+1)
            y = max_y;
        goto Check;
        }
    goto Game;

    Check:

    Locate(x+start_x,y+start_y);
    SetColor(1,2,0);
    printf("%c",Player);
    PrintMines(x,y);

    if(Text == 1)
        {
        ClearText();
        Text = 0;
        }
    if(map[x][y] == 2)
        {
        ClearText();
        Locate(1,20);
        SetColor(1,1,0);
        printf("K*A*B*O*O*M ! !  Oops, you found a landmine!\n\r");
        Normal();
        printf("\n\r%s, your final score was %d!", FirstName, score);
        goto GameOver;
        }
    if(map[x][y] == 1)
        {
        score--;
        if(score < 1)
            {
            ClearText();
            Locate(1,20);
            SetColor(1,1,0);
            printf("Sorry, but you don't have any points now!\n\r");
            goto GameOver;
            }
        goto Game;
        }
    if(map[x][y] == 3)
        {
        score = score + 25;
        num_flags--;
        Locate(1,20);
        SetColor(1,2,0);
        if(num_flags == 0)
            {
            printf("You got ALL of the flags!");
            score = score + 50;
            }
            else
            {
            printf("You got a flag!           ");
            }
        path++;
        map[x][y] = 1;
        Text = 1;
        goto Game;
        }
    map[x][y] = 1;
    i = PrintMines(x,y);
    score = score + 5 + i;
    path++;
    goto Game;

    GameOver:

    ShowMap(x,y);
    Normal();
    printf("\n\r\n\r\n\r\n\r\n\r\n\r\n\rGame Over!  Press RETURN.");

    while(_input != CR)
        {
        _input = getchar();
        }
    strncpy(&Firstname[0],FirstName,15);
    strncpy(&Lastname[0],LastName,15);
    i = HighScore(&Firstname[0],&Lastname[0],score);
    if(i == 1)
        {
        x = 30;
        y = 8;
        score = 1;
        path = 0;
        goto New;
        }
    else
        Normal();
        return(0);

    Instructions:

    ClearScreen();
    ReadFile("doors:mine/dox.1");
    Normal();
    getchar();
    ClearScreen();
    ReadFile("doors:mine/dox.2");
    Normal();
    getchar();
    goto Beginning;

}

void BreakFunction(int sign)
{
    exit(1);
}


void ClearText(void)
{
    Locate(1,20);
    Normal();
    printf("                                                ");
}

void ShowMap(int x2, int y2)
{
    int x, y,a = 0;
    SetColor(1,1,0);
    for(y = 1;y <= 16;y++)
        {
        /*
        Locate(4,y + 1);
        */
        for(x = 1;x <= 60;x++)
            {
            if(map[x][y] == 2)
                {
                if(map[x-1][y] != 2)
                    Locate(x+3,y+1);
                if(x == x2)
                    {
                    if(y == y2)
                        {
                        a = 1;
                        SetColor(1,1,4);
                        }
                    }
                if(a == 1)
                    {
                    SetColor(1,1,0);
                    a = 0;
                    }
                printf("x");
                }
            /*
            if(map[x][y] == 3)
                {
                SetColor(1,2,0);
                printf("%c", Flag);
                }
            if(map[x][y] == 0)
                {
                Normal();
                printf(" ");
                }
            if(map[x][y] == 1)
                {
                SetColor(0,0,4);
                printf(" ");
                } */
            }
        }
}

void Redraw(void)
{
    int x,y;
    SetColor(1,6,0);
    for(y = 1;y <= max_y; y++)
        {
        for(x = 1;x <= max_x; x++)
            {
            if(map[x][y] == 1)
                {
                Locate(x+start_x,y+start_y);
                printf(" ");
                }
            if(map[x][y] == 3)
                {
                Locate(x+start_x,y+start_y);
                printf("%c",Flag);
                }
            }
        }
}

int PrintMines(int x, int y)
{
    int mines = 0;

    if(map[x+1][y] == 2)
        mines++;
    if(map[x-1][y] == 2)
        mines++;
    if(map[x-1][y-1] == 2)
        mines++;
    if(map[x][y-1] == 2)
        mines++;
    if(map[x+1][y-1] == 2)
        mines++;
    if(map[x-1][y+1] == 2)
        mines++;
    if(map[x][y+1] == 2)
        mines++;
    if(map[x+1][y+1] == 2)
        mines++;
    Locate(74,3);
    SetColor(1,7,0);
    printf("%d",mines);
    return(mines);
}

void PrintScore(int score)
{
    Locate(71,6);
    if(score <= 999)
        printf(" ");
    if(score <= 99)
        printf(" ");
    if(score <= 9)
        printf(" ");
    SetColor(1,7,0);
    printf("%d ",score);
}

/* high score routine */

int HighScore(char Firstname[15], char Lastname[15], int Score)
{
    FILE *fp;
    char buffer[60];
    char firstname[10][15];
    char lastname[10][15];
    char name[10][40];
    int score[10][10];
    int i,n;
    int beat = 0;
    char c;

    if(Score < 0)
        Score = 0;
    ClearScreen();
    Open1:
    fp = fopen("doors:mine/hi.scores", "r");
    if (fp == NULL)
        {
        MakeScores();
        goto Open1;
        }
    for(n=0;n<=9;n++)
    {
        fgets(&buffer[0], 60, fp);
        sscanf(&buffer[0], "%s %s %d", &firstname[n][0], &lastname[n][0], &score[n][0]);
    }
    fclose(fp);
    for(i=0;i <= 9;i++)
    {
        if(strcmp(&Firstname[0],&firstname[i][0])==0)
            {
            if(strcmp(&Lastname[0],&lastname[i][0])==0)
                {
                if(Score <= score[i][0])
                    {
                    beat = 1;
                    goto List;
                    }
                else
                    {
                    for(n=i;n<=9;n++)
                        {
                        score[n][0] = score[n+1][0];
                        strncpy(&firstname[n][0],&firstname[n+1][0],15);
                        strncpy(&lastname[n][0],&lastname[n+1][0],15);
                        }
                    }
                }
            }
    }
    for(i=0;i <= 9;i++)
        {
        if(Score > score[i][0])
            {
            for(n=8;n>=i;n--)
                {
                    score[n+1][0] = score[n][0];
                    strncpy(&firstname[n+1][0],&firstname[n][0],15);
                    strncpy(&lastname[n+1][0],&lastname[n][0],15);
                }
            score[i][0] = Score;

            strncpy(&firstname[i][0],&Firstname[0],15);
            strncpy(&lastname[i][0],&Lastname[0],15);

            beat = 2;
            goto List;
            }
        }
    List:
    SetColor(1,1,0);
    Locate(33,0);
    printf("High Scores\n\r");
    SetColor(0,1,0);
    Locate(16,1);
    printf("---------------------------------------------");
    SetColor(1,2,4);
    Locate(16,2);
    printf("                                             ");
    Locate(16,2);
    sprintf(&name[0][0],"%s %s", &firstname[0][0], &lastname[0][0]);
    printf(" 1.  %-30s ",&name[0][0]);
    printf("%d",score[0][0]);
    for(i=1;i<=9;i++)
        {
        SetColor(0,2,0);
        if(strcmp(&Firstname[0],&firstname[i][0])==0)
            {
            if(strcmp(&Lastname[0],&lastname[i][0])==0)
                {
                SetColor(1,3,0);
                }
            }
        Locate(16,2+i);
        sprintf(&name[i][0],"%s %s", &firstname[i][0], &lastname[i][0]);
        printf("%2d.  %-30s ",i+1,&name[i][0]);
        SetColor(1,3,0);
        printf("%d",score[i][0]);
        }
    printf("\n\r\n\r");
    SetColor(1,3,0);
    if(beat == 0)
        printf("Sorry, %s, you didn't make the list.",Firstname);
    if(beat == 1)
        printf("%s, you didn't beat your old score, try again!", Firstname);
    if(beat == 2)
        printf("Alright! You made the list!");
    printf("\n\r\n\r");
    fp = fopen("doors:mine/hi.scores","w");
    for(i=0;i<=9;i++)
        {
        sprintf(&buffer[0], "%s %s %d\n", &firstname[i][0], &lastname[i][0], score[i][0]);
        fputs(&buffer[0], fp);
        }
    fclose(fp);
    SetColor(1,7,0);
    printf("Do you want to play again (y/N) ? ");
    c = getchar();
    if(c != 'y')
        {
        printf("N\n\r\n\r\n\r");
        return(0);
        }
    else
        return(1);
}

void MakeScores(void)
{
    FILE *fp;
    char buffer[60];
    int i;
    char *first = "no";
    char *last = "one";
    int score = 0;

    fp = fopen("doors:mine/hi.scores","w");
    for(i=0;i<=9;i++)
        {
        sprintf(&buffer[0], "%s %s %d\n", first, last, score);
        fputs(&buffer[0], fp);
        }
    fclose(fp);
}

/* begin doors routines */

void ClearScreen(void)
{
    printf("\xc%c[H%c[J", ESC, ESC);
}

void Locate(int Row, int Col)
{
    printf("%c[%d;%dH", ESC, Col+1, Row);
}

void PrintAt(int Row, int Col, char *Str)
{
    Locate(Row, Col);
    printf("%s", Str);
}

/* Bold = 1, Fore = 0-7, Back = 0-7 */
/* 0 = gray, 1 = red, 2 = green, 3 = yellow, 4 = blue, 5 = purple
   6 = cyan, 7 = white */
void SetColor(int Bold, int Fore, int Back)
{
    printf("%c[%d;%d;%dm", ESC, Bold, Fore + 30, Back + 40);
}

void SetForeColor(int Color)
{
    printf("%c[%dm", ESC, Color + 30);
}

void SetBackColor(int Color)
{
    printf("%c[%dm", ESC, Color + 40);
}

void SetColors(int Front, int Back)
{
    SetForeColor(Front);
    SetBackColor(Back);
}

void Normal(void)
{
    SetColor(0,7,0);
}

void ReadFile(char *filename)
{
    FILE *fp;
    char c;

    fp = fopen(filename, "r");
    if (fp != NULL)
    {
        while ((c = getc(fp)) != EOF)
        putc(c, stdout);
    }
    else
        printf("Can't open file:%s!\n", filename);

}

