ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/exp.C
(Generate patch)

Comparing deliantra/server/common/exp.C (file contents):
Revision 1.1 by elmex, Sun Aug 13 17:16:00 2006 UTC vs.
Revision 1.10 by pippijn, Sat Jan 6 14:42:28 2007 UTC

1/*
2 * static char *rcsid_arch_c =
3 * "$Id: exp.C,v 1.1 2006/08/13 17:16:00 elmex Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
11 7
12 This program is free software; you can redistribute it and/or modify 8 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 9 it under the terms of the GNU General Public License as published by
21 17
22 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 21
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 23*/
28 24
29#include <stdio.h> 25#include <stdio.h>
30#include <global.h> 26#include <global.h>
31 27
32sint64 *levels; 28sint64 *levels;
33 29
34#define TRUE 1
35#define FALSE 0
36
37float exp_att_mult[NROFATTACKS+2] = { 30float exp_att_mult[NROFATTACKS + 2] = {
38 0.0, /* AT_PHYSICAL */ 31 0.0, /* AT_PHYSICAL */
39 0.0, /* AT_MAGIC */ 32 0.0, /* AT_MAGIC */
40 0.0, /* AT_FIRE */ 33 0.0, /* AT_FIRE */
41 0.0, /* AT_ELECTRICITY */ 34 0.0, /* AT_ELECTRICITY */
42 0.0, /* AT_COLD */ 35 0.0, /* AT_COLD */
43 0.0, /* AT_WATER *//*AT_CONFUSION!*/ 36 0.0, /* AT_WATER *//*AT_CONFUSION! */
44 0.4, /* AT_ACID */ 37 0.4, /* AT_ACID */
45 1.5, /* AT_DRAIN */ 38 1.5, /* AT_DRAIN */
46 0.0, /* AT_WEAPONMAGIC */ 39 0.0, /* AT_WEAPONMAGIC */
47 0.1, /* AT_GHOSTHIT */ 40 0.1, /* AT_GHOSTHIT */
48 0.3, /* AT_POISON */ 41 0.3, /* AT_POISON */
49 0.2, /* AT_DISEASE */ 42 0.2, /* AT_DISEASE */
50 0.3, /* AT_PARALYZE */ 43 0.3, /* AT_PARALYZE */
51 0.0, /* AT_TURN_UNDEAD */ 44 0.0, /* AT_TURN_UNDEAD */
52 0.0, /* AT_FEAR */ 45 0.0, /* AT_FEAR */
53 0.0, /* AT_CANCELLATION */ 46 0.0, /* AT_CANCELLATION */
54 0.0, /* AT_DEPLETE */ 47 0.0, /* AT_DEPLETE */
55 0.0, /* AT_DEATH */ 48 0.0, /* AT_DEATH */
56 0.0, /* AT_CHAOS */ 49 0.0, /* AT_CHAOS */
57 0.0 /* AT_COUNTERSPELL */ 50 0.0 /* AT_COUNTERSPELL */
58}; 51};
59 52
60float exp_prot_mult[NROFATTACKS+2] = { 53float exp_prot_mult[NROFATTACKS + 2] = {
61 0.4, /* AT_PHYSICAL */ 54 0.4, /* AT_PHYSICAL */
62 0.5, /* AT_MAGIC */ 55 0.5, /* AT_MAGIC */
63 0.1, /* AT_FIRE */ 56 0.1, /* AT_FIRE */
64 0.1, /* AT_ELECTRICITY */ 57 0.1, /* AT_ELECTRICITY */
65 0.1, /* AT_COLD */ 58 0.1, /* AT_COLD */
66 0.1, /* AT_WATER */ 59 0.1, /* AT_WATER */
67 0.1, /* AT_ACID */ 60 0.1, /* AT_ACID */
68 0.1, /* AT_DRAIN */ 61 0.1, /* AT_DRAIN */
69 0.1, /* AT_WEAPONMAGIC */ 62 0.1, /* AT_WEAPONMAGIC */
70 0.1, /* AT_GHOSTHIT */ 63 0.1, /* AT_GHOSTHIT */
71 0.1, /* AT_POISON */ 64 0.1, /* AT_POISON */
72 0.1, /* AT_DISEASE */ 65 0.1, /* AT_DISEASE */
73 0.1, /* AT_PARALYZE */ 66 0.1, /* AT_PARALYZE */
74 0.1, /* AT_TURN_UNDEAD */ 67 0.1, /* AT_TURN_UNDEAD */
75 0.1, /* AT_FEAR */ 68 0.1, /* AT_FEAR */
76 0.0, /* AT_CANCELLATION */ 69 0.0, /* AT_CANCELLATION */
77 0.0, /* AT_DEPLETE */ 70 0.0, /* AT_DEPLETE */
78 0.0, /* AT_DEATH */ 71 0.0, /* AT_DEATH */
79 0.0, /* AT_CHAOS */ 72 0.0, /* AT_CHAOS */
80 0.0 /* AT_COUNTERSPELL */ 73 0.0 /* AT_COUNTERSPELL */
81
82}; 74};
83 75
84/* 76/*
85 * new_exp() is an alternative way to calculate experience based 77 * new_exp() is an alternative way to calculate experience based
86 * on the ability of a monster. 78 * on the ability of a monster.
87 * It's far from perfect, and doesn't consider everything which 79 * It's far from perfect, and doesn't consider everything which
88 * can be considered, thus it's only used in debugging. 80 * can be considered, thus it's only used in debugging.
89 * this is only used with one of the dumpflags, 81 * this is only used with one of the dumpflags,
90 * and not anyplace in the code. 82 * and not anyplace in the code.
91 */ 83 */
92 84
85int
93int new_exp(const object *ob) { 86new_exp (const object *ob)
87{
94 double att_mult, prot_mult, spec_mult; 88 double att_mult, prot_mult, spec_mult;
95 double exp; 89 double exp;
96 int i; 90 int i;
97 long mask = 1; 91 long mask = 1;
98 92
99 att_mult = prot_mult =spec_mult = 1.0; 93 att_mult = prot_mult = spec_mult = 1.0;
100 for(i=0;i<NROFATTACKS;i++) { 94 for (i = 0; i < NROFATTACKS; i++)
95 {
101 mask = 1<<i; 96 mask = 1 << i;
102 att_mult += (exp_att_mult[i] * ((ob->attacktype&mask) != FALSE)); 97 att_mult += (exp_att_mult[i] * ((ob->attacktype & mask) != 0));
103 /* We multiply & then divide to prevent roundoffs on the floats. 98 /* We multiply & then divide to prevent roundoffs on the floats.
104 * the doubling is to take into account the table and resistances 99 * the doubling is to take into account the table and resistances
105 * are lower than they once were. 100 * are lower than they once were.
106 */ 101 */
107 prot_mult += (exp_prot_mult[i] * 200*ob->resist[i]) / 100.0; 102 prot_mult += (exp_prot_mult[i] * 200 * ob->resist[i]) / 100.0;
108 } 103 }
109 spec_mult += (0.3*(QUERY_FLAG(ob,FLAG_SEE_INVISIBLE)!= FALSE)) + 104 spec_mult += (0.3 * (QUERY_FLAG (ob, FLAG_SEE_INVISIBLE) != 0)) +
110 (0.5*(QUERY_FLAG(ob,FLAG_SPLITTING)!= FALSE))+ 105 (0.5 * (QUERY_FLAG (ob, FLAG_SPLITTING) != 0)) +
111 (0.3*(QUERY_FLAG(ob,FLAG_HITBACK)!= FALSE)) + 106 (0.3 * (QUERY_FLAG (ob, FLAG_HITBACK) != 0)) +
112 (0.1*(QUERY_FLAG(ob,FLAG_REFL_MISSILE)!= FALSE)) + 107 (0.1 * (QUERY_FLAG (ob, FLAG_REFL_MISSILE) != 0)) +
113 (0.3*(QUERY_FLAG(ob,FLAG_REFL_SPELL)!= FALSE)) + 108 (0.3 * (QUERY_FLAG (ob, FLAG_REFL_SPELL) != 0)) +
114 (1.0*(QUERY_FLAG(ob,FLAG_NO_MAGIC)!= FALSE)) + 109 (1.0 * (QUERY_FLAG (ob, FLAG_NO_MAGIC) != 0)) +
115 (0.1*(QUERY_FLAG(ob,FLAG_PICK_UP)!= FALSE)) + 110 (0.1 * (QUERY_FLAG (ob, FLAG_PICK_UP) != 0)) +
116 (0.1*(QUERY_FLAG(ob,FLAG_USE_SCROLL)!= FALSE)) + 111 (0.1 * (QUERY_FLAG (ob, FLAG_USE_SCROLL) != 0)) +
117 (0.2*(QUERY_FLAG(ob,FLAG_USE_RANGE)!= FALSE)) + 112 (0.2 * (QUERY_FLAG (ob, FLAG_USE_RANGE) != 0)) + (0.1 * (QUERY_FLAG (ob, FLAG_USE_BOW) != 0));
118 (0.1*(QUERY_FLAG(ob,FLAG_USE_BOW)!= FALSE));
119 113
120 exp = (ob->stats.maxhp<5) ? 5 : ob->stats.maxhp; 114 exp = (ob->stats.maxhp < 5) ? 5 : ob->stats.maxhp;
121 exp *= (QUERY_FLAG(ob,FLAG_CAST_SPELL) && has_ability(ob)) 115 exp *= (QUERY_FLAG (ob, FLAG_CAST_SPELL) && has_ability (ob)) ? (40 + (ob->stats.maxsp > 80 ? 80 : ob->stats.maxsp)) / 40 : 1;
122 ? (40+(ob->stats.maxsp>80?80:ob->stats.maxsp))/40 : 1;
123 exp *= (80.0/(70.0+ob->stats.wc)) * (80.0/(70.0+ob->stats.ac)) * (50.0+ob->stats.dam)/50.0; 116 exp *= (80.0 / (70.0 + ob->stats.wc)) * (80.0 / (70.0 + ob->stats.ac)) * (50.0 + ob->stats.dam) / 50.0;
124 exp *= att_mult * prot_mult * spec_mult; 117 exp *= att_mult * prot_mult * spec_mult;
125 exp *= 2.0/(2.0-((FABS(ob->speed)<0.95)?FABS(ob->speed):0.95)); 118 exp *= 2.0 / (2.0 - ((FABS (ob->speed) < 0.95) ? FABS (ob->speed) : 0.95));
126 exp *= (20.0+ob->stats.Con)/20.0; 119 exp *= (20.0 + ob->stats.Con) / 20.0;
127 if (QUERY_FLAG(ob, FLAG_STAND_STILL)) 120 if (QUERY_FLAG (ob, FLAG_STAND_STILL))
128 exp /= 2; 121 exp /= 2;
129 122
130 return (int) exp; 123 return (int) exp;
131} 124}
132 125
133/* 126/*
134 * Returns true if the monster specified has any innate abilities. 127 * Returns true if the monster specified has any innate abilities.
135 */ 128 */
136 129
130int
137int has_ability(const object *ob) { 131has_ability (const object *ob)
132{
138 object *tmp; 133 object *tmp;
139 134
140 for(tmp=ob->inv;tmp!=NULL;tmp=tmp->below) 135 for (tmp = ob->inv; tmp != NULL; tmp = tmp->below)
141 if(tmp->type==SPELL||tmp->type==SPELLBOOK) 136 if (tmp->type == SPELL || tmp->type == SPELLBOOK)
142 return TRUE; 137 return true;
143 return FALSE; 138 return false;
144} 139}
145 140
146/* This loads the experience table from the exp_table 141/* This loads the experience table from the exp_table
147 * file. This tends to exit on any errors, since it 142 * file. This tends to exit on any errors, since it
148 * populates the table as it goes along, so if there 143 * populates the table as it goes along, so if there
149 * are errors, the table is likely in an inconsistent 144 * are errors, the table is likely in an inconsistent
150 * state. 145 * state.
151 */ 146 */
147void
152void init_experience(void) 148init_experience (void)
153{ 149{
154 char buf[MAX_BUF], *cp; 150 char buf[MAX_BUF], *cp;
155 int lastlevel=0, comp; 151 int lastlevel = 0, comp;
156 sint64 lastexp=-1, tmpexp; 152 sint64 lastexp = -1, tmpexp;
157 FILE *fp; 153 FILE *fp;
158
159 154
155
160 sprintf(buf,"%s/exp_table",settings.confdir); 156 sprintf (buf, "%s/exp_table", settings.confdir);
161 157
162 if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) { 158 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
159 {
163 return; 160 return;
164 } 161 }
165 while (fgets(buf, MAX_BUF-1, fp) != NULL) { 162 while (fgets (buf, MAX_BUF - 1, fp) != NULL)
166 if (buf[0] == '#') continue; 163 {
164 if (buf[0] == '#')
165 continue;
167 166
168 /* eliminate newline */ 167 /* eliminate newline */
169 if ((cp=strrchr(buf,'\n'))!=NULL) *cp='\0'; 168 if ((cp = strrchr (buf, '\n')) != NULL)
169 *cp = '\0';
170 170
171 /* Skip over empty lines */ 171 /* Skip over empty lines */
172 if (buf[0] == 0) continue; 172 if (buf[0] == 0)
173 cp = buf; 173 continue;
174 cp = buf;
174 while (isspace(*cp) && *cp!=0) cp++; 175 while (isspace (*cp) && *cp != 0)
176 cp++;
175 if (!strncasecmp(cp, "max_level",9)) { 177 if (!strncasecmp (cp, "max_level", 9))
178 {
176 if (settings.max_level) { 179 if (settings.max_level)
180 {
177 LOG(llevDebug, "Got more than one max_level value from exp_table file?\n"); 181 LOG (llevDebug, "Got more than one max_level value from exp_table file?\n");
178 free(levels); 182 free (levels);
179 } 183 }
180 settings.max_level = atoi(cp+9); 184 settings.max_level = atoi (cp + 9);
181 if (!settings.max_level) { 185 if (!settings.max_level)
186 {
182 LOG(llevDebug, "Got invalid max_level from exp_table file? %s\n", buf); 187 LOG (llevDebug, "Got invalid max_level from exp_table file? %s\n", buf);
183 } else { 188 }
189 else
190 {
184 levels = (sint64 *) calloc(settings.max_level +1, sizeof(sint64)); 191 levels = (sint64 *) calloc (settings.max_level + 1, sizeof (sint64));
185 } 192 }
186 } 193 }
187 while (isdigit(*cp) && *cp!=0) { 194 while (isdigit (*cp) && *cp != 0)
195 {
188 if (!settings.max_level) { 196 if (!settings.max_level)
197 {
189 LOG(llevError, "max_level is not set in exp_table file. Did you remember to update it?\n"); 198 LOG (llevError, "max_level is not set in exp_table file. Did you remember to update it?\n");
190 exit(1); 199 exit (1);
191 } 200 }
192 201
193 tmpexp = atoll(cp); 202 tmpexp = atoll (cp);
194 /* Do some sanity checking - if value is bogus, just exit because 203 /* Do some sanity checking - if value is bogus, just exit because
195 * the table otherwise is probably in an inconsistent state 204 * the table otherwise is probably in an inconsistent state
196 */ 205 */
197 if (tmpexp <= lastexp) { 206 if (tmpexp <= lastexp)
198#ifndef WIN32 207 {
199 LOG(llevError,"Experience for level %d is lower than previous level (%lld <= %lld)\n", 208 LOG (llevError, "Experience for level %d is lower than previous level (%" PRId64 " <= %" PRId64 ")\n", lastlevel + 1, tmpexp, lastexp);
200 lastlevel + 1, tmpexp, lastexp); 209 exit (1);
201#else 210 }
202 LOG(llevError,"Experience for level %d is lower than previous level (%I64d <= %I64d)\n",
203 lastlevel + 1, tmpexp, lastexp);
204#endif
205 exit(1);
206 }
207 lastlevel++; 211 lastlevel++;
208 if (lastlevel > settings.max_level) { 212 if (lastlevel > settings.max_level)
209 LOG(llevError,"Too many levels specified in table (%d > %d)\n", 213 {
210 lastlevel, settings.max_level); 214 LOG (llevError, "Too many levels specified in table (%d > %d)\n", lastlevel, settings.max_level);
211 exit(1); 215 exit (1);
212 } 216 }
213 levels[lastlevel] = tmpexp; 217 levels[lastlevel] = tmpexp;
214 lastexp = tmpexp; 218 lastexp = tmpexp;
215 /* First, skip over the number we just processed. Then skip over 219 /* First, skip over the number we just processed. Then skip over
216 * any spaces, commas, etc. 220 * any spaces, commas, etc.
217 */ 221 */
218 while (isdigit(*cp) && *cp!=0) cp++; 222 while (isdigit (*cp) && *cp != 0)
223 cp++;
219 while (!isdigit(*cp) && *cp!=0) cp++; 224 while (!isdigit (*cp) && *cp != 0)
220 } 225 cp++;
226 }
221 } 227 }
222 close_and_delete(fp, comp); 228 close_and_delete (fp, comp);
223 if (lastlevel != settings.max_level && lastlevel != 0) { 229 if (lastlevel != settings.max_level && lastlevel != 0)
230 {
224 LOG(llevError,"Warning: exp_table does not have %d entries (%d)\n", 231 LOG (llevError, "Warning: exp_table does not have %d entries (%d)\n", settings.max_level, lastlevel);
225 settings.max_level, lastlevel); 232 exit (1);
226 exit(1);
227 } 233 }
228} 234}
229 235
230/* Dump the table - useful in terms of debugging to make sure the 236/* Dump the table - useful in terms of debugging to make sure the
231 * format of the exp_table is correct. 237 * format of the exp_table is correct.
232 */ 238 */
233 239
240void
234void dump_experience() 241dump_experience ()
235{ 242{
236 int i; 243 int i;
237 244
238 for (i=1; i<= settings.max_level; i++) { 245 for (i = 1; i <= settings.max_level; i++)
246 {
239 fprintf(logfile,"%4d %20lld\n", i, levels[i]); 247 fprintf (logfile, "%4d %20lld\n", i, (long long) levels[i]);
240 } 248 }
241 exit(0); 249 exit (0);
242} 250}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines