forked from github/server
Merge branch 'master' into develop
This commit is contained in:
commit
dac6ef660d
|
@ -1058,6 +1058,21 @@ function test_give_silver()
|
||||||
assert_equal(10, u:get_item("money"))
|
assert_equal(10, u:get_item("money"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function test_build_castle_one_stage()
|
||||||
|
local r = region.create(0, 0, 'plain')
|
||||||
|
local f = faction.create('human')
|
||||||
|
local u = unit.create(f, r, 2)
|
||||||
|
|
||||||
|
u:add_item('stone', 4)
|
||||||
|
|
||||||
|
u:set_skill('building', 1)
|
||||||
|
u:add_order('MACHE BURG')
|
||||||
|
|
||||||
|
process_orders()
|
||||||
|
assert_equal(2, u.building.size)
|
||||||
|
assert_equal(2, u:get_item('stone'))
|
||||||
|
end
|
||||||
|
|
||||||
function test_build_castle()
|
function test_build_castle()
|
||||||
local r = region.create(0, 0, "plain")
|
local r = region.create(0, 0, "plain")
|
||||||
local f = create_faction('human')
|
local f = create_faction('human')
|
||||||
|
|
|
@ -29,6 +29,21 @@ function test_castle_names()
|
||||||
assert_equal("citadel", b:get_typename(6250))
|
assert_equal("citadel", b:get_typename(6250))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function test_build_castle_one_stage()
|
||||||
|
local r = region.create(0, 0, 'plain')
|
||||||
|
local f = faction.create('human')
|
||||||
|
local u = unit.create(f, r, 2)
|
||||||
|
|
||||||
|
u:add_item('stone', 4)
|
||||||
|
|
||||||
|
u:set_skill('building', 1)
|
||||||
|
u:add_order('MACHE BURG')
|
||||||
|
|
||||||
|
process_orders()
|
||||||
|
assert_equal(2, u.building.size)
|
||||||
|
assert_equal(2, u:get_item('stone'))
|
||||||
|
end
|
||||||
|
|
||||||
function test_build_castle_stages()
|
function test_build_castle_stages()
|
||||||
local r = region.create(0,0, "plain")
|
local r = region.create(0,0, "plain")
|
||||||
local f = faction.create("human")
|
local f = faction.create("human")
|
||||||
|
|
|
@ -28,29 +28,38 @@ static int cmp_scholars(const void *lhs, const void *rhs)
|
||||||
return (int)a->sk - (int)b->sk;
|
return (int)a->sk - (int)b->sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
int autostudy_init(scholar scholars[], int max_scholars, region *r)
|
int autostudy_init(scholar scholars[], int max_scholars, unit **units)
|
||||||
{
|
{
|
||||||
unit *u;
|
unit *unext = NULL, *u = *units;
|
||||||
|
faction *f = u->faction;
|
||||||
int nscholars = 0;
|
int nscholars = 0;
|
||||||
|
|
||||||
for (u = r->units; u; u = u->next) {
|
while (u) {
|
||||||
keyword_t kwd = init_order(u->thisorder, u->faction->locale);
|
keyword_t kwd = init_order(u->thisorder, u->faction->locale);
|
||||||
if (kwd == K_AUTOSTUDY) {
|
if (kwd == K_AUTOSTUDY) {
|
||||||
if (long_order_allowed(u)) {
|
if (long_order_allowed(u)) {
|
||||||
scholar * st = scholars + nscholars;
|
if (f == u->faction) {
|
||||||
skill_t sk = getskill(u->faction->locale);
|
scholar * st = scholars + nscholars;
|
||||||
if (check_student(u, u->thisorder, sk)) {
|
skill_t sk = getskill(u->faction->locale);
|
||||||
st->sk = sk;
|
if (check_student(u, u->thisorder, sk)) {
|
||||||
st->level = effskill_study(u, st->sk);
|
st->sk = sk;
|
||||||
st->learn = 0;
|
st->level = effskill_study(u, st->sk);
|
||||||
st->u = u;
|
st->learn = 0;
|
||||||
if (++nscholars == max_scholars) {
|
st->u = u;
|
||||||
log_fatal("you must increase MAXSCHOLARS");
|
if (++nscholars == max_scholars) {
|
||||||
|
log_fatal("you must increase MAXSCHOLARS");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!unext) {
|
||||||
|
unext = u;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
u = u->next;
|
||||||
}
|
}
|
||||||
|
*units = unext;
|
||||||
|
scholars[nscholars].u = NULL;
|
||||||
if (nscholars > 0) {
|
if (nscholars > 0) {
|
||||||
qsort(scholars, nscholars, sizeof(scholar), cmp_scholars);
|
qsort(scholars, nscholars, sizeof(scholar), cmp_scholars);
|
||||||
}
|
}
|
||||||
|
@ -145,15 +154,23 @@ void autostudy_run(scholar scholars[], int nscholars)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAXSCHOLARS 128
|
#define MAXSCHOLARS 512
|
||||||
|
|
||||||
void do_autostudy(region *r)
|
void do_autostudy(region *r)
|
||||||
{
|
{
|
||||||
|
static int max_scholars;
|
||||||
|
unit *units = r->units;
|
||||||
scholar scholars[MAXSCHOLARS];
|
scholar scholars[MAXSCHOLARS];
|
||||||
int i, nscholars = autostudy_init(scholars, MAXSCHOLARS, r);
|
while (units) {
|
||||||
autostudy_run(scholars, nscholars);
|
int i, nscholars = autostudy_init(scholars, MAXSCHOLARS, &units);
|
||||||
for (i = 0; i != nscholars; ++i) {
|
if (nscholars > max_scholars) {
|
||||||
int days = STUDYDAYS * scholars[i].learn;
|
stats_count("automate.max_scholars", nscholars - max_scholars);
|
||||||
learn_skill(scholars[i].u, scholars[i].sk, days);
|
max_scholars = nscholars;
|
||||||
|
}
|
||||||
|
autostudy_run(scholars, nscholars);
|
||||||
|
for (i = 0; i != nscholars; ++i) {
|
||||||
|
int days = STUDYDAYS * scholars[i].learn;
|
||||||
|
learn_skill(scholars[i].u, scholars[i].sk, days);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ typedef struct scholar {
|
||||||
|
|
||||||
void do_autostudy(struct region *r);
|
void do_autostudy(struct region *r);
|
||||||
|
|
||||||
int autostudy_init(scholar scholars[], int max_scholars, struct region *r);
|
int autostudy_init(scholar scholars[], int max_scholars, struct unit **units);
|
||||||
void autostudy_run(scholar scholars[], int nscholars);
|
void autostudy_run(scholar scholars[], int nscholars);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
static void test_autostudy_init(CuTest *tc) {
|
static void test_autostudy_init(CuTest *tc) {
|
||||||
scholar scholars[4];
|
scholar scholars[4];
|
||||||
unit *u1, *u2, *u3, *u4;
|
unit *u1, *u2, *u3, *u4, *u5, *ulist;
|
||||||
faction *f;
|
faction *f;
|
||||||
region *r;
|
region *r;
|
||||||
|
|
||||||
|
@ -35,10 +35,13 @@ static void test_autostudy_init(CuTest *tc) {
|
||||||
set_level(u2, SK_ENTERTAINMENT, 2);
|
set_level(u2, SK_ENTERTAINMENT, 2);
|
||||||
u3 = test_create_unit(f, r);
|
u3 = test_create_unit(f, r);
|
||||||
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
u4 = test_create_unit(test_create_faction(NULL), r);
|
u4 = test_create_unit(f, r);
|
||||||
u4->thisorder = create_order(K_AUTOSTUDY, f->locale, "Dudelidu");
|
u4->thisorder = create_order(K_AUTOSTUDY, f->locale, "Dudelidu");
|
||||||
|
u5 = test_create_unit(test_create_faction(NULL), r);
|
||||||
|
u5->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
scholars[3].u = NULL;
|
scholars[3].u = NULL;
|
||||||
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, r));
|
ulist = r->units;
|
||||||
|
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist));
|
||||||
CuAssertPtrNotNull(tc, test_find_messagetype(u4->faction->msgs, "error77"));
|
CuAssertPtrNotNull(tc, test_find_messagetype(u4->faction->msgs, "error77"));
|
||||||
CuAssertPtrEquals(tc, u2, scholars[0].u);
|
CuAssertPtrEquals(tc, u2, scholars[0].u);
|
||||||
CuAssertIntEquals(tc, 2, scholars[0].level);
|
CuAssertIntEquals(tc, 2, scholars[0].level);
|
||||||
|
@ -53,12 +56,20 @@ static void test_autostudy_init(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, 0, scholars[2].learn);
|
CuAssertIntEquals(tc, 0, scholars[2].learn);
|
||||||
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[2].sk);
|
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[2].sk);
|
||||||
CuAssertPtrEquals(tc, NULL, scholars[3].u);
|
CuAssertPtrEquals(tc, NULL, scholars[3].u);
|
||||||
|
CuAssertPtrEquals(tc, u5, ulist);
|
||||||
|
CuAssertIntEquals(tc, 1, autostudy_init(scholars, 4, &ulist));
|
||||||
|
CuAssertPtrEquals(tc, u5, scholars[0].u);
|
||||||
|
CuAssertIntEquals(tc, 0, scholars[0].level);
|
||||||
|
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
||||||
|
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].sk);
|
||||||
|
CuAssertPtrEquals(tc, NULL, scholars[1].u);
|
||||||
|
CuAssertPtrEquals(tc, NULL, ulist);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_autostudy_run(CuTest *tc) {
|
static void test_autostudy_run(CuTest *tc) {
|
||||||
scholar scholars[4];
|
scholar scholars[4];
|
||||||
unit *u1, *u2, *u3;
|
unit *u1, *u2, *u3, *ulist;
|
||||||
faction *f;
|
faction *f;
|
||||||
region *r;
|
region *r;
|
||||||
|
|
||||||
|
@ -76,7 +87,9 @@ static void test_autostudy_run(CuTest *tc) {
|
||||||
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
set_number(u3, 15);
|
set_number(u3, 15);
|
||||||
scholars[3].u = NULL;
|
scholars[3].u = NULL;
|
||||||
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, r));
|
ulist = r->units;
|
||||||
|
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist));
|
||||||
|
CuAssertPtrEquals(tc, NULL, ulist);
|
||||||
autostudy_run(scholars, 3);
|
autostudy_run(scholars, 3);
|
||||||
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
CuAssertIntEquals(tc, 0, scholars[0].learn);
|
||||||
CuAssertIntEquals(tc, 20, scholars[1].learn);
|
CuAssertIntEquals(tc, 20, scholars[1].learn);
|
||||||
|
@ -86,7 +99,7 @@ static void test_autostudy_run(CuTest *tc) {
|
||||||
|
|
||||||
static void test_autostudy_run_noteachers(CuTest *tc) {
|
static void test_autostudy_run_noteachers(CuTest *tc) {
|
||||||
scholar scholars[4];
|
scholar scholars[4];
|
||||||
unit *u1, *u2, *u3;
|
unit *u1, *u2, *u3, *ulist;
|
||||||
faction *f;
|
faction *f;
|
||||||
region *r;
|
region *r;
|
||||||
|
|
||||||
|
@ -104,7 +117,9 @@ static void test_autostudy_run_noteachers(CuTest *tc) {
|
||||||
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_PERCEPTION]);
|
||||||
set_number(u3, 15);
|
set_number(u3, 15);
|
||||||
scholars[3].u = NULL;
|
scholars[3].u = NULL;
|
||||||
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, r));
|
ulist = r->units;
|
||||||
|
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist));
|
||||||
|
CuAssertPtrEquals(tc, NULL, ulist);
|
||||||
autostudy_run(scholars, 3);
|
autostudy_run(scholars, 3);
|
||||||
CuAssertIntEquals(tc, 2, scholars[0].learn);
|
CuAssertIntEquals(tc, 2, scholars[0].learn);
|
||||||
CuAssertIntEquals(tc, 10, scholars[1].learn);
|
CuAssertIntEquals(tc, 10, scholars[1].learn);
|
||||||
|
|
156
src/gmtool.c
156
src/gmtool.c
|
@ -35,6 +35,7 @@
|
||||||
#include <util/lists.h>
|
#include <util/lists.h>
|
||||||
#include <util/macros.h>
|
#include <util/macros.h>
|
||||||
#include "util/path.h"
|
#include "util/path.h"
|
||||||
|
#include "util/rand.h"
|
||||||
#include "util/rng.h"
|
#include "util/rng.h"
|
||||||
#include "util/unicode.h"
|
#include "util/unicode.h"
|
||||||
|
|
||||||
|
@ -43,6 +44,10 @@
|
||||||
#include "listbox.h"
|
#include "listbox.h"
|
||||||
#include "teleport.h"
|
#include "teleport.h"
|
||||||
|
|
||||||
|
#include <selist.h>
|
||||||
|
#include <storage.h>
|
||||||
|
#include <lua.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -437,7 +442,10 @@ static void paint_info_region(window * wnd, const state * st)
|
||||||
line++;
|
line++;
|
||||||
umvwprintw(win, line++, 1, "%s, age %d", r->terrain->_name, r->age);
|
umvwprintw(win, line++, 1, "%s, age %d", r->terrain->_name, r->age);
|
||||||
if (r->land) {
|
if (r->land) {
|
||||||
|
int iron = region_getresource_level(r, get_resourcetype(R_IRON));
|
||||||
|
int stone = region_getresource_level(r, get_resourcetype(R_STONE));
|
||||||
mvwprintw(win, line++, 1, "$:%6d P:%5d", rmoney(r), rpeasants(r));
|
mvwprintw(win, line++, 1, "$:%6d P:%5d", rmoney(r), rpeasants(r));
|
||||||
|
mvwprintw(win, line++, 1, "S:%6d I:%5d", stone, iron);
|
||||||
mvwprintw(win, line++, 1, "H:%6d %s:%5d", rhorses(r),
|
mvwprintw(win, line++, 1, "H:%6d %s:%5d", rhorses(r),
|
||||||
(r->flags & RF_MALLORN) ? "M" : "T",
|
(r->flags & RF_MALLORN) ? "M" : "T",
|
||||||
r->land->trees[1] + r->land->trees[2]);
|
r->land->trees[1] + r->land->trees[2]);
|
||||||
|
@ -515,6 +523,33 @@ static void statusline(WINDOW * win, const char *str)
|
||||||
wnoutrefresh(win);
|
wnoutrefresh(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_resources(region *r, const struct terrain_type *terrain)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; terrain->production[i].type; ++i) {
|
||||||
|
rawmaterial *rm;
|
||||||
|
const terrain_production *production = terrain->production + i;
|
||||||
|
const resource_type *rtype = production->type;
|
||||||
|
|
||||||
|
for (rm = r->resources; rm; rm = rm->next) {
|
||||||
|
if (rm->rtype == rtype)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rm) {
|
||||||
|
struct rawmaterial_type *rmt;
|
||||||
|
set_resource(rm,
|
||||||
|
dice_rand(production->startlevel),
|
||||||
|
dice_rand(production->base),
|
||||||
|
dice_rand(production->divisor));
|
||||||
|
rmt = rmt_get(rtype);
|
||||||
|
if (rmt && rmt->terraform) {
|
||||||
|
rmt->terraform(rm, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void reset_region(region *r) {
|
static void reset_region(region *r) {
|
||||||
unit **up = &r->units;
|
unit **up = &r->units;
|
||||||
bool players = false;
|
bool players = false;
|
||||||
|
@ -540,6 +575,7 @@ static void reset_region(region *r) {
|
||||||
}
|
}
|
||||||
if (r->land) {
|
if (r->land) {
|
||||||
init_region(r);
|
init_region(r);
|
||||||
|
reset_resources(r, r->terrain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -585,6 +621,69 @@ static void terraform_at(coordinate * c, const terrain_type * terrain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void selection_walk(selection * selected, void(*callback)(region *, void *), void *udata) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i != MAXTHASH; ++i) {
|
||||||
|
tag **tp = &selected->tags[i];
|
||||||
|
while (*tp) {
|
||||||
|
region *r;
|
||||||
|
tag *t = *tp;
|
||||||
|
int nx = t->coord.x, ny = t->coord.y;
|
||||||
|
plane *pl = t->coord.pl;
|
||||||
|
|
||||||
|
pnormalize(&nx, &ny, pl);
|
||||||
|
r = findregion(nx, ny);
|
||||||
|
if (r != NULL) {
|
||||||
|
callback(r, udata);
|
||||||
|
}
|
||||||
|
tp = &t->nexthash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_levels_cb(region *r, void *udata) {
|
||||||
|
struct rawmaterial *res;
|
||||||
|
UNUSED_ARG(udata);
|
||||||
|
for (res = r->resources; res; res = res->next) {
|
||||||
|
if (res->level > 3) {
|
||||||
|
res->level = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BUG 2506: reset drained mountains to level 1
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fix_selection(selection * selected)
|
||||||
|
{
|
||||||
|
selection_walk(selected, reset_levels_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_selection(selection * selected)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i != MAXTHASH; ++i) {
|
||||||
|
tag **tp = &selected->tags[i];
|
||||||
|
while (*tp) {
|
||||||
|
region *r;
|
||||||
|
tag *t = *tp;
|
||||||
|
int nx = t->coord.x, ny = t->coord.y;
|
||||||
|
plane *pl = t->coord.pl;
|
||||||
|
|
||||||
|
pnormalize(&nx, &ny, pl);
|
||||||
|
r = findregion(nx, ny);
|
||||||
|
if (r != NULL) {
|
||||||
|
reset_region(r);
|
||||||
|
}
|
||||||
|
tp = &t->nexthash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
terraform_selection(selection * selected, const terrain_type * terrain)
|
terraform_selection(selection * selected, const terrain_type * terrain)
|
||||||
{
|
{
|
||||||
|
@ -694,7 +793,7 @@ void highlight_region(region * r, int toggle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void select_coordinate(struct selection *selected, int nx, int ny, int toggle)
|
void select_coordinate(struct selection *selected, int nx, int ny, bool toggle)
|
||||||
{
|
{
|
||||||
if (toggle)
|
if (toggle)
|
||||||
tag_region(selected, nx, ny);
|
tag_region(selected, nx, ny);
|
||||||
|
@ -702,7 +801,50 @@ void select_coordinate(struct selection *selected, int nx, int ny, int toggle)
|
||||||
untag_region(selected, nx, ny);
|
untag_region(selected, nx, ny);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { MODE_MARK, MODE_SELECT, MODE_UNMARK, MODE_UNSELECT };
|
enum select_t { MODE_MARK, MODE_SELECT, MODE_UNMARK, MODE_UNSELECT };
|
||||||
|
|
||||||
|
static void select_island(state *st, int selectmode)
|
||||||
|
{
|
||||||
|
region *r;
|
||||||
|
int nx = st->cursor.x;
|
||||||
|
int ny = st->cursor.y;
|
||||||
|
|
||||||
|
pnormalize(&nx, &ny, st->cursor.pl);
|
||||||
|
r = findregion(nx, ny);
|
||||||
|
if (r && r->land) {
|
||||||
|
selist *ql, *stack = NULL;
|
||||||
|
int qi = 0;
|
||||||
|
|
||||||
|
selist_push(&stack, r);
|
||||||
|
for (ql = stack, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||||
|
region *r = (region *)selist_get(ql, qi);
|
||||||
|
region *rnext[MAXDIRECTIONS];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fset(r, RF_MARK);
|
||||||
|
if (selectmode & MODE_SELECT) {
|
||||||
|
select_coordinate(st->selected, r->x, r->y,
|
||||||
|
selectmode == MODE_SELECT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
highlight_region(r, selectmode == MODE_MARK);
|
||||||
|
}
|
||||||
|
get_neighbours(r, rnext);
|
||||||
|
for (i = 0; i != MAXDIRECTIONS; ++i) {
|
||||||
|
region *rn = rnext[i];
|
||||||
|
if (rn && rn->land && !fval(rn, RF_MARK)) {
|
||||||
|
selist_push(&stack, rn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ql = stack, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||||
|
region *r = (region *)selist_get(ql, qi);
|
||||||
|
freset(r, RF_MARK);
|
||||||
|
}
|
||||||
|
selist_free(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void select_regions(state * st, int selectmode)
|
static void select_regions(state * st, int selectmode)
|
||||||
{
|
{
|
||||||
|
@ -856,6 +998,11 @@ static void select_regions(state * st, int selectmode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (findmode == 'i') {
|
||||||
|
sprintf(sbuffer, "%swand: ", status);
|
||||||
|
statusline(st->wnd_status->handle, sbuffer);
|
||||||
|
select_island(st, selectmode);
|
||||||
|
}
|
||||||
else if (findmode == 't') {
|
else if (findmode == 't') {
|
||||||
const struct terrain_type *terrain;
|
const struct terrain_type *terrain;
|
||||||
sprintf(sbuffer, "%sterrain: ", status);
|
sprintf(sbuffer, "%sterrain: ", status);
|
||||||
|
@ -1186,7 +1333,12 @@ static void handlekey(state * st, int c)
|
||||||
statusline(st->wnd_status->handle, "tag-");
|
statusline(st->wnd_status->handle, "tag-");
|
||||||
doupdate();
|
doupdate();
|
||||||
switch (getch()) {
|
switch (getch()) {
|
||||||
|
case 'r':
|
||||||
|
reset_selection(st->selected);
|
||||||
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
|
fix_selection(st->selected);
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
terraform_selection(st->selected, select_terrain(st, NULL));
|
terraform_selection(st->selected, select_terrain(st, NULL));
|
||||||
st->modified = 1;
|
st->modified = 1;
|
||||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
||||||
const char *prompt);
|
const char *prompt);
|
||||||
|
|
||||||
void highlight_region(struct region *r, int on);
|
void highlight_region(struct region *r, int on);
|
||||||
void select_coordinate(struct selection *selected, int x, int y, int on);
|
void select_coordinate(struct selection *selected, int x, int y, bool on);
|
||||||
void run_mapper(void);
|
void run_mapper(void);
|
||||||
|
|
||||||
extern int force_color;
|
extern int force_color;
|
||||||
|
|
|
@ -527,28 +527,19 @@ int build_skill(unit *u, int basesk, int skill_mod) {
|
||||||
* of the first object have already been finished. return the
|
* of the first object have already been finished. return the
|
||||||
* actual size that could be built.
|
* actual size that could be built.
|
||||||
*/
|
*/
|
||||||
int build(unit * u, const construction * ctype, int completed, int want, int skill_mod)
|
static int build_limited(unit * u, const construction * con, int completed, int want, int basesk, int *skill_total) {
|
||||||
{
|
int skills = *skill_total;
|
||||||
const construction *con = ctype;
|
|
||||||
int skills = INT_MAX; /* number of skill points remainig */
|
|
||||||
int basesk = 0;
|
|
||||||
int made = 0;
|
int made = 0;
|
||||||
|
|
||||||
if (want <= 0)
|
if (want <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (con == NULL) {
|
if (con == NULL) {
|
||||||
return ENOMATERIALS;
|
return ENOMATERIALS;
|
||||||
}
|
}
|
||||||
if (completed == con->maxsize) {
|
if (completed == con->maxsize) {
|
||||||
return ECOMPLETE;
|
return ECOMPLETE;
|
||||||
}
|
}
|
||||||
if (con->skill != NOSKILL) {
|
|
||||||
basesk = effskill(u, con->skill, 0);
|
|
||||||
if (basesk == 0)
|
|
||||||
return ENEEDSKILL;
|
|
||||||
|
|
||||||
skills = build_skill(u, basesk, skill_mod);
|
|
||||||
}
|
|
||||||
for (; want > 0 && skills > 0;) {
|
for (; want > 0 && skills > 0;) {
|
||||||
int err, n;
|
int err, n;
|
||||||
|
|
||||||
|
@ -615,9 +606,27 @@ int build(unit * u, const construction * ctype, int completed, int want, int ski
|
||||||
want -= n;
|
want -= n;
|
||||||
completed = completed + n;
|
completed = completed + n;
|
||||||
}
|
}
|
||||||
/* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
|
*skill_total = skills;
|
||||||
produceexp(u, ctype->skill, (made < u->number) ? made : u->number);
|
return made;
|
||||||
|
}
|
||||||
|
|
||||||
|
int build(unit * u, const construction * con, int completed, int want, int skill_mod)
|
||||||
|
{
|
||||||
|
int skills = INT_MAX; /* number of skill points remainig */
|
||||||
|
int made, basesk = 0;
|
||||||
|
|
||||||
|
assert(con->skill != NOSKILL);
|
||||||
|
basesk = effskill(u, con->skill, 0);
|
||||||
|
if (basesk == 0) {
|
||||||
|
return ENEEDSKILL;
|
||||||
|
}
|
||||||
|
|
||||||
|
skills = build_skill(u, basesk, skill_mod);
|
||||||
|
made = build_limited(u, con, completed, want, basesk, &skills);
|
||||||
|
/* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
|
||||||
|
if (made > 0) {
|
||||||
|
produceexp(u, con->skill, (made < u->number) ? made : u->number);
|
||||||
|
}
|
||||||
return made;
|
return made;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +695,7 @@ static int build_failure(unit *u, order *ord, const building_type *btype, int wa
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int build_stages(unit *u, const building_type *btype, int built, int n) {
|
static int build_stages(unit *u, const building_type *btype, int built, int n, int basesk, int *skill_total) {
|
||||||
|
|
||||||
const building_stage *stage;
|
const building_stage *stage;
|
||||||
int made = 0;
|
int made = 0;
|
||||||
|
@ -706,7 +715,7 @@ static int build_stages(unit *u, const building_type *btype, int built, int n) {
|
||||||
want = todo;
|
want = todo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = build(u, con, built, want, 0);
|
err = build_limited(u, con, built, want, basesk, skill_total);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (made == 0) {
|
if (made == 0) {
|
||||||
/* could not make any part at all */
|
/* could not make any part at all */
|
||||||
|
@ -744,10 +753,14 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
|
||||||
const char *btname;
|
const char *btname;
|
||||||
order *new_order = NULL;
|
order *new_order = NULL;
|
||||||
const struct locale *lang = u->faction->locale;
|
const struct locale *lang = u->faction->locale;
|
||||||
|
int skills, basesk; /* number of skill points remainig */
|
||||||
|
|
||||||
assert(u->number);
|
assert(u->number);
|
||||||
assert(btype->stages && btype->stages->construction);
|
assert(btype->stages && btype->stages->construction);
|
||||||
if (effskill(u, SK_BUILDING, 0) == 0) {
|
|
||||||
|
basesk = effskill(u, SK_BUILDING, 0);
|
||||||
|
skills = build_skill(u, basesk, 0);
|
||||||
|
if (skills == 0) {
|
||||||
cmistake(u, ord, 101, MSG_PRODUCE);
|
cmistake(u, ord, 101, MSG_PRODUCE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -832,7 +845,7 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
built = build_stages(u, btype, built, n);
|
built = build_stages(u, btype, built, n, basesk, &skills);
|
||||||
|
|
||||||
if (built < 0) {
|
if (built < 0) {
|
||||||
return build_failure(u, ord, btype, want, built);
|
return build_failure(u, ord, btype, want, built);
|
||||||
|
|
|
@ -22,8 +22,9 @@
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
typedef struct build_fixture {
|
typedef struct build_fixture {
|
||||||
faction *f;
|
faction *f;
|
||||||
|
@ -57,6 +58,53 @@ static unit * setup_build(build_fixture *bf) {
|
||||||
return bf->u;
|
return bf->u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static building_type *setup_castle(item_type *it_stone) {
|
||||||
|
building_type *btype;
|
||||||
|
building_stage *stage;
|
||||||
|
construction * cons;
|
||||||
|
|
||||||
|
btype = test_create_buildingtype("castle");
|
||||||
|
stage = btype->stages = calloc(1, sizeof(building_stage));
|
||||||
|
cons = stage->construction = calloc(1, sizeof(construction));
|
||||||
|
cons->materials = calloc(2, sizeof(requirement));
|
||||||
|
cons->materials[0].number = 1;
|
||||||
|
cons->materials[0].rtype = it_stone->rtype;
|
||||||
|
cons->minskill = 1;
|
||||||
|
cons->maxsize = 2;
|
||||||
|
cons->reqsize = 1;
|
||||||
|
cons->skill = SK_BUILDING;
|
||||||
|
stage = stage->next = calloc(1, sizeof(building_stage));
|
||||||
|
cons = stage->construction = calloc(1, sizeof(construction));
|
||||||
|
cons->materials = calloc(2, sizeof(requirement));
|
||||||
|
cons->materials[0].number = 1;
|
||||||
|
cons->materials[0].rtype = it_stone->rtype;
|
||||||
|
cons->minskill = 1;
|
||||||
|
cons->maxsize = 8;
|
||||||
|
cons->reqsize = 1;
|
||||||
|
cons->skill = SK_BUILDING;
|
||||||
|
return btype;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_build_building_stages(CuTest *tc) {
|
||||||
|
building_type *btype;
|
||||||
|
item_type *it_stone;
|
||||||
|
unit *u;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
init_resources();
|
||||||
|
it_stone = test_create_itemtype("stone");
|
||||||
|
btype = setup_castle(it_stone);
|
||||||
|
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||||
|
set_level(u, SK_BUILDING, 2);
|
||||||
|
i_change(&u->items, it_stone, 4);
|
||||||
|
build_building(u, btype, -1, INT_MAX, NULL);
|
||||||
|
CuAssertPtrNotNull(tc, u->building);
|
||||||
|
CuAssertIntEquals(tc, 2, u->building->size);
|
||||||
|
CuAssertIntEquals(tc, 2, i_get(u->items, it_stone));
|
||||||
|
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
static void teardown_build(build_fixture *bf) {
|
static void teardown_build(build_fixture *bf) {
|
||||||
free(bf->cons.materials);
|
free(bf->cons.materials);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
|
@ -395,6 +443,7 @@ CuSuite *get_build_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_build_with_ring);
|
SUITE_ADD_TEST(suite, test_build_with_ring);
|
||||||
SUITE_ADD_TEST(suite, test_build_with_potion);
|
SUITE_ADD_TEST(suite, test_build_with_potion);
|
||||||
SUITE_ADD_TEST(suite, test_build_building_success);
|
SUITE_ADD_TEST(suite, test_build_building_success);
|
||||||
|
SUITE_ADD_TEST(suite, test_build_building_stages);
|
||||||
SUITE_ADD_TEST(suite, test_build_building_with_golem);
|
SUITE_ADD_TEST(suite, test_build_building_with_golem);
|
||||||
SUITE_ADD_TEST(suite, test_build_building_no_materials);
|
SUITE_ADD_TEST(suite, test_build_building_no_materials);
|
||||||
SUITE_ADD_TEST(suite, test_build_destroy_cmd);
|
SUITE_ADD_TEST(suite, test_build_destroy_cmd);
|
||||||
|
|
|
@ -829,7 +829,7 @@ void free_land(land_region * lr)
|
||||||
free(lr);
|
free(lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void region_setresource(region * r, const resource_type * rtype, int value)
|
void region_setresource(region * r, const struct resource_type *rtype, int value)
|
||||||
{
|
{
|
||||||
rawmaterial *rm = r->resources;
|
rawmaterial *rm = r->resources;
|
||||||
while (rm) {
|
while (rm) {
|
||||||
|
@ -872,7 +872,18 @@ void region_setresource(region * r, const resource_type * rtype, int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int region_getresource(const region * r, const resource_type * rtype)
|
int region_getresource_level(const region * r, const struct resource_type * rtype)
|
||||||
|
{
|
||||||
|
const rawmaterial *rm;
|
||||||
|
for (rm = r->resources; rm; rm = rm->next) {
|
||||||
|
if (rm->rtype == rtype) {
|
||||||
|
return rm->level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int region_getresource(const region * r, const struct resource_type *rtype)
|
||||||
{
|
{
|
||||||
const rawmaterial *rm;
|
const rawmaterial *rm;
|
||||||
for (rm = r->resources; rm; rm = rm->next) {
|
for (rm = r->resources; rm; rm = rm->next) {
|
||||||
|
|
|
@ -263,6 +263,8 @@ extern "C" {
|
||||||
void region_setname(struct region *self, const char *name);
|
void region_setname(struct region *self, const char *name);
|
||||||
const char *region_getinfo(const struct region *self);
|
const char *region_getinfo(const struct region *self);
|
||||||
void region_setinfo(struct region *self, const char *name);
|
void region_setinfo(struct region *self, const char *name);
|
||||||
|
int region_getresource_level(const struct region * r,
|
||||||
|
const struct resource_type * rtype);
|
||||||
int region_getresource(const struct region *r,
|
int region_getresource(const struct region *r,
|
||||||
const struct resource_type *rtype);
|
const struct resource_type *rtype);
|
||||||
void region_setresource(struct region *r, const struct resource_type *rtype,
|
void region_setresource(struct region *r, const struct resource_type *rtype,
|
||||||
|
|
|
@ -46,8 +46,6 @@ void update_resources(region * r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int dice_rand(const char *s);
|
|
||||||
|
|
||||||
static void update_resource(struct rawmaterial *res, double modifier)
|
static void update_resource(struct rawmaterial *res, double modifier)
|
||||||
{
|
{
|
||||||
double amount = (res->level - res->startlevel) / 100.0 * res->divisor + 1;
|
double amount = (res->level - res->startlevel) / 100.0 * res->divisor + 1;
|
||||||
|
@ -59,6 +57,15 @@ static void update_resource(struct rawmaterial *res, double modifier)
|
||||||
assert(res->amount > 0);
|
assert(res->amount > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_resource(struct rawmaterial *rm, int level, int base, int divisor)
|
||||||
|
{
|
||||||
|
rm->level = level;
|
||||||
|
rm->startlevel = level;
|
||||||
|
rm->base = base;
|
||||||
|
rm->amount = base;
|
||||||
|
rm->divisor = divisor;
|
||||||
|
}
|
||||||
|
|
||||||
struct rawmaterial *
|
struct rawmaterial *
|
||||||
add_resource(region * r, int level, int base, int divisor,
|
add_resource(region * r, int level, int base, int divisor,
|
||||||
const resource_type * rtype)
|
const resource_type * rtype)
|
||||||
|
@ -67,13 +74,9 @@ const resource_type * rtype)
|
||||||
|
|
||||||
rm->next = r->resources;
|
rm->next = r->resources;
|
||||||
r->resources = rm;
|
r->resources = rm;
|
||||||
rm->level = level;
|
|
||||||
rm->startlevel = level;
|
|
||||||
rm->base = base;
|
|
||||||
rm->amount = base;
|
|
||||||
rm->divisor = divisor;
|
|
||||||
rm->flags = 0;
|
rm->flags = 0;
|
||||||
rm->rtype = rtype;
|
rm->rtype = rtype;
|
||||||
|
set_resource(rm, level, base, divisor);
|
||||||
return rm;
|
return rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ extern "C" {
|
||||||
const struct resource_type *);
|
const struct resource_type *);
|
||||||
struct rawmaterial_type *rmt_get(const struct resource_type *);
|
struct rawmaterial_type *rmt_get(const struct resource_type *);
|
||||||
|
|
||||||
|
void set_resource(struct rawmaterial *rm, int level, int base, int divisor);
|
||||||
struct rawmaterial *add_resource(struct region *r, int level,
|
struct rawmaterial *add_resource(struct region *r, int level,
|
||||||
int base, int divisor, const struct resource_type *rtype);
|
int base, int divisor, const struct resource_type *rtype);
|
||||||
struct rawmaterial_type *rmt_create(struct resource_type *rtype);
|
struct rawmaterial_type *rmt_create(struct resource_type *rtype);
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct skill {
|
typedef struct skill {
|
||||||
skill_t id : 8;
|
int id : 8;
|
||||||
int level : 8;
|
int level : 8;
|
||||||
int weeks : 8;
|
int weeks : 8;
|
||||||
int old : 8;
|
int old : 8;
|
||||||
|
|
Loading…
Reference in New Issue