mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-28 11:00:34 +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) {
|
||||
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;
|
||||
bool birth = false;
|
||||
bool birth = m.first;
|
||||
|
||||
if(m.last.d != STAY) {
|
||||
ld d = cellgfxdist(c, m.last.d) / 2;
|
||||
h0 = ddspin(c, m.last.d) * xpush0(d);
|
||||
t0 = ddspin(c, m.last.d) * xpush(d) * xtangent(-d*2);
|
||||
if(!birth) {
|
||||
ld d = cellgfxdist(c, m.prev.spin) / 2;
|
||||
h0 = ddspin(c, m.prev.spin) * xpush0(d);
|
||||
t0 = ddspin(c, m.prev.spin) * xpush(d) * xtangent(-d*2);
|
||||
}
|
||||
else birth = true;
|
||||
|
||||
if(m.next.d != STAY) {
|
||||
ld d = cellgfxdist(c, m.next.d) / 2;
|
||||
h1 = ddspin(c, m.next.d) * xpush0(d);
|
||||
t1 = ddspin(c, m.next.d) * xpush(d) * xtangent(-d*2);
|
||||
if(!m.last) {
|
||||
ld d = cellgfxdist(c, m.next.spin) / 2;
|
||||
h1 = ddspin(c, m.next.spin) * xpush0(d);
|
||||
t1 = ddspin(c, m.next.spin) * xpush(d) * xtangent(-d*2);
|
||||
}
|
||||
|
||||
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
|
||||
struct bowpoint {
|
||||
cellwalker prev, next;
|
||||
bool first, last;
|
||||
bool copied;
|
||||
bool mirrored;
|
||||
bowpoint() {}
|
||||
};
|
||||
|
||||
struct bowscore {
|
||||
int total;
|
||||
movei last, next, lastun;
|
||||
cell *con;
|
||||
bowpoint() : last(nullptr), next(nullptr), lastun(nullptr) { total = 0; }
|
||||
cellwalker last;
|
||||
int turns;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -56,14 +63,20 @@ EX int loading_time() {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
map<cell*, bowpoint> scores;
|
||||
scores[cwt.at] = bowpoint();
|
||||
scores[cwt.at].last = movei(cwt.at, STAY);
|
||||
map<cell*, bowscore> scores;
|
||||
scores[cwt.at].total = 0;
|
||||
|
||||
int best_score = -1; cell* best_score_at = cwt.at;
|
||||
|
||||
@ -71,38 +84,89 @@ EX int create_path() {
|
||||
cell *c1 = target_at[c->cpdist];
|
||||
if(c1 && c != c1) continue;
|
||||
if(c == c1) { best_score = -1; }
|
||||
bowpoint best;
|
||||
bowscore best;
|
||||
best.total = -1;
|
||||
forCellIdEx(c1, i, c) if(c1->cpdist < c->cpdist && scores.count(c1)) {
|
||||
auto last = scores[c1];
|
||||
auto& last = scores[c1];
|
||||
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(blocks(cw2.peek())) continue;
|
||||
if(cw2.at->monst) { ntotal += 10000; ntotal += 1280 >> c->cpdist; }
|
||||
ntotal += 2;
|
||||
int dir = 0;
|
||||
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(style == cbGeodesic) ntotal--;
|
||||
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);
|
||||
}
|
||||
if(best.total > best_score) { best_score = best.total; best_score_at = c; }
|
||||
if(best.total > -1) scores[c] = best;
|
||||
}
|
||||
|
||||
bowpath.clear();
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user