mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-11-04 15:53:00 +00:00 
			
		
		
		
	removed the MAX_EDGE limit
This commit is contained in:
		@@ -51,9 +51,11 @@ struct archimedean_tiling {
 | 
			
		||||
  
 | 
			
		||||
  vector<ld> inradius, circumradius, alphas;
 | 
			
		||||
  
 | 
			
		||||
  int matches[30][30];
 | 
			
		||||
  int periods[30];
 | 
			
		||||
  int tilegroup[30], groupoffset[30], tilegroups;
 | 
			
		||||
  vector<vector<int>> matches;
 | 
			
		||||
  vector<int> periods;
 | 
			
		||||
  vector<int> tilegroup;
 | 
			
		||||
  vector<int> groupoffset;
 | 
			
		||||
  int tilegroups;
 | 
			
		||||
 | 
			
		||||
  int errors;
 | 
			
		||||
  string errormsg;
 | 
			
		||||
@@ -130,18 +132,21 @@ void archimedean_tiling::make_match(int a, int i, int b, int j) {
 | 
			
		||||
    periods[a] = periods[b] = gcd(matches[a][b] - (j-i), periods[a]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** mostly to protect the user from entering too large numbers */
 | 
			
		||||
const int MAX_EDGE_ARCM = FULL_EDGE;
 | 
			
		||||
 | 
			
		||||
void archimedean_tiling::prepare() {
 | 
			
		||||
 | 
			
		||||
  euclidean_angle_sum = 0;
 | 
			
		||||
  for(int f: faces) euclidean_angle_sum += (f-2.) / f;
 | 
			
		||||
 | 
			
		||||
  for(int i: faces) if(i > MAX_EDGE) {
 | 
			
		||||
    errormsg = XLAT("currently no more than %1 edges", its(MAX_EDGE));
 | 
			
		||||
  for(int i: faces) if(i > MAX_EDGE_ARCM) {
 | 
			
		||||
    errormsg = XLAT("currently no more than %1 edges", its(MAX_EDGE_ARCM));
 | 
			
		||||
    errors++;
 | 
			
		||||
    return;
 | 
			
		||||
    }
 | 
			
		||||
  if(isize(faces) > MAX_EDGE/2) {
 | 
			
		||||
    errormsg = XLAT("currently no more than %1 faces in vertex", its(MAX_EDGE/2));
 | 
			
		||||
  if(isize(faces) > MAX_EDGE_ARCM/2) {
 | 
			
		||||
    errormsg = XLAT("currently no more than %1 faces in vertex", its(MAX_EDGE_ARCM/2));
 | 
			
		||||
    errors++;
 | 
			
		||||
    return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -192,8 +197,13 @@ void archimedean_tiling::prepare() {
 | 
			
		||||
  have_symmetry = false;
 | 
			
		||||
  for(int i=0; i<N; i++) if(invert[i]) have_symmetry = true;  
 | 
			
		||||
  
 | 
			
		||||
  for(int i=0; i<M; i++) for(int j=0; j<M; j++) matches[i][j] = i==j ? 0 : -1;
 | 
			
		||||
  matches.resize(M);
 | 
			
		||||
  for(int i=0; i<M; i++) {
 | 
			
		||||
    matches[i].resize(M);
 | 
			
		||||
    for(int j=0; j<M; j++) matches[i][j] = i==j ? 0 : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  periods.resize(M);
 | 
			
		||||
  for(int i=0; i<M; i++) periods[i] = i<2*N ? faces[i/2] : N;
 | 
			
		||||
  
 | 
			
		||||
  for(int i=0; i<N; i++) {
 | 
			
		||||
@@ -289,7 +299,9 @@ void archimedean_tiling::regroup() {
 | 
			
		||||
    make_match(i, 0, k, matches[i][j] + matches[j][k]);
 | 
			
		||||
    make_match(i, 0, k, matches[i][j] + matches[j][k] + gcd(periods[i], periods[j]));
 | 
			
		||||
    }
 | 
			
		||||
  for(int i=0; i<M; i++) tilegroup[i] = -1;
 | 
			
		||||
  tilegroup.clear();
 | 
			
		||||
  tilegroup.resize(M, -1);
 | 
			
		||||
  groupoffset.resize(M);
 | 
			
		||||
  tilegroups = 0;
 | 
			
		||||
  for(int i=0; i<M; i+=(have_symmetry?1:2)) if(tilegroup[i] == -1) {
 | 
			
		||||
    if(periods[i] < 0) periods[i] = -periods[i];
 | 
			
		||||
@@ -335,11 +347,13 @@ void archimedean_tiling::compute_geometry() {
 | 
			
		||||
  dynamicval<eGeometry> dv(geometry, gArchimedean);
 | 
			
		||||
  
 | 
			
		||||
  /* compute the geometry */
 | 
			
		||||
  inradius.resize(N);
 | 
			
		||||
  inradius.resize(N+1); inradius[N] = 0;
 | 
			
		||||
  circumradius.resize(N);
 | 
			
		||||
  alphas.resize(N);
 | 
			
		||||
  ld elmin = 0, elmax = hyperbolic ? 10 : sphere ? M_PI : 1;
 | 
			
		||||
  
 | 
			
		||||
  /* inradius[N] is used in farcorner and nearcorner. Probably a bug */
 | 
			
		||||
  
 | 
			
		||||
  if(real_faces == 2) {
 | 
			
		||||
    /* standard methods fail for dihedra, but the answer is easy */
 | 
			
		||||
    edgelength = 2 * M_PI / faces[0];
 | 
			
		||||
@@ -777,19 +791,19 @@ void fixup_matrix(transmatrix& T, const transmatrix& X, ld step) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
pair<ld, ld>& archimedean_tiling::get_triangle(heptagon *h, int cid) {
 | 
			
		||||
  return triangles[id_of(h)][(parent_index_of(h) + cid + MODFIXER) % neighbors_of(h)];
 | 
			
		||||
  return triangles[id_of(h)][gmod(parent_index_of(h) + cid, neighbors_of(h))];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
pair<int, int>& archimedean_tiling::get_adj(heptagon *h, int cid) {
 | 
			
		||||
  return adjacent[id_of(h)][(parent_index_of(h) + cid + MODFIXER) % neighbors_of(h)];
 | 
			
		||||
  return adjacent[id_of(h)][gmod(parent_index_of(h) + cid, neighbors_of(h))];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
pair<int, int>& archimedean_tiling::get_adj(const pair<int, int>& p, int delta) {
 | 
			
		||||
  return adjacent[p.first][(p.second + delta + MODFIXER) % isize(adjacent[p.first])];
 | 
			
		||||
  return adjacent[p.first][gmod(p.second + delta, isize(adjacent[p.first]))];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
pair<ld, ld>& archimedean_tiling::get_triangle(const pair<int, int>& p, int delta) {
 | 
			
		||||
  return triangles[p.first][(p.second + delta + MODFIXER) % isize(adjacent[p.first])];
 | 
			
		||||
  return triangles[p.first][gmod(p.second + delta, isize(adjacent[p.first]))];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
transmatrix adjcell_matrix(heptagon *h, int d) {
 | 
			
		||||
 
 | 
			
		||||
@@ -841,9 +841,7 @@ EX bool buildBarrierNowall(cell *c, eLand l2, int forced_dir IS(NODIR)) {
 | 
			
		||||
  bool warpv = warped_version(c->land, l2);
 | 
			
		||||
  if(warpv && !arcm::in() && !pseudohept(c)) return false;
 | 
			
		||||
  
 | 
			
		||||
  int ds[MAX_EDGE];
 | 
			
		||||
  for(int i=0; i<c->type; i++) ds[i] = i;
 | 
			
		||||
  for(int j=0; j<c->type; j++) swap(ds[j], ds[hrand(j+1)]);
 | 
			
		||||
  vector<int> ds = hrandom_permutation(c->type);
 | 
			
		||||
 | 
			
		||||
  for(int i=0; i<c->type; i++) {
 | 
			
		||||
    int d = forced_dir != NODIR ? forced_dir : (valence()>3) ? (2+(i&1)) : ds[i];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								bigstuff.cpp
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								bigstuff.cpp
									
									
									
									
									
								
							@@ -298,32 +298,32 @@ EX void generateTreasureIsland(cell *c) {
 | 
			
		||||
    beCIsland(c);
 | 
			
		||||
    if(c->wall == waCTree) return;
 | 
			
		||||
    }
 | 
			
		||||
  cell* ctab[MAX_EDGE];
 | 
			
		||||
  int qc = 0, qlo, qhi;
 | 
			
		||||
  vector<cell*> ctab;
 | 
			
		||||
  int qlo, qhi;
 | 
			
		||||
  for(int i=0; i<c->type; i++) {
 | 
			
		||||
    cell *c2 = createMov(c, i);
 | 
			
		||||
    if(!eubinary) currentmap->generateAlts(c2->master);
 | 
			
		||||
    if((eubinary || (c->master->alt && c2->master->alt)) && celldistAlt(c2) < celldistAlt(c)) {
 | 
			
		||||
      ctab[qc++] = c2;
 | 
			
		||||
      ctab.push_back(c2);
 | 
			
		||||
      qlo = i; qhi = i;
 | 
			
		||||
      while(true && qc < MAX_EDGE) {
 | 
			
		||||
      while(true && isize(ctab) < c->type) {
 | 
			
		||||
        qlo--;
 | 
			
		||||
        c2 = c->cmodmove(qlo);
 | 
			
		||||
        if(!eubinary && !c2->master->alt) break;
 | 
			
		||||
        if(celldistAlt(c2) >= celldistAlt(c)) break;
 | 
			
		||||
        ctab[qc++] = c2;
 | 
			
		||||
        ctab.push_back(c2);
 | 
			
		||||
        }
 | 
			
		||||
      while(true && qc < MAX_EDGE) {
 | 
			
		||||
      while(true && isize(ctab) < c->type) {
 | 
			
		||||
        qhi++;
 | 
			
		||||
        c2 = c->cmodmove(qhi);
 | 
			
		||||
        if(!eubinary && !c2->master->alt) break;
 | 
			
		||||
        if(celldistAlt(c2) >= celldistAlt(c)) break;
 | 
			
		||||
        ctab[qc++] = c2;
 | 
			
		||||
        ctab.push_back(c2);
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  if(!qc) { 
 | 
			
		||||
  if(ctab.empty()) { 
 | 
			
		||||
    printf("NO QC\n"); c->wall = waSea; 
 | 
			
		||||
    for(int i=0; i<c->type; i++) printf("%d ", celldistAlt(c->move(i)));
 | 
			
		||||
    printf("vs %d\n", celldistAlt(c));
 | 
			
		||||
@@ -338,9 +338,9 @@ EX void generateTreasureIsland(cell *c) {
 | 
			
		||||
    }
 | 
			
		||||
  if(src && c2->wall == waCTree && (eubinary||c->master->alt) && celldistAlt(c) <= -10 && geometry != gRhombic3) {
 | 
			
		||||
    bool end = true;
 | 
			
		||||
    for(int i=0; i<qc; i++) {
 | 
			
		||||
      generateTreasureIsland(ctab[i]);
 | 
			
		||||
      if(ctab[i]->wall != waCTree)
 | 
			
		||||
    for(cell *cc: ctab) {
 | 
			
		||||
      generateTreasureIsland(cc);
 | 
			
		||||
      if(cc->wall != waCTree)
 | 
			
		||||
        end = false;
 | 
			
		||||
      }
 | 
			
		||||
    // printf("%p: end=%d, qc=%d, dist=%d\n", c, end, qc, celldistAlt(c));
 | 
			
		||||
@@ -571,8 +571,8 @@ EX void buildEquidistant(cell *c) {
 | 
			
		||||
      // if(qcv != 1) { printf("qcv = %d\n", qcv);  exit(1); }
 | 
			
		||||
      cell *c2 = c->move(sid);
 | 
			
		||||
      int bsid = c->c.spin(sid);
 | 
			
		||||
      for(int j=0; j<7; j++) {
 | 
			
		||||
        int q = (bsid+j+42) % c2->type;
 | 
			
		||||
      for(int j=0; j<c2->type; j++) {
 | 
			
		||||
        int q = gmod(bsid+j, c2->type);
 | 
			
		||||
        cell *c3 = c2->move(q);
 | 
			
		||||
        if(coastval(c3, b) < mcv) {
 | 
			
		||||
          cell *c4 = c2->cmodmove(bsid+1);
 | 
			
		||||
@@ -581,7 +581,7 @@ EX void buildEquidistant(cell *c) {
 | 
			
		||||
          mcv2 = coastval(c4, b);
 | 
			
		||||
          break;
 | 
			
		||||
          }
 | 
			
		||||
        q = (bsid-j+MODFIXER) % c2->type;
 | 
			
		||||
        q = gmod(bsid-j, c2->type);
 | 
			
		||||
        c3 = c2->move(q);
 | 
			
		||||
        if(coastval(c3, b) < mcv) {
 | 
			
		||||
          cell *c4 = c2->cmodmove(bsid-1);
 | 
			
		||||
@@ -774,14 +774,12 @@ EX void buildEquidistant(cell *c) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
EX cell *randomDown(cell *c) {
 | 
			
		||||
  cell *tab[MAX_EDGE];
 | 
			
		||||
  int q=0;
 | 
			
		||||
  vector<cell*> tab;
 | 
			
		||||
  for(int i=0; i<c->type; i++) 
 | 
			
		||||
    if(c->move(i) && coastval(c->move(i), laIvoryTower) < coastval(c, laIvoryTower))
 | 
			
		||||
      tab[q++] = c->move(i);
 | 
			
		||||
  if(!q) return NULL;
 | 
			
		||||
  if(q==1) return tab[0];
 | 
			
		||||
  return tab[hrand(q)];
 | 
			
		||||
      tab.push_back(c->move(i));
 | 
			
		||||
  if(isize(tab)==1) return tab[0];
 | 
			
		||||
  return hrand_elt(tab, (cell*)nullptr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
EX int edgeDepth(cell *c) {
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ struct blizzardcell {
 | 
			
		||||
  transmatrix *gm;
 | 
			
		||||
  char wmap;
 | 
			
		||||
  int inward, outward, ward;
 | 
			
		||||
  int qty[MAX_EDGE];
 | 
			
		||||
  vector<int> qty;
 | 
			
		||||
  vector<snowball*> inorder, outorder;
 | 
			
		||||
  int inid, outid;
 | 
			
		||||
  ~blizzardcell() { for(auto i: inorder) delete i; }
 | 
			
		||||
@@ -77,6 +77,7 @@ EX void drawBlizzards() {
 | 
			
		||||
    auto& bc = *bcells[i];
 | 
			
		||||
    cell *c = bc.c;
 | 
			
		||||
    bc.inward = bc.outward = 0;
 | 
			
		||||
    bc.qty.resize(c->type);
 | 
			
		||||
    for(int i=0; i<c->type; i++) {
 | 
			
		||||
      int& qty = bc.qty[i];
 | 
			
		||||
      qty = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -858,7 +858,10 @@ void celldrawer::draw_halfvine() {
 | 
			
		||||
    queuepolyat(GDIM == 2 ? Vdepth : V2, cgi.shSemiFloor[0], darkena(vcol, fd, 0xFF), PPR::WALL3A);
 | 
			
		||||
    {dynamicval<color_t> p(poly_outline, OUTLINE_TRANS); queuepolyat(V2 * spin(M_PI*2/3), cgi.shSemiFloorShadow, SHADOW_WALL, GDIM == 2 ? PPR::WALLSHADOW : PPR::TRANSPARENT_SHADOW); }
 | 
			
		||||
    auto& side = queuepolyat(V2, cgi.shSemiFloorSide[SIDE_WALL], darkena(vcol, fd, 0xFF), PPR::WALL3A-2+away(V2));
 | 
			
		||||
    if(GDIM == 3 && qfi.fshape) side.tinf = &floor_texture_vertices[shar.id];
 | 
			
		||||
    if(GDIM == 3 && qfi.fshape) {
 | 
			
		||||
      side.tinf = &floor_texture_vertices[shar.id];
 | 
			
		||||
      ensure_vertex_number(*side.tinf, side.cnt);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    if(cgi.validsidepar[SIDE_WALL]) forCellIdEx(c2, j, c) {
 | 
			
		||||
      int dis = i-j;
 | 
			
		||||
@@ -1570,6 +1573,7 @@ void celldrawer::draw_features_and_walls_3d() {
 | 
			
		||||
          #endif
 | 
			
		||||
          {
 | 
			
		||||
            poly.tinf = &floor_texture_vertices[qfi.fshape->id];
 | 
			
		||||
            ensure_vertex_number(*poly.tinf, poly.cnt);
 | 
			
		||||
            poly.offset_texture = 0;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
@@ -1813,7 +1817,7 @@ void celldrawer::draw_cellstat() {
 | 
			
		||||
  
 | 
			
		||||
    auto si = patterns::getpatterninfo0(c);
 | 
			
		||||
    
 | 
			
		||||
    for(int i=(si.dir + MODFIXER) % si.symmetries; i<c->type; i += si.symmetries) {
 | 
			
		||||
    for(int i= gmod(si.dir, si.symmetries); i<c->type; i += si.symmetries) {
 | 
			
		||||
      queuepoly(V * ddspin(c, i) * (si.reflect?Mirror:Id), cgi.shAsymmetric, darkena(0x000000, 0, 0xC0));
 | 
			
		||||
      si.dir += si.symmetries;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ EX eMonster who_kills_me;
 | 
			
		||||
 | 
			
		||||
EX int lastkills;
 | 
			
		||||
 | 
			
		||||
EX bool legalmoves[MAX_EDGE+1];
 | 
			
		||||
EX vector<bool> legalmoves;
 | 
			
		||||
 | 
			
		||||
EX bool hasSafeOrb(cell *c) {
 | 
			
		||||
  return 
 | 
			
		||||
@@ -402,11 +402,11 @@ EX void checkmove() {
 | 
			
		||||
  // do not activate orbs!
 | 
			
		||||
  for(int i=0; i<ittypes; i++) orbusedbak[i] = orbused[i];
 | 
			
		||||
 | 
			
		||||
  for(int i=0; i<=MAX_EDGE; i++) legalmoves[i] = false;
 | 
			
		||||
  legalmoves.clear(); legalmoves.resize(cwt.at->type+1, false);
 | 
			
		||||
 | 
			
		||||
  canmove = haveRangedTarget();
 | 
			
		||||
  items[itWarning]+=2;
 | 
			
		||||
  if(movepcto(-1, 0, true)) canmove = legalmoves[MAX_EDGE] = true;
 | 
			
		||||
  if(movepcto(-1, 0, true)) canmove = legalmoves[cwt.at->type] = true;
 | 
			
		||||
  
 | 
			
		||||
  if(vid.mobilecompasssize || !canmove)
 | 
			
		||||
    for(int i=0; i<cwt.at->type; i++) 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								complex.cpp
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								complex.cpp
									
									
									
									
									
								
							@@ -64,7 +64,7 @@ EX namespace whirlwind {
 | 
			
		||||
    qdirs = 0;
 | 
			
		||||
    if(d == 0) return;
 | 
			
		||||
    int qdf = 0, qdt = 0;
 | 
			
		||||
    int cats[MAX_EDGE];
 | 
			
		||||
    vector<int> cats(c->type);
 | 
			
		||||
    for(int i=0; i<c->type; i++) 
 | 
			
		||||
      cats[i] = cat(createMov(c,i));
 | 
			
		||||
    for(int i=0; i<c->type; i++)
 | 
			
		||||
@@ -2923,11 +2923,10 @@ EX namespace kraken {
 | 
			
		||||
    for(int i=0; i<isize(dcal); i++) {
 | 
			
		||||
      cell *c = dcal[i];
 | 
			
		||||
      if(c->monst == moKrakenH && !c->stuntime && !isWateryOrBoat(c)) {
 | 
			
		||||
        int qdir = 0;
 | 
			
		||||
        cell *ctab[MAX_EDGE];
 | 
			
		||||
        forCellEx(c2, c) if(isWatery(c2)) ctab[qdir++] = c2;
 | 
			
		||||
        hrandom_shuffle(ctab, qdir);
 | 
			
		||||
        while(qdir--) trymove(ctab[qdir]);
 | 
			
		||||
        vector<cell*> ctab;
 | 
			
		||||
        forCellEx(c2, c) if(isWatery(c2)) ctab.push_back(c2);
 | 
			
		||||
        hrandom_shuffle(ctab);
 | 
			
		||||
        for(auto& cc: ctab) trymove(cc);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -4052,14 +4051,6 @@ EX namespace dungeon {
 | 
			
		||||
        }
 | 
			
		||||
  
 | 
			
		||||
      if(c->wparam) {
 | 
			
		||||
        /* int q = 0;
 | 
			
		||||
        cell* downs[MAX_EDGE];
 | 
			
		||||
        forCellEx(c2, c) {
 | 
			
		||||
          buildEquidistant(c2);
 | 
			
		||||
          if(coastvalEdge(c2) > coastvalEdge(c)) downs[q++] = c2;
 | 
			
		||||
          }
 | 
			
		||||
        if(q) downs[hrand(q)]->wall = waLadder;
 | 
			
		||||
        */
 | 
			
		||||
        cell *c2 = 
 | 
			
		||||
          WDIM == 3 ? random_child(c, coastvalEdge) :
 | 
			
		||||
          c->wparam == 1 ? ts::add(c, 1, 2, coastvalEdge) :
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ EX movedir vectodir(hyperpoint P) {
 | 
			
		||||
 | 
			
		||||
  ld binv = 99;
 | 
			
		||||
  
 | 
			
		||||
  ld dirdist[MAX_EDGE];
 | 
			
		||||
  vector<ld> dirdist(cwt.at->type);
 | 
			
		||||
 | 
			
		||||
  for(int i=0; i<cwt.at->type; i++) {
 | 
			
		||||
    transmatrix T = currentmap->adj(cwt.at, (cwt + i).spin);
 | 
			
		||||
@@ -139,7 +139,7 @@ EX void calcMousedest() {
 | 
			
		||||
  
 | 
			
		||||
  cellwalker bcwt = cwt;
 | 
			
		||||
  
 | 
			
		||||
  ld dists[MAX_EDGE];
 | 
			
		||||
  vector<ld> dists(cwt.at->type);
 | 
			
		||||
  
 | 
			
		||||
  transmatrix U = ggmatrix(cwt.at);
 | 
			
		||||
  
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								crystal.cpp
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								crystal.cpp
									
									
									
									
									
								
							@@ -13,6 +13,7 @@ EX namespace crystal {
 | 
			
		||||
 | 
			
		||||
#if HDR
 | 
			
		||||
static const int MAXDIM = 7;
 | 
			
		||||
static const int MAX_EDGE_CRYSTAL = 2 * MAXDIM;
 | 
			
		||||
 | 
			
		||||
struct coord : public array<int, MAXDIM> {
 | 
			
		||||
  coord operator + (coord b) { for(int i=0; i<MAXDIM; i++) b[i] += self[i]; return b; }  
 | 
			
		||||
@@ -279,7 +280,7 @@ struct crystal_structure {
 | 
			
		||||
    if(count_bugs()) {
 | 
			
		||||
      printf("bugs found\n");
 | 
			
		||||
      }
 | 
			
		||||
    if(dir > MAX_EDGE || dim > MAXDIM) {
 | 
			
		||||
    if(dir > MAX_EDGE_CRYSTAL || dim > MAXDIM) {
 | 
			
		||||
      printf("Dimension or directions exceeded -- I have generated it, but won't play");
 | 
			
		||||
      exit(0);
 | 
			
		||||
      }
 | 
			
		||||
@@ -722,7 +723,7 @@ bool is_bi(crystal_structure& cs, coord co) {
 | 
			
		||||
  return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
array<array<int,2>, MAX_EDGE> distlimit_table = {{
 | 
			
		||||
array<array<int,2>, MAX_EDGE_CRYSTAL> distlimit_table = {{
 | 
			
		||||
  {{SEE_ALL,SEE_ALL}}, {{SEE_ALL,SEE_ALL}}, {{SEE_ALL,SEE_ALL}}, {{SEE_ALL,SEE_ALL}}, {{15, 10}}, 
 | 
			
		||||
  {{6, 4}}, {{5, 3}}, {{4, 3}}, {{4, 3}}, {{3, 2}}, {{3, 2}}, {{3, 2}}, {{3, 2}}, {{3, 2}}
 | 
			
		||||
  }};
 | 
			
		||||
@@ -1257,7 +1258,7 @@ EX void build_rugdata() {
 | 
			
		||||
    const transmatrix& V = gp.second;
 | 
			
		||||
 | 
			
		||||
    auto co = m->get_coord(c);
 | 
			
		||||
    ldcoord vcoord[MAX_EDGE];
 | 
			
		||||
    vector<ldcoord> vcoord(c->type);
 | 
			
		||||
 | 
			
		||||
    for(int i=0; i<c->type; i++) 
 | 
			
		||||
      if(valence() == 4)
 | 
			
		||||
@@ -1270,7 +1271,7 @@ EX void build_rugdata() {
 | 
			
		||||
      v->flat = coord_to_flat(co);
 | 
			
		||||
      v->valid = true;
 | 
			
		||||
      
 | 
			
		||||
      rugpoint *p[MAX_EDGE];
 | 
			
		||||
      rugpoint *p[MAX_EDGE_CRYSTAL];
 | 
			
		||||
      
 | 
			
		||||
      for(int i=0; i<c->type; i++) {
 | 
			
		||||
        p[i] = addRugpoint(V * get_corner_position(c, i), 0);
 | 
			
		||||
@@ -1284,7 +1285,7 @@ EX void build_rugdata() {
 | 
			
		||||
    else {
 | 
			
		||||
      hyperpoint hco = coord_to_flat(co, 4);
 | 
			
		||||
      hco[3] -= cut_level * rug::modelscale;
 | 
			
		||||
      hyperpoint vco[MAX_EDGE];
 | 
			
		||||
      vector<hyperpoint> vco(c->type);
 | 
			
		||||
      for(int i=0; i<c->type; i++) {
 | 
			
		||||
        vco[i] = coord_to_flat(vcoord[i], 4);
 | 
			
		||||
        vco[i][3] -= cut_level * rug::modelscale;
 | 
			
		||||
@@ -1325,8 +1326,7 @@ EX void set_crystal(int sides) {
 | 
			
		||||
  static char buf[20];
 | 
			
		||||
  sprintf(buf, "{%d,4}", sides);
 | 
			
		||||
  ginf[gCrystal].tiling_name = buf;
 | 
			
		||||
  if(sides < MAX_EDGE)
 | 
			
		||||
    ginf[gCrystal].distlimit = distlimit_table[sides];
 | 
			
		||||
  ginf[gCrystal].distlimit = distlimit_table[min(sides, MAX_EDGE_CRYSTAL-1)];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
void test_crt() {
 | 
			
		||||
 
 | 
			
		||||
@@ -557,7 +557,7 @@ EX void moverefresh(bool turn IS(true)) {
 | 
			
		||||
          c->monst = moReptile;
 | 
			
		||||
          c->hitpoints = 3;
 | 
			
		||||
          c->stuntime = 0;
 | 
			
		||||
          int gooddirs[MAX_EDGE], qdirs = 0;
 | 
			
		||||
          vector<int> gooddirs;
 | 
			
		||||
          // in the peace mode, a reptile will
 | 
			
		||||
          // prefer to walk on the ground, rather than the chasm
 | 
			
		||||
          for(int i=0; i<c->type; i++) {
 | 
			
		||||
@@ -565,9 +565,9 @@ EX void moverefresh(bool turn IS(true)) {
 | 
			
		||||
            int i1 = (i+c->type-3) % c->type;
 | 
			
		||||
            if(c->move(i0) && passable(c->move(i0), c, 0)) 
 | 
			
		||||
            if(c->move(i1) && passable(c->move(i1), c, 0)) 
 | 
			
		||||
              gooddirs[qdirs++] = i;
 | 
			
		||||
              gooddirs.push_back(i);
 | 
			
		||||
            }
 | 
			
		||||
          if(qdirs) c->mondir = gooddirs[hrand(qdirs)];
 | 
			
		||||
          c->mondir = hrand_elt(gooddirs, c->mondir);
 | 
			
		||||
          playSound(c, "click");
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ void geometry_information::init_floorshapes() {
 | 
			
		||||
  for(auto sh: all_escher_floorshapes) sh->id = ids++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
typedef pair<transmatrix, array<transmatrix, MAX_EDGE>> matrixitem;
 | 
			
		||||
typedef pair<transmatrix, vector<transmatrix>> matrixitem;
 | 
			
		||||
 | 
			
		||||
struct mesher {
 | 
			
		||||
  eGeometry g;
 | 
			
		||||
@@ -119,6 +119,7 @@ struct matrixlist {
 | 
			
		||||
matrixitem genitem(const transmatrix& m1, const transmatrix& m2, int nsym) {
 | 
			
		||||
  matrixitem mi;
 | 
			
		||||
  mi.first = m1;
 | 
			
		||||
  mi.second.resize(nsym);
 | 
			
		||||
  for(int i=0; i<nsym; i++)
 | 
			
		||||
    mi.second[i] = spin(2*M_PI*i/nsym) * m2;
 | 
			
		||||
  return mi;
 | 
			
		||||
@@ -281,6 +282,7 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld
 | 
			
		||||
      }
 | 
			
		||||
    
 | 
			
		||||
    for(int k=0; k<SIDEPARS; k++) {
 | 
			
		||||
      fsh.gpside[k].resize(c->type);
 | 
			
		||||
      for(int i=0; i<c->type; i++) {
 | 
			
		||||
        sizeto(fsh.gpside[k][i], id);
 | 
			
		||||
        bshape(fsh.gpside[k][i][id], PPR::LAKEWALL); 
 | 
			
		||||
@@ -435,7 +437,8 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
 | 
			
		||||
    for(int i=0; i<=cor; i++)
 | 
			
		||||
      hpcpush(mid_at(hpxy(0,0), cornerlist[i%cor], SHADMUL));
 | 
			
		||||
    
 | 
			
		||||
    for(int k=0; k<SIDEPARS; k++) 
 | 
			
		||||
    for(int k=0; k<SIDEPARS; k++) {
 | 
			
		||||
      fsh.gpside[k].resize(cor);
 | 
			
		||||
      for(int cid=0; cid<cor; cid++) {
 | 
			
		||||
        sizeto(fsh.gpside[k][cid], id);
 | 
			
		||||
        bshape(fsh.gpside[k][cid][id], fsh.prio);
 | 
			
		||||
@@ -443,6 +446,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
 | 
			
		||||
        hpcpush(iddspin(c, cid) * cornerlist[(cid+1)%cor]);
 | 
			
		||||
        chasmifyPoly(dlow_table[k], dhi_table[k], k);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  for(auto pfsh: all_escher_floorshapes) {
 | 
			
		||||
@@ -481,6 +485,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
 | 
			
		||||
      m.n.sym = cor;
 | 
			
		||||
 | 
			
		||||
      int v = sidir+siid;
 | 
			
		||||
      for(auto& mvi: m.v) mvi.second.resize(cor);
 | 
			
		||||
      
 | 
			
		||||
      for(int ii=0; ii<2; ii++) {
 | 
			
		||||
        int i = 0;       
 | 
			
		||||
@@ -545,6 +550,9 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
 | 
			
		||||
            texture_order([&] (ld x, ld y) { hpcpush(orthogonal_move(normalize(C0 + v1 * x + v2 * y), dfloor_table[k])); });
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        finishshape();
 | 
			
		||||
        ensure_vertex_number(*last);
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
      for(int co=0; co<2; co++) {
 | 
			
		||||
@@ -574,12 +582,21 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
 | 
			
		||||
            texture_order([&] (ld x, ld y) { hpcpush(orthogonal_move(normalize(C0 + v1 * x + v2 * y), top + h * (x+y))); });
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        finishshape();
 | 
			
		||||
        ensure_vertex_number(*last);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      for(int l=0; l<SIDEPARS; l++) {
 | 
			
		||||
        for(auto& li: fsh.side[l]) li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
        for(int e=0; e<MAX_EDGE; e++)
 | 
			
		||||
          for(auto& li: fsh.gpside[l][e]) li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
        for(auto& li: fsh.side[l]) {
 | 
			
		||||
          li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
          ensure_vertex_number(li);
 | 
			
		||||
          }
 | 
			
		||||
        for(auto& gs: fsh.gpside[l])
 | 
			
		||||
          for(auto& li: gs) {
 | 
			
		||||
            li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
            ensure_vertex_number(li);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
@@ -592,7 +609,8 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
 | 
			
		||||
        for(auto& li: fsh.levels[l]) li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
        fsh.side[l] = shFullFloor.side[l];
 | 
			
		||||
        for(auto& li: fsh.side[l]) li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
        for(int e=0; e<MAX_EDGE; e++) {
 | 
			
		||||
        fsh.gpside[l].resize(c->type);
 | 
			
		||||
        for(int e=0; e<c->type; e++) {
 | 
			
		||||
          fsh.gpside[l][e] = shFullFloor.gpside[l][e];
 | 
			
		||||
          for(auto& li: fsh.gpside[l][e]) li.tinf = &floor_texture_vertices[fsh.id];
 | 
			
		||||
          }
 | 
			
		||||
@@ -1016,16 +1034,28 @@ void draw_shape_for_texture(floorshape* sh) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  // SL2 needs 6 times more
 | 
			
		||||
  for(int a=0; a<MAX_EDGE*6; a++)
 | 
			
		||||
    texture_order([&] (ld x, ld y) {
 | 
			
		||||
      hyperpoint h = center + v1 * x + v2 * y;
 | 
			
		||||
      hyperpoint inmodel;
 | 
			
		||||
      applymodel(h, inmodel);
 | 
			
		||||
      glvec2 v;
 | 
			
		||||
      v[0] = (1 + inmodel[0] * vid.scale) / 2;
 | 
			
		||||
      v[1] = (1 - inmodel[1] * vid.scale) / 2;
 | 
			
		||||
      ftv.tvertices.push_back(glhr::makevertex(v[0], v[1], 0));
 | 
			
		||||
      });
 | 
			
		||||
  texture_order([&] (ld x, ld y) {
 | 
			
		||||
    hyperpoint h = center + v1 * x + v2 * y;
 | 
			
		||||
    hyperpoint inmodel;
 | 
			
		||||
    applymodel(h, inmodel);
 | 
			
		||||
    glvec2 v;
 | 
			
		||||
    v[0] = (1 + inmodel[0] * vid.scale) / 2;
 | 
			
		||||
    v[1] = (1 - inmodel[1] * vid.scale) / 2;
 | 
			
		||||
    ftv.tvertices.push_back(glhr::makevertex(v[0], v[1], 0));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** copy the texture vertices so that there are at least qty of them */
 | 
			
		||||
EX void ensure_vertex_number(basic_textureinfo& bti, int qty) {
 | 
			
		||||
  int s = isize(bti.tvertices);
 | 
			
		||||
  while(isize(bti.tvertices) <= qty) {
 | 
			
		||||
    for(int i=0; i<s; i++) bti.tvertices.push_back(bti.tvertices[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** ensure_vertex_number for a hpcshape */
 | 
			
		||||
EX void ensure_vertex_number(hpcshape& sh) {
 | 
			
		||||
  ensure_vertex_number(*sh.tinf, sh.e - sh.s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
const int FLOORTEXTURESIZE = 4096;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								game.cpp
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								game.cpp
									
									
									
									
									
								
							@@ -43,8 +43,21 @@ EX int hrand(int i) {
 | 
			
		||||
#if HDR
 | 
			
		||||
template<class T, class... U> T pick(T x, U... u) { std::initializer_list<T> i = {x,u...}; return *(i.begin() + hrand(1+sizeof...(u))); }
 | 
			
		||||
template<class T> void hrandom_shuffle(T* x, int n) { for(int k=1; k<n; k++) swap(x[k], x[hrand(k+1)]); }
 | 
			
		||||
template<class T> void hrandom_shuffle(T& container) { hrandom_shuffle(&container[0], isize(container)); }
 | 
			
		||||
template<class U> auto hrand_elt(U& container) -> decltype(container[0]) { return container[hrand(isize(container))]; }
 | 
			
		||||
template<class T, class U> T hrand_elt(U& container, T default_value) { 
 | 
			
		||||
  if(container.empty()) return default_value; 
 | 
			
		||||
  return container[hrand(isize(container))]; 
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
EX vector<int> hrandom_permutation(int qty) {
 | 
			
		||||
  vector<int> res(qty);
 | 
			
		||||
  for(int i=0; i<qty; i++) res[i] = i;
 | 
			
		||||
  hrandom_shuffle(res);
 | 
			
		||||
  return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** Use \link hrngen \endlink to generate a floating point number between 0 and 1.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								geometry.cpp
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								geometry.cpp
									
									
									
									
									
								
							@@ -63,7 +63,8 @@ struct floorshape {
 | 
			
		||||
  int pstrength; // pattern strength in 3D
 | 
			
		||||
  int fstrength; // frame strength in 3D
 | 
			
		||||
  PPR prio;
 | 
			
		||||
  vector<hpcshape> b, shadow, side[SIDEPARS], gpside[SIDEPARS][MAX_EDGE], levels[SIDEPARS], cone[2];
 | 
			
		||||
  vector<hpcshape> b, shadow, side[SIDEPARS], levels[SIDEPARS], cone[2];
 | 
			
		||||
  vector<vector<hpcshape>> gpside[SIDEPARS];
 | 
			
		||||
  floorshape() { prio = PPR::FLOOR; pstrength = fstrength = 10; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@@ -112,8 +113,7 @@ struct geometry_information {
 | 
			
		||||
  /** distance from heptagon center to heptagon vertex (either hexf or hcrossf) */
 | 
			
		||||
  ld rhexf;
 | 
			
		||||
 | 
			
		||||
  transmatrix heptmove[MAX_EDGE], hexmove[MAX_EDGE];
 | 
			
		||||
  transmatrix invhexmove[MAX_EDGE];
 | 
			
		||||
  vector<transmatrix> heptmove, hexmove, invhexmove;
 | 
			
		||||
 | 
			
		||||
  int base_distlimit;
 | 
			
		||||
 | 
			
		||||
@@ -381,7 +381,7 @@ hpcshape
 | 
			
		||||
  /* Goldberg parameters */
 | 
			
		||||
  #if CAP_GP
 | 
			
		||||
  struct gpdata_t {
 | 
			
		||||
    transmatrix Tf[MAX_EDGE][32][32][6];
 | 
			
		||||
    vector<array<array<array<transmatrix, 6>, 32>, 32>> Tf;
 | 
			
		||||
    transmatrix corners;
 | 
			
		||||
    ld alpha;
 | 
			
		||||
    int area;
 | 
			
		||||
@@ -478,6 +478,10 @@ void geometry_information::prepare_basics() {
 | 
			
		||||
  
 | 
			
		||||
  finish:
 | 
			
		||||
  
 | 
			
		||||
  heptmove.resize(S7);
 | 
			
		||||
  hexmove.resize(S7);
 | 
			
		||||
  invhexmove.resize(S7);
 | 
			
		||||
  
 | 
			
		||||
  for(int d=0; d<S7; d++)
 | 
			
		||||
    heptmove[d] = spin(-d * ALPHA) * xpush(tessf) * spin(M_PI);
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,7 @@ EX namespace gp {
 | 
			
		||||
    transmatrix adjm;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  EX int fixg6(int x) { return (x + MODFIXER) % SG6; }
 | 
			
		||||
  EX int fixg6(int x) { return gmod(x, SG6); }
 | 
			
		||||
  
 | 
			
		||||
  EX int get_code(const local_info& li) {
 | 
			
		||||
    return 
 | 
			
		||||
@@ -137,7 +137,7 @@ EX namespace gp {
 | 
			
		||||
  
 | 
			
		||||
  EX int pseudohept_val(cell *c) {
 | 
			
		||||
    loc v = get_coord(c);
 | 
			
		||||
    return (v.first - v.second + MODFIXER)%3;
 | 
			
		||||
    return gmod(v.first - v.second, 3);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  // mapping of the local equilateral triangle
 | 
			
		||||
@@ -578,6 +578,7 @@ EX namespace gp {
 | 
			
		||||
      loctoh_ort(param * loc(0,1)),
 | 
			
		||||
      C03
 | 
			
		||||
      ));
 | 
			
		||||
    cgi.gpdata->Tf.resize(S7);
 | 
			
		||||
    for(int i=0; i<S7; i++) {
 | 
			
		||||
      transmatrix T = dir_matrix(i);
 | 
			
		||||
      for(int x=-16; x<16; x++)
 | 
			
		||||
 
 | 
			
		||||
@@ -3248,7 +3248,7 @@ EX bool placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, color_t
 | 
			
		||||
  if(NONSTDVAR || !standard_tiling()) {
 | 
			
		||||
    #if CAP_ARCM
 | 
			
		||||
    if(arcm::in() && !PURE)
 | 
			
		||||
      i = (i + arcm::parent_index_of(c->master)/DUALMUL + MODFIXER) % c->type;
 | 
			
		||||
      i = gmod(i + arcm::parent_index_of(c->master)/DUALMUL, c->type);
 | 
			
		||||
    #endif
 | 
			
		||||
    draw_shapevec(c, V2, qfi.fshape->gpside[sidepar][i], col, prio);
 | 
			
		||||
    return false;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								hud.cpp
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								hud.cpp
									
									
									
									
									
								
							@@ -437,7 +437,7 @@ EX void drawStats() {
 | 
			
		||||
    #if CAP_QUEUE
 | 
			
		||||
    queuecircle(xmove, yb, rad, 0xFF0000FF);
 | 
			
		||||
    queuecircle(xmove, yb, rad*SKIPFAC, 
 | 
			
		||||
      legalmoves[MAX_EDGE] ? 0xFF0000FF : 0xFF000080
 | 
			
		||||
      legalmoves[cwt.at->type] ? 0xFF0000FF : 0xFF000080
 | 
			
		||||
      );
 | 
			
		||||
    #endif
 | 
			
		||||
    #if CAP_SHAPES
 | 
			
		||||
 
 | 
			
		||||
@@ -110,7 +110,7 @@ struct gcell {
 | 
			
		||||
#define landparam_color LHU.landpar_color
 | 
			
		||||
#define fval LHU.fi.fieldval
 | 
			
		||||
 | 
			
		||||
#define MAX_EDGE 18
 | 
			
		||||
#define FULL_EDGE 120
 | 
			
		||||
 | 
			
		||||
template<class T> struct walker;
 | 
			
		||||
 | 
			
		||||
@@ -125,10 +125,12 @@ template<class T> struct walker;
 | 
			
		||||
 *  and freed with tailored_free.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int gmod(int i, int j);
 | 
			
		||||
 | 
			
		||||
template<class T> struct connection_table {
 | 
			
		||||
 | 
			
		||||
  /** Table of moves. This is the maximum size, but tailored_alloc allocates less. */
 | 
			
		||||
  T* move_table[MAX_EDGE + (MAX_EDGE + sizeof(char*) - 1) / sizeof(char*)];
 | 
			
		||||
  T* move_table[FULL_EDGE + (FULL_EDGE + sizeof(char*) - 1) / sizeof(char*)];
 | 
			
		||||
  
 | 
			
		||||
  unsigned char *spintable() { return (unsigned char*) (&move_table[full()->degree()]); }
 | 
			
		||||
 | 
			
		||||
@@ -145,7 +147,7 @@ template<class T> struct connection_table {
 | 
			
		||||
  /** on non-orientable surfaces, the d-th edge may be mirrored */
 | 
			
		||||
  bool mirror(int d) { return spintable() [d] & 128; }  
 | 
			
		||||
  /** 'fix' the edge number d to get the actual index in [0, degree()) */
 | 
			
		||||
  int fix(int d) { return (d + MODFIXER) % full()->degree(); }
 | 
			
		||||
  int fix(int d) { return gmod(d, full()->degree()); }
 | 
			
		||||
  /** T in the direction i */
 | 
			
		||||
  T*& move(int i) { return move_table[i]; }
 | 
			
		||||
  /** T in the direction i, modulo degree() */
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ EX namespace mapeditor {
 | 
			
		||||
      c->hitpoints = c2->hitpoints;
 | 
			
		||||
      if(c2->mondir != NODIR) {
 | 
			
		||||
        auto si2 = patterns::getpatterninfo0(c2);
 | 
			
		||||
        c->mondir = (c2->mondir - si2.dir + si.dir + MODFIXER) % c->type;
 | 
			
		||||
        c->mondir = gmod(c2->mondir - si2.dir + si.dir, c->type);
 | 
			
		||||
        // todo reflect
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
@@ -434,7 +434,7 @@ namespace mapstream {
 | 
			
		||||
        // printf("%p:%d,%d -> %p\n", c2, relspin[parent], dir, c);
 | 
			
		||||
        
 | 
			
		||||
        // spinval becomes xspinval
 | 
			
		||||
        rspin = (c2->c.spin(dir) - f.read_char() + MODFIXER) % (c->type - sub);
 | 
			
		||||
        rspin = gmod(c2->c.spin(dir) - f.read_char(), c->type - sub);
 | 
			
		||||
        if(GDIM == 3 && rspin && !hybri) {
 | 
			
		||||
          println(hlog, "rspin in 3D");
 | 
			
		||||
          throw hstream_exception();
 | 
			
		||||
@@ -898,7 +898,7 @@ namespace mapeditor {
 | 
			
		||||
        c->hitpoints = copywhat->hitpoints;
 | 
			
		||||
        c->stuntime = copywhat->stuntime; 
 | 
			
		||||
        if(copywhat->mondir == NODIR) c->mondir = NODIR;
 | 
			
		||||
        else c->mondir = ((where.first.mirrored == where.second.mirrored ? 1 : -1) * (copywhat->mondir - where.second.spin) + cdir + MODFIXER) % c->type;
 | 
			
		||||
        else c->mondir = gmod((where.first.mirrored == where.second.mirrored ? 1 : -1) * (copywhat->mondir - where.second.spin) + cdir, c->type);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    checkUndo();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								monstermove.cpp
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								monstermove.cpp
									
									
									
									
									
								
							@@ -19,7 +19,7 @@ EX int sagephase = 0;
 | 
			
		||||
EX vector<cell*> targets;
 | 
			
		||||
 | 
			
		||||
/** monsters to move, ordered by the number of possible good moves */
 | 
			
		||||
vector<cell*> movesofgood[MAX_EDGE+1];
 | 
			
		||||
grow_vector<vector<cell*>> movesofgood;
 | 
			
		||||
 | 
			
		||||
EX vector<pair<cell*, int> > butterflies;
 | 
			
		||||
 | 
			
		||||
@@ -538,11 +538,12 @@ EX int totalbulldistance(cell *c, int k) {
 | 
			
		||||
  return tbd;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
EX void determinizeBull(cell *c, int *posdir, int& nc) {
 | 
			
		||||
EX void determinizeBull(cell *c, vector<int>& posdir) {
 | 
			
		||||
  // determinize the Angry Beast movement:
 | 
			
		||||
  // use the previous PC's positions as the tiebreaker
 | 
			
		||||
  int nc = isize(posdir);
 | 
			
		||||
  for(int k=0; k<SHSIZE && nc>1; k++) {
 | 
			
		||||
    int pts[MAX_EDGE];
 | 
			
		||||
    vector<int> pts(nc);
 | 
			
		||||
    for(int d=0; d<nc; d++) pts[d] = totalbulldistance(c->cmove(posdir[d]), k);
 | 
			
		||||
 | 
			
		||||
    int bestpts = 1000;
 | 
			
		||||
@@ -551,46 +552,46 @@ EX void determinizeBull(cell *c, int *posdir, int& nc) {
 | 
			
		||||
    for(int d=0; d<nc; d++) if(pts[d] == bestpts) posdir[nc0++] = posdir[d];
 | 
			
		||||
    nc = nc0;
 | 
			
		||||
    }
 | 
			
		||||
  posdir.resize(nc);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
EX int determinizeBullPush(cellwalker bull) {
 | 
			
		||||
  int nc = 2;
 | 
			
		||||
  int dirs[2], positive;
 | 
			
		||||
  vector<int> dirs(2);
 | 
			
		||||
  int positive;
 | 
			
		||||
  bull += wstep;
 | 
			
		||||
  cell *c2 = bull.at;
 | 
			
		||||
  if(!(c2->type & 1)) return 1; // irrelevant
 | 
			
		||||
  int d = c2->type / 2;
 | 
			
		||||
  bull += d; dirs[0] = positive = bull.spin;
 | 
			
		||||
  bull -= 2*d; dirs[1] = bull.spin;
 | 
			
		||||
  determinizeBull(c2, dirs, nc);
 | 
			
		||||
  determinizeBull(c2, dirs);
 | 
			
		||||
  if(dirs[0] == positive) return -1;
 | 
			
		||||
  return 1;
 | 
			
		||||
  }    
 | 
			
		||||
 | 
			
		||||
int posdir[MAX_EDGE], nc;
 | 
			
		||||
vector<int> global_posdir;
 | 
			
		||||
 | 
			
		||||
EX int pickMoveDirection(cell *c, flagtype mf) {
 | 
			
		||||
  int bestval = stayval(c, mf);
 | 
			
		||||
  nc = 1; posdir[0] = -1;
 | 
			
		||||
  global_posdir = {-1};
 | 
			
		||||
 | 
			
		||||
  // printf("stayval [%p, %s]: %d\n", c, dnameof(c->monst), bestval);
 | 
			
		||||
  for(int d=0; d<c->type; d++) {
 | 
			
		||||
    cell *c2 = c->move(d);
 | 
			
		||||
    int val = moveval(c, c2, d, mf);
 | 
			
		||||
    // printf("[%d] %p: val=%5d pass=%d\n", d, c2, val, passable(c2,c,0));
 | 
			
		||||
    if(val > bestval) nc = 0, bestval = val;
 | 
			
		||||
    if(val == bestval) posdir[nc++] = d;
 | 
			
		||||
    if(val > bestval) global_posdir.clear(), bestval = val;
 | 
			
		||||
    if(val == bestval) global_posdir.push_back(d);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  if(c->monst == moRagingBull) 
 | 
			
		||||
    determinizeBull(c, posdir, nc);
 | 
			
		||||
    determinizeBull(c, global_posdir);
 | 
			
		||||
    
 | 
			
		||||
  if(!nc) return -1;
 | 
			
		||||
  return posdir[hrand(nc)];
 | 
			
		||||
  return hrand_elt(global_posdir, -1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
EX int pickDownDirection(cell *c, flagtype mf) {
 | 
			
		||||
  int downs[MAX_EDGE], qdowns = 0;
 | 
			
		||||
  vector<int> downs;
 | 
			
		||||
  int bestdif = -100;
 | 
			
		||||
  forCellIdEx(c2, i, c) {
 | 
			
		||||
    if(gravityLevelDiff(c2, c) < 0 && passable_for(c->monst, c2, c, P_MIRROR) &&
 | 
			
		||||
@@ -602,12 +603,11 @@ EX int pickDownDirection(cell *c, flagtype mf) {
 | 
			
		||||
      // printf("i=%d md=%d dif=%d\n", i, c->mondir, cdif);
 | 
			
		||||
      if(c2->wall == waClosePlate || c->wall == waClosePlate)
 | 
			
		||||
        cdif += 20;
 | 
			
		||||
      if(cdif > bestdif) bestdif = cdif, qdowns = 0;
 | 
			
		||||
      if(cdif == bestdif) downs[qdowns++] = i;
 | 
			
		||||
      if(cdif > bestdif) bestdif = cdif, downs.clear();
 | 
			
		||||
      if(cdif == bestdif) downs.push_back(i);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  if(!qdowns) return -1;
 | 
			
		||||
  return downs[hrand(qdowns)];
 | 
			
		||||
  return hrand_elt(downs, -1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
// Angry Beast attack
 | 
			
		||||
@@ -657,7 +657,7 @@ EX cell *moveNormal(cell *c, flagtype mf) {
 | 
			
		||||
  int d;
 | 
			
		||||
  
 | 
			
		||||
  if(c->stuntime) {
 | 
			
		||||
    if(cellEdgeUnstable(c, MF_STUNNED)) d = pickDownDirection(c, mf), nc = 1, posdir[0] = d;
 | 
			
		||||
    if(cellEdgeUnstable(c, MF_STUNNED)) d = pickDownDirection(c, mf), global_posdir = {d};
 | 
			
		||||
    else return NULL;
 | 
			
		||||
    }
 | 
			
		||||
  else {
 | 
			
		||||
@@ -706,8 +706,8 @@ EX cell *moveNormal(cell *c, flagtype mf) {
 | 
			
		||||
    }
 | 
			
		||||
  else {
 | 
			
		||||
    bool attacking = false;
 | 
			
		||||
    for(int i=0; i<nc; i++) {
 | 
			
		||||
      cell *c2 = c->move(posdir[i]);
 | 
			
		||||
    for(int dir: global_posdir) {
 | 
			
		||||
      cell *c2 = c->move(dir);
 | 
			
		||||
 | 
			
		||||
      if(isPlayerOn(c2)) {
 | 
			
		||||
        killThePlayerAt(m, c2, 0); 
 | 
			
		||||
@@ -725,8 +725,8 @@ EX cell *moveNormal(cell *c, flagtype mf) {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    
 | 
			
		||||
    if(!attacking) for(int i=0; i<nc; i++) {
 | 
			
		||||
      movei mi(c, posdir[i]);
 | 
			
		||||
    if(!attacking) for(int dir: global_posdir) {
 | 
			
		||||
      movei mi(c, dir);
 | 
			
		||||
      if(!c->monst) c->monst = m;
 | 
			
		||||
      moveMonster(mi);
 | 
			
		||||
      if(m == moRagingBull) beastAttack(mi.t, false, false);
 | 
			
		||||
@@ -1152,13 +1152,12 @@ EX void groupmove(eMonster movtype, flagtype mf) {
 | 
			
		||||
  
 | 
			
		||||
  for(int i=0; i<isize(gendfs); i++) {
 | 
			
		||||
    cell *c = gendfs[i];
 | 
			
		||||
    int dirtable[MAX_EDGE], qdirtable=0;
 | 
			
		||||
    vector<int> dirtable;
 | 
			
		||||
    
 | 
			
		||||
    forCellIdAll(c2,t,c) dirtable[qdirtable++] = t;
 | 
			
		||||
    hrandom_shuffle(dirtable, qdirtable);
 | 
			
		||||
    forCellIdAll(c2,t,c) dirtable.push_back(t);
 | 
			
		||||
    hrandom_shuffle(dirtable);
 | 
			
		||||
 | 
			
		||||
    while(qdirtable--) {
 | 
			
		||||
      int t = dirtable[qdirtable];
 | 
			
		||||
    for(auto& t: dirtable) {
 | 
			
		||||
      groupmove2(movei(c, t).rev(),movtype,mf);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
@@ -1287,13 +1286,12 @@ EX void movehex(bool mounted, int colorpair) {
 | 
			
		||||
  
 | 
			
		||||
  for(int i=0; i<isize(hexdfs); i++) {
 | 
			
		||||
    cell *c = hexdfs[i];
 | 
			
		||||
    int dirtable[MAX_EDGE], qdirtable=0;
 | 
			
		||||
    vector<int> dirtable;
 | 
			
		||||
    for(int t=0; t<c->type; t++) if(c->move(t) && inpair(c->move(t), colorpair))
 | 
			
		||||
      dirtable[qdirtable++] = t;
 | 
			
		||||
      dirtable.push_back(t);
 | 
			
		||||
      
 | 
			
		||||
    hrandom_shuffle(dirtable, qdirtable);
 | 
			
		||||
    while(qdirtable--) {
 | 
			
		||||
      int t = dirtable[qdirtable];
 | 
			
		||||
    hrandom_shuffle(dirtable);
 | 
			
		||||
    for(auto& t: dirtable) {
 | 
			
		||||
      hexvisit(c->move(t), c, t, mounted, colorpair);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -1306,13 +1304,11 @@ EX void movehex_rest(bool mounted) {
 | 
			
		||||
    if(c->monst == moHexSnake) {
 | 
			
		||||
      colorpair = snake_pair(c);
 | 
			
		||||
      if(!goodmount(c, mounted)) continue;
 | 
			
		||||
      int t[MAX_EDGE];
 | 
			
		||||
      for(int i=0; i<c->type; i++) t[i] = i;
 | 
			
		||||
      for(int j=1; j<c->type; j++) swap(t[j], t[hrand(j+1)]);
 | 
			
		||||
      vector<int> dirtable = hrandom_permutation(c->type);
 | 
			
		||||
      for(int u=0; u<c->type; u++) {
 | 
			
		||||
        createMov(c, t[u]);
 | 
			
		||||
        if(inpair(c->move(t[u]), colorpair))
 | 
			
		||||
          hexvisit(c, c->move(t[u]), c->c.spin(t[u]), mounted, colorpair);
 | 
			
		||||
        createMov(c, dirtable[u]);
 | 
			
		||||
        if(inpair(c->move(dirtable[u]), colorpair))
 | 
			
		||||
          hexvisit(c, c->move(dirtable[u]), c->c.spin(dirtable[u]), mounted, colorpair);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    if(c->monst == moHexSnake) {
 | 
			
		||||
@@ -1429,7 +1425,7 @@ EX void moveshadow() {
 | 
			
		||||
EX void moveghosts() {
 | 
			
		||||
 | 
			
		||||
  if(invismove) return;
 | 
			
		||||
  for(int d=0; d<=MAX_EDGE; d++) movesofgood[d].clear();  
 | 
			
		||||
  movesofgood.clear();
 | 
			
		||||
 | 
			
		||||
  for(int i=0; i<isize(ghosts); i++) {
 | 
			
		||||
    cell *c = ghosts[i];
 | 
			
		||||
@@ -1444,19 +1440,18 @@ EX void moveghosts() {
 | 
			
		||||
        if(ghostmove(c->monst, c->move(k), c) && !isPlayerOn(c->move(k)))
 | 
			
		||||
          goodmoves++;
 | 
			
		||||
      
 | 
			
		||||
      movesofgood[goodmoves].push_back(c);
 | 
			
		||||
      movesofgood.grow(goodmoves).push_back(c);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  for(int d=0; d<=MAX_EDGE; d++) for(int i=0; i<isize(movesofgood[d]); i++) {
 | 
			
		||||
    cell *c = movesofgood[d][i];
 | 
			
		||||
  for(auto& v: movesofgood) for(cell *c: v) {
 | 
			
		||||
 | 
			
		||||
    if(c->stuntime) continue;    
 | 
			
		||||
    if(isPowerMonster(c) && !playerInPower()) continue;
 | 
			
		||||
    
 | 
			
		||||
    if(isGhostMover(c->monst) && c->cpdist >= 1) {
 | 
			
		||||
      
 | 
			
		||||
      int mdir[MAX_EDGE];
 | 
			
		||||
      vector<int> mdir;
 | 
			
		||||
 | 
			
		||||
      for(int j=0; j<c->type; j++) 
 | 
			
		||||
        if(c->move(j) && canAttack(c, c->monst, c->move(j), c->move(j)->monst, AF_GETPLAYER | AF_ONLY_FBUG)) {
 | 
			
		||||
@@ -1466,12 +1461,11 @@ EX void moveghosts() {
 | 
			
		||||
          goto nextghost;
 | 
			
		||||
          }
 | 
			
		||||
    
 | 
			
		||||
      int qmpos = 0;
 | 
			
		||||
      for(int k=0; k<c->type; k++) if(c->move(k) && c->move(k)->cpdist < c->cpdist)
 | 
			
		||||
        if(ghostmove(c->monst, c->move(k), c))
 | 
			
		||||
          mdir[qmpos++] = k;
 | 
			
		||||
      if(!qmpos) continue;
 | 
			
		||||
      int d = mdir[hrand(qmpos)];
 | 
			
		||||
          mdir.push_back(k);
 | 
			
		||||
      if(mdir.empty()) continue;
 | 
			
		||||
      int d = hrand_elt(mdir);
 | 
			
		||||
      cell *c2 = c->move(d);
 | 
			
		||||
      if(c2->monst == moTortoise && c2->stuntime > 1) {
 | 
			
		||||
        addMessage(XLAT("%The1 scares %the2 a bit!", c->monst, c2->monst));
 | 
			
		||||
@@ -1606,15 +1600,16 @@ EX void movegolems(flagtype flags) {
 | 
			
		||||
      for(int i=0; i<ittypes; i++) recorduse[i] = orbused[i];
 | 
			
		||||
 | 
			
		||||
      DEBB(DF_TURN, ("stayval"));
 | 
			
		||||
      int bestv = stayvalue(m, c), bq = 0, bdirs[MAX_EDGE];
 | 
			
		||||
      int bestv = stayvalue(m, c);
 | 
			
		||||
      vector<int> bdirs;
 | 
			
		||||
 | 
			
		||||
      DEBB(DF_TURN, ("moveval"));
 | 
			
		||||
      for(int k=0; k<c->type; k++) if(c->move(k)) {
 | 
			
		||||
        cell *c2 = c->move(k);
 | 
			
		||||
        int val = movevalue(m, c, c2, flags);
 | 
			
		||||
 | 
			
		||||
        if(val > bestv) bestv = val, bq = 0;
 | 
			
		||||
        if(val == bestv) bdirs[bq++] = k;
 | 
			
		||||
        if(val > bestv) bestv = val, bdirs.clear();
 | 
			
		||||
        if(val == bestv) bdirs.push_back(k);
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
      if(m == moTameBomberbird) {
 | 
			
		||||
@@ -1622,8 +1617,8 @@ EX void movegolems(flagtype flags) {
 | 
			
		||||
        if(c2 && !c2->monst) {
 | 
			
		||||
          int val = movevalue(m, c, c2, flags);
 | 
			
		||||
          // printf("val = %d bestv = %d\n", 
 | 
			
		||||
          if(val > bestv) bestv = val, bq = 0;
 | 
			
		||||
          if(val == bestv) bdirs[bq++] = STRONGWIND;
 | 
			
		||||
          if(val > bestv) bestv = val, bdirs.clear();
 | 
			
		||||
          if(val == bestv) bdirs.push_back(STRONGWIND);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1631,8 +1626,8 @@ EX void movegolems(flagtype flags) {
 | 
			
		||||
      
 | 
			
		||||
//    printf("stayvalue = %d, result = %d, bq = %d\n", stayvalue(m,c), bestv, bq);
 | 
			
		||||
        
 | 
			
		||||
      if(bq == 0) continue;
 | 
			
		||||
      int dir = bdirs[hrand(bq)];
 | 
			
		||||
      if(bdirs.empty()) continue;
 | 
			
		||||
      int dir = hrand_elt(bdirs);
 | 
			
		||||
      auto mi = movei(c, dir);
 | 
			
		||||
      auto& c2 = mi.t;
 | 
			
		||||
      if(c2->monst) {
 | 
			
		||||
@@ -1882,16 +1877,16 @@ EX void consMove(cell *c, eMonster param) {
 | 
			
		||||
      if(c2 && c2->pathdist < c->pathdist)
 | 
			
		||||
        goodmoves++;
 | 
			
		||||
      }
 | 
			
		||||
    movesofgood[goodmoves].push_back(c);
 | 
			
		||||
    movesofgood.grow(goodmoves).push_back(c);
 | 
			
		||||
    }
 | 
			
		||||
  else 
 | 
			
		||||
    movesofgood[0].push_back(c);
 | 
			
		||||
    movesofgood.grow(0).push_back(c);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
EX void moveNormals(eMonster param) {
 | 
			
		||||
  pathdata pd(param);
 | 
			
		||||
 | 
			
		||||
  for(int d=0; d<=MAX_EDGE; d++) movesofgood[d].clear();
 | 
			
		||||
  
 | 
			
		||||
  movesofgood.clear();
 | 
			
		||||
 | 
			
		||||
  for(int i=0; i<isize(pathqm); i++) 
 | 
			
		||||
    consMove(pathqm[i], param);
 | 
			
		||||
@@ -1902,8 +1897,7 @@ EX void moveNormals(eMonster param) {
 | 
			
		||||
    if(c->pathdist == PINFD) consMove(c, param);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for(int d=0; d<=MAX_EDGE; d++) for(int i=0; i<isize(movesofgood[d]); i++) {
 | 
			
		||||
    cell *c = movesofgood[d][i];
 | 
			
		||||
  for(auto& v: movesofgood) for(cell *c: v) {
 | 
			
		||||
    if(minf[c->monst].mgroup == moYeti) {
 | 
			
		||||
      moveNormal(c, MF_PATHDIST);
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								netgen.cpp
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								netgen.cpp
									
									
									
									
									
								
							@@ -57,15 +57,15 @@ EX namespace netgen {
 | 
			
		||||
  vec center[MAXCELLS];
 | 
			
		||||
  double rot[MAXCELLS];  
 | 
			
		||||
  int glued[MAXCELLS];
 | 
			
		||||
  int nei[MAXCELLS][MAX_EDGE];
 | 
			
		||||
  vector<int> nei[MAXCELLS];
 | 
			
		||||
 | 
			
		||||
  // auxiliary data
 | 
			
		||||
  double raylen[MAXCELLS];
 | 
			
		||||
  double edgist[MAXCELLS];  
 | 
			
		||||
  char patek[MAXCELLS][MAX_EDGE];
 | 
			
		||||
  vector<char> patek[MAXCELLS];
 | 
			
		||||
  
 | 
			
		||||
  // data generated by HyperRogue
 | 
			
		||||
  hyperpoint hcenter[MAXCELLS][MAX_EDGE+1];
 | 
			
		||||
  vector<hyperpoint> hcenter[MAXCELLS];
 | 
			
		||||
  
 | 
			
		||||
  // Functions handling the data.
 | 
			
		||||
  //==============================
 | 
			
		||||
@@ -79,7 +79,8 @@ EX namespace netgen {
 | 
			
		||||
    if(mode == 1)
 | 
			
		||||
    for(int ii=0; ii<CELLS; ii++) if(dcal[ii] == c) {
 | 
			
		||||
    
 | 
			
		||||
      hcenter[ii][MAX_EDGE] = V * C0;
 | 
			
		||||
      hcenter[ii].resize(c->type+1);
 | 
			
		||||
      hcenter[ii][c->type] = V * C0;
 | 
			
		||||
 | 
			
		||||
      if(c->type == S7) {
 | 
			
		||||
        for(int i=0; i<c->type; i++) {
 | 
			
		||||
@@ -110,11 +111,12 @@ EX namespace netgen {
 | 
			
		||||
 | 
			
		||||
    for(int i=0; i<CELLS; i++) {
 | 
			
		||||
      ct[i] = dcal[i]->type;
 | 
			
		||||
      for(int k=0; k<8; k++)
 | 
			
		||||
      for(int k=0; k<=ct[i]; k++)
 | 
			
		||||
        vx[i][2*k] = hcenter[i][k][0],
 | 
			
		||||
        vx[i][2*k+1] = hcenter[i][k][1];
 | 
			
		||||
      
 | 
			
		||||
      for(int k=0; k<ct[i]; k++) nei[i][k] = -1;
 | 
			
		||||
      nei[i].clear();
 | 
			
		||||
      nei[i].resize(ct[i], -1);
 | 
			
		||||
 | 
			
		||||
      for(int j=0; j<CELLS; j++) {
 | 
			
		||||
        cell *c1 = dcal[i];
 | 
			
		||||
@@ -148,6 +150,8 @@ EX namespace netgen {
 | 
			
		||||
    
 | 
			
		||||
    for(int i=0; i<CELLS; i++) scan(f, ct[i]);
 | 
			
		||||
 | 
			
		||||
    for(int i=0; i<CELLS; i++) nei[i].resize(ct[i]);
 | 
			
		||||
 | 
			
		||||
    for(int i=0; i<CELLS; i++) for(int j=0; j<16; j++) scan(f, vx[i][j]);
 | 
			
		||||
 | 
			
		||||
    for(int i=0; i<CELLS; i++) 
 | 
			
		||||
@@ -343,6 +347,7 @@ EX namespace netgen {
 | 
			
		||||
    SDL_FillRect(net, NULL, 0xFFFFFF);
 | 
			
		||||
    
 | 
			
		||||
    int pateks = 0;
 | 
			
		||||
    for(int i=0; i<CELLS; i++) patek[i].resize(ct[i]);
 | 
			
		||||
    
 | 
			
		||||
    int zeroi = nei[0][0];
 | 
			
		||||
    int zeroe = 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								orbs.cpp
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								orbs.cpp
									
									
									
									
									
								
							@@ -321,8 +321,7 @@ EX bool reflectingBarrierAt(cell *c) {
 | 
			
		||||
EX bool reflectingBarrierAt(cellwalker& c, int d) {
 | 
			
		||||
  if(d >= 3) return true;
 | 
			
		||||
  if(d <= -3) return true;
 | 
			
		||||
  d = c.spin + d + MODFIXER;
 | 
			
		||||
  d%=c.at->type;
 | 
			
		||||
  d = gmod(c.spin + d, c.at->type);
 | 
			
		||||
  if(!c.at->move(d)) return true;
 | 
			
		||||
  
 | 
			
		||||
  return reflectingBarrierAt(c.at->move(d));
 | 
			
		||||
@@ -1104,8 +1103,7 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
 | 
			
		||||
  
 | 
			
		||||
  // nature
 | 
			
		||||
  if(items[itOrbNature] && numplayers() == 1 && c->monst != moFriendlyIvy) {
 | 
			
		||||
    int dirs[MAX_EDGE];
 | 
			
		||||
    int qsides = 0;
 | 
			
		||||
    vector<int> dirs;
 | 
			
		||||
    forCellIdCM(cf, d, c)
 | 
			
		||||
      if(cf->monst == moFriendlyIvy) {
 | 
			
		||||
 | 
			
		||||
@@ -1118,11 +1116,11 @@ EX eItem targetRangedOrb(cell *c, orbAction a) {
 | 
			
		||||
          if(strictlyAgainstGravity(c, cf, false, MF_IVY)) continue;
 | 
			
		||||
          if(monstersnear(cwt.at, NULL, moPlayer, c, cwt.at)) continue;
 | 
			
		||||
          }
 | 
			
		||||
        dirs[qsides++] = d;
 | 
			
		||||
        dirs.push_back(d);
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
    if(qsides > 0) {
 | 
			
		||||
      int di = dirs[hrand(qsides)];
 | 
			
		||||
    int di = hrand_elt(dirs, -1);
 | 
			
		||||
    if(di != -1) {
 | 
			
		||||
      if(!isCheck(a)) growIvyTo(movei(c, di).rev());
 | 
			
		||||
      return itOrbNature;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -1278,8 +1278,8 @@ EX int pattern_threecolor(cell *c) {
 | 
			
		||||
  #if CAP_GP
 | 
			
		||||
  if(S3 == 3 && !(S7&1) && gp_threecolor() == 1 && c->master->c7 != c) {
 | 
			
		||||
    auto li = gp::get_local_info(c);
 | 
			
		||||
    int rel = (li.relative.first - li.relative.second + MODFIXER) % 3;
 | 
			
		||||
    int par = (gp::param.first - gp::param.second + MODFIXER) % 3;
 | 
			
		||||
    int rel = gmod(li.relative.first - li.relative.second, 3);
 | 
			
		||||
    int par = gmod(gp::param.first - gp::param.second, 3);
 | 
			
		||||
    if(rel == 0)
 | 
			
		||||
      return pattern_threecolor(c->master->c7);
 | 
			
		||||
    else if(rel == par)
 | 
			
		||||
@@ -1335,7 +1335,7 @@ EX int pattern_threecolor(cell *c) {
 | 
			
		||||
    #if CAP_GP
 | 
			
		||||
    if(gp_threecolor() == 2) {
 | 
			
		||||
      auto li = gp::get_local_info(c);
 | 
			
		||||
      int sp = (MODFIXER + li.relative.first + 2 * li.relative.second) % 3;
 | 
			
		||||
      int sp = gmod(li.relative.first + 2 * li.relative.second, 3);
 | 
			
		||||
      if(sp != 0) {
 | 
			
		||||
        if(li.last_dir & 1) 
 | 
			
		||||
          sp = 3 - sp;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								quotient.cpp
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								quotient.cpp
									
									
									
									
									
								
							@@ -12,25 +12,16 @@ namespace hr {
 | 
			
		||||
 | 
			
		||||
EX namespace quotientspace {
 | 
			
		||||
  
 | 
			
		||||
  bool operator == (const code& c1, const code &c2) {
 | 
			
		||||
    for(int i=0; i<=S7; i++) if(c1.c[i] != c2.c[i]) return false;
 | 
			
		||||
    return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  bool operator < (const code& c1, const code &c2) {
 | 
			
		||||
    for(int i=0; i<=S7; i++) if(c1.c[i] != c2.c[i]) return c1.c[i] < c2.c[i];
 | 
			
		||||
    return false;
 | 
			
		||||
    }  
 | 
			
		||||
 | 
			
		||||
  int cod(heptagon *h) {
 | 
			
		||||
    return zebra40(h->c7);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  code get(heptspin hs) {
 | 
			
		||||
    code res;
 | 
			
		||||
    res.c[0] = cod(hs.at);
 | 
			
		||||
    res.connections.resize(S7);
 | 
			
		||||
    res.connections[0] = cod(hs.at);
 | 
			
		||||
    for(int i=1; i<=S7; i++) {
 | 
			
		||||
      res.c[i] = cod((hs + wstep).at);
 | 
			
		||||
      res.connections[i] = cod((hs + wstep).at);
 | 
			
		||||
      hs += 1;
 | 
			
		||||
      }
 | 
			
		||||
    return res;
 | 
			
		||||
@@ -45,7 +36,11 @@ EX namespace quotientspace {
 | 
			
		||||
 | 
			
		||||
#if HDR
 | 
			
		||||
struct code {
 | 
			
		||||
  int c[MAX_EDGE+1];
 | 
			
		||||
  vector<int> connections;
 | 
			
		||||
 | 
			
		||||
  bool operator == (const code &c2) const { return connections == c2.connections; }
 | 
			
		||||
  bool operator < (const code &c2) const { return connections < c2.connections; }
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
struct hrmap_quotient : hrmap_standard {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								rug.cpp
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								rug.cpp
									
									
									
									
									
								
							@@ -609,7 +609,7 @@ EX void buildRug() {
 | 
			
		||||
    rugpoint *v = p.second;
 | 
			
		||||
    
 | 
			
		||||
    if(arcm::in() || (euclid && quotient)) {
 | 
			
		||||
      rugpoint *p[MAX_EDGE+1];
 | 
			
		||||
      vector<rugpoint*> p(c->type+1);
 | 
			
		||||
      for(int j=0; j<c->type; j++) p[j] = findOrAddRugpoint(ggmatrix(c) * get_corner_position(c, j), v->dist);
 | 
			
		||||
      for(int j=0; j<c->type; j++) addTriangle(v, p[j], p[(j+1) % c->type]);
 | 
			
		||||
      
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user