Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 * static char *rcsid_arch_c = 00003 * "$Id: exp.c 11578 2009-02-23 22:02:27Z lalo $"; 00004 */ 00005 00006 /* 00007 CrossFire, A Multiplayer game for X-windows 00008 00009 Copyright (C) 2006 Mark Wedel & Crossfire Development Team 00010 Copyright (C) 1992 Frank Tore Johansen 00011 00012 This program is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 2 of the License, or 00015 (at your option) any later version. 00016 00017 This program is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with this program; if not, write to the Free Software 00024 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00025 00026 The authors can be reached via e-mail at crossfire-devel@real-time.com 00027 */ 00028 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <string.h> 00037 #include <global.h> 00038 00039 sint64 *levels; 00041 #define TRUE 1 00042 #define FALSE 0 00043 00044 static const float exp_att_mult[NROFATTACKS+2] = { 00045 0.0, /* AT_PHYSICAL */ 00046 0.0, /* AT_MAGIC */ 00047 0.0, /* AT_FIRE */ 00048 0.0, /* AT_ELECTRICITY */ 00049 0.0, /* AT_COLD */ 00050 0.0, /* AT_WATER *//*AT_CONFUSION!*/ 00051 0.4, /* AT_ACID */ 00052 1.5, /* AT_DRAIN */ 00053 0.0, /* AT_WEAPONMAGIC */ 00054 0.1, /* AT_GHOSTHIT */ 00055 0.3, /* AT_POISON */ 00056 0.2, /* AT_DISEASE */ 00057 0.3, /* AT_PARALYZE */ 00058 0.0, /* AT_TURN_UNDEAD */ 00059 0.0, /* AT_FEAR */ 00060 0.0, /* AT_CANCELLATION */ 00061 0.0, /* AT_DEPLETE */ 00062 0.0, /* AT_DEATH */ 00063 0.0, /* AT_CHAOS */ 00064 0.0 /* AT_COUNTERSPELL */ 00065 }; 00066 00067 static const float exp_prot_mult[NROFATTACKS+2] = { 00068 0.4, /* AT_PHYSICAL */ 00069 0.5, /* AT_MAGIC */ 00070 0.1, /* AT_FIRE */ 00071 0.1, /* AT_ELECTRICITY */ 00072 0.1, /* AT_COLD */ 00073 0.1, /* AT_WATER */ 00074 0.1, /* AT_ACID */ 00075 0.1, /* AT_DRAIN */ 00076 0.1, /* AT_WEAPONMAGIC */ 00077 0.1, /* AT_GHOSTHIT */ 00078 0.1, /* AT_POISON */ 00079 0.1, /* AT_DISEASE */ 00080 0.1, /* AT_PARALYZE */ 00081 0.1, /* AT_TURN_UNDEAD */ 00082 0.1, /* AT_FEAR */ 00083 0.0, /* AT_CANCELLATION */ 00084 0.0, /* AT_DEPLETE */ 00085 0.0, /* AT_DEATH */ 00086 0.0, /* AT_CHAOS */ 00087 0.0 /* AT_COUNTERSPELL */ 00088 }; 00089 00104 sint64 new_exp(const object *ob) { 00105 double att_mult, prot_mult, spec_mult; 00106 double exp; 00107 int i; 00108 long mask = 1; 00109 00110 att_mult = prot_mult = spec_mult = 1.0; 00111 for (i = 0; i < NROFATTACKS; i++) { 00112 mask = 1<<i; 00113 att_mult += (exp_att_mult[i]*((ob->attacktype&mask) != FALSE)); 00114 /* We multiply & then divide to prevent roundoffs on the floats. 00115 * the doubling is to take into account the table and resistances 00116 * are lower than they once were. 00117 */ 00118 prot_mult += (exp_prot_mult[i] * 200 * ob->resist[i]) / 100.0; 00119 } 00120 00121 if (prot_mult < 0) 00122 prot_mult = 1; 00123 00124 spec_mult += (0.3*(QUERY_FLAG(ob, FLAG_SEE_INVISIBLE) != FALSE))+ 00125 (0.5*(QUERY_FLAG(ob, FLAG_SPLITTING) != FALSE))+ 00126 (0.3*(QUERY_FLAG(ob, FLAG_HITBACK) != FALSE))+ 00127 (0.1*(QUERY_FLAG(ob, FLAG_REFL_MISSILE) != FALSE))+ 00128 (0.3*(QUERY_FLAG(ob, FLAG_REFL_SPELL) != FALSE))+ 00129 (1.0*(QUERY_FLAG(ob, FLAG_NO_MAGIC) != FALSE))+ 00130 (0.1*(QUERY_FLAG(ob, FLAG_USE_SCROLL) != FALSE))+ 00131 (0.2*(QUERY_FLAG(ob, FLAG_USE_RANGE) != FALSE))+ 00132 (0.1*(QUERY_FLAG(ob, FLAG_USE_BOW) != FALSE)); 00133 00134 exp = MAX(ob->stats.maxhp, 5); 00135 exp *= (QUERY_FLAG(ob, FLAG_CAST_SPELL) && has_ability(ob)) ? (40+MIN(ob->stats.maxsp, 80))/40 : 1; 00136 exp *= (80.0/(70.0+ob->stats.wc))*(80.0/(70.0+ob->stats.ac))*(50.0+ob->stats.dam)/50.0; 00137 exp *= att_mult*prot_mult*spec_mult; 00138 exp *= 2.0/(2.0-(MIN(FABS(ob->speed), 0.95))); 00139 exp *= (20.0+ob->stats.Con)/20.0; 00140 if (QUERY_FLAG(ob, FLAG_STAND_STILL)) 00141 exp /= 2; 00142 00143 return (sint64)exp; 00144 } 00145 00151 int has_ability(const object *ob) { 00152 object *tmp; 00153 00154 for (tmp = ob->inv; tmp != NULL; tmp = tmp->below) 00155 if (tmp->type == SPELL || tmp->type == SPELLBOOK) 00156 return TRUE; 00157 return FALSE; 00158 } 00159 00170 void init_experience(void) { 00171 char buf[MAX_BUF], *cp; 00172 int lastlevel = 0, comp; 00173 sint64 lastexp = -1, tmpexp; 00174 FILE *fp; 00175 00176 snprintf(buf, sizeof(buf), "%s/exp_table", settings.confdir); 00177 00178 if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL) { 00179 LOG(llevError, "Fatal error: could not open experience table (%s)\n", buf); 00180 exit(1); 00181 } 00182 while (fgets(buf, MAX_BUF-1, fp) != NULL) { 00183 if (buf[0] == '#') 00184 continue; 00185 00186 /* eliminate newline */ 00187 if ((cp = strrchr(buf, '\n')) != NULL) 00188 *cp = '\0'; 00189 00190 /* Skip over empty lines */ 00191 if (buf[0] == 0) 00192 continue; 00193 cp = buf; 00194 while (isspace(*cp) && *cp != 0) 00195 cp++; 00196 if (!strncasecmp(cp, "max_level", 9)) { 00197 if (settings.max_level) { 00198 LOG(llevDebug, "Got more than one max_level value from exp_table file?\n"); 00199 free(levels); 00200 } 00201 settings.max_level = atoi(cp+9); 00202 if (!settings.max_level) { 00203 LOG(llevDebug, "Got invalid max_level from exp_table file? %s\n", buf); 00204 } else { 00205 levels = calloc(settings.max_level+1, sizeof(sint64)); 00206 } 00207 } 00208 while (isdigit(*cp) && *cp != 0) { 00209 if (!settings.max_level) { 00210 LOG(llevError, "max_level is not set in exp_table file. Did you remember to update it?\n"); 00211 exit(1); 00212 } 00213 00214 tmpexp = atoll(cp); 00215 /* Do some sanity checking - if value is bogus, just exit because 00216 * the table otherwise is probably in an inconsistent state 00217 */ 00218 if (tmpexp <= lastexp) { 00219 #ifndef WIN32 00220 LOG(llevError, "Experience for level %d is lower than previous level (%lld <= %lld)\n", lastlevel+1, tmpexp, lastexp); 00221 #else 00222 LOG(llevError, "Experience for level %d is lower than previous level (%I64d <= %I64d)\n", lastlevel+1, tmpexp, lastexp); 00223 #endif 00224 exit(1); 00225 } 00226 lastlevel++; 00227 if (lastlevel > settings.max_level) { 00228 LOG(llevError, "Too many levels specified in table (%d > %d)\n", lastlevel, settings.max_level); 00229 exit(1); 00230 } 00231 levels[lastlevel] = tmpexp; 00232 lastexp = tmpexp; 00233 /* First, skip over the number we just processed. Then skip over 00234 * any spaces, commas, etc. 00235 */ 00236 while (isdigit(*cp) && *cp != 0) 00237 cp++; 00238 while (!isdigit(*cp) && *cp != 0) 00239 cp++; 00240 } 00241 } 00242 close_and_delete(fp, comp); 00243 if (settings.max_level == 0 || lastlevel != settings.max_level) { 00244 LOG(llevError, "Fatal: exp_table does not have any level definition or not %d as defined, found %d.\n", settings.max_level, lastlevel); 00245 exit(1); 00246 } 00247 if (lastlevel != settings.max_level && lastlevel != 0) { 00248 LOG(llevError, "Warning: exp_table does not have %d entries (%d)\n", settings.max_level, lastlevel); 00249 exit(1); 00250 } 00251 } 00252 00257 void dump_experience(void) { 00258 int i; 00259 00260 for (i = 1; i <= settings.max_level; i++) { 00261 fprintf(logfile, "%4d %20"FMT64"\n", i, levels[i]); 00262 } 00263 exit(0); 00264 } 00265 00269 void free_experience(void) { 00270 FREE_AND_CLEAR(levels); 00271 }