/*
 *                         C O M M A N D S . C
 *
 *  Routines for the asynchron processing of empire shell commands.
 *
 *  Version      : $Revision: 1.7 $
 *
 *  Created      : Thu May 26 22:39:48 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  Last modified: Thu Jul 14 19:49:29 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
#if !defined(lint)
static const char *vcid = "$Id: commands.c,v 1.7 1994/07/15 00:49:26 drepper Exp $";
#endif /* lint */

#include <assert.h>
#include <ctype.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

#include "empire.h"

/*
 * prototypes for local functions
 */
static Bool processBreak(Bool first, Bool last, char *str, void *data);
static Bool processNation(Bool first, Bool last, char *str, void *data);

/*
 * exported variables
 */
int charToCommArr[] = {
    ['c'] ILSEP commIdxCiv,    ['m'] ILSEP commIdxMil,
    ['u'] ILSEP commIdxUW,     ['f'] ILSEP commIdxFood,
    ['s'] ILSEP commIdxShell,  ['g'] ILSEP commIdxGun,
    ['p'] ILSEP commIdxPetrol, ['i'] ILSEP commIdxIron,
    ['d'] ILSEP commIdxDust,   ['b'] ILSEP commIdxBars,
    ['o'] ILSEP commIdxOil,    ['l'] ILSEP commIdxLcm,
    ['h'] ILSEP commIdxHcm,    ['r'] ILSEP commIdxRad
};
char commToCharArr[] = {
    [commIdxCiv]    ILSEP 'c', [commIdxMil]  ILSEP 'm',
    [commIdxUW]     ILSEP 'u', [commIdxFood] ILSEP 'f',
    [commIdxShell]  ILSEP 's', [commIdxGun]  ILSEP 'g',
    [commIdxPetrol] ILSEP 'p', [commIdxIron] ILSEP 'i',
    [commIdxDust]   ILSEP 'd', [commIdxBars] ILSEP 'b',
    [commIdxOil]    ILSEP 'o', [commIdxLcm]  ILSEP 'l',
    [commIdxHcm]    ILSEP 'h', [commIdxRad]  ILSEP 'r'
};

/*
 * exported functions
 */
Bool breakCommand(void)
{
    return sendCmdStr(processBreak, NULL, NULL, "break\n");
}

Bool
nationCommand(void)
{
    return sendCmdStr(processNation, NULL, NULL, "nation\n");
}

Bool
strToInt(char **str, int *i)
{
    char *cp;
    char save;

    /* format is { \t}*[-]{0-9}+{^0-9} */
    while (isspace(**str)) (*str)++;

    cp = *str;
    
    /* process the sign */
    if (**str == '-' || **str == '+') {
	(*str)++;
    }

    if (!isdigit(**str)) return False;
    
    while (isdigit(*++(*str)));
    
    save = **str;
    **str = '\0';

    *i = atoi(cp);

    **str = save;

    return True;
}

Bool
strToFloat(char **str, float *f)
{
    char *cp;
    char save;

    /* format is { \t}*[-]{0-9}+[.{0-9}+][{eE}{0-9}+]{^0-9} */
    while (isspace(**str)) (*str)++;

    cp = *str;
    
    /* process the sign */
    if (**str == '-' || **str == '+') {
	(*str)++;
    }

    if (!isdigit(**str)) return False;
    while (isdigit(*++(*str)));

    if (**str == '.') {
	(*str)++;
	if (!isdigit(**str)) return False;
	while (isdigit(*++(*str)));
    }

    if (**str == 'e' || **str == 'E') {
	(*str)++;
	if (**str == '-' || **str == '+') (*str)++;
	if (!isdigit(**str)) return False;
	while (isdigit(*++(*str)));
    }
    
    save = **str;
    **str = '\0';

    *f = (float)atof(cp);

    **str = save;

    return True;
}

Bool
strToCoord(char **str, int *x, int *y)
{
    return strToInt(str, x) && *(*str)++==',' && strToInt(str, y);
}

Bool
strToRange(char **str, int *x1, int *y1, int *x2, int *y2)
{
    if (!strToInt(str, x1)) return False;

    if (**str==':') {
	(*str)++;
	if (!strToInt(str, x2)) return False;
    } else {
	*x2 = *x1;
    }

    if (*(*str)++!=',') return False;

    if (!strToInt(str, y1)) return False;

    if (**str==':') {
	(*str)++;
	if (!strToInt(str, y2)) return False;
    } else {
	*y2 = *y1;
    }

    return True;
}

Bool
addDirToCoord(char **str, int *x, int *y)
{
    while (**str) {
	switch (*(*str)++) {
	case 'h':
	    return True;
	    break;
	case 'y':
	    (*x)--;
	    (*y)--;
	    break;
	case 'u':
	    (*x)++;
	    (*y)--;
	    break;
	case 'g':
	    *x -= 2;
	    break;
	case 'j':
	    *x += 2;
	break;
	case 'b':
	    (*x)--;
	    (*y)++;
	    break;
	case 'n':
	    (*x)++;
	    (*y)++;
	    break;
	case '-':
	case '0'...'9':
	    (*str)--;
	    strToCoord(str, x, y);
	    break;
	default:
	    return False;
	}
    }

    return True;
}


char *
charToSectorName(char typeChar)
{
    static struct {
	char ch;
	char *name;
    } sects[] = {
	{ ' ', "unknown" },
	{ '!', "headquarter" },
	{ '#', "bridge head" },
	{ '%', "refinery" },
	{ ')', "radar installation" },
	{ '*', "airfield" },
	{ '+', "highway" },
	{ '-', "wilderness" },
	{ '.', "sea" },
	{ '/', "wasteland" },
	{ '=', "bridge span" },
	{ '?', "unknown enemy sector" },
	{ '^', "mountain" },
	{ 'a', "agribusiness" },
	{ 'b', "bank" },
	{ 'c', "capital" },
	{ 'd', "defense plant" },
	{ 'e', "enlistment center" },
	{ 'f', "fortress" },
	{ 'g', "gold mine" },
	{ 'h', "harbor" },
	{ 'i', "shell industry" },
	{ 'j', "light manufactuaring" },
	{ 'k', "heavy manufactuaring" },
	{ 'l', "library" },
	{ 'm', "mine" },
	{ 'n', "nuclear plant" },
	{ 'o', "oil field" },
	{ 'p', "park" },
	{ 'r', "research lab" },
	{ 's', "sanctuary" },
	{ 't', "technical center" },
	{ 'u', "uranium mine" },
	{ 'w', "warehouse" } };
    int low = 0;
    int high = XtNumber(sects)-1;

    while (1) {
	int idx = low+(high-low+1)/2;
	int cmp = sects[idx].ch-typeChar;

	if (!cmp) {
	    return sects[idx].name;
	}
	assert(low != high);
	
	if (cmp < 0) {
	    low = idx+1;
	} else {
	    high = idx-1;
	}
    }
    /* NOTREACHED */
}

/*
 * local functions
 */
/* ARGSUSED */
static Bool
processBreak(Bool first, Bool last, char *str, void *data)
{
    if (last) {
	(void)dumpCommand(0, 0, 2, 0, True);
    }

    return True;
}

#define NATIONHEADERLINES 4
static Bool
processNation(Bool first, Bool last, char *str, void *data)
{
    static int lineCount = 0;
    double dbl;

    if (first) {
	lineCount = 0;
    }

    if (last) {
	redisplaySectors(mapWidget,
			 -empire.xMapSize/2, -empire.yMapSize/2,
			 empire.xMapSize/2-1, empire.yMapSize/2-1);
	XClearArea(
	    XtDisplay(contentWidget),
	    XtWindow(contentWidget),
	    0, 0, 0, 0, True);
	
	return True;
    }

    if (lineCount++ < NATIONHEADERLINES) {
	return True;
    }

    switch (lineCount) {
    case (NATIONHEADERLINES+1) ... 10:
#ifdef USE_REALM
	sscanf(str, "#%d %d:%d,%d:%d #%d %d:%d,%d:%d #%d %d:%d,%d:%d",
	       ...);
#endif /* USE_REALM */
	break;
    case 11:
	sscanf(str, " The treasury has $%lf Military reserves: %d",
	       &empire.treasury, &empire.milReserve);
	break;
    case 12:
	sscanf(str, "Education.......... %lf Happiness....... %lf",
	       &empire.education, &empire.happiness);
	break;
    case 13:
	sscanf(str, "Technology......... %lf Research........ %lf",
	       &empire.technology, &empire.research);
	break;
    case 14:
	sscanf(str, "Technology factor : %lf%% Plague factor : %lf",
	       &empire.techFactor, &empire.plagueFactor);
	break;
    case 15:
	/* empty line */
	break;
    case 16:
	sscanf(str, "Max population : %d", &empire.maxPop);
	break;
    case 17:
	sscanf(str, "Max safe population for civs/uws: %d/%d",
	       &empire.savePopNom, &empire.savePopDenom);
	break;
    case 18:
	sscanf(str, "Happiness needed is %lf", &empire.needHappy);
	break;
    }

    return True;
}

/*
 * Local Variables:
 *  mode:c
 *  c-indent-level:4
 *  c-continued-statement-offset:4
 *  c-continued-brace-offset:0
 *  c-brace-offset:0
 *  c-imaginary-offset:0
 *  c-argdecl-indent:4
 *  c-label-offset:-2
 * End:
 */
