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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines