mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-06-26 15:12:48 +00:00
crossbow:: mimics shoot too
This commit is contained in:
parent
9da8206a9f
commit
41e28c34b2
@ -2626,22 +2626,22 @@ void celldrawer::add_map_effects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(1) {
|
if(1) {
|
||||||
for(auto& m: bow::last_bowpath) if(m.next.s == c) {
|
for(auto& m: bow::last_bowpath) if(m.next.at == c) {
|
||||||
|
|
||||||
hyperpoint h0 = C0, t0 = Hypc, h1 = C0, t1 = Hypc;
|
hyperpoint h0 = C0, t0 = Hypc, h1 = C0, t1 = Hypc;
|
||||||
bool birth = false;
|
bool birth = m.first;
|
||||||
|
|
||||||
if(m.last.d != STAY) {
|
if(!birth) {
|
||||||
ld d = cellgfxdist(c, m.last.d) / 2;
|
ld d = cellgfxdist(c, m.prev.spin) / 2;
|
||||||
h0 = ddspin(c, m.last.d) * xpush0(d);
|
h0 = ddspin(c, m.prev.spin) * xpush0(d);
|
||||||
t0 = ddspin(c, m.last.d) * xpush(d) * xtangent(-d*2);
|
t0 = ddspin(c, m.prev.spin) * xpush(d) * xtangent(-d*2);
|
||||||
}
|
}
|
||||||
else birth = true;
|
else birth = true;
|
||||||
|
|
||||||
if(m.next.d != STAY) {
|
if(!m.last) {
|
||||||
ld d = cellgfxdist(c, m.next.d) / 2;
|
ld d = cellgfxdist(c, m.next.spin) / 2;
|
||||||
h1 = ddspin(c, m.next.d) * xpush0(d);
|
h1 = ddspin(c, m.next.spin) * xpush0(d);
|
||||||
t1 = ddspin(c, m.next.d) * xpush(d) * xtangent(-d*2);
|
t1 = ddspin(c, m.next.spin) * xpush(d) * xtangent(-d*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ld t = frac(ptick(PURE?500:250));
|
ld t = frac(ptick(PURE?500:250));
|
||||||
|
100
crossbow.cpp
100
crossbow.cpp
@ -38,10 +38,17 @@ EX bool crossbow_mode() { return weapon == wCrossbow; }
|
|||||||
|
|
||||||
#if HDR
|
#if HDR
|
||||||
struct bowpoint {
|
struct bowpoint {
|
||||||
|
cellwalker prev, next;
|
||||||
|
bool first, last;
|
||||||
|
bool copied;
|
||||||
|
bool mirrored;
|
||||||
|
bowpoint() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bowscore {
|
||||||
int total;
|
int total;
|
||||||
movei last, next, lastun;
|
cellwalker last;
|
||||||
cell *con;
|
int turns;
|
||||||
bowpoint() : last(nullptr), next(nullptr), lastun(nullptr) { total = 0; }
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -56,14 +63,20 @@ EX int loading_time() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EX bool blocks(cell *c) {
|
EX bool blocks(cell *c) {
|
||||||
if(isWall(c) && c->wall != waMirrorWall) return true;
|
if(isWall(c) && !among(c->wall, waMirrorWall, waMirror, waCloud)) return true;
|
||||||
|
// if(c->monst && isMultitile(c->monst)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX int qadd(cellwalker a, cellwalker b) {
|
||||||
|
hassert(a.at == b.at);
|
||||||
|
for(int i=0; i<a.at->type; i++) if(a+i == b) return i;
|
||||||
|
return NODIR;
|
||||||
|
}
|
||||||
|
|
||||||
EX int create_path() {
|
EX int create_path() {
|
||||||
map<cell*, bowpoint> scores;
|
map<cell*, bowscore> scores;
|
||||||
scores[cwt.at] = bowpoint();
|
scores[cwt.at].total = 0;
|
||||||
scores[cwt.at].last = movei(cwt.at, STAY);
|
|
||||||
|
|
||||||
int best_score = -1; cell* best_score_at = cwt.at;
|
int best_score = -1; cell* best_score_at = cwt.at;
|
||||||
|
|
||||||
@ -71,38 +84,89 @@ EX int create_path() {
|
|||||||
cell *c1 = target_at[c->cpdist];
|
cell *c1 = target_at[c->cpdist];
|
||||||
if(c1 && c != c1) continue;
|
if(c1 && c != c1) continue;
|
||||||
if(c == c1) { best_score = -1; }
|
if(c == c1) { best_score = -1; }
|
||||||
bowpoint best;
|
bowscore best;
|
||||||
best.total = -1;
|
best.total = -1;
|
||||||
forCellIdEx(c1, i, c) if(c1->cpdist < c->cpdist && scores.count(c1)) {
|
forCellIdEx(c1, i, c) if(c1->cpdist < c->cpdist && scores.count(c1)) {
|
||||||
auto last = scores[c1];
|
auto& last = scores[c1];
|
||||||
int ntotal = last.total;
|
int ntotal = last.total;
|
||||||
auto cw2 = cellwalker(c, i);
|
auto ocw2 = cellwalker(c, i);
|
||||||
|
auto cw2 = ocw2;
|
||||||
if(inmirror(c)) cw2 = mirror::reflect(cw2);
|
if(inmirror(c)) cw2 = mirror::reflect(cw2);
|
||||||
if(blocks(cw2.peek())) continue;
|
if(blocks(cw2.peek())) continue;
|
||||||
if(cw2.at->monst) { ntotal += 10000; ntotal += 1280 >> c->cpdist; }
|
if(cw2.at->monst) { ntotal += 10000; ntotal += 1280 >> c->cpdist; }
|
||||||
ntotal += 2;
|
ntotal += 2;
|
||||||
|
int dir = 0;
|
||||||
if(c->cpdist > 1) {
|
if(c->cpdist > 1) {
|
||||||
int d = abs(szgmod(last.lastun.d - c->c.spin(i), c1->type));
|
dir = qadd(last.last, ocw2+wstep);
|
||||||
|
int d = abs(szgmod(dir, c1->type));
|
||||||
if(d != c1->type / 2) {
|
if(d != c1->type / 2) {
|
||||||
if(style == cbGeodesic) ntotal--;
|
if(style == cbGeodesic) ntotal--;
|
||||||
if(style == cbBull) continue;
|
if(style == cbBull) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ntotal > best.total) { best.total = ntotal; best.lastun = movei(c, i); best.last = movei(cw2.at, cw2.spin); best.con = c1; best.next = movei(cw2.at, STAY); }
|
else {
|
||||||
|
dir = qadd(cwt, ocw2+wstep);
|
||||||
|
}
|
||||||
|
if(ntotal > best.total) {
|
||||||
|
best.total = ntotal;
|
||||||
|
best.last = ocw2;
|
||||||
|
best.turns = dir;
|
||||||
|
}
|
||||||
best.total = max(best.total, ntotal);
|
best.total = max(best.total, ntotal);
|
||||||
}
|
}
|
||||||
if(best.total > best_score) { best_score = best.total; best_score_at = c; }
|
if(best.total > best_score) { best_score = best.total; best_score_at = c; }
|
||||||
if(best.total > -1) scores[c] = best;
|
if(best.total > -1) scores[c] = best;
|
||||||
}
|
}
|
||||||
|
|
||||||
bowpath.clear();
|
|
||||||
if(best_score == -1) return best_score;
|
if(best_score == -1) return best_score;
|
||||||
while(best_score_at != cwt.at) {
|
|
||||||
bowpath.push_back(scores[best_score_at]); best_score_at = bowpath.back().con; scores[best_score_at].next = bowpath.back().last.rev();
|
|
||||||
}
|
|
||||||
bowpath.push_back(scores[best_score_at]);
|
|
||||||
|
|
||||||
reverse(bowpath.begin(), bowpath.end());
|
vector<int> dirseq = { NODIR };
|
||||||
|
while(best_score_at != cwt.at) {
|
||||||
|
auto& at = scores[best_score_at];
|
||||||
|
dirseq.push_back(at.turns);
|
||||||
|
best_score_at = at.last.peek();
|
||||||
|
}
|
||||||
|
reverse(dirseq.begin(), dirseq.end());
|
||||||
|
|
||||||
|
println(hlog, "dirseq = ", dirseq);
|
||||||
|
|
||||||
|
bowpath.clear();
|
||||||
|
vector<cellwalker> bolts = { cwt };
|
||||||
|
for(auto m: mirror::mirrors) bolts.push_back(m.second);
|
||||||
|
|
||||||
|
set<cell*> broken_mirrors;
|
||||||
|
|
||||||
|
for(auto d: dirseq) {
|
||||||
|
bool first = bowpath.empty();
|
||||||
|
vector<cellwalker> nbolts;
|
||||||
|
set<cell*> next_broken_mirrors = broken_mirrors;
|
||||||
|
for(auto bolt: bolts) {
|
||||||
|
bowpath.emplace_back();
|
||||||
|
auto& p = bowpath.back();
|
||||||
|
p.prev = bolt;
|
||||||
|
p.first = first;
|
||||||
|
if(d == NODIR || blocks(bolt.at)) { p.next = bolt; p.last = true; }
|
||||||
|
else {
|
||||||
|
if(inmirror(bolt.at) || bolt.at->wall == waMirrorWall) bolt = mirror::reflect(bolt);
|
||||||
|
bolt += d;
|
||||||
|
p.next = bolt; p.last = false;
|
||||||
|
bolt += wstep;
|
||||||
|
if(among(bolt.at->wall, waCloud, waMirror) && !broken_mirrors.count(bolt.at)) {
|
||||||
|
auto &mir = mirror::mirrors;
|
||||||
|
vector<pair<int, cellwalker>> bmir;
|
||||||
|
swap(mir, bmir);
|
||||||
|
mirror::createHere(bolt, 0);
|
||||||
|
swap(mir, bmir);
|
||||||
|
for(auto b: bmir) nbolts.push_back(b.second);
|
||||||
|
next_broken_mirrors.insert(bolt.at);
|
||||||
|
}
|
||||||
|
nbolts.push_back(bolt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bolts = nbolts;
|
||||||
|
broken_mirrors = next_broken_mirrors;
|
||||||
|
}
|
||||||
|
|
||||||
return best_score;
|
return best_score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user