ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/exp.C
Revision: 1.16
Committed: Sun Jul 1 05:00:17 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.15: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

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