Crossfire Server, Trunk  R21466
exp.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
28 static const float exp_att_mult[NROFATTACKS] = {
29  0.0, /* AT_PHYSICAL */
30  0.0, /* AT_MAGIC */
31  0.0, /* AT_FIRE */
32  0.0, /* AT_ELECTRICITY */
33  0.0, /* AT_COLD */
34  0.0, /* AT_CONFUSION */
35  0.4, /* AT_ACID */
36  1.5, /* AT_DRAIN */
37  0.0, /* AT_WEAPONMAGIC */
38  0.1, /* AT_GHOSTHIT */
39  0.3, /* AT_POISON */
40  0.1, /* AT_SLOW */
41  0.3, /* AT_PARALYZE */
42  0.0, /* AT_TURN_UNDEAD */
43  0.0, /* AT_FEAR */
44  0.0, /* AT_CANCELLATION */
45  0.0, /* AT_DEPLETE */
46  0.0, /* AT_DEATH */
47  0.0, /* AT_CHAOS */
48  0.0, /* AT_COUNTERSPELL */
49  0.5, /* AT_GODPOWER */
50  0.1, /* AT_HOLYWORD */
51  0.2, /* AT_BLIND */
52  0.0, /* AT_INTERNAL */
53  0.5, /* AT_LIFE_STEALING */
54  0.2, /* AT_DISEASE */
55 };
56 
57 static const float exp_prot_mult[NROFATTACKS] = {
58  0.4, /* AT_PHYSICAL */
59  0.5, /* AT_MAGIC */
60  0.1, /* AT_FIRE */
61  0.1, /* AT_ELECTRICITY */
62  0.1, /* AT_COLD */
63  0.1, /* AT_CONFUSION */
64  0.1, /* AT_ACID */
65  0.1, /* AT_DRAIN */
66  0.1, /* AT_WEAPONMAGIC */
67  0.1, /* AT_GHOSTHIT */
68  0.1, /* AT_POISON */
69  0.0, /* AT_SLOW */
70  0.1, /* AT_PARALYZE */
71  0.1, /* AT_TURN_UNDEAD */
72  0.1, /* AT_FEAR */
73  0.0, /* AT_CANCELLATION */
74  0.0, /* AT_DEPLETE */
75  0.0, /* AT_DEATH */
76  0.0, /* AT_CHAOS */
77  0.0, /* AT_COUNTERSPELL */
78  0.0, /* AT_GODPOWER */
79  0.1, /* AT_HOLYWORD */
80  0.0, /* AT_BLIND */
81  0.0, /* AT_INTERNAL */
82  0.0, /* AT_LIFE_STEALING */
83  0.1, /* AT_DISEASE */
84 };
85 
100 int64_t new_exp(const object *ob) {
101  double att_mult, prot_mult, spec_mult;
102  double exp;
103  int i;
104  long mask = 1;
105 
106  att_mult = prot_mult = spec_mult = 1.0;
107  for (i = 0; i < NROFATTACKS; i++) {
108  mask = 1<<i;
109  att_mult += (exp_att_mult[i]*((ob->attacktype&mask) != FALSE));
110  /* We multiply & then divide to prevent roundoffs on the floats.
111  * the doubling is to take into account the table and resistances
112  * are lower than they once were.
113  */
114  /* prot_mult should increase by fairly minor amounts -
115  * for example, if a creature has resist physical 30,
116  * and exp mult on that is 0.4, then prot_mult should really
117  * go up by 1.2 - still a considerable increase.
118  */
119  prot_mult += (exp_prot_mult[i]*ob->resist[i])/10.0;
120  }
121 
122  if (prot_mult < 0)
123  prot_mult = 1;
124 
125  spec_mult += (0.3*(QUERY_FLAG(ob, FLAG_SEE_INVISIBLE) != FALSE))+
126  (0.5*(QUERY_FLAG(ob, FLAG_SPLITTING) != FALSE))+
127  (0.3*(QUERY_FLAG(ob, FLAG_HITBACK) != FALSE))+
128  (0.1*(QUERY_FLAG(ob, FLAG_REFL_MISSILE) != FALSE))+
129  (0.3*(QUERY_FLAG(ob, FLAG_REFL_SPELL) != FALSE))+
130  (1.0*(QUERY_FLAG(ob, FLAG_NO_MAGIC) != FALSE))+
131  (0.1*(QUERY_FLAG(ob, FLAG_USE_SCROLL) != FALSE))+
132  (0.2*(QUERY_FLAG(ob, FLAG_USE_RANGE) != FALSE))+
133  (0.1*(QUERY_FLAG(ob, FLAG_USE_BOW) != FALSE));
134 
135  exp = MAX(ob->stats.maxhp, 5);
136  exp *= (QUERY_FLAG(ob, FLAG_CAST_SPELL) && has_ability(ob)) ? (40+MIN(ob->stats.maxsp, 80))/40 : 1;
137  exp *= (80.0/(70.0+ob->stats.wc))*(80.0/(70.0+ob->stats.ac))*(50.0+ob->stats.dam)/50.0;
138  exp *= att_mult*prot_mult*spec_mult;
139 /* exp *= 2.0/(2.0-(MIN(FABS(ob->speed), 0.95)));*/
140  exp *= 2.0/(2.0-FABS(ob->speed));
141  exp *= (20.0+ob->stats.Con)/20.0;
142  if (QUERY_FLAG(ob, FLAG_STAND_STILL))
143  exp /= 2;
144 
145  return (int64_t)exp;
146 }
147 
153 int has_ability(const object *ob) {
154  return object_find_by_type(ob, SPELL) != NULL || object_find_by_type(ob, SPELLBOOK) != NULL;
155 }
156 
167 void init_experience(void) {
168  char buf[MAX_BUF], *cp;
169  int lastlevel = 0;
170  int64_t lastexp = -1, tmpexp;
171  FILE *fp;
172 
173  snprintf(buf, sizeof(buf), "%s/exp_table", settings.confdir);
174  if ((fp = fopen(buf, "r")) == NULL) {
175  LOG(llevError, "Fatal error: could not open experience table (%s)\n", buf);
176  exit(1);
177  }
178  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
179  if (buf[0] == '#')
180  continue;
181 
182  /* eliminate newline */
183  if ((cp = strrchr(buf, '\n')) != NULL)
184  *cp = '\0';
185 
186  /* Skip over empty lines and whitespace */
187  cp = buf;
188  while (isspace(*cp) && *cp != 0)
189  cp++;
190  if ( *cp == 0 ) continue;
191 
192  /* Set max_level */
193  if (!strncasecmp(cp, "max_level", 9)) {
194  if (settings.max_level) {
195  LOG(llevDebug, "Got more than one max_level value from exp_table file?\n");
196  free(levels);
197  }
198  settings.max_level = atoi(cp+9);
199  if (!settings.max_level) {
200  LOG(llevDebug, "Got invalid max_level from exp_table file? %s\n", buf);
201  } else {
202  levels = calloc(settings.max_level+1, sizeof(int64_t));
203  }
204  }
205  while (isdigit(*cp) && *cp != 0) {
206  if (!settings.max_level) {
207  LOG(llevError, "max_level is not set in exp_table file. Did you remember to update it?\n");
208  exit(1);
209  }
210 
211  tmpexp = atoll(cp);
212  /* Do some sanity checking - if value is bogus, just exit because
213  * the table otherwise is probably in an inconsistent state
214  */
215  if (tmpexp <= lastexp) {
216  LOG(llevError, "Experience for level %d is lower than previous level (%"FMT64" <= %"FMT64")\n", lastlevel+1, tmpexp, lastexp);
217  exit(1);
218  }
219  lastlevel++;
220  if (lastlevel > settings.max_level) {
221  LOG(llevError, "Too many levels specified in table (%d > %d)\n", lastlevel, settings.max_level);
222  exit(1);
223  }
224  levels[lastlevel] = tmpexp;
225  lastexp = tmpexp;
226  /* First, skip over the number we just processed. Then skip over
227  * any spaces, commas, etc.
228  */
229  while (isdigit(*cp) && *cp != 0)
230  cp++;
231  while (!isdigit(*cp) && *cp != 0)
232  cp++;
233  }
234  }
235  fclose(fp);
236  if (settings.max_level == 0 || lastlevel != settings.max_level) {
237  LOG(llevError, "Fatal: exp_table does not have any level definition or not %d as defined, found %d.\n", settings.max_level, lastlevel);
238  exit(1);
239  }
240  if (lastlevel != settings.max_level && lastlevel != 0) {
241  LOG(llevError, "Warning: exp_table does not have %d entries (%d)\n", settings.max_level, lastlevel);
242  exit(1);
243  }
244 }
245 
250 void dump_experience(void) {
251  int i;
252 
253  for (i = 1; i <= settings.max_level; i++) {
254  fprintf(logfile, "%4d %20"FMT64"\n", i, levels[i]);
255  }
256  exit(0);
257 }
258 
262 void free_experience(void) {
264 }
EXTERN FILE * logfile
Definition: global.h:142
#define FLAG_NO_MAGIC
Definition: define.h:276
int8_t ac
Definition: living.h:38
#define FLAG_HITBACK
Definition: define.h:267
#define FLAG_USE_SCROLL
Definition: define.h:292
#define FABS(x)
Definition: define.h:22
object * object_find_by_type(const object *who, int type)
Definition: object.c:3924
#define FLAG_STAND_STILL
Definition: define.h:309
int has_ability(const object *ob)
Definition: exp.c:153
int16_t max_level
Definition: global.h:305
static const float exp_prot_mult[NROFATTACKS]
Definition: exp.c:57
void dump_experience(void)
Definition: exp.c:250
void init_experience(void)
Definition: exp.c:167
#define FALSE
Definition: compat.h:11
#define MAX(x, y)
Definition: compat.h:20
int16_t maxsp
Definition: living.h:43
int8_t Con
Definition: living.h:36
#define MIN(x, y)
Definition: compat.h:17
#define FLAG_SEE_INVISIBLE
Definition: define.h:253
int16_t maxhp
Definition: living.h:41
#define FLAG_REFL_SPELL
Definition: define.h:275
#define FLAG_USE_RANGE
Definition: define.h:293
#define snprintf
Definition: win32.h:46
#define FMT64
Definition: compat.h:12
int16_t dam
Definition: living.h:46
void free_experience(void)
Definition: exp.c:262
float speed
Definition: object.h:328
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define MAX_BUF
Definition: define.h:35
#define FLAG_CAST_SPELL
Definition: define.h:291
int strncasecmp(const char *s1, const char *s2, int n)
Definition: porting.c:224
int8_t wc
Definition: living.h:37
const char * confdir
Definition: global.h:247
signed __int64 int64_t
Definition: win32.h:168
int16_t resist[NROFATTACKS]
Definition: object.h:342
int64_t new_exp(const object *ob)
Definition: exp.c:100
uint32_t attacktype
Definition: object.h:343
living stats
Definition: object.h:369
struct Settings settings
Definition: init.c:39
#define FLAG_SPLITTING
Definition: define.h:266
#define NROFATTACKS
Definition: attack.h:17
#define atoll
Definition: win32.h:170
int64_t * levels
Definition: exp.c:26
static const float exp_att_mult[NROFATTACKS]
Definition: exp.c:28
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
#define FREE_AND_CLEAR(xyz)
Definition: global.h:201
#define FLAG_REFL_MISSILE
Definition: define.h:273
#define FLAG_USE_BOW
Definition: define.h:294