first version of the Land of Dice

This commit is contained in:
Zeno Rogue 2021-05-23 15:57:39 +02:00
parent 744f03c7d6
commit feaef63f22
6 changed files with 217 additions and 4 deletions

View File

@ -146,7 +146,7 @@ void celldrawer::setcolors() {
case laDesert: case laKraken: case laDocks:
case laMotion: case laGraveyard: case laWineyard: case laLivefjord:
case laRlyeh: case laHell: case laCrossroads: case laJungle:
case laAlchemist: case laFrog: case laCursed:
case laAlchemist: case laFrog: case laCursed: case laDice:
fcol = floorcolors[c->land]; break;
case laCA:
@ -1600,6 +1600,10 @@ void celldrawer::draw_features() {
}
poly_outline = OUTLINE_DEFAULT;
}
else if(c->wall == waDie) {
dice::draw_die(c, V);
}
else if(c->wall == waExplosiveBarrel) {
if(GDIM == 3 && qfi.fshape) {

View File

@ -899,6 +899,186 @@ EX void ambush(cell *c, int dogs) {
if(result)
addMessage(XLAT("You are ambushed!"));
}
EX }
EX namespace dice {
/* vector<vector<int>> sides = {
{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 = {
{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},
{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}
};
vector<vector<int>> spins;
int order;
int faces() { return isize(sides); }
EX void generate_on(cell *c) {
c->wparam = hrand(faces()) + faces() * (1 + hrand(3) * 2);
}
bool prepared;
void prepare() {
if(prepared) return;
prepared = true;
spins = sides;
order = faces() == 8 ? 4 : 5;
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");
}
}
EX void roll(movei mi) {
prepare();
auto &cto = mi.t;
auto &th = mi.s;
int rdir = mi.dir_force();
int t = th->type;
int val = th->wparam % faces();
int dir = th->wparam / faces();
int si = isize(sides[val]);
if(t % si) { println(hlog, "error: bad roll\n"); return; }
int sideid = (rdir - dir) * si / t;
if(sideid < 0) sideid += si;
int val1 = sides[val][sideid];
int si1 = isize(sides[val1]);
println(hlog, tie(val, si, rdir), " to ", tie(val1, si1));
int sideid1 = spins[val][sideid];
int t1 = cto->type;
if(t1 % si1) { println(hlog, "error: bad roll target\n"); return; }
int rdir1 = mi.rev_dir_force();
int dir1 = rdir1 - sideid1 * t1 / si1;
dir1 = gmod(dir1, t1);
th->wall = waNone;
cto->wall = waDie;
cto->wparam = val1 + faces() * dir1;
}
EX void draw_die(cell *c, const shiftmatrix& V) {
prepare();
int val = c->wparam % faces();
int dir = c->wparam / faces();
queuestr(V, .5, its(val+1), 0xFFFFFFFF);
auto& side = sides[val];
int si = isize(side);
for(int i=0; i<si; i++) {
int d = dir + c->type * i / isize(side);
d = gmod(d, c->type);
hyperpoint nxt = tC0(currentmap->adj(c, d));
hyperpoint mid = normalize(C0 * 1.3 + nxt * -.3);
queuestr(V * rgpushxto0(mid), .25, its(side[i]+1), 0xFFFFFFFF);
}
shiftmatrix V1 = V * iddspin(c, dir) * spin(M_PI);
vector<bool> face_drawn(faces(), false);
vector<pair<transmatrix, int> > facequeue;
auto add_to_queue = [&] (const transmatrix& T, int d) {
if(face_drawn[d]) return;
face_drawn[d] = true;
facequeue.emplace_back(T, d);
};
add_to_queue(Id, val);
ld outradius, inradius;
if(1) {
dynamicval<eGeometry> g(geometry, gSphere);
ld alpha = 360 * degree / order;
inradius = edge_of_triangle_with_angles(alpha, 60*degree, 60*degree);
outradius = edge_of_triangle_with_angles(60*degree, alpha, 60*degree);
}
ld dieradius = 0.5;
ld base_to_base;
if(1) {
dynamicval<eGeometry> g(geometry, gSpace534);
hyperpoint h = cspin(2, 0, outradius) * zpush0(-dieradius);
base_to_base = binsearch(-5, 5, [h] (ld d) {
return (zpush(d) * h)[2] >= sin_auto(vid.depth);
});
// ld base_to_base = cspin(2, 0, outradius) * zpush0(-dieradius);
}
vector<pair<ld, int> > ordering;
for(int i=0; i<faces(); i++) {
transmatrix T = facequeue[i].first;
int ws = facequeue[i].second;
for(int d=0; d<si; d++) {
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]);
}
if(1) {
dynamicval<eGeometry> g(geometry, gSpace534);
hyperpoint h = zpush(base_to_base) * T * zpush0(dieradius);
ld z = asin_auto(h[2]);
ordering.emplace_back(-z, i);
}
}
sort(ordering.begin(), ordering.end());
for(auto o: ordering) {
int i = o.second;
transmatrix T = facequeue[i].first;
for(int d=0; d<=si; d++) {
hyperpoint h;
ld z = 0;
if(1) {
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);
z = asin_auto(h[2]);
h /= cos_auto(z);
}
h[2] = h[3]; h[3] = 0;
h = zshift(h, geom3::scale_at_lev(z));
curvepoint(h);
}
queuecurve(V1, 0xFFFFFFFF, 0x40A040FF, PPR::WALL);
}
}
EX }
}

View File

@ -1683,13 +1683,24 @@ MONSTER('H', 0x181818, "Hag", moHexer, CF_FACE_UP, RESERVED, moYeti,
LAND(0xC0C0FF, "Cursed Land", laCursed, 0, itCursed, RESERVED,
"This land is full of curses!")
ITEM('/', 0x211F6F, "Cursed Gold", itCursed, IC_TREASURE, ZERO, RESERVED, osNone,
"A cursed gold.")
ITEM('o', 0x208020, "Orb of the Woods", itOrbWoods, IC_ORB, ZERO, RESERVED, osTerraform,
"Lets you swap positions with the trees.")
LAND(0xC0C0FF, "Land of Dice", laDice, 0, itCursed, RESERVED,
"This land is full of dice!")
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!")
WALL('d', 0x181818, "Rollable Die", waDie, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone, NODESC)
WALL('d', 0x181818, "Rollable Die", waDie1, ZERO, RESERVED, 0, sgNone, NODESC)
WALL('d', 0x181818, "Rollable Die", waDie2, ZERO, RESERVED, 0, sgNone, NODESC)
//shmupspecials
MONSTER( '@', 0xC0C0C0, "Rogue", moPlayer, CF_FACE_UP | CF_PLAYER, RESERVED, moNone, "In the Shoot'em Up mode, you are armed with thrown Knives.")

View File

@ -374,6 +374,8 @@ EX void pushThumper(const movei& mi) {
cto->wall = waCrateOnTarget;
th->wall = waCrateTarget;
}
else if(w == waDie)
dice::roll(mi);
else
cto->wall = w;
if(explode) cto->wall = waFireTrap, cto->wparam = explode;
@ -382,7 +384,9 @@ EX void pushThumper(const movei& mi) {
}
EX bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) {
if(tgt->wall == waBoat || tgt->wall == waStrandedBoat) return false;
if(thumper->wall == waDie && tgt->type == 7)
return false;
if(tgt->wall == waBoat || tgt->wall == waStrandedBoat) return false;
if(isReptile(tgt->wall)) return false;
if(isWatery(tgt) && !tgt->monst)
return true;

View File

@ -745,7 +745,7 @@ EX namespace geom3 {
// projection: projection parameter
// factor: zoom factor
ld abslev_to_projection(ld abslev) {
EX ld abslev_to_projection(ld abslev) {
if(sphere || euclid) return vid.camera+abslev;
return tanh(abslev) / tanh(vid.camera);
}

View File

@ -2585,6 +2585,20 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
break;
}
case laDice: {
if(fargen) {
int pct = hrand(100);
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;
}
case laCursed: {
if(fargen) {
c->wall = waStone;