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.4 by root, Sun Sep 3 00:18:39 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.4 2006/09/03 00:18:39 root 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
34float exp_att_mult[NROFATTACKS+2] = { 30float exp_att_mult[NROFATTACKS + 2] = {
35 0.0, /* AT_PHYSICAL */ 31 0.0, /* AT_PHYSICAL */
36 0.0, /* AT_MAGIC */ 32 0.0, /* AT_MAGIC */
37 0.0, /* AT_FIRE */ 33 0.0, /* AT_FIRE */
38 0.0, /* AT_ELECTRICITY */ 34 0.0, /* AT_ELECTRICITY */
39 0.0, /* AT_COLD */ 35 0.0, /* AT_COLD */
40 0.0, /* AT_WATER *//*AT_CONFUSION!*/ 36 0.0, /* AT_WATER *//*AT_CONFUSION! */
41 0.4, /* AT_ACID */ 37 0.4, /* AT_ACID */
42 1.5, /* AT_DRAIN */ 38 1.5, /* AT_DRAIN */
43 0.0, /* AT_WEAPONMAGIC */ 39 0.0, /* AT_WEAPONMAGIC */
44 0.1, /* AT_GHOSTHIT */ 40 0.1, /* AT_GHOSTHIT */
45 0.3, /* AT_POISON */ 41 0.3, /* AT_POISON */
46 0.2, /* AT_DISEASE */ 42 0.2, /* AT_DISEASE */
47 0.3, /* AT_PARALYZE */ 43 0.3, /* AT_PARALYZE */
48 0.0, /* AT_TURN_UNDEAD */ 44 0.0, /* AT_TURN_UNDEAD */
49 0.0, /* AT_FEAR */ 45 0.0, /* AT_FEAR */
50 0.0, /* AT_CANCELLATION */ 46 0.0, /* AT_CANCELLATION */
51 0.0, /* AT_DEPLETE */ 47 0.0, /* AT_DEPLETE */
52 0.0, /* AT_DEATH */ 48 0.0, /* AT_DEATH */
53 0.0, /* AT_CHAOS */ 49 0.0, /* AT_CHAOS */
54 0.0 /* AT_COUNTERSPELL */ 50 0.0 /* AT_COUNTERSPELL */
55}; 51};
56 52
57float exp_prot_mult[NROFATTACKS+2] = { 53float exp_prot_mult[NROFATTACKS + 2] = {
58 0.4, /* AT_PHYSICAL */ 54 0.4, /* AT_PHYSICAL */
59 0.5, /* AT_MAGIC */ 55 0.5, /* AT_MAGIC */
60 0.1, /* AT_FIRE */ 56 0.1, /* AT_FIRE */
61 0.1, /* AT_ELECTRICITY */ 57 0.1, /* AT_ELECTRICITY */
62 0.1, /* AT_COLD */ 58 0.1, /* AT_COLD */
63 0.1, /* AT_WATER */ 59 0.1, /* AT_WATER */
64 0.1, /* AT_ACID */ 60 0.1, /* AT_ACID */
65 0.1, /* AT_DRAIN */ 61 0.1, /* AT_DRAIN */
66 0.1, /* AT_WEAPONMAGIC */ 62 0.1, /* AT_WEAPONMAGIC */
67 0.1, /* AT_GHOSTHIT */ 63 0.1, /* AT_GHOSTHIT */
68 0.1, /* AT_POISON */ 64 0.1, /* AT_POISON */
69 0.1, /* AT_DISEASE */ 65 0.1, /* AT_DISEASE */
70 0.1, /* AT_PARALYZE */ 66 0.1, /* AT_PARALYZE */
71 0.1, /* AT_TURN_UNDEAD */ 67 0.1, /* AT_TURN_UNDEAD */
72 0.1, /* AT_FEAR */ 68 0.1, /* AT_FEAR */
73 0.0, /* AT_CANCELLATION */ 69 0.0, /* AT_CANCELLATION */
74 0.0, /* AT_DEPLETE */ 70 0.0, /* AT_DEPLETE */
75 0.0, /* AT_DEATH */ 71 0.0, /* AT_DEATH */
76 0.0, /* AT_CHAOS */ 72 0.0, /* AT_CHAOS */
77 0.0 /* AT_COUNTERSPELL */ 73 0.0 /* AT_COUNTERSPELL */
78
79}; 74};
80 75
81/* 76/*
82 * new_exp() is an alternative way to calculate experience based 77 * new_exp() is an alternative way to calculate experience based
83 * on the ability of a monster. 78 * on the ability of a monster.
84 * It's far from perfect, and doesn't consider everything which 79 * It's far from perfect, and doesn't consider everything which
85 * can be considered, thus it's only used in debugging. 80 * can be considered, thus it's only used in debugging.
86 * this is only used with one of the dumpflags, 81 * this is only used with one of the dumpflags,
87 * and not anyplace in the code. 82 * and not anyplace in the code.
88 */ 83 */
89 84
85int
90int new_exp(const object *ob) { 86new_exp (const object *ob)
87{
91 double att_mult, prot_mult, spec_mult; 88 double att_mult, prot_mult, spec_mult;
92 double exp; 89 double exp;
93 int i; 90 int i;
94 long mask = 1; 91 long mask = 1;
95 92
96 att_mult = prot_mult =spec_mult = 1.0; 93 att_mult = prot_mult = spec_mult = 1.0;
97 for(i=0;i<NROFATTACKS;i++) { 94 for (i = 0; i < NROFATTACKS; i++)
95 {
98 mask = 1<<i; 96 mask = 1 << i;
99 att_mult += (exp_att_mult[i] * ((ob->attacktype&mask) != 0)); 97 att_mult += (exp_att_mult[i] * ((ob->attacktype & mask) != 0));
100 /* We multiply & then divide to prevent roundoffs on the floats. 98 /* We multiply & then divide to prevent roundoffs on the floats.
101 * the doubling is to take into account the table and resistances 99 * the doubling is to take into account the table and resistances
102 * are lower than they once were. 100 * are lower than they once were.
103 */ 101 */
104 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;
105 } 103 }
106 spec_mult += (0.3*(QUERY_FLAG(ob,FLAG_SEE_INVISIBLE)!= 0)) + 104 spec_mult += (0.3 * (QUERY_FLAG (ob, FLAG_SEE_INVISIBLE) != 0)) +
107 (0.5*(QUERY_FLAG(ob,FLAG_SPLITTING)!= 0))+ 105 (0.5 * (QUERY_FLAG (ob, FLAG_SPLITTING) != 0)) +
108 (0.3*(QUERY_FLAG(ob,FLAG_HITBACK)!= 0)) + 106 (0.3 * (QUERY_FLAG (ob, FLAG_HITBACK) != 0)) +
109 (0.1*(QUERY_FLAG(ob,FLAG_REFL_MISSILE)!= 0)) + 107 (0.1 * (QUERY_FLAG (ob, FLAG_REFL_MISSILE) != 0)) +
110 (0.3*(QUERY_FLAG(ob,FLAG_REFL_SPELL)!= 0)) + 108 (0.3 * (QUERY_FLAG (ob, FLAG_REFL_SPELL) != 0)) +
111 (1.0*(QUERY_FLAG(ob,FLAG_NO_MAGIC)!= 0)) + 109 (1.0 * (QUERY_FLAG (ob, FLAG_NO_MAGIC) != 0)) +
112 (0.1*(QUERY_FLAG(ob,FLAG_PICK_UP)!= 0)) + 110 (0.1 * (QUERY_FLAG (ob, FLAG_PICK_UP) != 0)) +
113 (0.1*(QUERY_FLAG(ob,FLAG_USE_SCROLL)!= 0)) + 111 (0.1 * (QUERY_FLAG (ob, FLAG_USE_SCROLL) != 0)) +
114 (0.2*(QUERY_FLAG(ob,FLAG_USE_RANGE)!= 0)) + 112 (0.2 * (QUERY_FLAG (ob, FLAG_USE_RANGE) != 0)) + (0.1 * (QUERY_FLAG (ob, FLAG_USE_BOW) != 0));
115 (0.1*(QUERY_FLAG(ob,FLAG_USE_BOW)!= 0));
116 113
117 exp = (ob->stats.maxhp<5) ? 5 : ob->stats.maxhp; 114 exp = (ob->stats.maxhp < 5) ? 5 : ob->stats.maxhp;
118 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;
119 ? (40+(ob->stats.maxsp>80?80:ob->stats.maxsp))/40 : 1;
120 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;
121 exp *= att_mult * prot_mult * spec_mult; 117 exp *= att_mult * prot_mult * spec_mult;
122 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));
123 exp *= (20.0+ob->stats.Con)/20.0; 119 exp *= (20.0 + ob->stats.Con) / 20.0;
124 if (QUERY_FLAG(ob, FLAG_STAND_STILL)) 120 if (QUERY_FLAG (ob, FLAG_STAND_STILL))
125 exp /= 2; 121 exp /= 2;
126 122
127 return (int) exp; 123 return (int) exp;
128} 124}
129 125
130/* 126/*
131 * Returns true if the monster specified has any innate abilities. 127 * Returns true if the monster specified has any innate abilities.
132 */ 128 */
133 129
130int
134int has_ability(const object *ob) { 131has_ability (const object *ob)
132{
135 object *tmp; 133 object *tmp;
136 134
137 for(tmp=ob->inv;tmp!=NULL;tmp=tmp->below) 135 for (tmp = ob->inv; tmp != NULL; tmp = tmp->below)
138 if(tmp->type==SPELL||tmp->type==SPELLBOOK) 136 if (tmp->type == SPELL || tmp->type == SPELLBOOK)
139 return true; 137 return true;
140 return false; 138 return false;
141} 139}
142 140
143/* This loads the experience table from the exp_table 141/* This loads the experience table from the exp_table
144 * file. This tends to exit on any errors, since it 142 * file. This tends to exit on any errors, since it
145 * populates the table as it goes along, so if there 143 * populates the table as it goes along, so if there
146 * are errors, the table is likely in an inconsistent 144 * are errors, the table is likely in an inconsistent
147 * state. 145 * state.
148 */ 146 */
147void
149void init_experience(void) 148init_experience (void)
150{ 149{
151 char buf[MAX_BUF], *cp; 150 char buf[MAX_BUF], *cp;
152 int lastlevel=0, comp; 151 int lastlevel = 0, comp;
153 sint64 lastexp=-1, tmpexp; 152 sint64 lastexp = -1, tmpexp;
154 FILE *fp; 153 FILE *fp;
155
156 154
155
157 sprintf(buf,"%s/exp_table",settings.confdir); 156 sprintf (buf, "%s/exp_table", settings.confdir);
158 157
159 if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) { 158 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
159 {
160 return; 160 return;
161 } 161 }
162 while (fgets(buf, MAX_BUF-1, fp) != NULL) { 162 while (fgets (buf, MAX_BUF - 1, fp) != NULL)
163 {
163 if (buf[0] == '#') continue; 164 if (buf[0] == '#')
165 continue;
164 166
165 /* eliminate newline */ 167 /* eliminate newline */
166 if ((cp=strrchr(buf,'\n'))!=NULL) *cp='\0'; 168 if ((cp = strrchr (buf, '\n')) != NULL)
169 *cp = '\0';
167 170
168 /* Skip over empty lines */ 171 /* Skip over empty lines */
169 if (buf[0] == 0) continue; 172 if (buf[0] == 0)
173 continue;
170 cp = buf; 174 cp = buf;
171 while (isspace(*cp) && *cp!=0) cp++; 175 while (isspace (*cp) && *cp != 0)
176 cp++;
172 if (!strncasecmp(cp, "max_level",9)) { 177 if (!strncasecmp (cp, "max_level", 9))
178 {
173 if (settings.max_level) { 179 if (settings.max_level)
180 {
174 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");
175 free(levels); 182 free (levels);
176 } 183 }
177 settings.max_level = atoi(cp+9); 184 settings.max_level = atoi (cp + 9);
178 if (!settings.max_level) { 185 if (!settings.max_level)
186 {
179 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);
188 }
180 } else { 189 else
190 {
181 levels = (sint64 *) calloc(settings.max_level +1, sizeof(sint64)); 191 levels = (sint64 *) calloc (settings.max_level + 1, sizeof (sint64));
182 } 192 }
183 } 193 }
184 while (isdigit(*cp) && *cp!=0) { 194 while (isdigit (*cp) && *cp != 0)
195 {
185 if (!settings.max_level) { 196 if (!settings.max_level)
197 {
186 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");
187 exit(1); 199 exit (1);
188 } 200 }
189 201
190 tmpexp = atoll(cp); 202 tmpexp = atoll (cp);
191 /* Do some sanity checking - if value is bogus, just exit because 203 /* Do some sanity checking - if value is bogus, just exit because
192 * the table otherwise is probably in an inconsistent state 204 * the table otherwise is probably in an inconsistent state
193 */ 205 */
194 if (tmpexp <= lastexp) { 206 if (tmpexp <= lastexp)
195#ifndef WIN32 207 {
196 LOG(llevError,"Experience for level %d is lower than previous level (%lld <= %lld)\n",
197 lastlevel + 1, tmpexp, lastexp);
198#else
199 LOG(llevError,"Experience for level %d is lower than previous level (%I64d <= %I64d)\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);
201#endif
202 exit(1); 209 exit (1);
203 } 210 }
204 lastlevel++; 211 lastlevel++;
205 if (lastlevel > settings.max_level) { 212 if (lastlevel > settings.max_level)
213 {
206 LOG(llevError,"Too many levels specified in table (%d > %d)\n", 214 LOG (llevError, "Too many levels specified in table (%d > %d)\n", lastlevel, settings.max_level);
207 lastlevel, settings.max_level);
208 exit(1); 215 exit (1);
209 } 216 }
210 levels[lastlevel] = tmpexp; 217 levels[lastlevel] = tmpexp;
211 lastexp = tmpexp; 218 lastexp = tmpexp;
212 /* First, skip over the number we just processed. Then skip over 219 /* First, skip over the number we just processed. Then skip over
213 * any spaces, commas, etc. 220 * any spaces, commas, etc.
214 */ 221 */
215 while (isdigit(*cp) && *cp!=0) cp++; 222 while (isdigit (*cp) && *cp != 0)
223 cp++;
216 while (!isdigit(*cp) && *cp!=0) cp++; 224 while (!isdigit (*cp) && *cp != 0)
225 cp++;
217 } 226 }
218 } 227 }
219 close_and_delete(fp, comp); 228 close_and_delete (fp, comp);
220 if (lastlevel != settings.max_level && lastlevel != 0) { 229 if (lastlevel != settings.max_level && lastlevel != 0)
230 {
221 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);
222 settings.max_level, lastlevel);
223 exit(1); 232 exit (1);
224 } 233 }
225} 234}
226 235
227/* 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
228 * format of the exp_table is correct. 237 * format of the exp_table is correct.
229 */ 238 */
230 239
240void
231void dump_experience() 241dump_experience ()
232{ 242{
233 int i; 243 int i;
234 244
235 for (i=1; i<= settings.max_level; i++) { 245 for (i = 1; i <= settings.max_level; i++)
246 {
236 fprintf(logfile,"%4d %20lld\n", i, (long long)levels[i]); 247 fprintf (logfile, "%4d %20lld\n", i, (long long) levels[i]);
237 } 248 }
238 exit(0); 249 exit (0);
239} 250}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines