src/main.c

Thu, 17 Apr 2014 12:16:14 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 17 Apr 2014 12:16:14 +0200
changeset 46
4dcfb4c58b6d
parent 35
6c64b7a073af
child 47
d726e4b46c33
permissions
-rw-r--r--

netcode is now aware of connection losses

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2014 Mike Becker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "terminal-chess.h"
#include "game.h"
#include "input.h"
#include "colors.h"
#include <string.h>
#include <time.h>
#include <getopt.h>

int get_settings(int argc, char **argv, Settings *settings) {
    char *valid;
    unsigned long int time, port;
    uint8_t timeunit = 60;
    size_t len;
    
    for (int opt ; (opt = getopt(argc, argv, "a:bhp:rst:")) != -1 ;) {
        switch (opt) {
        case 'b':
            settings->gameinfo.servercolor = BLACK;
            break;
        case 'r':
            settings->gameinfo.servercolor = rand() & 1 ? WHITE : BLACK;
            break;
        case 's':
            settings->singlemachine = 1;
            break;
        case 't':
        case 'a':
            len = strlen(optarg);
            if (optarg[len-1] == 's') {
                optarg[len-1] = '\0';
                timeunit = 1;
            }
            
            if ((time = strtoul(optarg, &valid, 10))*timeunit > UINT16_MAX
                || *valid != '\0') {
                fprintf(stderr, "Specified time is invalid (%s)"
                    "- Maximum: 65535 seconds (1092 minutes)\n", optarg);
                return 1;
            } else {
                settings->gameinfo.timecontrol = 1;
                if (opt=='t') {
                    settings->gameinfo.time = timeunit * time;
                } else {
                    settings->gameinfo.addtime = time;
                }
            }
            break;
        case 'p':
            port = strtol(optarg, &valid, 10);
            if (port < 1025 || port > 65535 || *valid != '\0') {
                fprintf(stderr,
                    "Invalid port number (%s) - choose a number between "
                    "1025 and 65535\n",
                    optarg);
                return 1;
            } else {
                settings->port = optarg;
            }
            break;
        case 'h':
        case '?':
            settings->printhelp = 1;
            break;
        }
    }
    
    if (optind == argc - 1) {
        settings->serverhost = argv[optind];
    } else if (optind < argc - 1) {
        fprintf(stderr, "Too many arguments\n");
        return 1;
    }
    
    return 0;
}

Settings default_settings() {
    Settings settings;
    memset(&settings, 0, sizeof(Settings));
    settings.gameinfo.servercolor = WHITE;
    settings.port = "27015";
    return settings;
}

void dump_gameinfo(GameInfo *gameinfo) {
    int serverwhite = gameinfo->servercolor == WHITE;
    attron(A_UNDERLINE);
    printw("Game details\n");
    attroff(A_UNDERLINE);
    printw("  Server:     %s\n  Client:     %s\n",
        serverwhite?"White":"Black", serverwhite?"Black":"White"
    );
    if (gameinfo->timecontrol) {
        if (gameinfo->time % 60) {
            printw("  Time limit: %ds + %ds\n",
                gameinfo->time, gameinfo->addtime);
        } else {
            printw("  Time limit: %dm + %ds\n",
                gameinfo->time/60, gameinfo->addtime);
        }
    } else {
        printw("  No time limit\n");
    }
    refresh();
}

void leavescr() {
    endwin();
}

int main(int argc, char **argv) {
    srand(time(NULL));
    
    Settings settings = default_settings();
    if (get_settings(argc, argv, &settings)) {
        return 1;
    }
    
    if (settings.printhelp) {
        printf(
            "Usage: terminal-chess [OPTION]... [HOST]\n"
            "Starts/joins a network chess game\n"
            "\nGeneral options\n"
            "  -h            This help page\n"
            "  -p            TCP port to use (default: 27015)\n"
            "\nServer options\n"
            "  -a <time>     Specifies the time to add after each move\n"
            "  -b            Server plays black pieces (default: white)\n"
            "  -r            Distribute color randomly\n"
            "  -s            Single machine mode\n"
            "  -t <time>     Specifies time limit (default: no limit)\n"
            "\nNotes\n"
            "The time unit for -a is seconds and for -t minutes by default. To "
            "specify\nseconds for the -t option, use the s suffix.\n"
            "Example: -t 150s\n"
        );
        return EXIT_SUCCESS;
    }    
    initscr();
    halfdelay(1);
    keypad(stdscr, TRUE);
    if (has_colors()) {
        start_color();
        init_colorpairs();
        bkgd(COLOR_PAIR(COL_APP));
    } else {
        fprintf(stderr, "Non-colored terminals are not supported yet.");
        endwin();
        return EXIT_FAILURE;
    }
    atexit(leavescr);
    
    int exitcode;
    if (settings.singlemachine) {
        game_start_singlemachine(&settings);
        exitcode = EXIT_SUCCESS;
    } else {
        exitcode = is_server(&settings) ?
            server_run(&settings) : client_run(&settings);
    }
    
    mvaddstr(getmaxy(stdscr)-1, 0,
        "Game has ended. Press any key to leave...");
    refresh();
    cbreak();
    flushinp();
    getch();
    
    return exitcode;
}

mercurial