forked from github/server
autostudy framework
This commit is contained in:
parent
0eb030194c
commit
ee8a02c425
13 changed files with 130 additions and 13 deletions
|
@ -86,6 +86,7 @@ ENDIF()
|
||||||
|
|
||||||
set (ERESSEA_SRC
|
set (ERESSEA_SRC
|
||||||
vortex.c
|
vortex.c
|
||||||
|
automate.c
|
||||||
move.c
|
move.c
|
||||||
piracy.c
|
piracy.c
|
||||||
spells.c
|
spells.c
|
||||||
|
|
71
src/automate.c
Normal file
71
src/automate.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include "kernel/faction.h"
|
||||||
|
#include "kernel/order.h"
|
||||||
|
#include "kernel/region.h"
|
||||||
|
#include "kernel/unit.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
#include "automate.h"
|
||||||
|
#include "keyword.h"
|
||||||
|
#include "study.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct student {
|
||||||
|
unit *u;
|
||||||
|
skill_t sk;
|
||||||
|
int level;
|
||||||
|
} student;
|
||||||
|
|
||||||
|
#define MAXSTUDENTS 128
|
||||||
|
|
||||||
|
int cmp_students(const void *lhs, const void *rhs) {
|
||||||
|
const student *a = (const student *)lhs;
|
||||||
|
const student *b = (const student *)rhs;
|
||||||
|
if (a->sk == b->sk) {
|
||||||
|
/* sort by level, descending: */
|
||||||
|
return b->level - a->level;
|
||||||
|
}
|
||||||
|
/* order by skill */
|
||||||
|
return (int)a->sk - (int)b->sk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_autostudy(region *r) {
|
||||||
|
unit *u;
|
||||||
|
int nstudents = 0;
|
||||||
|
student students[MAXSTUDENTS];
|
||||||
|
|
||||||
|
for (u = r->units; u; u = u->next) {
|
||||||
|
keyword_t kwd = getkeyword(u->thisorder);
|
||||||
|
if (kwd == K_AUTOSTUDY) {
|
||||||
|
student * st = students + nstudents;
|
||||||
|
if (++nstudents == MAXSTUDENTS) {
|
||||||
|
log_fatal("you must increase MAXSTUDENTS");
|
||||||
|
}
|
||||||
|
st->u = u;
|
||||||
|
init_order(u->thisorder, u->faction->locale);
|
||||||
|
st->sk = getskill(u->faction->locale);
|
||||||
|
st->level = effskill_study(u, st->sk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nstudents > 0) {
|
||||||
|
int i, taught = 0;
|
||||||
|
skill_t sk = NOSKILL;
|
||||||
|
student *teacher = NULL, *student = NULL;
|
||||||
|
|
||||||
|
qsort(students, nstudents, sizeof(student), cmp_students);
|
||||||
|
for (i = 0; i != nstudents; ++i) {
|
||||||
|
if (students[i].u) {
|
||||||
|
if (sk == NOSKILL) {
|
||||||
|
sk = students[i].sk;
|
||||||
|
}
|
||||||
|
else if (sk != students[i].sk) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
students[i].u = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/automate.h
Normal file
28
src/automate.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 1998-2018, Enno Rehling <enno@eressea.de>
|
||||||
|
Katja Zedel <katze@felidae.kn-bremen.de
|
||||||
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef H_GC_AUTOMATE
|
||||||
|
#define H_GC_AUTOMATE
|
||||||
|
|
||||||
|
struct region;
|
||||||
|
|
||||||
|
void do_autostudy(struct region *r);
|
||||||
|
|
||||||
|
#endif
|
|
@ -135,7 +135,8 @@ const char *parameters[MAXPARAMS] = {
|
||||||
"GRUPPE",
|
"GRUPPE",
|
||||||
"PARTEITARNUNG",
|
"PARTEITARNUNG",
|
||||||
"BAEUME",
|
"BAEUME",
|
||||||
"ALLIANZ"
|
"ALLIANZ",
|
||||||
|
"AUTO"
|
||||||
};
|
};
|
||||||
|
|
||||||
int findoption(const char *s, const struct locale *lang)
|
int findoption(const char *s, const struct locale *lang)
|
||||||
|
|
|
@ -214,12 +214,12 @@ static int create_data(keyword_t kwd, const char *s,
|
||||||
order_data *data;
|
order_data *data;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
assert(kwd!=NOKEYWORD);
|
assert(kwd != NOKEYWORD);
|
||||||
|
|
||||||
if (!s || *s == 0) {
|
if (!s || *s == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (kwd==K_STUDY) {
|
if (kwd == K_STUDY || kwd == K_AUTOSTUDY) {
|
||||||
const char * sptr = s;
|
const char * sptr = s;
|
||||||
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
|
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
|
||||||
if (sk != SK_MAGIC && sk != NOSKILL) {
|
if (sk != SK_MAGIC && sk != NOSKILL) {
|
||||||
|
@ -332,6 +332,14 @@ order *parse_order(const char *s, const struct locale * lang)
|
||||||
sptr = sp;
|
sptr = sp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (kwd == K_STUDY) {
|
||||||
|
const char *sp = sptr;
|
||||||
|
p = parse_token_depr(&sp);
|
||||||
|
if (p && isparam(p, lang, P_AUTO)) {
|
||||||
|
kwd = K_AUTOSTUDY;
|
||||||
|
sptr = sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (kwd != NOKEYWORD) {
|
if (kwd != NOKEYWORD) {
|
||||||
order *ord = (order *)malloc(sizeof(order));
|
order *ord = (order *)malloc(sizeof(order));
|
||||||
create_order_i(ord, kwd, sptr, persistent, noerror, lang);
|
create_order_i(ord, kwd, sptr, persistent, noerror, lang);
|
||||||
|
@ -366,6 +374,7 @@ bool is_repeated(keyword_t kwd)
|
||||||
case K_STEAL:
|
case K_STEAL:
|
||||||
case K_SABOTAGE:
|
case K_SABOTAGE:
|
||||||
case K_STUDY:
|
case K_STUDY:
|
||||||
|
case K_AUTOSTUDY:
|
||||||
case K_TEACH:
|
case K_TEACH:
|
||||||
case K_GROW:
|
case K_GROW:
|
||||||
case K_PLANT:
|
case K_PLANT:
|
||||||
|
@ -406,6 +415,7 @@ bool is_exclusive(const order * ord)
|
||||||
case K_STEAL:
|
case K_STEAL:
|
||||||
case K_SABOTAGE:
|
case K_SABOTAGE:
|
||||||
case K_STUDY:
|
case K_STUDY:
|
||||||
|
case K_AUTOSTUDY:
|
||||||
case K_TEACH:
|
case K_TEACH:
|
||||||
case K_GROW:
|
case K_GROW:
|
||||||
case K_PLANT:
|
case K_PLANT:
|
||||||
|
@ -447,6 +457,7 @@ bool is_long(keyword_t kwd)
|
||||||
case K_STEAL:
|
case K_STEAL:
|
||||||
case K_SABOTAGE:
|
case K_SABOTAGE:
|
||||||
case K_STUDY:
|
case K_STUDY:
|
||||||
|
case K_AUTOSTUDY:
|
||||||
case K_TEACH:
|
case K_TEACH:
|
||||||
case K_GROW:
|
case K_GROW:
|
||||||
case K_PLANT:
|
case K_PLANT:
|
||||||
|
@ -541,7 +552,7 @@ keyword_t init_order(const struct order *ord, const struct locale *lang)
|
||||||
|
|
||||||
assert(sk < MAXSKILLS);
|
assert(sk < MAXSKILLS);
|
||||||
assert(lang);
|
assert(lang);
|
||||||
assert(kwd == K_STUDY);
|
assert(kwd == K_STUDY || kwd == K_AUTOSTUDY);
|
||||||
str = skillname(sk, lang);
|
str = skillname(sk, lang);
|
||||||
if (strchr(str, ' ') == NULL) {
|
if (strchr(str, ' ') == NULL) {
|
||||||
init_tokens_str(str);
|
init_tokens_str(str);
|
||||||
|
@ -575,7 +586,7 @@ keyword_t init_order_depr(const struct order *ord)
|
||||||
{
|
{
|
||||||
if (ord) {
|
if (ord) {
|
||||||
keyword_t kwd = ORD_KEYWORD(ord);
|
keyword_t kwd = ORD_KEYWORD(ord);
|
||||||
assert(kwd != K_STUDY);
|
assert(kwd != K_STUDY && kwd != K_AUTOSTUDY);
|
||||||
}
|
}
|
||||||
return init_order(ord, NULL);
|
return init_order(ord, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,7 @@ typedef enum {
|
||||||
P_FACTIONSTEALTH,
|
P_FACTIONSTEALTH,
|
||||||
P_TREES,
|
P_TREES,
|
||||||
P_ALLIANCE,
|
P_ALLIANCE,
|
||||||
|
P_AUTO,
|
||||||
MAXPARAMS,
|
MAXPARAMS,
|
||||||
NOPARAM
|
NOPARAM
|
||||||
} param_t;
|
} param_t;
|
||||||
|
|
|
@ -1310,13 +1310,12 @@ int eff_skill(const unit * u, const skill *sv, const region *r)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int effskill_study(const unit * u, skill_t sk, const region * r)
|
int effskill_study(const unit * u, skill_t sk)
|
||||||
{
|
{
|
||||||
skill *sv = unit_skill(u, sk);
|
skill *sv = unit_skill(u, sk);
|
||||||
if (sv && sv->level > 0) {
|
if (sv && sv->level > 0) {
|
||||||
int mlevel = sv->level;
|
int mlevel = sv->level;
|
||||||
if (!r) r = u->region;
|
mlevel += get_modifier(u, sv->id, sv->level, u->region, true);
|
||||||
mlevel += get_modifier(u, sv->id, sv->level, r, true);
|
|
||||||
if (mlevel > 0)
|
if (mlevel > 0)
|
||||||
return mlevel;
|
return mlevel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ extern "C" {
|
||||||
void clone_men(const struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */
|
void clone_men(const struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */
|
||||||
|
|
||||||
int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r);
|
int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r);
|
||||||
int effskill_study(const struct unit *u, skill_t sk, const struct region *r);
|
int effskill_study(const struct unit *u, skill_t sk);
|
||||||
|
|
||||||
int get_modifier(const struct unit *u, skill_t sk, int level,
|
int get_modifier(const struct unit *u, skill_t sk, int level,
|
||||||
const struct region *r, bool noitem);
|
const struct region *r, bool noitem);
|
||||||
|
|
|
@ -149,5 +149,6 @@ const char *keywords[MAXKEYWORDS] = {
|
||||||
"promote",
|
"promote",
|
||||||
"pay",
|
"pay",
|
||||||
"loot",
|
"loot",
|
||||||
|
"autostudy",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ extern "C"
|
||||||
K_PROMOTION,
|
K_PROMOTION,
|
||||||
K_PAY,
|
K_PAY,
|
||||||
K_LOOT,
|
K_LOOT,
|
||||||
|
K_AUTOSTUDY,
|
||||||
MAXKEYWORDS,
|
MAXKEYWORDS,
|
||||||
NOKEYWORD
|
NOKEYWORD
|
||||||
} keyword_t;
|
} keyword_t;
|
||||||
|
|
|
@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <modules/gmcmd.h>
|
#include <modules/gmcmd.h>
|
||||||
|
|
||||||
#include "alchemy.h"
|
#include "alchemy.h"
|
||||||
|
#include "automate.h"
|
||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
#include "economy.h"
|
#include "economy.h"
|
||||||
#include "keyword.h"
|
#include "keyword.h"
|
||||||
|
@ -4001,6 +4002,7 @@ void init_processor(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
p += 10;
|
p += 10;
|
||||||
|
add_proc_region(p, do_autostudy, "study automation");
|
||||||
add_proc_order(p, K_TEACH, teach_cmd, PROC_THISORDER | PROC_LONGORDER,
|
add_proc_order(p, K_TEACH, teach_cmd, PROC_THISORDER | PROC_LONGORDER,
|
||||||
"Lehren");
|
"Lehren");
|
||||||
p += 10;
|
p += 10;
|
||||||
|
|
|
@ -69,7 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define TEACH_ALL 1
|
#define TEACH_ALL 1
|
||||||
#define TEACH_FRIENDS
|
#define TEACH_FRIENDS
|
||||||
|
|
||||||
static skill_t getskill(const struct locale *lang)
|
skill_t getskill(const struct locale *lang)
|
||||||
{
|
{
|
||||||
char token[128];
|
char token[128];
|
||||||
const char * s = gettoken(token, sizeof(token));
|
const char * s = gettoken(token, sizeof(token));
|
||||||
|
@ -331,7 +331,7 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
sk = teachskill[t];
|
sk = teachskill[t];
|
||||||
}
|
}
|
||||||
if (sk != NOSKILL
|
if (sk != NOSKILL
|
||||||
&& effskill_study(teacher, sk, 0) - TEACHDIFFERENCE > effskill_study(student, sk, 0)) {
|
&& effskill_study(teacher, sk) - TEACHDIFFERENCE > effskill_study(student, sk)) {
|
||||||
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,7 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
init_order(student->thisorder, student->faction->locale);
|
init_order(student->thisorder, student->faction->locale);
|
||||||
sk = getskill(student->faction->locale);
|
sk = getskill(student->faction->locale);
|
||||||
if (sk != NOSKILL
|
if (sk != NOSKILL
|
||||||
&& effskill_study(teacher, sk, 0) - TEACHDIFFERENCE >= effskill(student, sk, 0)) {
|
&& effskill_study(teacher, sk) - TEACHDIFFERENCE >= effskill(student, sk)) {
|
||||||
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,7 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effskill_study(student, sk, 0) > effskill_study(teacher, sk, 0)
|
if (effskill_study(student, sk, NULL) > effskill_study(teacher, sk)
|
||||||
- TEACHDIFFERENCE) {
|
- TEACHDIFFERENCE) {
|
||||||
if (feedback) {
|
if (feedback) {
|
||||||
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
|
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
||||||
int study_cmd(struct unit *u, struct order *ord);
|
int study_cmd(struct unit *u, struct order *ord);
|
||||||
|
|
||||||
magic_t getmagicskill(const struct locale *lang);
|
magic_t getmagicskill(const struct locale *lang);
|
||||||
|
skill_t getskill(const struct locale *lang);
|
||||||
bool is_migrant(struct unit *u);
|
bool is_migrant(struct unit *u);
|
||||||
int study_cost(struct unit *u, skill_t talent);
|
int study_cost(struct unit *u, skill_t talent);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue