first version of the Land of Dice
This commit is contained in:
parent
b879682d82
commit
6a6ed4ea0d
|
@ -104,6 +104,8 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
|
||||||
|
|
||||||
if(m1 == moArrowTrap && arrow_stuns(m2)) return true;
|
if(m1 == moArrowTrap && arrow_stuns(m2)) return true;
|
||||||
|
|
||||||
|
if(m2 == moAnimatedDie && !(flags & (AF_MAGIC | AF_CRUSH))) return false;
|
||||||
|
|
||||||
if(among(m2, moAltDemon, moHexDemon, moPair, moCrusher, moNorthPole, moSouthPole, moMonk) && !(flags & (AF_EAT | AF_MAGIC | AF_BULL | AF_CRUSH)))
|
if(among(m2, moAltDemon, moHexDemon, moPair, moCrusher, moNorthPole, moSouthPole, moMonk) && !(flags & (AF_EAT | AF_MAGIC | AF_BULL | AF_CRUSH)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -1601,8 +1601,19 @@ void celldrawer::draw_features() {
|
||||||
poly_outline = OUTLINE_DEFAULT;
|
poly_outline = OUTLINE_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(c->wall == waDie) {
|
else if(among(c->wall, waRichDie, waBlandDie)) {
|
||||||
dice::draw_die(c, V);
|
color_t col = darkena(winf[c->wall].color, 0, 0xFF);
|
||||||
|
|
||||||
|
ld footphase;
|
||||||
|
Vboat = V;
|
||||||
|
bool animated = applyAnimation(c, Vboat, footphase, LAYER_BOAT);
|
||||||
|
if(animated) {
|
||||||
|
transmatrix U = inverse_shift(V, Vboat);
|
||||||
|
U = rgpushxto0(tC0(U));
|
||||||
|
Vboat = V * U;
|
||||||
|
}
|
||||||
|
die_target = V;
|
||||||
|
dice::draw_die(c, Vboat, 1, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(c->wall == waExplosiveBarrel) {
|
else if(c->wall == waExplosiveBarrel) {
|
||||||
|
|
314
complex2.cpp
314
complex2.cpp
|
@ -904,73 +904,148 @@ EX }
|
||||||
|
|
||||||
EX namespace dice {
|
EX namespace dice {
|
||||||
|
|
||||||
/* vector<vector<int>> sides = {
|
struct die_structure {
|
||||||
{1, 3, 5}, {0, 4, 2}, {3, 1, 7}, {2, 6, 0}, {5, 7, 1}, {4, 0, 6}, {7, 5, 3}, {6, 2, 4}
|
vector<vector<int>> sides;
|
||||||
}; */
|
vector<vector<int>> spins;
|
||||||
|
vector<int> hardness;
|
||||||
vector<vector<int>> sides = {
|
int faces;
|
||||||
|
int order;
|
||||||
|
die_structure(int ord, const vector<vector<int>>& v) {
|
||||||
|
sides = v;
|
||||||
|
spins = sides;
|
||||||
|
faces = isize(sides);
|
||||||
|
order = ord;
|
||||||
|
for(int i=0; i<faces; i++)
|
||||||
|
for(int j=0; j<isize(sides[i]); j++) {
|
||||||
|
int i1 = sides[i][j];
|
||||||
|
spins[i][j] = -1;
|
||||||
|
for(int k=0; k<isize(sides[i1]); k++)
|
||||||
|
if(sides[i1][k] == i)
|
||||||
|
spins[i][j] = k;
|
||||||
|
if(spins[i][j] == -1)
|
||||||
|
println(hlog, "asymmetric");
|
||||||
|
}
|
||||||
|
hardness.resize(faces, 99);
|
||||||
|
hardness.back() = 0;
|
||||||
|
for(int it=0; it<faces; it++)
|
||||||
|
for(int i=0; i<faces; i++)
|
||||||
|
for(int j: sides[i])
|
||||||
|
hardness[i] = min(hardness[i], hardness[j]+1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
die_structure d20(5, {
|
||||||
{13-1, 7-1, 19-1}, {20-1, 12-1, 18-1}, {19-1, 17-1, 16-1}, {14-1, 18-1, 11-1}, {13-1, 18-1, 15-1},
|
{13-1, 7-1, 19-1}, {20-1, 12-1, 18-1}, {19-1, 17-1, 16-1}, {14-1, 18-1, 11-1}, {13-1, 18-1, 15-1},
|
||||||
{14-1, 9-1, 16-1}, { 1-1, 15-1, 17-1}, {20-1, 16-1, 10-1}, {19-1, 6-1, 11-1}, { 8-1, 17-1, 12-1},
|
{14-1, 9-1, 16-1}, { 1-1, 15-1, 17-1}, {20-1, 16-1, 10-1}, {19-1, 6-1, 11-1}, { 8-1, 17-1, 12-1},
|
||||||
{13-1, 9-1, 4-1}, { 2-1, 10-1, 15-1}, { 1-1, 11-1, 5-1}, {20-1, 4-1, 6-1}, { 7-1, 5-1, 12-1},
|
{13-1, 9-1, 4-1}, { 2-1, 10-1, 15-1}, { 1-1, 11-1, 5-1}, {20-1, 4-1, 6-1}, { 7-1, 5-1, 12-1},
|
||||||
{ 8-1, 6-1, 3-1}, { 7-1, 10-1, 3-1}, { 2-1, 5-1, 4-1}, { 1-1, 3-1, 9-1}, { 8-1, 2-1, 14-1}
|
{ 8-1, 6-1, 3-1}, { 7-1, 10-1, 3-1}, { 2-1, 5-1, 4-1}, { 1-1, 3-1, 9-1}, { 8-1, 2-1, 14-1}
|
||||||
|
});
|
||||||
|
|
||||||
|
die_structure d8(4, {
|
||||||
|
{1, 3, 5}, {0, 4, 2}, {3, 1, 7}, {2, 6, 0}, {5, 7, 1}, {4, 0, 6}, {7, 5, 3}, {6, 2, 4}
|
||||||
|
});
|
||||||
|
|
||||||
|
die_structure d4(3, {{3,2,1}, {3,0,2}, {1,0,3}, {0,1,2}});
|
||||||
|
|
||||||
|
#if HDR
|
||||||
|
struct die_data {
|
||||||
|
struct die_structure *which;
|
||||||
|
int val;
|
||||||
|
int dir;
|
||||||
|
int happy();
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
vector<vector<int>> spins;
|
int die_data::happy() {
|
||||||
int order;
|
if(val == which->faces-1) return 1;
|
||||||
|
if(val == 0) return -1;
|
||||||
int faces() { return isize(sides); }
|
return 0;
|
||||||
|
|
||||||
EX void generate_on(cell *c) {
|
|
||||||
c->wparam = hrand(faces()) + faces() * (1 + hrand(3) * 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prepared;
|
EX map<cell*, die_data> data;
|
||||||
|
|
||||||
void prepare() {
|
EX void generate_random(cell *c) {
|
||||||
if(prepared) return;
|
auto& dd = data[c];
|
||||||
prepared = true;
|
dd.which = pick(&d4, &d8, &d20);
|
||||||
spins = sides;
|
dd.val = hrand(dd.which->faces);
|
||||||
order = faces() == 8 ? 4 : 5;
|
dd.dir = 1 + hrand(3) * 2;
|
||||||
for(int i=0; i<faces(); i++)
|
}
|
||||||
for(int j=0; j<isize(sides[i]); j++) {
|
|
||||||
int i1 = sides[i][j];
|
EX void generate_specific(cell *c, die_structure *ds, int min_hardness, int max_hardness) {
|
||||||
spins[i][j] = -1;
|
auto& dd = data[c];
|
||||||
for(int k=0; k<isize(sides[i1]); k++)
|
dd.which = ds;
|
||||||
if(sides[i1][k] == i)
|
dd.dir = 1 + hrand(3) * 2;
|
||||||
spins[i][j] = k;
|
vector<int> sides;
|
||||||
if(spins[i][j] == -1)
|
for(int i=0; i<ds->faces; i++)
|
||||||
println(hlog, "asymmetric");
|
if(ds->hardness[i] >= min_hardness && ds->hardness[i] <= max_hardness)
|
||||||
}
|
sides.push_back(i);
|
||||||
|
dd.val = sides[hrand(isize(sides))];
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void roll(movei mi) {
|
EX void generate_full(cell *c, int hard) {
|
||||||
prepare();
|
int pct = hrand(100);
|
||||||
|
int pct2 = hrand(4000);
|
||||||
|
if(pct < 1) {
|
||||||
|
c->wall = waBlandDie;
|
||||||
|
generate_specific(c, &d4, 0, 99);
|
||||||
|
}
|
||||||
|
else if(pct < 3) {
|
||||||
|
c->wall = waBlandDie;
|
||||||
|
generate_specific(c, &d8, 0, 1);
|
||||||
|
}
|
||||||
|
else if(pct < 5) {
|
||||||
|
c->wall = waBlandDie;
|
||||||
|
generate_specific(c, &d20, 0, 1);
|
||||||
|
}
|
||||||
|
else if(pct < 9) {
|
||||||
|
c->wall = waRichDie;
|
||||||
|
generate_specific(c, &d20, 4, 5);
|
||||||
|
}
|
||||||
|
else if(pct < 10) {
|
||||||
|
c->wall = waRichDie;
|
||||||
|
generate_specific(c, &d8, 2, 3);
|
||||||
|
}
|
||||||
|
else if(pct2 < 1) {
|
||||||
|
c->monst = moAnimatedDie;
|
||||||
|
generate_specific(c, &d4, 0, 99);
|
||||||
|
}
|
||||||
|
else if(pct2 < 40) {
|
||||||
|
c->monst = moAnimatedDie;
|
||||||
|
generate_specific(c, &d8, 0, 99);
|
||||||
|
}
|
||||||
|
else if(pct2 < 40 + hard) {
|
||||||
|
c->monst = moAnimatedDie;
|
||||||
|
generate_specific(c, &d20, 0, 99);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EX die_data roll_effect(movei mi, die_data dd) {
|
||||||
auto &cto = mi.t;
|
auto &cto = mi.t;
|
||||||
auto &th = mi.s;
|
auto &th = mi.s;
|
||||||
|
|
||||||
int rdir = mi.dir_force();
|
int rdir = mi.dir_force();
|
||||||
int t = th->type;
|
int t = th->type;
|
||||||
|
|
||||||
int val = th->wparam % faces();
|
int val = dd.val;
|
||||||
int dir = th->wparam / faces();
|
int dir = dd.dir;
|
||||||
|
|
||||||
int si = isize(sides[val]);
|
auto& dw = dd.which;
|
||||||
|
|
||||||
if(t % si) { println(hlog, "error: bad roll\n"); return; }
|
int si = isize(dw->sides[val]);
|
||||||
|
|
||||||
|
if(t % si) { println(hlog, "error: bad roll\n"); return dd; }
|
||||||
|
|
||||||
int sideid = (rdir - dir) * si / t;
|
int sideid = (rdir - dir) * si / t;
|
||||||
if(sideid < 0) sideid += si;
|
if(sideid < 0) sideid += si;
|
||||||
|
|
||||||
int val1 = sides[val][sideid];
|
int val1 = dw->sides[val][sideid];
|
||||||
|
|
||||||
int si1 = isize(sides[val1]);
|
int si1 = isize(dw->sides[val1]);
|
||||||
|
|
||||||
println(hlog, tie(val, si, rdir), " to ", tie(val1, si1));
|
int sideid1 = dw->spins[val][sideid];
|
||||||
|
|
||||||
int sideid1 = spins[val][sideid];
|
|
||||||
|
|
||||||
int t1 = cto->type;
|
int t1 = cto->type;
|
||||||
if(t1 % si1) { println(hlog, "error: bad roll target\n"); return; }
|
if(t1 % si1) { println(hlog, "error: bad roll target\n"); return dd; }
|
||||||
|
|
||||||
int rdir1 = mi.rev_dir_force();
|
int rdir1 = mi.rev_dir_force();
|
||||||
|
|
||||||
|
@ -978,30 +1053,70 @@ EX namespace dice {
|
||||||
|
|
||||||
dir1 = gmod(dir1, t1);
|
dir1 = gmod(dir1, t1);
|
||||||
|
|
||||||
th->wall = waNone;
|
dd.val = val1;
|
||||||
cto->wall = waDie;
|
dd.dir = dir1;
|
||||||
cto->wparam = val1 + faces() * dir1;
|
return dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void roll(movei mi) {
|
||||||
|
auto &cto = mi.t;
|
||||||
|
auto &th = mi.s;
|
||||||
|
|
||||||
|
changes.map_value(data, cto);
|
||||||
|
changes.map_value(data, th);
|
||||||
|
data[cto] = roll_effect(mi, data[th]);
|
||||||
|
data.erase(th);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void draw_die(cell *c, const shiftmatrix& V) {
|
EX void draw_die(cell *c, const shiftmatrix& V, ld scale, color_t color) {
|
||||||
prepare();
|
if(!data.count(c)) {
|
||||||
int val = c->wparam % faces();
|
queuepoly(V, cgi.shAsymmetric, 0xFF0000FF);
|
||||||
int dir = c->wparam / faces();
|
return;
|
||||||
queuestr(V, .5, its(val+1), 0xFFFFFFFF);
|
}
|
||||||
auto& side = sides[val];
|
|
||||||
int si = isize(side);
|
eGeometry orig = geometry;
|
||||||
|
bool fpp = GDIM == 3;
|
||||||
|
|
||||||
|
auto& dd = data[c];
|
||||||
|
int val = dd.val;
|
||||||
|
int dir = dd.dir;
|
||||||
|
auto& dw = dd.which;
|
||||||
|
|
||||||
for(int i=0; i<si; i++) {
|
auto& side = dw->sides[val];
|
||||||
int d = dir + c->type * i / isize(side);
|
int si = isize(side);
|
||||||
d = gmod(d, c->type);
|
|
||||||
hyperpoint nxt = tC0(currentmap->adj(c, d));
|
if(c == lmouseover_distant) {
|
||||||
hyperpoint mid = normalize(C0 * 1.3 + nxt * -.3);
|
set<cell*> visited;
|
||||||
queuestr(V * rgpushxto0(mid), .25, its(side[i]+1), 0xFFFFFFFF);
|
struct celldata_t {
|
||||||
|
cell* c;
|
||||||
|
die_data dd;
|
||||||
|
shiftmatrix V;
|
||||||
|
};
|
||||||
|
vector<celldata_t> data;
|
||||||
|
auto visit = [&] (cell *c, die_data dd, shiftmatrix V) {
|
||||||
|
if(visited.count(c)) return;
|
||||||
|
visited.insert(c);
|
||||||
|
data.emplace_back(celldata_t{c, dd, V});
|
||||||
|
};
|
||||||
|
visit(c, dd, V);
|
||||||
|
for(int i=0; i<isize(data); i++) {
|
||||||
|
auto dat = data[i];
|
||||||
|
queuestr(fpp ? dat.V * zpush(cgi.FLOOR) : dat.V, .5, its(dat.dd.val+1), 0xFF8000FF);
|
||||||
|
if(i <= 22)
|
||||||
|
forCellIdEx(c2, id, dat.c) if(!ctof(c2) && !visited.count(c2)) {
|
||||||
|
auto re = roll_effect(movei(dat.c, id), dat.dd);
|
||||||
|
shiftmatrix V2 = dat.V * currentmap->adj(dat.c, id);
|
||||||
|
gridline(dat.V, C0, V2, C0, 0xFF800080, 0);
|
||||||
|
visit(c2, re, V2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shiftmatrix V1 = V * iddspin(c, dir) * spin(M_PI);
|
shiftmatrix V1 = V * ddspin(c, dir) * spin(M_PI);
|
||||||
|
|
||||||
vector<bool> face_drawn(faces(), false);
|
// loop:
|
||||||
|
|
||||||
|
vector<bool> face_drawn(dd.which->faces, false);
|
||||||
|
|
||||||
vector<pair<transmatrix, int> > facequeue;
|
vector<pair<transmatrix, int> > facequeue;
|
||||||
|
|
||||||
|
@ -1011,46 +1126,64 @@ EX namespace dice {
|
||||||
facequeue.emplace_back(T, d);
|
facequeue.emplace_back(T, d);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_to_queue(Id, val);
|
transmatrix S = Id;
|
||||||
|
|
||||||
ld outradius, inradius;
|
ld outradius, inradius;
|
||||||
|
|
||||||
if(1) {
|
if(1) {
|
||||||
dynamicval<eGeometry> g(geometry, gSphere);
|
dynamicval<eGeometry> g(geometry, gSphere);
|
||||||
ld alpha = 360 * degree / order;
|
ld alpha = 360 * degree / dw->order;
|
||||||
inradius = edge_of_triangle_with_angles(alpha, 60*degree, 60*degree);
|
inradius = edge_of_triangle_with_angles(alpha, 60*degree, 60*degree);
|
||||||
outradius = edge_of_triangle_with_angles(60*degree, alpha, 60*degree);
|
outradius = edge_of_triangle_with_angles(60*degree, alpha, 60*degree);
|
||||||
}
|
}
|
||||||
|
|
||||||
ld dieradius = 0.5;
|
hyperpoint shift = inverse_shift(V1, tC0(die_target));
|
||||||
|
hyperpoint log_shift = inverse_exp(shiftless(shift)) * (inradius / cgi.hexhexdist);
|
||||||
|
|
||||||
|
if(1) {
|
||||||
|
dynamicval<eGeometry> g(geometry, gSphere);
|
||||||
|
hyperpoint de = direct_exp(log_shift);
|
||||||
|
S = rgpushxto0(de);
|
||||||
|
if(GDIM == 3) {
|
||||||
|
for(int i=0; i<4; i++) swap(S[i][2], S[i][3]);
|
||||||
|
for(int i=0; i<4; i++) swap(S[2][i], S[3][i]);
|
||||||
|
}
|
||||||
|
for(int i=0; i<4; i++) S[i][1] *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_to_queue(S, val);
|
||||||
|
|
||||||
|
ld dieradius = scale / 2;
|
||||||
|
|
||||||
|
if(dw->faces == 20) dieradius /= 1.3;
|
||||||
|
if(dw->faces == 8) dieradius /= 1.15;
|
||||||
|
|
||||||
ld base_to_base;
|
ld base_to_base;
|
||||||
|
|
||||||
if(1) {
|
if(1) {
|
||||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||||
hyperpoint h = cspin(2, 0, outradius) * zpush0(-dieradius);
|
hyperpoint h = cspin(2, 0, M_PI-outradius) * zpush0(-dieradius);
|
||||||
base_to_base = binsearch(-5, 5, [h] (ld d) {
|
base_to_base = binsearch(-5, 5, [h] (ld d) {
|
||||||
return (zpush(d) * h)[2] >= sin_auto(vid.depth);
|
return (zpush(d) * h)[2] >= sin_auto(vid.depth);
|
||||||
});
|
});
|
||||||
// ld base_to_base = cspin(2, 0, outradius) * zpush0(-dieradius);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<ld, int> > ordering;
|
vector<pair<ld, int> > ordering;
|
||||||
|
|
||||||
for(int i=0; i<faces(); i++) {
|
for(int i=0; i<dw->faces; i++) {
|
||||||
|
|
||||||
transmatrix T = facequeue[i].first;
|
transmatrix T = facequeue[i].first;
|
||||||
int ws = facequeue[i].second;
|
int ws = facequeue[i].second;
|
||||||
|
|
||||||
for(int d=0; d<si; d++) {
|
for(int d=0; d<si; d++) {
|
||||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||||
add_to_queue(T * cspin(0, 1, 2*M_PI*d/si) * cspin(2, 0, inradius) * cspin(0, 1, M_PI-2*M_PI*spins[ws][d]/si), sides[ws][d]);
|
add_to_queue(T * cspin(0, 1, 2*M_PI*d/si) * cspin(2, 0, inradius) * cspin(0, 1, M_PI-2*M_PI*dw->spins[ws][d]/si), dw->sides[ws][d]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1) {
|
if(1) {
|
||||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||||
hyperpoint h = zpush(base_to_base) * T * zpush0(dieradius);
|
hyperpoint h = zpush(base_to_base) * T * zpush0(dieradius);
|
||||||
ld z = asin_auto(h[2]);
|
ld z = fpp ? hdist0(h) : asin_auto(h[2]);
|
||||||
ordering.emplace_back(-z, i);
|
ordering.emplace_back(-z, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1061,22 +1194,49 @@ EX namespace dice {
|
||||||
int i = o.second;
|
int i = o.second;
|
||||||
transmatrix T = facequeue[i].first;
|
transmatrix T = facequeue[i].first;
|
||||||
|
|
||||||
|
transmatrix face;
|
||||||
|
|
||||||
|
hyperpoint sum = zpush(base_to_base) * C0 * -3;
|
||||||
|
|
||||||
|
auto sphere_to_space = [&] (hyperpoint h) {
|
||||||
|
if(fpp) return h;
|
||||||
|
ld z = asin_auto(h[2]);
|
||||||
|
h /= cos_auto(z);
|
||||||
|
h[2] = h[3]; h[3] = 0;
|
||||||
|
dynamicval<eGeometry> g(geometry, orig);
|
||||||
|
return zshift(h, geom3::scale_at_lev(z));
|
||||||
|
};
|
||||||
|
|
||||||
for(int d=0; d<=si; d++) {
|
for(int d=0; d<=si; d++) {
|
||||||
hyperpoint h;
|
hyperpoint h, hs;
|
||||||
ld z = 0;
|
|
||||||
if(1) {
|
if(1) {
|
||||||
dynamicval<eGeometry> g(geometry, gSpace534);
|
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||||
h = zpush(base_to_base) * T * cspin(0, 1, 2*M_PI*(d+.5)/si) * cspin(2, 0, outradius) * zpush0(dieradius);
|
h = zpush(base_to_base) * T * cspin(0, 1, 2*M_PI*(d+.5)/si) * cspin(2, 0, outradius) * zpush0(dieradius);
|
||||||
z = asin_auto(h[2]);
|
set_column(face, d, h);
|
||||||
h /= cos_auto(z);
|
sum += h;
|
||||||
|
hs = sphere_to_space(h);
|
||||||
}
|
}
|
||||||
h[2] = h[3]; h[3] = 0;
|
curvepoint(hs);
|
||||||
h = zshift(h, geom3::scale_at_lev(z));
|
|
||||||
curvepoint(h);
|
|
||||||
}
|
}
|
||||||
queuecurve(V1, 0xFFFFFFFF, 0x40A040FF, PPR::WALL);
|
|
||||||
}
|
set_column(face, 3, sum);
|
||||||
|
|
||||||
|
queuecurve(V1, 0xFFFFFFFF, color & 0xFFFFFF9F, PPR::WALL);
|
||||||
|
|
||||||
|
pointfunction pf = [&] (ld x, ld y) {
|
||||||
|
hyperpoint hs;
|
||||||
|
dynamicval<eGeometry> g(geometry, gSpace534);
|
||||||
|
return sphere_to_space(normalize(face * hyperpoint(1/3. -y/2 -x, 1/3. + y, 1/3. -y/2 +x, 1e-2)));
|
||||||
|
};
|
||||||
|
|
||||||
|
int fid = dw->faces - facequeue[i].second;
|
||||||
|
if(dw->faces == 4) fid = facequeue[i].second + 1;
|
||||||
|
string s;
|
||||||
|
if(fid == 6) s = "6.";
|
||||||
|
else if(fid == 9) s = "9.";
|
||||||
|
else s = its(fid);
|
||||||
|
write_in_space(V1, max_glfont_size, dw->faces < 10 ? -1.2 : -.75, s, 0xFFFFFFFF, 0, 8, PPR::WALL, pf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EX }
|
EX }
|
||||||
|
|
17
content.cpp
17
content.cpp
|
@ -1700,11 +1700,20 @@ LAND(0xC0C0FF, "Land of Dice", laDice, 0, itCursed, RESERVED,
|
||||||
ITEM('/', 0xD0D0D8, "Crystal Die", itDice, IC_TREASURE, ZERO, RESERVED, osNone,
|
ITEM('/', 0xD0D0D8, "Crystal Die", itDice, IC_TREASURE, ZERO, RESERVED, osNone,
|
||||||
"A nice souvenir from the Land of Dice. Make sure to collect the whole set!")
|
"A nice souvenir from the Land of Dice. Make sure to collect the whole set!")
|
||||||
|
|
||||||
WALL('d', 0x181818, "Rollable Die", waDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone, NODESC)
|
WALL('d', 0x7F6A10, "Unhappy Die", waRichDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone,
|
||||||
|
"Sentent dice like to be in a position such that their highest number is on top, or somewhere close. "
|
||||||
WALL('d', 0x181818, "Rollable Die", waDie1, ZERO, RESERVED, 0, sgNone, NODESC)
|
"Unfortunately, someone has rolled this one into a wrong position, and did not fix this. "
|
||||||
WALL('d', 0x181818, "Rollable Die", waDie2, ZERO, RESERVED, 0, sgNone, NODESC)
|
"It will reward you if you roll it so that the highest number is on top again!")
|
||||||
|
WALL('d', 0x106010, "Happy Die", waBlandDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone,
|
||||||
|
"A happy sentent die. You can roll it.")
|
||||||
|
|
||||||
|
MONSTER('d', 0x603010, "Animated Die", moAnimatedDie, ZERO, RESERVED, moHexDemon,
|
||||||
|
"When sentient dice are too long in an incorrect position, they start to move on their own, "
|
||||||
|
"and attack everyone. You can still convince Animated Dice of your good intentions by "
|
||||||
|
"rolling them into a position such that the highest number is on top. "
|
||||||
|
"If you do, the die will stop moving and (if it happens in the Land of Dice) you will be rewarded. "
|
||||||
|
"Other rolls and attacks are not allowed."
|
||||||
|
)
|
||||||
|
|
||||||
//shmupspecials
|
//shmupspecials
|
||||||
MONSTER( '@', 0xC0C0C0, "Rogue", moPlayer, CF_FACE_UP | CF_PLAYER, RESERVED, moNone, "In the Shoot'em Up mode, you are armed with thrown Knives.")
|
MONSTER( '@', 0xC0C0C0, "Rogue", moPlayer, CF_FACE_UP | CF_PLAYER, RESERVED, moNone, "In the Shoot'em Up mode, you are armed with thrown Knives.")
|
||||||
|
|
|
@ -481,6 +481,7 @@ EX void bfs() {
|
||||||
else if(isMagneticPole(c2->monst)) havewhat |= HF_MAGNET;
|
else if(isMagneticPole(c2->monst)) havewhat |= HF_MAGNET;
|
||||||
else if(c2->monst == moAltDemon) havewhat |= HF_ALT;
|
else if(c2->monst == moAltDemon) havewhat |= HF_ALT;
|
||||||
else if(c2->monst == moHexDemon) havewhat |= HF_HEXD;
|
else if(c2->monst == moHexDemon) havewhat |= HF_HEXD;
|
||||||
|
else if(c2->monst == moAnimatedDie) havewhat |= HF_HEXD;
|
||||||
else if(c2->monst == moMonk) havewhat |= HF_MONK;
|
else if(c2->monst == moMonk) havewhat |= HF_MONK;
|
||||||
else if(c2->monst == moShark || c2->monst == moCShark || among(c2->monst, moRusalka, moPike)) havewhat |= HF_SHARK;
|
else if(c2->monst == moShark || c2->monst == moCShark || among(c2->monst, moRusalka, moPike)) havewhat |= HF_SHARK;
|
||||||
else if(c2->monst == moAirElemental)
|
else if(c2->monst == moAirElemental)
|
||||||
|
|
20
game.cpp
20
game.cpp
|
@ -379,8 +379,22 @@ EX void pushThumper(const movei& mi) {
|
||||||
cto->wall = waCrateOnTarget;
|
cto->wall = waCrateOnTarget;
|
||||||
th->wall = waCrateTarget;
|
th->wall = waCrateTarget;
|
||||||
}
|
}
|
||||||
else if(w == waDie)
|
else if(among(w, waRichDie, waBlandDie)) {
|
||||||
dice::roll(mi);
|
th->wall = waNone;
|
||||||
|
cto->wall = w;
|
||||||
|
animateMovement(mi, LAYER_BOAT);
|
||||||
|
dice::roll(mi);
|
||||||
|
if(w == waRichDie && dice::data[cto].happy() > 0) {
|
||||||
|
cto->wall = waBlandDie;
|
||||||
|
if(cto->land == laDice && th->land == laDice) {
|
||||||
|
items[itDice]++;
|
||||||
|
addMessage(XLAT("The die is now happy, and you are rewarded!"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addMessage(XLAT("The die is now happy, but won't reward you outside of the Land of Dice!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
cto->wall = w;
|
cto->wall = w;
|
||||||
if(explode) cto->wall = waFireTrap, cto->wparam = explode;
|
if(explode) cto->wall = waFireTrap, cto->wparam = explode;
|
||||||
|
@ -389,7 +403,7 @@ EX void pushThumper(const movei& mi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EX bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) {
|
EX bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) {
|
||||||
if(thumper->wall == waDie && tgt->type == 7)
|
if(among(thumper->wall, waRichDie, waBlandDie) && ctof(tgt))
|
||||||
return false;
|
return false;
|
||||||
if(tgt->wall == waBoat || tgt->wall == waStrandedBoat) return false;
|
if(tgt->wall == waBoat || tgt->wall == waStrandedBoat) return false;
|
||||||
if(isReptile(tgt->wall)) return false;
|
if(isReptile(tgt->wall)) return false;
|
||||||
|
|
21
graph.cpp
21
graph.cpp
|
@ -814,7 +814,7 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
||||||
(it == itBombEgg || it == itTrollEgg) ? &cgi.shEgg :
|
(it == itBombEgg || it == itTrollEgg) ? &cgi.shEgg :
|
||||||
it == itFrog ? &cgi.shDisk :
|
it == itFrog ? &cgi.shDisk :
|
||||||
it == itHunting ? &cgi.shTriangle :
|
it == itHunting ? &cgi.shTriangle :
|
||||||
it == itDodeca ? &cgi.shDodeca :
|
(it == itDodeca || it == itDice) ? &cgi.shDodeca :
|
||||||
xch == '*' ? &cgi.shGem[ct6] :
|
xch == '*' ? &cgi.shGem[ct6] :
|
||||||
xch == '(' ? &cgi.shKnife :
|
xch == '(' ? &cgi.shKnife :
|
||||||
it == itShard ? &cgi.shMFloor.b[0] :
|
it == itShard ? &cgi.shMFloor.b[0] :
|
||||||
|
@ -2251,7 +2251,15 @@ EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t
|
||||||
queuepoly(V, cgi.shAsteroid[1], darkena(col, 0, 0xFF));
|
queuepoly(V, cgi.shAsteroid[1], darkena(col, 0, 0xFF));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case moAnimatedDie: {
|
||||||
|
if(where)
|
||||||
|
dice::draw_die(where, V, 1, darkena(col, 0, 0xFF));
|
||||||
|
else
|
||||||
|
queuepoly(V, cgi.shDodeca, darkena(col, 0, 0xFF));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2518,6 +2526,8 @@ void drawWormSegments() {
|
||||||
|
|
||||||
EX bool dont_face_pc = false;
|
EX bool dont_face_pc = false;
|
||||||
|
|
||||||
|
EX shiftmatrix die_target;
|
||||||
|
|
||||||
EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, color_t asciicol) {
|
EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, color_t asciicol) {
|
||||||
#if CAP_SHAPES
|
#if CAP_SHAPES
|
||||||
|
|
||||||
|
@ -2876,6 +2886,13 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col
|
||||||
// golems, knights, and hyperbugs don't face the player (mondir-controlled)
|
// golems, knights, and hyperbugs don't face the player (mondir-controlled)
|
||||||
// also whatever in the lineview mode, and whatever in the quotient geometry
|
// also whatever in the lineview mode, and whatever in the quotient geometry
|
||||||
|
|
||||||
|
else if(c->monst == moAnimatedDie) {
|
||||||
|
transmatrix U = inverse_shift(Vparam, Vs);
|
||||||
|
U = rgpushxto0(tC0(U));
|
||||||
|
die_target = Vparam;
|
||||||
|
res = res && drawMonsterTypeDH(m, c, Vparam * U, col, darkhistory, footphase, asciicol);
|
||||||
|
}
|
||||||
|
|
||||||
else if((hasFacing(c) && c->mondir != NODIR) || history::on || quotient || dont_face_pc) {
|
else if((hasFacing(c) && c->mondir != NODIR) || history::on || quotient || dont_face_pc) {
|
||||||
if(c->monst == moKrakenH) Vs = Vb, nospins = nospinb;
|
if(c->monst == moKrakenH) Vs = Vb, nospins = nospinb;
|
||||||
if(!nospins && c->mondir < c->type) Vs = Vs * ddspin(c, c->mondir, M_PI);
|
if(!nospins && c->mondir < c->type) Vs = Vs * ddspin(c, c->mondir, M_PI);
|
||||||
|
|
12
landgen.cpp
12
landgen.cpp
|
@ -2586,16 +2586,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case laDice: {
|
case laDice: {
|
||||||
if(fargen) {
|
if(fargen && !ctof(c))
|
||||||
int pct = hrand(100);
|
dice::generate_full(c, items[itDice] + yendor::hardness());
|
||||||
if(pct < 10)
|
|
||||||
c->wall = waDie;
|
|
||||||
// c->wall = pick(waNone, waNone, waStone, waNone, waNone, waStone, waNone, waNone, waStone, waBigStatue, waCrateCrate, waDie);
|
|
||||||
if(c->wall == waDie) {
|
|
||||||
if(ctof(c)) c->wall = waNone;
|
|
||||||
else dice::generate_on(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,9 @@ EX void moveEffect(const movei& mi, eMonster m) {
|
||||||
animateMovement(mi.rev(), LAYER_BOAT);
|
animateMovement(mi.rev(), LAYER_BOAT);
|
||||||
tortoise::move_baby(cf, ct);
|
tortoise::move_baby(cf, ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m == moAnimatedDie && mi.proper())
|
||||||
|
dice::roll(mi);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void moveMonster(const movei& mi) {
|
EX void moveMonster(const movei& mi) {
|
||||||
|
@ -1086,6 +1089,11 @@ EX void groupmove2(const movei& mi, eMonster movtype, flagtype mf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return;
|
else return;
|
||||||
|
|
||||||
|
if(c->monst == moAnimatedDie) {
|
||||||
|
forCellEx(c3, from) if(c3 != c && c3->monst == moAnimatedDie)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(from->monst) {
|
if(from->monst) {
|
||||||
if(mf & MF_MOUNT) {
|
if(mf & MF_MOUNT) {
|
||||||
|
|
4
orbs.cpp
4
orbs.cpp
|
@ -808,6 +808,8 @@ EX eMonster summonedAt(cell *dest) {
|
||||||
return moMiner;
|
return moMiner;
|
||||||
if(dest->wall == waMineOpen || dest->wall == waMineMine || dest->wall == waMineUnknown)
|
if(dest->wall == waMineOpen || dest->wall == waMineMine || dest->wall == waMineUnknown)
|
||||||
return moBomberbird;
|
return moBomberbird;
|
||||||
|
if(dest->wall == waRichDie)
|
||||||
|
return moAnimatedDie;
|
||||||
if(dest->wall == waTrapdoor)
|
if(dest->wall == waTrapdoor)
|
||||||
return dest->land == laPalace ? moFatGuard : moOrangeDog;
|
return dest->land == laPalace ? moFatGuard : moOrangeDog;
|
||||||
if(dest->land == laFrog && dest->wall == waNone) {
|
if(dest->land == laFrog && dest->wall == waNone) {
|
||||||
|
@ -906,6 +908,8 @@ void summonAt(cell *dest) {
|
||||||
dest->stuntime = 3;
|
dest->stuntime = 3;
|
||||||
if(dest->monst == moPirate || dest->monst == moViking || (dest->monst == moRatling && dest->wall == waSea))
|
if(dest->monst == moPirate || dest->monst == moViking || (dest->monst == moRatling && dest->wall == waSea))
|
||||||
dest->wall = waBoat, dest->item = itNone;
|
dest->wall = waBoat, dest->item = itNone;
|
||||||
|
if(dest->monst == moAnimatedDie)
|
||||||
|
dest->wall = waNone;
|
||||||
if(dest->monst == moViking && dest->land == laKraken)
|
if(dest->monst == moViking && dest->land == laKraken)
|
||||||
dest->item = itOrbFish;
|
dest->item = itOrbFish;
|
||||||
if(dest->wall == waStrandedBoat)
|
if(dest->wall == waStrandedBoat)
|
||||||
|
|
14
pcmove.cpp
14
pcmove.cpp
|
@ -628,6 +628,18 @@ bool pcmove::actual_move() {
|
||||||
activateActiv(c2, true);
|
activateActiv(c2, true);
|
||||||
return after_instant(false);
|
return after_instant(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(c2->monst == moAnimatedDie) {
|
||||||
|
mip = determinePush(cwt, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); });
|
||||||
|
if(mip.proper()) {
|
||||||
|
auto tgt = roll_effect(mip, dice::data[c2]);
|
||||||
|
if(tgt.happy() > 0) {
|
||||||
|
changes.ccell(c2);
|
||||||
|
c2->monst = moNone;
|
||||||
|
c2->wall = waRichDie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(isPushable(c2->wall) && !c2->monst && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
if(isPushable(c2->wall) && !c2->monst && !nonAdjacentPlayer(c2, cwt.at) && fmsMove) {
|
||||||
mip = determinePush(cwt, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); });
|
mip = determinePush(cwt, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, cwt.at); });
|
||||||
|
@ -745,6 +757,8 @@ void pcmove::tell_why_cannot_attack() {
|
||||||
addMessage(XLAT("You cannot attack Raiders directly!"));
|
addMessage(XLAT("You cannot attack Raiders directly!"));
|
||||||
else if(isSwitch(c2->monst))
|
else if(isSwitch(c2->monst))
|
||||||
addMessage(XLAT("You cannot attack Jellies in their wall form!"));
|
addMessage(XLAT("You cannot attack Jellies in their wall form!"));
|
||||||
|
else if(c2->monst == moAnimatedDie)
|
||||||
|
addMessage(XLAT("You can only push this die if the highest number would be on the top!"));
|
||||||
else
|
else
|
||||||
addMessage(XLAT("For some reason... cannot attack!"));
|
addMessage(XLAT("For some reason... cannot attack!"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue