Das Thilo Gross System

This commit is contained in:
Enno Rehling 2002-02-23 16:18:26 +00:00
parent a7acaff1c4
commit 9067a238cc
7 changed files with 158 additions and 108 deletions

View File

@ -247,11 +247,8 @@ change_level(unit * u, skill_t sk, int bylevel)
{ {
skill * sv = get_skill(u, sk); skill * sv = get_skill(u, sk);
assert(bylevel>0); assert(bylevel>0);
if (sv==0) set_skill(u, sk, bylevel, 0, false); if (sv==0) sv = add_skill(u, sk);
else { sk_set(sv, sv->level+bylevel);
sv->level = (unsigned char)(sv->level+bylevel);
sv->learning = 0;
}
} }
#endif #endif

View File

@ -1468,18 +1468,25 @@ readgame(boolean backup)
if (global.data_version<NEWSKILL_VERSION) { if (global.data_version<NEWSKILL_VERSION) {
/* convert old data */ /* convert old data */
while ((sk = (skill_t) ri(F)) != NOSKILL) { while ((sk = (skill_t) ri(F)) != NOSKILL) {
int skill = ri(F) / u->number; int days = ri(F) / u->number;
int lvl = level(skill); int lvl = level(days);
int weeks = (skill - level_days(lvl))/30; int weeks = lvl + 1 - (days - level_days(lvl))/30;
if (weeks || lvl) { assert(weeks>0 && weeks<=lvl+1);
set_skill(u, sk, lvl, 2*weeks, true); if (lvl) {
skill * sv = add_skill(u, sk);
sv->level = (unsigned char)lvl;
sv->weeks = (unsigned char)weeks;
} }
} }
} else { } else {
while ((sk = (skill_t) ri(F)) != NOSKILL) { while ((sk = (skill_t) ri(F)) != NOSKILL) {
int level = ri(F); int level = ri(F);
int weeks = ri(F); int weeks = ri(F);
set_skill(u, sk, level, weeks, true); if (level) {
skill * sv = add_skill(u, sk);
sv->level = (unsigned char)level;
sv->weeks = (unsigned char)weeks;
}
} }
} }
#endif #endif
@ -2069,11 +2076,11 @@ writegame(char *path, char quiet)
#else #else
for (i=0;i!=u->skill_size;++i) { for (i=0;i!=u->skill_size;++i) {
skill * sv = u->skills+i; skill * sv = u->skills+i;
assert(sv->level>=0 && sv->learning>=0 && sv->learning<=sv->level*2); assert(sv->level>=0 && sv->weeks>=0 && sv->weeks<=sv->level*2);
if (sv->learning || sv->level) { if (sv->level>0) {
wi(F, sv->id); wi(F, sv->id);
wi(F, sv->level); wi(F, sv->level);
wi(F, sv->learning); wi(F, sv->weeks);
} }
} }
#endif #endif

View File

@ -34,6 +34,7 @@
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
#include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -257,46 +258,86 @@ level(int days)
} }
#if !SKILLPOINTS #if !SKILLPOINTS
void
reduce_skill(unit *u, skill * sv, int change) /*
#define MAXLEVEL 32
static struct {
int permutations;
int * chances;
} upgrade[MAXLEVEL];
static double
fak(int n)
{ {
if (sv->learning>=change) { int i;
/* just forget a few weeks */ double f=1;
sv->learning = (unsigned char)(sv->learning-change); for (i=2;i<n;++i) f=f*i;
} else { return f;
}
void
sk_set(skill * sv, int level)
{
double i;
int weeks; int weeks;
unsigned char oldlevel = sv->level; int multi=1+(level/16);
attrib *a; if (upgrade[level].permutations==0) {
int m;
change -= sv->learning; int ctr = 1;
while (change>=sv->level && sv->level > 0) { int n = level * 2 / multi;
change -= sv->level; upgrade[level].permutations = 1 << n;
--sv->level; if (n>0) upgrade[level].chances = malloc(sizeof(double)*n);
for (m=0;m!=n;++m) {
upgrade[level].chances[m] = (int)(fak(n)/(fak(m)*fak(n-m)));
ctr += upgrade[level].chances[m];
}
assert(ctr==upgrade[level].permutations);
}
i = rand() % upgrade[level].permutations;
for (weeks=0;weeks!=level*2/multi;++weeks) {
if (i<=upgrade[level].chances[weeks]) break;
else i-=upgrade[level].chances[weeks];
}
weeks*=multi;
sv->weeks = (unsigned char)(weeks+1);
sv->level = (unsigned char)level;
} }
if (change && sv->level > 0 && change<sv->level) {
/* this is not an exact science... it would be better to set
* sv->learning so that the average time to rise was = change.
*/ */
--sv->level;
weeks = (sv->level-change)*2;
} else {
weeks = 0;
}
sv->learning = (unsigned char)weeks;
for(a = a_find(u->attribs, &at_showskchange);a;a = a->nexttype) { void
if(a->data.sa[0] == sv->id) { sk_set(skill * sv, int level)
a->data.sa[1] = (short)(a->data.sa[1] + (sv->level-oldlevel)); {
break; sv->weeks = (unsigned char)skill_weeks(level);
sv->level = (unsigned char)level;
} }
int
skill_weeks(int level)
/* how many weeks must i study to get from level to level+1 */
{
/* derzeit gleichverteilt. MUSS geändert werden! */
return (1+rand()%(level*2+1));
} }
if(a == NULL) {
a = a_add(&u->attribs, a_new(&at_showskchange)); void
a->data.sa[0] = sv->id; reduce_skill(unit *u, skill * sv, int weeks)
a->data.sa[1] = (short)(sv->level-oldlevel); {
boolean reroll = false;
while (sv->level>0 && weeks>sv->level) {
weeks -= sv->level;
--sv->level;
} }
if (sv->level*2+1<sv->weeks) reroll = true;
if (sv->level>0) {
if (rand()%sv->level < weeks) {
--sv->level;
reroll = true;
} }
assert(sv->level>=0 && sv->learning>=0 && sv->learning<=sv->level*2); } else {
reroll = true;
}
if (reroll) sv->weeks = (unsigned char)skill_weeks(sv->level);
assert(sv->level>=0 && sv->weeks>=0 && sv->weeks<=sv->level*2);
} }
int int
@ -304,8 +345,8 @@ skill_compare(const skill * sk, const skill * sc)
{ {
if (sk->level > sc->level) return 1; if (sk->level > sc->level) return 1;
if (sk->level < sc->level) return -1; if (sk->level < sc->level) return -1;
if (sk->learning > sc->learning) return 1; if (sk->weeks < sc->weeks) return 1;
if (sk->learning < sc->learning) return -1; if (sk->weeks > sc->weeks) return -1;
return 0; return 0;
} }
#endif #endif

View File

@ -29,7 +29,7 @@ typedef struct skill {
#else #else
unsigned char id; unsigned char id;
unsigned char level; unsigned char level;
unsigned char learning; unsigned char weeks;
#endif #endif
} skill; } skill;
@ -58,7 +58,10 @@ extern int level(int days);
#else #else
# define skill_level(level) (level) # define skill_level(level) (level)
extern void reduce_skill(struct unit *u, skill * sv, int change); extern void reduce_skill(struct unit *u, skill * sv, int change);
extern int skill_weeks(int level);
extern int skill_compare(const skill * sk, const skill * sc); extern int skill_compare(const skill * sk, const skill * sc);
extern void sk_set(skill * sv, int level);
#endif #endif

View File

@ -150,7 +150,7 @@ do_shock(unit *u, char *reason)
#else #else
for (i=0;i!=u->skill_size;++i) if (rand()%5==0) { for (i=0;i!=u->skill_size;++i) if (rand()%5==0) {
skill * sv = u->skills+i; skill * sv = u->skills+i;
int weeks = (sv->level * sv->level - sv->level) / 2 + sv->learning; int weeks = (sv->level * sv->level - sv->level) / 2;
int change = (weeks+9) / 10; int change = (weeks+9) / 10;
reduce_skill(u, sv, change); reduce_skill(u, sv, change);
} }

View File

@ -523,12 +523,14 @@ change_skill(unit * u, skill_t id, int byvalue)
static int static int
change_skill_transfermen(unit * u, skill_t id, int byvalue) change_skill_transfermen(unit * u, skill_t id, int byvalue)
{ {
skill *i = u->skills; skill * sv = u->skills;
for (; i != u->skills + u->skill_size; ++i) while (sv != u->skills + u->skill_size) {
if (i->id == id) { if (sv->id == id) {
i->value = max(0, i->value + byvalue); sv->value = max(0, sv->value + byvalue);
return i->value; return sv->value;
}
++sv;
} }
set_skill(u, id, byvalue); set_skill(u, id, byvalue);
@ -603,8 +605,7 @@ set_level(unit * u, skill_t id, int value)
skill * sv = u->skills; skill * sv = u->skills;
while (sv != u->skills + u->skill_size) { while (sv != u->skills + u->skill_size) {
if (sv->id == id) { if (sv->id == id) {
sv->level = (unsigned char)value; sk_set(sv, value);
sv->learning = 0;
break; break;
} }
++sv; ++sv;
@ -775,20 +776,13 @@ transfermen(unit * u, unit * u2, int n)
} }
#else #else
skill * sv; skill * sv;
assert(u2->number+n>0);
for (sv=u->skills;sv!=u->skills+u->skill_size;++sv) { for (sv=u->skills;sv!=u->skills+u->skill_size;++sv) {
if (u2->number == 0) {
set_skill(u2, sv->id, sv->level, sv->learning, false);
} else {
skill * sn = get_skill(u2, sv->id); skill * sn = get_skill(u2, sv->id);
if (sn) { if (sn==NULL) sn = add_skill(u2, sv->id);
int level = ((sv->level*n+sn->level*u2->number)/(u2->number+n)); /* level abrunden, wochen aufrunden. */
sn->level = (unsigned char)level; sn->level = (unsigned char)((sv->level*n+sn->level*u2->number)/(u2->number+n));
if (sn->learning>sv->learning) sn->learning=sv->learning; sn->weeks = (unsigned char)((sv->weeks*n+sn->weeks*u2->number+u2->number+n-1)/(u2->number+n));
} else {
int level = (sv->level*n/(u2->number+n));
set_level(u2, sv->id, level);
}
}
} }
#endif #endif
a = a_find(u->attribs, &at_effect); a = a_find(u->attribs, &at_effect);
@ -921,18 +915,38 @@ set_number(unit * u, int count)
#if !SKILLPOINTS #if !SKILLPOINTS
attrib_type at_showskchange = { attrib_type at_showskchange = {
"showskchange", NULL, NULL, NULL, NULL, NULL "showskchange", NULL, NULL, NULL, NULL, NULL, ATF_UNIQUE
}; };
boolean boolean
learn_skill(unit * u, skill_t sk, double chance) learn_skill(unit * u, skill_t sk, double chance)
{ {
skill * sv = u->skills;
if (chance < 1.0 && rand()%10000>=chance*10000) return false;
while (sv != u->skills + u->skill_size) {
assert (sv->weeks>0);
if (sv->id == sk) {
if (sv->weeks<=1) {
sk_set(sv, sv->level+1);
} else {
sv->weeks--;
}
return true;
}
++sv;
}
++u->skill_size;
u->skills = realloc(u->skills, u->skill_size * sizeof(skill));
sv = (u->skills + u->skill_size - 1);
sk_set(sv, 1);
return true;
}
/*
int coins, heads = 0; int coins, heads = 0;
int level = 0; int level = 0;
int weeks = 0; int weeks = 0;
skill * sv; skill * sv;
assert (chance <= 1.0); assert (chance <= 1.0);
if (chance < 1.0 && rand()%10000>=chance*10000) return false;
sv = get_skill(u, sk); sv = get_skill(u, sk);
if (sv) { if (sv) {
level = sv->level; level = sv->level;
@ -953,29 +967,9 @@ learn_skill(unit * u, skill_t sk, double chance)
set_skill(u, sk, level, weeks, false); set_skill(u, sk, level, weeks, false);
return heads==0; return heads==0;
} }
*/
void /*
set_skill(unit * u, skill_t id, int level, int weeks, boolean load)
{
attrib *a;
skill *i = u->skills;
unsigned char oldlevel = 0;
assert(level>=0 && weeks>=0 && weeks<=level*2);
for (; i != u->skills + u->skill_size; ++i) {
if (i->id == id) {
oldlevel = i->level;
if (level || weeks) {
i->level = (unsigned char)level;
i->learning = (unsigned char)weeks;
} else {
*i = *(u->skills + u->skill_size - 1);
--u->skill_size;
}
return;
}
}
if(load == false) { if(load == false) {
for(a = a_find(u->attribs, &at_showskchange);a;a = a->nexttype) { for(a = a_find(u->attribs, &at_showskchange);a;a = a->nexttype) {
if(a->data.sa[0] == id) { if(a->data.sa[0] == id) {
@ -989,16 +983,24 @@ set_skill(unit * u, skill_t id, int level, int weeks, boolean load)
a->data.sa[1] = (short)(level-oldlevel); a->data.sa[1] = (short)(level-oldlevel);
} }
} }
*/
if (!level && !weeks) { skill *
return; add_skill(unit * u, skill_t id)
{
skill * sv = u->skills;
#ifndef NDEBUG
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
assert(sv->id != id);
} }
#endif
++u->skill_size; ++u->skill_size;
u->skills = realloc(u->skills, u->skill_size * sizeof(skill)); u->skills = realloc(u->skills, u->skill_size * sizeof(skill));
i = (u->skills + u->skill_size - 1); sv = (u->skills + u->skill_size - 1);
i->level = (unsigned char)level; sv->level = (unsigned char)0;
i->learning = (unsigned char)weeks; sv->weeks = (unsigned char)1;
i->id = (unsigned char)id; sv->id = (unsigned char)id;
return sv;
} }
skill * skill *
@ -1006,7 +1008,7 @@ get_skill(const unit * u, skill_t sk)
{ {
skill * sv = u->skills; skill * sv = u->skills;
while (sv!=u->skills+u->skill_size) { while (sv!=u->skills+u->skill_size) {
assert(sv->level>=0 && sv->learning>=0); assert(sv->level>=0 && sv->weeks>=0);
if (sv->id==sk) return sv; if (sv->id==sk) return sv;
++sv; ++sv;
} }
@ -1018,9 +1020,9 @@ has_skill(const unit * u, skill_t sk)
{ {
skill * sv = u->skills; skill * sv = u->skills;
while (sv!=u->skills+u->skill_size) { while (sv!=u->skills+u->skill_size) {
assert(sv->level>=0 && sv->learning>=0); assert(sv->level>=0 && sv->weeks>=0);
if (sv->id==sk) { if (sv->id==sk) {
return (sv->level>0 || sv->learning>0); return (sv->level>0);
} }
++sv; ++sv;
} }

View File

@ -117,7 +117,7 @@ extern int get_skill(const struct unit * u, skill_t id);
#define has_skill(u, id) (get_skill(u, id)>0) #define has_skill(u, id) (get_skill(u, id)>0)
#define change_level(u, sk, bylevel) set_level(u, sk, max(0,get_level(u,sk)+bylevel)); #define change_level(u, sk, bylevel) set_level(u, sk, max(0,get_level(u,sk)+bylevel));
#else #else
extern void set_skill(struct unit * u, skill_t id, int level, int weeks, boolean load); extern struct skill * add_skill(struct unit * u, skill_t id);
extern struct skill * get_skill(const struct unit * u, skill_t id); extern struct skill * get_skill(const struct unit * u, skill_t id);
extern boolean has_skill(const unit* u, skill_t sk); extern boolean has_skill(const unit* u, skill_t sk);
#endif #endif