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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines