mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-13 10:50:35 +00:00
crossbow:: geometric lines option
This commit is contained in:
parent
8984cd8cd2
commit
c336e9d385
@ -1554,7 +1554,8 @@ EX void initConfig() {
|
||||
};
|
||||
param_enum(bow::style, "bow_style", "bow_style", bow::style)
|
||||
-> editable({{"bull line", "Can go in either direction on odd shapes. 3 turns to reload."},
|
||||
{"geodesic", "Graph geodesic: any sequence of tiles is OK as long as there are no shortcuts. 4 turns to reload."}},
|
||||
{"geodesic", "Graph geodesic: any sequence of tiles is OK as long as there are no shortcuts. 4 turns to reload."},
|
||||
{"geometric", "Approximations of geometric straight lines."}},
|
||||
"crossbow straight line style", 'l')
|
||||
-> set_need_confirm()
|
||||
-> set_value_to = [] (bow::eCrossbowStyle s) { bool b = game_active; if(s != bow::style) stop_game(); bow::style = s; if(b) start_game(); };
|
||||
|
112
crossbow.cpp
112
crossbow.cpp
@ -27,7 +27,7 @@ EX namespace bow {
|
||||
|
||||
#if HDR
|
||||
enum eWeapon { wBlade, wCrossbow };
|
||||
enum eCrossbowStyle { cbBull, cbGeodesic };
|
||||
enum eCrossbowStyle { cbBull, cbGeodesic, cbGeometric };
|
||||
#endif
|
||||
|
||||
EX eWeapon weapon;
|
||||
@ -79,7 +79,37 @@ EX int qadd(cellwalker a, cellwalker b) {
|
||||
return NODIR;
|
||||
}
|
||||
|
||||
EX int create_path() {
|
||||
int best_score_res;
|
||||
|
||||
EX int bolt_score(cellwalker cw2) {
|
||||
int d = cw2.at->cpdist;
|
||||
int ntotal = 2;
|
||||
if(inmirror(cw2.at)) cw2 = mirror::reflect(cw2);
|
||||
if(blocks(cw2.cpeek())) return -1;
|
||||
if(thruVine(cw2.at, cw2.cpeek())) return -1;
|
||||
|
||||
if(cw2.at->monst) {
|
||||
flagtype attackflags = AF_BOW;
|
||||
if(items[itOrbSpeed]&1) attackflags |= AF_FAST;
|
||||
if(items[itOrbSlaying]) attackflags |= AF_CRUSH;
|
||||
if(items[itCurseWeakness]) attackflags |= AF_WEAK;
|
||||
if(canAttack(cw2.cpeek(), moPlayer, cw2.at, cw2.at->monst, attackflags)) {
|
||||
ntotal += 10000; ntotal += 1280 >> d;
|
||||
}
|
||||
}
|
||||
|
||||
for(int t=0; t<cw2.at->type; t++) {
|
||||
cell *c1 = cw2.at->cmove(t);
|
||||
if(!logical_adjacent(cw2.cpeek(), moPlayer, c1)) continue;
|
||||
if(canAttack(cw2.cpeek(),moPlayer,c1,c1->monst,AF_STAB)) {
|
||||
ntotal += 10000; ntotal += 1280 >> d;
|
||||
}
|
||||
}
|
||||
|
||||
return ntotal;
|
||||
}
|
||||
|
||||
EX vector<int> create_dirseq() {
|
||||
map<cell*, bowscore> scores;
|
||||
scores[cwt.at].total = 0;
|
||||
|
||||
@ -93,33 +123,11 @@ EX int create_path() {
|
||||
best.total = -1;
|
||||
forCellIdEx(c1, i, c) if(c1->cpdist < c->cpdist && scores.count(c1)) {
|
||||
auto& last = scores[c1];
|
||||
int ntotal = last.total;
|
||||
auto ocw2 = cellwalker(c, i);
|
||||
auto cw2 = ocw2;
|
||||
if(inmirror(c)) cw2 = mirror::reflect(cw2);
|
||||
if(blocks(cw2.cpeek())) continue;
|
||||
if(thruVine(cw2.at, cw2.cpeek())) continue;
|
||||
int bonus = bolt_score(ocw2);
|
||||
if(bonus < 0) continue;
|
||||
int ntotal = last.total + bonus;
|
||||
|
||||
if(cw2.at->monst) {
|
||||
flagtype attackflags = AF_BOW;
|
||||
if(items[itOrbSpeed]&1) attackflags |= AF_FAST;
|
||||
if(items[itOrbSlaying]) attackflags |= AF_CRUSH;
|
||||
if(items[itCurseWeakness]) attackflags |= AF_WEAK;
|
||||
if(canAttack(cw2.cpeek(), moPlayer, cw2.at, cw2.at->monst, attackflags)) {
|
||||
ntotal += 10000; ntotal += 1280 >> c->cpdist;
|
||||
}
|
||||
}
|
||||
|
||||
for(int t=0; t<cw2.at->type; t++) {
|
||||
cell *c1 = cw2.at->move(t);
|
||||
if(!c) continue;
|
||||
if(!logical_adjacent(cw2.cpeek(), moPlayer, c1)) continue;
|
||||
if(canAttack(cw2.cpeek(),moPlayer,c1,c1->monst,AF_STAB)) {
|
||||
ntotal += 10000; ntotal += 1280 >> c->cpdist;
|
||||
}
|
||||
}
|
||||
|
||||
ntotal += 2;
|
||||
int dir = 0;
|
||||
if(c->cpdist > 1) {
|
||||
dir = qadd(last.last, ocw2+wstep);
|
||||
@ -143,7 +151,7 @@ EX int create_path() {
|
||||
if(best.total > -1) scores[c] = best;
|
||||
}
|
||||
|
||||
if(best_score == -1) return best_score;
|
||||
if(best_score == -1) return {};
|
||||
|
||||
vector<int> dirseq = { NODIR };
|
||||
while(best_score_at != cwt.at) {
|
||||
@ -153,6 +161,51 @@ EX int create_path() {
|
||||
}
|
||||
reverse(dirseq.begin(), dirseq.end());
|
||||
|
||||
best_score_res = best_score;
|
||||
return dirseq;
|
||||
}
|
||||
|
||||
EX vector<int> create_dirseq_geometric() {
|
||||
cell *tgt = nullptr;
|
||||
for(auto t: target_at) tgt = t.second;
|
||||
if(!tgt) return {};
|
||||
hyperpoint h = tC0(currentmap->relative_matrix(tgt, cwt.at, C0));
|
||||
transmatrix T = spintox(h);
|
||||
|
||||
best_score_res = 0;
|
||||
cellwalker at = cwt;
|
||||
vector<int> dirseq;
|
||||
while(true) {
|
||||
int best_i = -1;
|
||||
ld best_y = HUGE_VAL;
|
||||
for(int i=0; i<at.at->type; i++) {
|
||||
cellwalker at1 = at + i;
|
||||
if(at1.cpeek()->cpdist != at.at->cpdist + 1) continue;
|
||||
transmatrix U = T * currentmap->adj(at.at, at1.spin);
|
||||
hyperpoint U0 = tC0(U);
|
||||
hyperpoint T0 = tC0(T);
|
||||
if(U0[0] < T0[0] + 1e-6) continue;
|
||||
ld y;
|
||||
if(GDIM == 3) y = hypot(U0[1], U0[2]); else y = abs(U0[1]) + (U0[1] > 0 ? 1e-6 : 0);
|
||||
if(y < best_y) { best_y = y; best_i = i; }
|
||||
}
|
||||
if(best_i < 0) break;
|
||||
at = at + best_i;
|
||||
int bonus = bolt_score(at + wstep);
|
||||
if(bonus < 0) break;
|
||||
best_score_res += bonus;
|
||||
dirseq.push_back(best_i);
|
||||
T = T * currentmap->adj(at.at, at.spin);
|
||||
at = at + wstep;
|
||||
}
|
||||
|
||||
return dirseq;
|
||||
}
|
||||
|
||||
EX int create_path() {
|
||||
auto dirseq = style == cbGeometric ? create_dirseq_geometric() : create_dirseq();
|
||||
if(dirseq.empty()) return -1;
|
||||
|
||||
struct bolt {
|
||||
cellwalker at;
|
||||
flagtype flags;
|
||||
@ -198,7 +251,7 @@ EX int create_path() {
|
||||
broken_mirrors = next_broken_mirrors;
|
||||
}
|
||||
|
||||
return best_score;
|
||||
return best_score_res;
|
||||
}
|
||||
|
||||
EX void clear_bowpath() {
|
||||
@ -255,6 +308,7 @@ EX void add_fire(cell *c) {
|
||||
}
|
||||
else {
|
||||
t = c;
|
||||
if(style == cbGeometric) { target_at = {}; target_at[c->cpdist] = c; }
|
||||
int res = create_path();
|
||||
if(res == -1) {
|
||||
if(!emp) {
|
||||
|
Loading…
Reference in New Issue
Block a user