Crossfire Server, Trunk  R20513
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 */
187  if (buf[0] == 0)
188  continue;
189  cp = buf;
190  while (isspace(*cp) && *cp != 0)
191  cp++;
192  if (!strncasecmp(cp, "max_level", 9)) {
193  if (settings.max_level) {
194  LOG(llevDebug, "Got more than one max_level value from exp_table file?\n");
195  free(levels);
196  }
197  settings.max_level = atoi(cp+9);
198  if (!settings.max_level) {
199  LOG(llevDebug, "Got invalid max_level from exp_table file? %s\n", buf);
200  } else {
201  levels = calloc(settings.max_level+1, sizeof(int64_t));
202  }
203  }
204  while (isdigit(*cp) && *cp != 0) {
205  if (!settings.max_level) {
206  LOG(llevError, "max_level is not set in exp_table file. Did you remember to update it?\n");
207  exit(1);
208  }
209 
210  tmpexp = atoll(cp);
211  /* Do some sanity checking - if value is bogus, just exit because
212  * the table otherwise is probably in an inconsistent state
213  */
214  if (tmpexp <= lastexp) {
215  LOG(llevError, "Experience for level %d is lower than previous level (%"FMT64" <= %"FMT64")\n", lastlevel+1, tmpexp, lastexp);
216  exit(1);
217  }
218  lastlevel++;
219  if (lastlevel > settings.max_level) {
220  LOG(llevError, "Too many levels specified in table (%d > %d)\n", lastlevel, settings.max_level);
221  exit(1);
222  }
223  levels[lastlevel] = tmpexp;
224  lastexp = tmpexp;
225  /* First, skip over the number we just processed. Then skip over
226  * any spaces, commas, etc.
227  */
228  while (isdigit(*cp) && *cp != 0)
229  cp++;
230  while (!isdigit(*cp) && *cp != 0)
231  cp++;
232  }
233  }
234  fclose(fp);
235  if (settings.max_level == 0 || lastlevel != settings.max_level) {
236  LOG(llevError, "Fatal: exp_table does not have any level definition or not %d as defined, found %d.\n", settings.max_level, lastlevel);
237  exit(1);
238  }
239  if (lastlevel != settings.max_level && lastlevel != 0) {
240  LOG(llevError, "Warning: exp_table does not have %d entries (%d)\n", settings.max_level, lastlevel);
241  exit(1);
242  }
243 }
244 
249 void dump_experience(void) {
250  int i;
251 
252  for (i = 1; i <= settings.max_level; i++) {
253  fprintf(logfile, "%4d %20"FMT64"\n", i, levels[i]);
254  }
255  exit(0);
256 }
257 
261 void free_experience(void) {
263 }
EXTERN FILE * logfile
Used by server/daemon.c.
Definition: global.h:144
Error, serious thing.
Definition: logger.h:11
#define FLAG_NO_MAGIC
Spells (some) can&#39;t pass this object.
Definition: define.h:276
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
#define FLAG_HITBACK
Object will hit back when hit.
Definition: define.h:267
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:292
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
object * object_find_by_type(const object *who, int type)
Find object in inventory.
Definition: object.c:3903
#define FLAG_STAND_STILL
NPC will not (ever) move.
Definition: define.h:309
int has_ability(const object *ob)
Checks whether object has innate abilities (spell/spellbook in inventory).
Definition: exp.c:153
int16_t max_level
This is read out of exp_table.
Definition: global.h:300
static const float exp_prot_mult[NROFATTACKS]
Definition: exp.c:57
See Spellbook.
Definition: object.h:203
void dump_experience(void)
Dump the experience table, then calls exit() - useful in terms of debugging to make sure the format o...
Definition: exp.c:249
void init_experience(void)
This loads the experience table from the exp_table file.
Definition: exp.c:167
#define FALSE
Definition: compat.h:11
#define MAX(x, y)
Definition: compat.h:20
Global type definitions and header inclusions.
int16_t maxsp
Max spell points.
Definition: living.h:42
int8_t Con
Definition: living.h:35
#define MIN(x, y)
Definition: compat.h:17
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:253
int16_t maxhp
Max hit points.
Definition: living.h:40
#define FLAG_REFL_SPELL
Spells (some) will reflect from object.
Definition: define.h:275
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:293
#define snprintf
Definition: win32.h:46
#define FMT64
Definition: compat.h:12
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
void free_experience(void)
Frees experience-related memory.
Definition: exp.c:261
float speed
The overall speed of this object.
Definition: object.h:328
See Spell.
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:291
int strncasecmp(const char *s1, const char *s2, int n)
Case-insensitive comparaison of strings.
Definition: porting.c:224
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
const char * confdir
Configuration files.
Definition: global.h:243
signed __int64 int64_t
Definition: win32.h:168
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:341
int64_t new_exp(const object *ob)
Alternative way to calculate experience based on the ability of a monster.
Definition: exp.c:100
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:342
living stats
Str, Con, Dex, etc.
Definition: object.h:368
Only for debugging purposes.
Definition: logger.h:13
struct Settings settings
Server settings.
Definition: init.c:40
#define FLAG_SPLITTING
Object splits into stats.food other objs.
Definition: define.h:266
#define NROFATTACKS
Definition: attack.h:17
#define atoll
Definition: win32.h:170
int64_t * levels
Number of levels for which we have experience.
Definition: exp.c:26
static const float exp_att_mult[NROFATTACKS]
Definition: exp.c:28
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
#define FREE_AND_CLEAR(xyz)
Free the pointer and then set it to NULL.
Definition: global.h:203
#define FLAG_REFL_MISSILE
Arrows will reflect from object.
Definition: define.h:273
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:294