autostudy framework

This commit is contained in:
Enno Rehling 2018-07-05 20:06:32 +02:00 committed by Enno Rehling
parent 0eb030194c
commit ee8a02c425
13 changed files with 130 additions and 13 deletions

View File

@ -86,6 +86,7 @@ ENDIF()
set (ERESSEA_SRC
vortex.c
automate.c
move.c
piracy.c
spells.c

71
src/automate.c Normal file
View 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
View 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

View File

@ -135,7 +135,8 @@ const char *parameters[MAXPARAMS] = {
"GRUPPE",
"PARTEITARNUNG",
"BAEUME",
"ALLIANZ"
"ALLIANZ",
"AUTO"
};
int findoption(const char *s, const struct locale *lang)

View File

@ -214,12 +214,12 @@ static int create_data(keyword_t kwd, const char *s,
order_data *data;
int id;
assert(kwd!=NOKEYWORD);
assert(kwd != NOKEYWORD);
if (!s || *s == 0) {
return 0;
}
if (kwd==K_STUDY) {
if (kwd == K_STUDY || kwd == K_AUTOSTUDY) {
const char * sptr = s;
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
if (sk != SK_MAGIC && sk != NOSKILL) {
@ -332,6 +332,14 @@ order *parse_order(const char *s, const struct locale * lang)
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) {
order *ord = (order *)malloc(sizeof(order));
create_order_i(ord, kwd, sptr, persistent, noerror, lang);
@ -366,6 +374,7 @@ bool is_repeated(keyword_t kwd)
case K_STEAL:
case K_SABOTAGE:
case K_STUDY:
case K_AUTOSTUDY:
case K_TEACH:
case K_GROW:
case K_PLANT:
@ -406,6 +415,7 @@ bool is_exclusive(const order * ord)
case K_STEAL:
case K_SABOTAGE:
case K_STUDY:
case K_AUTOSTUDY:
case K_TEACH:
case K_GROW:
case K_PLANT:
@ -447,6 +457,7 @@ bool is_long(keyword_t kwd)
case K_STEAL:
case K_SABOTAGE:
case K_STUDY:
case K_AUTOSTUDY:
case K_TEACH:
case K_GROW:
case K_PLANT:
@ -541,7 +552,7 @@ keyword_t init_order(const struct order *ord, const struct locale *lang)
assert(sk < MAXSKILLS);
assert(lang);
assert(kwd == K_STUDY);
assert(kwd == K_STUDY || kwd == K_AUTOSTUDY);
str = skillname(sk, lang);
if (strchr(str, ' ') == NULL) {
init_tokens_str(str);
@ -575,7 +586,7 @@ keyword_t init_order_depr(const struct order *ord)
{
if (ord) {
keyword_t kwd = ORD_KEYWORD(ord);
assert(kwd != K_STUDY);
assert(kwd != K_STUDY && kwd != K_AUTOSTUDY);
}
return init_order(ord, NULL);
}

View File

@ -130,6 +130,7 @@ typedef enum {
P_FACTIONSTEALTH,
P_TREES,
P_ALLIANCE,
P_AUTO,
MAXPARAMS,
NOPARAM
} param_t;

View File

@ -1310,13 +1310,12 @@ int eff_skill(const unit * u, const skill *sv, const region *r)
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);
if (sv && sv->level > 0) {
int mlevel = sv->level;
if (!r) r = u->region;
mlevel += get_modifier(u, sv->id, sv->level, r, true);
mlevel += get_modifier(u, sv->id, sv->level, u->region, true);
if (mlevel > 0)
return mlevel;
}

View File

@ -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 */
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,
const struct region *r, bool noitem);

View File

@ -149,5 +149,6 @@ const char *keywords[MAXKEYWORDS] = {
"promote",
"pay",
"loot",
"autostudy",
};

View File

@ -72,6 +72,7 @@ extern "C"
K_PROMOTION,
K_PAY,
K_LOOT,
K_AUTOSTUDY,
MAXKEYWORDS,
NOKEYWORD
} keyword_t;

View File

@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <modules/gmcmd.h>
#include "alchemy.h"
#include "automate.h"
#include "battle.h"
#include "economy.h"
#include "keyword.h"
@ -4001,6 +4002,7 @@ void init_processor(void)
}
p += 10;
add_proc_region(p, do_autostudy, "study automation");
add_proc_order(p, K_TEACH, teach_cmd, PROC_THISORDER | PROC_LONGORDER,
"Lehren");
p += 10;

View File

@ -69,7 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define TEACH_ALL 1
#define TEACH_FRIENDS
static skill_t getskill(const struct locale *lang)
skill_t getskill(const struct locale *lang)
{
char token[128];
const char * s = gettoken(token, sizeof(token));
@ -331,7 +331,7 @@ int teach_cmd(unit * teacher, struct order *ord)
sk = teachskill[t];
}
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);
}
}
@ -343,7 +343,7 @@ int teach_cmd(unit * teacher, struct order *ord)
init_order(student->thisorder, student->faction->locale);
sk = getskill(student->faction->locale);
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);
}
}
@ -432,7 +432,7 @@ int teach_cmd(unit * teacher, struct order *ord)
continue;
}
if (effskill_study(student, sk, 0) > effskill_study(teacher, sk, 0)
if (effskill_study(student, sk, NULL) > effskill_study(teacher, sk)
- TEACHDIFFERENCE) {
if (feedback) {
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",

View File

@ -33,6 +33,7 @@ extern "C" {
int study_cmd(struct unit *u, struct order *ord);
magic_t getmagicskill(const struct locale *lang);
skill_t getskill(const struct locale *lang);
bool is_migrant(struct unit *u);
int study_cost(struct unit *u, skill_t talent);