2004-06-23 00:00:36 +02:00
|
|
|
/* vi: set ts=2:
|
|
|
|
+-------------------+
|
|
|
|
| | Christian Schlittchen <corwin@amber.kn-bremen.de>
|
|
|
|
| Eressea PBEM host | Enno Rehling <enno@eressea-pbem.de>
|
|
|
|
| (c) 1998 - 2004 | Katja Zedel <katze@felidae.kn-bremen.de>
|
|
|
|
| |
|
|
|
|
+-------------------+
|
|
|
|
|
|
|
|
This program may not be used, modified or distributed
|
|
|
|
without prior permission by the authors of Eressea.
|
|
|
|
*/
|
|
|
|
|
2003-11-10 00:36:11 +01:00
|
|
|
#include <config.h>
|
|
|
|
#include "eressea.h"
|
|
|
|
|
|
|
|
#include "order.h"
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
#include <assert.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
typedef struct locale_data {
|
|
|
|
struct order_data * short_orders[MAXKEYWORDS];
|
|
|
|
const struct locale * lang;
|
|
|
|
} locale_data;
|
|
|
|
|
|
|
|
static struct locale_data * locale_array[16];
|
2004-06-26 22:51:19 +02:00
|
|
|
static int nlocales = 0;
|
|
|
|
|
|
|
|
#undef SHORT_STRINGS
|
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
typedef struct order_data {
|
|
|
|
char * _str;
|
|
|
|
keyword_t _keyword;
|
|
|
|
int _lindex : 7;
|
|
|
|
int _refcount : 16;
|
|
|
|
} order_data;
|
|
|
|
|
|
|
|
static void
|
|
|
|
release_data(order_data * data)
|
|
|
|
{
|
|
|
|
if (data) {
|
|
|
|
if (--data->_refcount == 0) {
|
|
|
|
if (data->_str) free(data->_str);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-30 19:07:46 +02:00
|
|
|
void
|
2005-05-09 21:57:44 +02:00
|
|
|
replace_order(order * dst, const order * src)
|
2005-04-30 19:07:46 +02:00
|
|
|
{
|
2005-05-09 21:57:44 +02:00
|
|
|
release_data(dst->data);
|
|
|
|
dst->data = src->data;
|
|
|
|
++src->data->_refcount;
|
2005-04-30 19:07:46 +02:00
|
|
|
dst->_persistent = src->_persistent;
|
|
|
|
}
|
|
|
|
|
2003-11-10 00:36:11 +01:00
|
|
|
keyword_t
|
2004-06-21 18:45:27 +02:00
|
|
|
get_keyword(const order * ord)
|
2003-11-10 00:36:11 +01:00
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
if (ord==NULL) {
|
|
|
|
return NOKEYWORD;
|
|
|
|
}
|
2005-05-09 21:57:44 +02:00
|
|
|
return ord->data->_keyword;
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
char *
|
2003-11-10 00:36:11 +01:00
|
|
|
getcommand(const order * ord)
|
|
|
|
{
|
2004-06-26 22:51:19 +02:00
|
|
|
char sbuffer[DISPLAYSIZE*2];
|
|
|
|
char * str = sbuffer;
|
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
assert(ord->data->_lindex<nlocales);
|
2004-06-26 22:51:19 +02:00
|
|
|
if (ord->_persistent) *str++ = '@';
|
|
|
|
#ifdef SHORT_STRINGS
|
2005-05-09 21:57:44 +02:00
|
|
|
if (ord->data->_keyword!=NOKEYWORD) {
|
|
|
|
const struct locale * lang = locale_array[ord->data->_lindex]->lang;
|
2004-06-26 22:51:19 +02:00
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
strcpy(str, LOC(lang, keywords[ord->data->_keyword]));
|
2004-06-26 22:51:19 +02:00
|
|
|
str += strlen(str);
|
2005-05-09 21:57:44 +02:00
|
|
|
if (ord->data->_str) {
|
2004-06-26 22:51:19 +02:00
|
|
|
*str++ = ' ';
|
|
|
|
*str = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2005-05-09 21:57:44 +02:00
|
|
|
if (ord->data->_str) strcpy(str, ord->data->_str);
|
2004-06-26 22:51:19 +02:00
|
|
|
return strdup(sbuffer);
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
free_order(order * ord)
|
|
|
|
{
|
2005-05-09 21:57:44 +02:00
|
|
|
if (ord!=NULL) {
|
|
|
|
release_data(ord->data);
|
2005-04-30 19:16:17 +02:00
|
|
|
free(ord);
|
|
|
|
}
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
order *
|
2005-05-09 21:57:44 +02:00
|
|
|
copy_order(order * src)
|
2003-11-10 00:36:11 +01:00
|
|
|
{
|
2005-05-09 21:57:44 +02:00
|
|
|
if (src!=NULL) {
|
|
|
|
order * ord = (order*)malloc(sizeof(order));
|
|
|
|
ord->next = NULL;
|
|
|
|
ord->_persistent = src->_persistent;
|
|
|
|
ord->data = src->data;
|
|
|
|
++ord->data->_refcount;
|
|
|
|
return ord;
|
|
|
|
}
|
|
|
|
return NULL;
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
set_order(struct order ** destp, struct order * src)
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
if (*destp==src) return;
|
|
|
|
free_order(*destp);
|
2005-05-09 21:57:44 +02:00
|
|
|
*destp = copy_order(src);
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
free_orders(order ** olist)
|
|
|
|
{
|
|
|
|
while (*olist) {
|
|
|
|
order * ord = *olist;
|
|
|
|
*olist = ord->next;
|
2004-06-27 14:19:58 +02:00
|
|
|
ord->next = NULL;
|
2003-11-10 00:36:11 +01:00
|
|
|
free_order(ord);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
order *
|
|
|
|
parse_order(const char * s, const struct locale * lang)
|
|
|
|
{
|
2005-02-19 15:09:22 +01:00
|
|
|
while (*s && !isalnum(*(unsigned char*)s) && !ispunct(*(unsigned char*)s)) ++s;
|
2004-06-21 18:45:27 +02:00
|
|
|
if (*s==0) return NULL;
|
|
|
|
else {
|
2005-04-23 11:47:03 +02:00
|
|
|
keyword_t kwd;
|
2004-06-26 22:51:19 +02:00
|
|
|
const char * sptr;
|
2005-04-23 11:47:03 +02:00
|
|
|
order * ord = NULL;
|
|
|
|
int persistent = 0;
|
2004-06-26 22:51:19 +02:00
|
|
|
int i;
|
|
|
|
|
2005-04-23 11:47:03 +02:00
|
|
|
#ifdef AT_PERSISTENT
|
|
|
|
while (*s=='@') {
|
|
|
|
persistent = 1;
|
|
|
|
++s;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
sptr = s;
|
|
|
|
kwd = findkeyword(parse_token(&sptr), lang);
|
2005-05-09 21:57:44 +02:00
|
|
|
while (isspace(*(unsigned char*)sptr)) ++sptr;
|
2005-04-23 11:47:03 +02:00
|
|
|
|
|
|
|
/* if this is just nonsense, then we skip it. */
|
|
|
|
if (lomem) {
|
|
|
|
switch (kwd) {
|
|
|
|
case K_KOMMENTAR:
|
|
|
|
case NOKEYWORD:
|
|
|
|
return NULL;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
for (i=0;i!=nlocales;++i) {
|
2005-05-09 21:57:44 +02:00
|
|
|
if (locale_array[i]->lang==lang) break;
|
2004-06-26 22:51:19 +02:00
|
|
|
}
|
2005-05-09 21:57:44 +02:00
|
|
|
if (i==nlocales) {
|
|
|
|
locale_array[nlocales] = (locale_data*)calloc(1, sizeof(locale_data));
|
|
|
|
locale_array[nlocales]->lang = lang;
|
|
|
|
++nlocales;
|
|
|
|
}
|
|
|
|
|
|
|
|
ord = (order*)malloc(sizeof(order));
|
2005-04-23 11:47:03 +02:00
|
|
|
ord->_persistent = persistent;
|
2004-06-26 22:51:19 +02:00
|
|
|
ord->next = NULL;
|
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
if (kwd!=NOKEYWORD && *sptr == 0) {
|
|
|
|
ord->data = locale_array[i]->short_orders[kwd];
|
|
|
|
if (ord->data != NULL) {
|
|
|
|
++ord->data->_refcount;
|
2004-06-26 22:51:19 +02:00
|
|
|
}
|
2005-05-09 21:57:44 +02:00
|
|
|
} else {
|
|
|
|
ord->data = NULL;
|
2004-06-26 22:51:19 +02:00
|
|
|
}
|
2005-05-09 21:57:44 +02:00
|
|
|
|
|
|
|
if (ord->data==NULL) {
|
|
|
|
ord->data = (order_data*)malloc(sizeof(order_data));
|
|
|
|
ord->data->_lindex = (unsigned char)i;
|
|
|
|
ord->data->_str = NULL;
|
|
|
|
ord->data->_refcount = 1;
|
|
|
|
ord->data->_keyword = kwd;
|
|
|
|
if (kwd!=NOKEYWORD && *sptr == 0) {
|
|
|
|
locale_array[i]->short_orders[kwd] = ord->data;
|
|
|
|
++ord->data->_refcount;
|
|
|
|
}
|
|
|
|
#ifdef SHORT_STRINGS
|
|
|
|
if (ord->data->_keyword==NOKEYWORD) {
|
|
|
|
ord->data->_str = strdup(s);
|
|
|
|
} else {
|
|
|
|
if (*sptr) {
|
|
|
|
ord->data->_str = strdup(sptr);
|
|
|
|
}
|
|
|
|
}
|
2004-06-26 22:51:19 +02:00
|
|
|
#else
|
2005-05-09 21:57:44 +02:00
|
|
|
ord->data->_str = strdup(s);
|
2004-06-26 22:51:19 +02:00
|
|
|
#endif
|
2005-05-09 21:57:44 +02:00
|
|
|
}
|
2004-06-26 22:51:19 +02:00
|
|
|
return ord;
|
2004-06-21 18:45:27 +02:00
|
|
|
}
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
2005-05-01 13:32:24 +02:00
|
|
|
boolean
|
|
|
|
is_repeated(const order * ord)
|
|
|
|
{
|
2005-05-09 21:57:44 +02:00
|
|
|
const struct locale * lang = locale_array[ord->data->_lindex]->lang;
|
2005-05-01 13:32:24 +02:00
|
|
|
param_t param;
|
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
switch (ord->data->_keyword) {
|
2005-05-01 13:32:24 +02:00
|
|
|
case K_CAST:
|
|
|
|
case K_BUY:
|
|
|
|
case K_SELL:
|
|
|
|
case K_ROUTE:
|
|
|
|
case K_DRIVE:
|
|
|
|
case K_WORK:
|
|
|
|
case K_BESIEGE:
|
|
|
|
case K_ENTERTAIN:
|
|
|
|
case K_TAX:
|
|
|
|
case K_RESEARCH:
|
|
|
|
case K_SPY:
|
|
|
|
case K_STEAL:
|
|
|
|
case K_SABOTAGE:
|
|
|
|
case K_STUDY:
|
|
|
|
case K_TEACH:
|
|
|
|
case K_ZUECHTE:
|
|
|
|
case K_PIRACY:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
#if GROWING_TREES
|
|
|
|
case K_PFLANZE:
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case K_FOLLOW:
|
|
|
|
/* FOLLOW is only a long order if we are following a ship. */
|
|
|
|
parser_pushstate();
|
|
|
|
init_tokens(ord);
|
|
|
|
skip_token();
|
|
|
|
param = getparam(lang);
|
|
|
|
parser_popstate();
|
|
|
|
|
|
|
|
if (param == P_SHIP) return true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case K_MAKE:
|
|
|
|
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
|
|
|
|
* Arten von MACHE zaehlen aber als neue defaults und werden
|
|
|
|
* behandelt wie die anderen (deswegen kein break nach case
|
|
|
|
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
|
|
|
|
* abgespeichert). */
|
|
|
|
parser_pushstate();
|
|
|
|
init_tokens(ord); /* initialize token-parser */
|
|
|
|
skip_token();
|
|
|
|
param = getparam(lang);
|
|
|
|
parser_popstate();
|
|
|
|
|
|
|
|
if (param != P_TEMP) return true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2003-11-10 00:36:11 +01:00
|
|
|
boolean
|
2005-04-30 19:07:46 +02:00
|
|
|
is_exclusive(const order * ord)
|
2003-11-10 00:36:11 +01:00
|
|
|
{
|
2005-05-09 21:57:44 +02:00
|
|
|
const struct locale * lang = locale_array[ord->data->_lindex]->lang;
|
2005-04-30 19:07:46 +02:00
|
|
|
param_t param;
|
|
|
|
|
2005-05-09 21:57:44 +02:00
|
|
|
switch (ord->data->_keyword) {
|
2005-04-30 19:07:46 +02:00
|
|
|
case K_MOVE:
|
|
|
|
case K_WEREWOLF:
|
|
|
|
/* these should not become persistent */
|
|
|
|
case K_ROUTE:
|
|
|
|
case K_DRIVE:
|
|
|
|
case K_WORK:
|
|
|
|
case K_BESIEGE:
|
|
|
|
case K_ENTERTAIN:
|
|
|
|
case K_TAX:
|
|
|
|
case K_RESEARCH:
|
|
|
|
case K_SPY:
|
|
|
|
case K_STEAL:
|
|
|
|
case K_SABOTAGE:
|
|
|
|
case K_STUDY:
|
|
|
|
case K_TEACH:
|
|
|
|
case K_ZUECHTE:
|
|
|
|
case K_PIRACY:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
#if GROWING_TREES
|
|
|
|
case K_PFLANZE:
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case K_FOLLOW:
|
|
|
|
/* FOLLOW is only a long order if we are following a ship. */
|
|
|
|
parser_pushstate();
|
|
|
|
init_tokens(ord);
|
|
|
|
skip_token();
|
|
|
|
param = getparam(lang);
|
|
|
|
parser_popstate();
|
|
|
|
|
|
|
|
if (param == P_SHIP) return true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case K_MAKE:
|
|
|
|
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
|
|
|
|
* Arten von MACHE zaehlen aber als neue defaults und werden
|
|
|
|
* behandelt wie die anderen (deswegen kein break nach case
|
|
|
|
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
|
|
|
|
* abgespeichert). */
|
|
|
|
parser_pushstate();
|
|
|
|
init_tokens(ord); /* initialize token-parser */
|
|
|
|
skip_token();
|
|
|
|
param = getparam(lang);
|
|
|
|
parser_popstate();
|
|
|
|
|
|
|
|
if (param != P_TEMP) return true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean
|
|
|
|
is_persistent(const order * ord)
|
|
|
|
{
|
|
|
|
boolean persist = ord->_persistent!=0;
|
2005-05-09 21:57:44 +02:00
|
|
|
switch (ord->data->_keyword) {
|
2005-04-30 19:07:46 +02:00
|
|
|
case K_MOVE:
|
|
|
|
case K_WEREWOLF:
|
2004-06-26 22:51:19 +02:00
|
|
|
case NOKEYWORD:
|
2005-04-30 19:07:46 +02:00
|
|
|
/* lang, aber niemals persistent! */
|
2004-06-26 22:51:19 +02:00
|
|
|
return false;
|
2005-04-30 19:07:46 +02:00
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
case K_KOMMENTAR:
|
|
|
|
case K_LIEFERE:
|
|
|
|
return true;
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
2005-04-30 19:07:46 +02:00
|
|
|
|
2005-05-01 13:32:24 +02:00
|
|
|
return persist || is_repeated(ord);
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2004-06-26 22:51:19 +02:00
|
|
|
write_order(const order * ord, const struct locale * lang, char * buffer, size_t size)
|
2003-11-10 00:36:11 +01:00
|
|
|
{
|
2005-05-09 21:57:44 +02:00
|
|
|
if (ord==0 || ord->data->_keyword==NOKEYWORD) {
|
2004-06-23 00:00:36 +02:00
|
|
|
buffer[0]=0;
|
|
|
|
} else {
|
2004-06-26 23:03:42 +02:00
|
|
|
char * s = getcommand(ord);
|
|
|
|
strncpy(buffer, s, size);
|
2004-07-02 21:08:53 +02:00
|
|
|
free(s);
|
2004-06-23 00:00:36 +02:00
|
|
|
}
|
|
|
|
return buffer;
|
2003-11-10 00:36:11 +01:00
|
|
|
}
|