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);
assert(bylevel>0);
if (sv==0) set_skill(u, sk, bylevel, 0, false);
else {
sv->level = (unsigned char)(sv->level+bylevel);
sv->learning = 0;
}
if (sv==0) sv = add_skill(u, sk);
sk_set(sv, sv->level+bylevel);
}
#endif

View File

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

View File

@ -34,6 +34,7 @@
/* libc includes */
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
@ -257,46 +258,86 @@ level(int days)
}
#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) {
/* just forget a few weeks */
sv->learning = (unsigned char)(sv->learning-change);
} else {
int weeks;
unsigned char oldlevel = sv->level;
attrib *a;
int i;
double f=1;
for (i=2;i<n;++i) f=f*i;
return f;
}
change -= sv->learning;
while (change>=sv->level && sv->level > 0) {
change -= sv->level;
--sv->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) {
if(a->data.sa[0] == sv->id) {
a->data.sa[1] = (short)(a->data.sa[1] + (sv->level-oldlevel));
break;
}
}
if(a == NULL) {
a = a_add(&u->attribs, a_new(&at_showskchange));
a->data.sa[0] = sv->id;
a->data.sa[1] = (short)(sv->level-oldlevel);
void
sk_set(skill * sv, int level)
{
double i;
int weeks;
int multi=1+(level/16);
if (upgrade[level].permutations==0) {
int m;
int ctr = 1;
int n = level * 2 / multi;
upgrade[level].permutations = 1 << n;
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);
}
assert(sv->level>=0 && sv->learning>=0 && sv->learning<=sv->level*2);
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;
}
*/
void
sk_set(skill * sv, int level)
{
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));
}
void
reduce_skill(unit *u, skill * sv, int weeks)
{
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;
}
} 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
@ -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->learning > sc->learning) return 1;
if (sk->learning < sc->learning) return -1;
if (sk->weeks < sc->weeks) return 1;
if (sk->weeks > sc->weeks) return -1;
return 0;
}
#endif

View File

@ -29,7 +29,7 @@ typedef struct skill {
#else
unsigned char id;
unsigned char level;
unsigned char learning;
unsigned char weeks;
#endif
} skill;
@ -58,7 +58,10 @@ extern int level(int days);
#else
# define skill_level(level) (level)
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 void sk_set(skill * sv, int level);
#endif

View File

@ -150,7 +150,7 @@ do_shock(unit *u, char *reason)
#else
for (i=0;i!=u->skill_size;++i) if (rand()%5==0) {
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;
reduce_skill(u, sv, change);
}

View File

@ -523,13 +523,15 @@ change_skill(unit * u, skill_t id, int byvalue)
static int
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)
if (i->id == id) {
i->value = max(0, i->value + byvalue);
return i->value;
while (sv != u->skills + u->skill_size) {
if (sv->id == id) {
sv->value = max(0, sv->value + byvalue);
return sv->value;
}
++sv;
}
set_skill(u, id, byvalue);
@ -603,8 +605,7 @@ set_level(unit * u, skill_t id, int value)
skill * sv = u->skills;
while (sv != u->skills + u->skill_size) {
if (sv->id == id) {
sv->level = (unsigned char)value;
sv->learning = 0;
sk_set(sv, value);
break;
}
++sv;
@ -775,20 +776,13 @@ transfermen(unit * u, unit * u2, int n)
}
#else
skill * sv;
assert(u2->number+n>0);
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);
if (sn) {
int level = ((sv->level*n+sn->level*u2->number)/(u2->number+n));
sn->level = (unsigned char)level;
if (sn->learning>sv->learning) sn->learning=sv->learning;
} else {
int level = (sv->level*n/(u2->number+n));
set_level(u2, sv->id, level);
}
}
skill * sn = get_skill(u2, sv->id);
if (sn==NULL) sn = add_skill(u2, sv->id);
/* level abrunden, wochen aufrunden. */
sn->level = (unsigned char)((sv->level*n+sn->level*u2->number)/(u2->number+n));
sn->weeks = (unsigned char)((sv->weeks*n+sn->weeks*u2->number+u2->number+n-1)/(u2->number+n));
}
#endif
a = a_find(u->attribs, &at_effect);
@ -921,18 +915,38 @@ set_number(unit * u, int count)
#if !SKILLPOINTS
attrib_type at_showskchange = {
"showskchange", NULL, NULL, NULL, NULL, NULL
"showskchange", NULL, NULL, NULL, NULL, NULL, ATF_UNIQUE
};
boolean
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 level = 0;
int weeks = 0;
skill * sv;
assert (chance <= 1.0);
if (chance < 1.0 && rand()%10000>=chance*10000) return false;
sv = get_skill(u, sk);
if (sv) {
level = sv->level;
@ -953,29 +967,9 @@ learn_skill(unit * u, skill_t sk, double chance)
set_skill(u, sk, level, weeks, false);
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) {
for(a = a_find(u->attribs, &at_showskchange);a;a = a->nexttype) {
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);
}
}
*/
if (!level && !weeks) {
return;
skill *
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->skills = realloc(u->skills, u->skill_size * sizeof(skill));
i = (u->skills + u->skill_size - 1);
i->level = (unsigned char)level;
i->learning = (unsigned char)weeks;
i->id = (unsigned char)id;
sv = (u->skills + u->skill_size - 1);
sv->level = (unsigned char)0;
sv->weeks = (unsigned char)1;
sv->id = (unsigned char)id;
return sv;
}
skill *
@ -1006,7 +1008,7 @@ get_skill(const unit * u, skill_t sk)
{
skill * sv = u->skills;
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;
++sv;
}
@ -1018,9 +1020,9 @@ has_skill(const unit * u, skill_t sk)
{
skill * sv = u->skills;
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->level>0 || sv->learning>0);
return (sv->level>0);
}
++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 change_level(u, sk, bylevel) set_level(u, sk, max(0,get_level(u,sk)+bylevel));
#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 boolean has_skill(const unit* u, skill_t sk);
#endif