Crossfire Server, Branches 1.12  R18729
exp.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_arch_c =
3  * "$Id: exp.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <global.h>
38 
39 sint64 *levels;
41 #define TRUE 1
42 #define FALSE 0
43 
44 static const float exp_att_mult[NROFATTACKS+2] = {
45  0.0, /* AT_PHYSICAL */
46  0.0, /* AT_MAGIC */
47  0.0, /* AT_FIRE */
48  0.0, /* AT_ELECTRICITY */
49  0.0, /* AT_COLD */
50  0.0, /* AT_WATER *//*AT_CONFUSION!*/
51  0.4, /* AT_ACID */
52  1.5, /* AT_DRAIN */
53  0.0, /* AT_WEAPONMAGIC */
54  0.1, /* AT_GHOSTHIT */
55  0.3, /* AT_POISON */
56  0.2, /* AT_DISEASE */
57  0.3, /* AT_PARALYZE */
58  0.0, /* AT_TURN_UNDEAD */
59  0.0, /* AT_FEAR */
60  0.0, /* AT_CANCELLATION */
61  0.0, /* AT_DEPLETE */
62  0.0, /* AT_DEATH */
63  0.0, /* AT_CHAOS */
64  0.0 /* AT_COUNTERSPELL */
65 };
66 
67 static const float exp_prot_mult[NROFATTACKS+2] = {
68  0.4, /* AT_PHYSICAL */
69  0.5, /* AT_MAGIC */
70  0.1, /* AT_FIRE */
71  0.1, /* AT_ELECTRICITY */
72  0.1, /* AT_COLD */
73  0.1, /* AT_WATER */
74  0.1, /* AT_ACID */
75  0.1, /* AT_DRAIN */
76  0.1, /* AT_WEAPONMAGIC */
77  0.1, /* AT_GHOSTHIT */
78  0.1, /* AT_POISON */
79  0.1, /* AT_DISEASE */
80  0.1, /* AT_PARALYZE */
81  0.1, /* AT_TURN_UNDEAD */
82  0.1, /* AT_FEAR */
83  0.0, /* AT_CANCELLATION */
84  0.0, /* AT_DEPLETE */
85  0.0, /* AT_DEATH */
86  0.0, /* AT_CHAOS */
87  0.0 /* AT_COUNTERSPELL */
88 };
89 
104 sint64 new_exp(const object *ob) {
105  double att_mult, prot_mult, spec_mult;
106  double exp;
107  int i;
108  long mask = 1;
109 
110  att_mult = prot_mult = spec_mult = 1.0;
111  for (i = 0; i < NROFATTACKS; i++) {
112  mask = 1<<i;
113  att_mult += (exp_att_mult[i]*((ob->attacktype&mask) != FALSE));
114  /* We multiply & then divide to prevent roundoffs on the floats.
115  * the doubling is to take into account the table and resistances
116  * are lower than they once were.
117  */
118  prot_mult += (exp_prot_mult[i] * 200 * ob->resist[i]) / 100.0;
119  }
120 
121  if (prot_mult < 0)
122  prot_mult = 1;
123 
124  spec_mult += (0.3*(QUERY_FLAG(ob, FLAG_SEE_INVISIBLE) != FALSE))+
125  (0.5*(QUERY_FLAG(ob, FLAG_SPLITTING) != FALSE))+
126  (0.3*(QUERY_FLAG(ob, FLAG_HITBACK) != FALSE))+
127  (0.1*(QUERY_FLAG(ob, FLAG_REFL_MISSILE) != FALSE))+
128  (0.3*(QUERY_FLAG(ob, FLAG_REFL_SPELL) != FALSE))+
129  (1.0*(QUERY_FLAG(ob, FLAG_NO_MAGIC) != FALSE))+
130  (0.1*(QUERY_FLAG(ob, FLAG_USE_SCROLL) != FALSE))+
131  (0.2*(QUERY_FLAG(ob, FLAG_USE_RANGE) != FALSE))+
132  (0.1*(QUERY_FLAG(ob, FLAG_USE_BOW) != FALSE));
133 
134  exp = MAX(ob->stats.maxhp, 5);
135  exp *= (QUERY_FLAG(ob, FLAG_CAST_SPELL) && has_ability(ob)) ? (40+MIN(ob->stats.maxsp, 80))/40 : 1;
136  exp *= (80.0/(70.0+ob->stats.wc))*(80.0/(70.0+ob->stats.ac))*(50.0+ob->stats.dam)/50.0;
137  exp *= att_mult*prot_mult*spec_mult;
138  exp *= 2.0/(2.0-(MIN(FABS(ob->speed), 0.95)));
139  exp *= (20.0+ob->stats.Con)/20.0;
140  if (QUERY_FLAG(ob, FLAG_STAND_STILL))
141  exp /= 2;
142 
143  return (sint64)exp;
144 }
145 
151 int has_ability(const object *ob) {
152  object *tmp;
153 
154  for (tmp = ob->inv; tmp != NULL; tmp = tmp->below)
155  if (tmp->type == SPELL || tmp->type == SPELLBOOK)
156  return TRUE;
157  return FALSE;
158 }
159 
170 void init_experience(void) {
171  char buf[MAX_BUF], *cp;
172  int lastlevel = 0, comp;
173  sint64 lastexp = -1, tmpexp;
174  FILE *fp;
175 
176  snprintf(buf, sizeof(buf), "%s/exp_table", settings.confdir);
177 
178  if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) {
179  LOG(llevError, "Fatal error: could not open experience table (%s)\n", buf);
180  exit(1);
181  }
182  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
183  if (buf[0] == '#')
184  continue;
185 
186  /* eliminate newline */
187  if ((cp = strrchr(buf, '\n')) != NULL)
188  *cp = '\0';
189 
190  /* Skip over empty lines */
191  if (buf[0] == 0)
192  continue;
193  cp = buf;
194  while (isspace(*cp) && *cp != 0)
195  cp++;
196  if (!strncasecmp(cp, "max_level", 9)) {
197  if (settings.max_level) {
198  LOG(llevDebug, "Got more than one max_level value from exp_table file?\n");
199  free(levels);
200  }
201  settings.max_level = atoi(cp+9);
202  if (!settings.max_level) {
203  LOG(llevDebug, "Got invalid max_level from exp_table file? %s\n", buf);
204  } else {
205  levels = calloc(settings.max_level+1, sizeof(sint64));
206  }
207  }
208  while (isdigit(*cp) && *cp != 0) {
209  if (!settings.max_level) {
210  LOG(llevError, "max_level is not set in exp_table file. Did you remember to update it?\n");
211  exit(1);
212  }
213 
214  tmpexp = atoll(cp);
215  /* Do some sanity checking - if value is bogus, just exit because
216  * the table otherwise is probably in an inconsistent state
217  */
218  if (tmpexp <= lastexp) {
219 #ifndef WIN32
220  LOG(llevError, "Experience for level %d is lower than previous level (%lld <= %lld)\n", lastlevel+1, tmpexp, lastexp);
221 #else
222  LOG(llevError, "Experience for level %d is lower than previous level (%I64d <= %I64d)\n", lastlevel+1, tmpexp, lastexp);
223 #endif
224  exit(1);
225  }
226  lastlevel++;
227  if (lastlevel > settings.max_level) {
228  LOG(llevError, "Too many levels specified in table (%d > %d)\n", lastlevel, settings.max_level);
229  exit(1);
230  }
231  levels[lastlevel] = tmpexp;
232  lastexp = tmpexp;
233  /* First, skip over the number we just processed. Then skip over
234  * any spaces, commas, etc.
235  */
236  while (isdigit(*cp) && *cp != 0)
237  cp++;
238  while (!isdigit(*cp) && *cp != 0)
239  cp++;
240  }
241  }
242  close_and_delete(fp, comp);
243  if (settings.max_level == 0 || lastlevel != settings.max_level) {
244  LOG(llevError, "Fatal: exp_table does not have any level definition or not %d as defined, found %d.\n", settings.max_level, lastlevel);
245  exit(1);
246  }
247  if (lastlevel != settings.max_level && lastlevel != 0) {
248  LOG(llevError, "Warning: exp_table does not have %d entries (%d)\n", settings.max_level, lastlevel);
249  exit(1);
250  }
251 }
252 
257 void dump_experience(void) {
258  int i;
259 
260  for (i = 1; i <= settings.max_level; i++) {
261  fprintf(logfile, "%4d %20"FMT64"\n", i, levels[i]);
262  }
263  exit(0);
264 }
265 
269 void free_experience(void) {
271 }
EXTERN FILE * logfile
Definition: global.h:220
#define FLAG_NO_MAGIC
Definition: define.h:572
sint8 ac
Definition: living.h:79
#define FALSE
Definition: exp.c:42
#define FLAG_HITBACK
Definition: define.h:563
#define FLAG_USE_SCROLL
Definition: define.h:588
#define FABS(x)
Definition: define.h:61
#define FLAG_STAND_STILL
Definition: define.h:605
int has_ability(const object *ob)
Definition: exp.c:151
sint16 max_level
Definition: global.h:391
sint64 * levels
Definition: exp.c:39
#define FLAG_SPLITTING
Definition: define.h:562
void close_and_delete(FILE *fp, int compressed)
Definition: porting.c:748
void dump_experience(void)
Definition: exp.c:257
void init_experience(void)
Definition: exp.c:170
sint16 maxsp
Definition: living.h:84
sint8 Con
Definition: living.h:78
#define FLAG_SEE_INVISIBLE
Definition: define.h:549
sint16 maxhp
Definition: living.h:82
#define FLAG_REFL_SPELL
Definition: define.h:571
sint16 dam
Definition: living.h:87
#define SPELL
Definition: define.h:283
struct obj * below
Definition: object.h:145
#define TRUE
Definition: exp.c:41
void free_experience(void)
Definition: exp.c:269
#define MAX(x, y)
Definition: define.h:70
sint64 new_exp(const object *ob)
Definition: exp.c:104
float speed
Definition: object.h:181
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define MAX_BUF
Definition: define.h:81
#define FLAG_CAST_SPELL
Definition: define.h:587
int strncasecmp(const char *s1, const char *s2, int n)
Definition: porting.c:402
sint8 wc
Definition: living.h:79
const char * confdir
Definition: global.h:333
#define MIN(x, y)
Definition: define.h:67
sint16 resist[NROFATTACKS]
Definition: object.h:192
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
uint32 attacktype
Definition: object.h:193
living stats
Definition: object.h:219
struct Settings settings
Definition: init.c:48
#define NROFATTACKS
Definition: attack.h:45
static const float exp_att_mult[NROFATTACKS+2]
Definition: exp.c:44
struct obj * inv
Definition: object.h:148
#define SPELLBOOK
Definition: define.h:266
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
#define FLAG_USE_RANGE
Definition: define.h:589
#define FREE_AND_CLEAR(xyz)
Definition: global.h:282
#define FLAG_REFL_MISSILE
Definition: define.h:569
FILE * open_and_uncompress(const char *name, int flag, int *compressed)
Definition: porting.c:724
#define FLAG_USE_BOW
Definition: define.h:590
uint8 type
Definition: object.h:189
static const float exp_prot_mult[NROFATTACKS+2]
Definition: exp.c:67