properly create missing monster faction when spawning dragons.

remove cached monster faction (static).
Conflicts:
	src/kernel/faction.c
This commit is contained in:
Enno Rehling 2014-08-16 13:46:34 +02:00
parent 206e0a2fc5
commit 138a4c10a0
3 changed files with 363 additions and 349 deletions

View File

@ -1,7 +1,7 @@
/* /*
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@ -68,526 +68,539 @@ faction *factions;
*/ */
void free_faction(faction * f) void free_faction(faction * f)
{ {
if (f->msgs) if (f->msgs)
free_messagelist(f->msgs); free_messagelist(f->msgs);
while (f->battles) { while (f->battles) {
struct bmsg *bm = f->battles; struct bmsg *bm = f->battles;
f->battles = bm->next; f->battles = bm->next;
if (bm->msgs) if (bm->msgs)
free_messagelist(bm->msgs); free_messagelist(bm->msgs);
free(bm); free(bm);
} }
while (f->groups) { while (f->groups) {
group *g = f->groups; group *g = f->groups;
f->groups = g->next; f->groups = g->next;
free_group(g); free_group(g);
} }
freelist(f->allies); freelist(f->allies);
free(f->email); free(f->email);
free(f->banner); free(f->banner);
free(f->passw); free(f->passw);
free(f->name); free(f->name);
while (f->attribs) { while (f->attribs) {
a_remove(&f->attribs, f->attribs); a_remove(&f->attribs, f->attribs);
} }
i_freeall(&f->items); i_freeall(&f->items);
freelist(f->ursprung); freelist(f->ursprung);
} }
void set_show_item(faction * f, const struct item_type *itype) void set_show_item(faction * f, const struct item_type *itype)
{ {
attrib *a = a_add(&f->attribs, a_new(&at_showitem)); attrib *a = a_add(&f->attribs, a_new(&at_showitem));
a->data.v = (void *)itype; a->data.v = (void *)itype;
} }
faction *get_monsters(void) faction *get_monsters(void) {
{
static faction *monsters;
static int gamecookie = -1;
if (gamecookie != global.cookie) {
monsters = NULL;
gamecookie = global.cookie;
}
if (!monsters) {
faction *f; faction *f;
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if ((f->flags & FFL_NPC) && !(f->flags & FFL_DEFENDER)) { if ((f->flags & FFL_NPC) && !(f->flags & FFL_DEFENDER)) {
return monsters = f; return f;
} }
} }
if (!monsters) { return 0;
/* shit! */ }
monsters = findfaction(666);
faction *get_or_create_monsters(void)
{
faction *f = get_monsters();
if (!f) {
/* shit! */
f = findfaction(666);
} }
if (monsters) { if (!f) {
fset(monsters, FFL_NPC | FFL_NOIDLEOUT); const race *rc = rc_find("dragon");
f = addfaction("noreply@eressea.de", NULL, rc, NULL, 0);
renumber_faction(f, 666);
faction_setname(f, "Monster");
f->options = 0;
} }
} if (f) {
return monsters; fset(f, FFL_NPC | FFL_NOIDLEOUT);
}
return f;
} }
const unit *random_unit_in_faction(const faction * f) const unit *random_unit_in_faction(const faction * f)
{ {
unit *u; unit *u;
int c = 0, u_nr; int c = 0, u_nr;
for (u = f->units; u; u = u->next) for (u = f->units; u; u = u->next)
c++; c++;
u_nr = rng_int() % c; u_nr = rng_int() % c;
c = 0; c = 0;
for (u = f->units; u; u = u->next) for (u = f->units; u; u = u->next)
if (u_nr == c) if (u_nr == c)
return u; return u;
/* Hier sollte er nie ankommen */ /* Hier sollte er nie ankommen */
return NULL; return NULL;
} }
const char *factionname(const faction * f) const char *factionname(const faction * f)
{ {
typedef char name[OBJECTIDSIZE + 1]; typedef char name[OBJECTIDSIZE + 1];
static name idbuf[8]; static name idbuf[8];
static int nextbuf = 0; static int nextbuf = 0;
char *ibuf = idbuf[(++nextbuf) % 8]; char *ibuf = idbuf[(++nextbuf) % 8];
if (f && f->name) { if (f && f->name) {
slprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no)); slprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no));
} else { }
strcpy(ibuf, "Unbekannte Partei (?)"); else {
} strcpy(ibuf, "Unbekannte Partei (?)");
return ibuf; }
return ibuf;
} }
int resolve_faction(variant id, void *address) int resolve_faction(variant id, void *address)
{ {
int result = 0; int result = 0;
faction *f = NULL; faction *f = NULL;
if (id.i != 0) { if (id.i != 0) {
f = findfaction(id.i); f = findfaction(id.i);
if (f == NULL) { if (f == NULL) {
result = -1; result = -1;
}
} }
} *(faction **)address = f;
*(faction **) address = f; return result;
return result;
} }
#define MAX_FACTION_ID (36*36*36*36) #define MAX_FACTION_ID (36*36*36*36)
static int unused_faction_id(void) static int unused_faction_id(void)
{ {
int id = rng_int() % MAX_FACTION_ID; int id = rng_int() % MAX_FACTION_ID;
while (!faction_id_is_unused(id)) { while (!faction_id_is_unused(id)) {
id++; id++;
if (id == MAX_FACTION_ID) if (id == MAX_FACTION_ID)
id = 0; id = 0;
} }
return id; return id;
} }
faction *addfaction(const char *email, const char *password, faction *addfaction(const char *email, const char *password,
const struct race * frace, const struct locale * loc, int subscription) const struct race * frace, const struct locale * loc, int subscription)
{ {
faction *f = calloc(sizeof(faction), 1); faction *f = calloc(sizeof(faction), 1);
char buf[128]; char buf[128];
assert(frace); assert(frace);
if (set_email(&f->email, email) != 0) {
log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), email);
}
if (set_email(&f->email, email) != 0) { faction_setpassword(f, password);
log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), email);
}
faction_setpassword(f, password); f->alliance_joindate = turn;
f->lastorders = turn;
f->alive = 1;
f->age = 0;
f->race = frace;
f->magiegebiet = 0;
f->locale = loc;
f->subscription = subscription;
f->alliance_joindate = turn; f->options =
f->lastorders = turn; want(O_REPORT) | want(O_ZUGVORLAGE) | want(O_COMPUTER) | want(O_COMPRESS) |
f->alive = 1; want(O_ADRESSEN) | want(O_STATISTICS);
f->age = 0;
f->race = frace;
f->magiegebiet = 0;
f->locale = loc;
f->subscription = subscription;
f->options = f->no = unused_faction_id();
want(O_REPORT) | want(O_ZUGVORLAGE) | want(O_COMPUTER) | want(O_COMPRESS) | if (rule_region_owners()) {
want(O_ADRESSEN) | want(O_STATISTICS); alliance *al = makealliance(f->no, NULL);
setalliance(f, al);
}
addlist(&factions, f);
fhash(f);
f->no = unused_faction_id(); slprintf(buf, sizeof(buf), "%s %s", LOC(loc, "factiondefault"), factionid(f));
if (rule_region_owners()) { f->name = _strdup(buf);
alliance *al = makealliance(f->no, NULL);
setalliance(f, al);
}
addlist(&factions, f);
fhash(f);
slprintf(buf, sizeof(buf), "%s %s", LOC(loc, "factiondefault"), factionid(f)); if (!f->race) {
f->name = _strdup(buf); log_warning("creating a faction that has no race", factionid(f));
}
return f; return f;
} }
unit *addplayer(region * r, faction * f) unit *addplayer(region * r, faction * f)
{ {
unit *u; unit *u;
char buffer[32]; char buffer[32];
assert(f->units == NULL); assert(f->units == NULL);
set_ursprung(f, 0, r->x, r->y); set_ursprung(f, 0, r->x, r->y);
u = createunit(r, f, 1, f->race); u = createunit(r, f, 1, f->race);
equip_items(&u->faction->items, get_equipment("new_faction")); equip_items(&u->faction->items, get_equipment("new_faction"));
equip_unit(u, get_equipment("first_unit")); equip_unit(u, get_equipment("first_unit"));
sprintf(buffer, "first_%s", u_race(u)->_name[0]); sprintf(buffer, "first_%s", u_race(u)->_name[0]);
equip_unit(u, get_equipment(buffer)); equip_unit(u, get_equipment(buffer));
u->hp = unit_max_hp(u) * u->number; u->hp = unit_max_hp(u) * u->number;
fset(u, UFL_ISNEW); fset(u, UFL_ISNEW);
if (f->race == get_race(RC_DAEMON)) { if (f->race == get_race(RC_DAEMON)) {
race_t urc; race_t urc;
race *rc; race *rc;
do { do {
urc = (race_t) (rng_int() % MAXRACES); urc = (race_t)(rng_int() % MAXRACES);
rc = get_race(urc); rc = get_race(urc);
} while (rc == NULL || urc == RC_DAEMON || !playerrace(rc)); } while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
u->irace = rc; u->irace = rc;
} }
return u; return u;
} }
bool checkpasswd(const faction * f, const char *passwd, bool shortp) bool checkpasswd(const faction * f, const char *passwd, bool shortp)
{ {
if (unicode_utf8_strcasecmp(f->passw, passwd) == 0) if (unicode_utf8_strcasecmp(f->passw, passwd) == 0)
return true; return true;
return false; return false;
} }
variant read_faction_reference(struct storage * store) variant read_faction_reference(struct storage * store)
{ {
variant id; variant id;
READ_INT(store, &id.i); READ_INT(store, &id.i);
return id; return id;
} }
void write_faction_reference(const faction * f, struct storage *store) void write_faction_reference(const faction * f, struct storage *store)
{ {
WRITE_INT(store, f ? f->no : 0); WRITE_INT(store, f ? f->no : 0);
} }
void destroyfaction(faction * f) void destroyfaction(faction * f)
{ {
unit *u = f->units; unit *u = f->units;
faction *ff; faction *ff;
if (!f->alive) { if (!f->alive) {
return; return;
}
fset(f, FFL_QUIT);
if (f->spellbook) {
spellbook_clear(f->spellbook);
free(f->spellbook);
f->spellbook = 0;
}
while (f->battles) {
struct bmsg *bm = f->battles;
f->battles = bm->next;
if (bm->msgs) {
free_messagelist(bm->msgs);
} }
free(bm); fset(f, FFL_QUIT);
}
while (u) { if (f->spellbook) {
/* give away your stuff, make zombies if you cannot (quest items) */ spellbook_clear(f->spellbook);
int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS); free(f->spellbook);
if (result != 0) { f->spellbook = 0;
unit *zombie = u; }
u = u->nextF; while (f->battles) {
make_zombie(zombie); struct bmsg *bm = f->battles;
} else { f->battles = bm->next;
region *r = u->region; if (bm->msgs) {
free_messagelist(bm->msgs);
}
free(bm);
}
if (!fval(r->terrain, SEA_REGION) && !!playerrace(u_race(u))) { while (u) {
const race *rc = u_race(u); /* give away your stuff, make zombies if you cannot (quest items) */
int m = rmoney(r); int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS);
if (result != 0) {
unit *zombie = u;
u = u->nextF;
make_zombie(zombie);
}
else {
region *r = u->region;
if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { if (!fval(r->terrain, SEA_REGION) && !!playerrace(u_race(u))) {
int p = rpeasants(u->region); const race *rc = u_race(u);
int h = rhorses(u->region); int m = rmoney(r);
item *itm;
/* Personen gehen nur an die Bauern, wenn sie auch von dort if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) {
* stammen */ int p = rpeasants(u->region);
if (rc->ec_flags & ECF_REC_HORSES) { /* Zentauren an die Pferde */ int h = rhorses(u->region);
h += u->number; item *itm;
} else { /* Orks zählen nur zur Hälfte */
p += (int)(u->number * rc->recruit_multi); /* Personen gehen nur an die Bauern, wenn sie auch von dort
} * stammen */
for (itm = u->items; itm; itm = itm->next) { if (rc->ec_flags & ECF_REC_HORSES) { /* Zentauren an die Pferde */
if (itm->type->flags & ITF_ANIMAL) { h += u->number;
h += itm->number; }
else { /* Orks zählen nur zur Hälfte */
p += (int)(u->number * rc->recruit_multi);
}
for (itm = u->items; itm; itm = itm->next) {
if (itm->type->flags & ITF_ANIMAL) {
h += itm->number;
}
}
rsetpeasants(r, p);
rsethorses(r, h);
}
m += get_money(u);
rsetmoney(r, m);
} }
} set_number(u, 0);
rsetpeasants(r, p); u = u->nextF;
rsethorses(r, h);
} }
m += get_money(u);
rsetmoney(r, m);
}
set_number(u, 0);
u = u->nextF;
} }
} f->alive = 0;
f->alive = 0; /* no way! f->units = NULL; */
/* no way! f->units = NULL; */ handle_event(f->attribs, "destroy", f);
handle_event(f->attribs, "destroy", f); for (ff = factions; ff; ff = ff->next) {
for (ff = factions; ff; ff = ff->next) { group *g;
group *g; ally *sf, *sfn;
ally *sf, *sfn;
/* Alle HELFE für die Partei löschen */ /* Alle HELFE für die Partei löschen */
for (sf = ff->allies; sf; sf = sf->next) { for (sf = ff->allies; sf; sf = sf->next) {
if (sf->faction == f) { if (sf->faction == f) {
removelist(&ff->allies, sf); removelist(&ff->allies, sf);
break; break;
} }
} }
for (g = ff->groups; g; g = g->next) { for (g = ff->groups; g; g = g->next) {
for (sf = g->allies; sf;) { for (sf = g->allies; sf;) {
sfn = sf->next; sfn = sf->next;
if (sf->faction == f) { if (sf->faction == f) {
removelist(&g->allies, sf); removelist(&g->allies, sf);
break; break;
}
sf = sfn;
}
} }
sf = sfn;
}
} }
}
/* units of other factions that were disguised as this faction /* units of other factions that were disguised as this faction
* have their disguise replaced by ordinary faction hiding. */ * have their disguise replaced by ordinary faction hiding. */
if (rule_stealth_faction()) { if (rule_stealth_faction()) {
region *rc; region *rc;
for (rc = regions; rc; rc = rc->next) { for (rc = regions; rc; rc = rc->next) {
for (u = rc->units; u; u = u->next) { for (u = rc->units; u; u = u->next) {
attrib *a = a_find(u->attribs, &at_otherfaction); attrib *a = a_find(u->attribs, &at_otherfaction);
if (!a) if (!a)
continue; continue;
if (get_otherfaction(a) == f) { if (get_otherfaction(a) == f) {
a_removeall(&u->attribs, &at_otherfaction); a_removeall(&u->attribs, &at_otherfaction);
fset(u, UFL_ANON_FACTION); fset(u, UFL_ANON_FACTION);
}
}
} }
}
} }
}
} }
int get_alliance(const faction * a, const faction * b) int get_alliance(const faction * a, const faction * b)
{ {
const ally *sf = a->allies; const ally *sf = a->allies;
for (; sf != NULL; sf = sf->next) { for (; sf != NULL; sf = sf->next) {
if (sf->faction == b) { if (sf->faction == b) {
return sf->status; return sf->status;
}
} }
} return 0;
return 0;
} }
void set_alliance(faction * a, faction * b, int status) void set_alliance(faction * a, faction * b, int status)
{ {
ally **sfp; ally **sfp;
sfp = &a->allies; sfp = &a->allies;
while (*sfp) { while (*sfp) {
ally *sf = *sfp; ally *sf = *sfp;
if (sf->faction == b) if (sf->faction == b)
break; break;
sfp = &sf->next; sfp = &sf->next;
} }
if (*sfp == NULL) { if (*sfp == NULL) {
ally *sf = *sfp = malloc(sizeof(ally)); ally *sf = *sfp = malloc(sizeof(ally));
sf->next = NULL; sf->next = NULL;
sf->status = status; sf->status = status;
sf->faction = b; sf->faction = b;
return; return;
} }
(*sfp)->status |= status; (*sfp)->status |= status;
} }
void renumber_faction(faction * f, int no) void renumber_faction(faction * f, int no)
{ {
funhash(f); funhash(f);
f->no = no; f->no = no;
fhash(f); fhash(f);
fset(f, FFL_NEWID); fset(f, FFL_NEWID);
} }
#ifdef SMART_INTERVALS #ifdef SMART_INTERVALS
void update_interval(struct faction *f, struct region *r) void update_interval(struct faction *f, struct region *r)
{ {
if (r == NULL || f == NULL) if (r == NULL || f == NULL)
return; return;
if (f->first == NULL || f->first->index > r->index) { if (f->first == NULL || f->first->index > r->index) {
f->first = r; f->first = r;
} }
if (f->last == NULL || f->last->index <= r->index) { if (f->last == NULL || f->last->index <= r->index) {
f->last = r; f->last = r;
} }
} }
#endif #endif
const char *faction_getname(const faction * self) const char *faction_getname(const faction * self)
{ {
return self->name ? self->name : ""; return self->name ? self->name : "";
} }
void faction_setname(faction * self, const char *name) void faction_setname(faction * self, const char *name)
{ {
free(self->name); free(self->name);
if (name) if (name)
self->name = _strdup(name); self->name = _strdup(name);
} }
const char *faction_getemail(const faction * self) const char *faction_getemail(const faction * self)
{ {
return self->email ? self->email : ""; return self->email ? self->email : "";
} }
void faction_setemail(faction * self, const char *email) void faction_setemail(faction * self, const char *email)
{ {
free(self->email); free(self->email);
if (email) if (email)
self->email = _strdup(email); self->email = _strdup(email);
} }
const char *faction_getbanner(const faction * self) const char *faction_getbanner(const faction * self)
{ {
return self->banner ? self->banner : ""; return self->banner ? self->banner : "";
} }
void faction_setbanner(faction * self, const char *banner) void faction_setbanner(faction * self, const char *banner)
{ {
free(self->banner); free(self->banner);
if (banner) if (banner)
self->banner = _strdup(banner); self->banner = _strdup(banner);
} }
void faction_setpassword(faction * f, const char *passw) void faction_setpassword(faction * f, const char *passw)
{ {
free(f->passw); free(f->passw);
if (passw) if (passw)
f->passw = _strdup(passw); f->passw = _strdup(passw);
else else
f->passw = _strdup(itoa36(rng_int())); f->passw = _strdup(itoa36(rng_int()));
} }
bool valid_race(const struct faction *f, const struct race *rc) bool valid_race(const struct faction *f, const struct race *rc)
{ {
if (f->race == rc) if (f->race == rc)
return true; return true;
else { else {
const char *str = get_param(f->race->parameters, "other_race"); const char *str = get_param(f->race->parameters, "other_race");
if (str) if (str)
return (bool) (rc_find(str) == rc); return (bool)(rc_find(str) == rc);
return false; return false;
} }
} }
const char *faction_getpassword(const faction * f) const char *faction_getpassword(const faction * f)
{ {
return f->passw; return f->passw;
} }
struct alliance *f_get_alliance(const struct faction *f) struct alliance *f_get_alliance(const struct faction *f)
{ {
if (f->alliance && !(f->alliance->flags & ALF_NON_ALLIED)) { if (f->alliance && !(f->alliance->flags & ALF_NON_ALLIED)) {
return f->alliance; return f->alliance;
} }
return NULL; return NULL;
} }
struct spellbook * faction_get_spellbook(struct faction *f) struct spellbook * faction_get_spellbook(struct faction *f)
{ {
if (f->spellbook) { if (f->spellbook) {
return f->spellbook; return f->spellbook;
} }
if (f->magiegebiet!=M_GRAY) { if (f->magiegebiet != M_GRAY) {
return get_spellbook(magic_school[f->magiegebiet]); return get_spellbook(magic_school[f->magiegebiet]);
} }
return 0; return 0;
} }
static int allied_skillcount(const faction * f, skill_t sk) static int allied_skillcount(const faction * f, skill_t sk)
{ {
int num = 0; int num = 0;
alliance *a = f_get_alliance(f); alliance *a = f_get_alliance(f);
quicklist *members = a->members; quicklist *members = a->members;
int qi; int qi;
for (qi = 0; members; ql_advance(&members, &qi, 1)) { for (qi = 0; members; ql_advance(&members, &qi, 1)) {
faction *m = (faction *) ql_get(members, qi); faction *m = (faction *)ql_get(members, qi);
num += count_skill(m, sk); num += count_skill(m, sk);
} }
return num; return num;
} }
static int allied_skilllimit(const faction * f, skill_t sk) static int allied_skilllimit(const faction * f, skill_t sk)
{ {
static int value = -1; static int value = -1;
if (value < 0) { if (value < 0) {
value = get_param_int(global.parameters, "alliance.skilllimit", 0); value = get_param_int(global.parameters, "alliance.skilllimit", 0);
} }
return value; return value;
} }
int count_skill(faction * f, skill_t sk) int count_skill(faction * f, skill_t sk)
{ {
int n = 0; int n = 0;
unit *u; unit *u;
for (u = f->units; u; u = u->nextF) { for (u = f->units; u; u = u->nextF) {
if (has_skill(u, sk)) { if (has_skill(u, sk)) {
if (!is_familiar(u)) { if (!is_familiar(u)) {
n += u->number; n += u->number;
} }
}
} }
} return n;
return n;
} }
int skill_limit(faction * f, skill_t sk) int skill_limit(faction * f, skill_t sk)
{ {
int m = INT_MAX; int m = INT_MAX;
int al = allied_skilllimit(f, sk); int al = allied_skilllimit(f, sk);
if (al > 0) { if (al > 0) {
if (sk != SK_ALCHEMY && sk != SK_MAGIC) if (sk != SK_ALCHEMY && sk != SK_MAGIC)
return INT_MAX; return INT_MAX;
if (f_get_alliance(f)) { if (f_get_alliance(f)) {
int ac = listlen(f->alliance->members); /* number of factions */ int ac = listlen(f->alliance->members); /* number of factions */
int fl = (al + ac - 1) / ac; /* faction limit, rounded up */ int fl = (al + ac - 1) / ac; /* faction limit, rounded up */
/* the faction limit may not be achievable because it would break the alliance-limit */ /* the faction limit may not be achievable because it would break the alliance-limit */
int sc = al - allied_skillcount(f, sk); int sc = al - allied_skillcount(f, sk);
if (sc <= 0) if (sc <= 0)
return 0; return 0;
return fl; return fl;
}
} }
} if (sk == SK_MAGIC) {
if (sk == SK_MAGIC) { m = max_magicians(f);
m = max_magicians(f); }
} else if (sk == SK_ALCHEMY) { else if (sk == SK_ALCHEMY) {
m = get_param_int(global.parameters, "rules.maxskills.alchemy", m = get_param_int(global.parameters, "rules.maxskills.alchemy",
MAXALCHEMISTS); MAXALCHEMISTS);
} }
return m; return m;
} }

View File

@ -114,6 +114,7 @@ typedef struct faction {
extern struct faction *factions; extern struct faction *factions;
struct faction *get_monsters(void); struct faction *get_monsters(void);
struct faction *get_or_create_monsters(void);
int max_magicians(const faction * f); int max_magicians(const faction * f);
void set_show_item(faction * f, const struct item_type *itype); void set_show_item(faction * f, const struct item_type *itype);

View File

@ -889,7 +889,7 @@ static int nrand(int start, int sub)
void spawn_dragons(void) void spawn_dragons(void)
{ {
region *r; region *r;
faction *monsters = get_monsters(); faction *monsters = get_or_create_monsters();
for (r = regions; r; r = r->next) { for (r = regions; r; r = r->next) {
unit *u; unit *u;