mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-11-04 07:43:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1055 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1055 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// newconformist explorable explanation
 | 
						|
// example commandline: -noplayer -rugtsize 4096 -smart 1 -canvas B -ncee
 | 
						|
// set CAP_NCONF (and change the path) if you have access to newconformist
 | 
						|
 | 
						|
#include "rogueviz.h"
 | 
						|
 | 
						|
#if CAP_NCONF
 | 
						|
 | 
						|
#ifndef CAP_DRAW
 | 
						|
#define CAP_DRAW 0
 | 
						|
#endif
 | 
						|
 | 
						|
#define main nconf_main
 | 
						|
#undef self
 | 
						|
#include "nconf.cpp"
 | 
						|
#undef main
 | 
						|
#endif
 | 
						|
 | 
						|
namespace hr {
 | 
						|
 | 
						|
namespace nconf2 {
 | 
						|
 | 
						|
string rfname;
 | 
						|
 | 
						|
enum class ptype : char { outside, inside, inside_left_up, inside_left_down, top, bottom, left_inf, right_inf, marked };
 | 
						|
 | 
						|
dqi_line& queueline1(const hyperpoint& H1, const hyperpoint& H2, color_t col, int prf = 0, PPR prio = PPR::LINE) {
 | 
						|
  return queueline(shiftless(H1), shiftless(H2), col, prf, prio);
 | 
						|
  }
 | 
						|
 | 
						|
void add_border(vector<string>& v, int cy) {
 | 
						|
  int Y = isize(v), X = isize(v[0]);
 | 
						|
  char nx = '6';
 | 
						|
  for(int y=0; y<Y; y++)
 | 
						|
  for(int x=0; x<X; x++)
 | 
						|
    if(v[y][x] != '1')
 | 
						|
    if((y && v[y-1][x] == '1') || (y<Y-1 && v[y+1][x] == '1') || (x && v[y][x-1] == '1') || (x<X-1 && v[y][x+1] == '1'))
 | 
						|
      v[y][x] = y < cy ? '4' : y > cy ? '5' : (nx++);  
 | 
						|
  }
 | 
						|
 | 
						|
vector<string> gensquare(int X, int Y) {
 | 
						|
  vector<string> res(Y+4, string (X+4, '0'));
 | 
						|
  for(int y=0; y<Y; y++)
 | 
						|
  for(int x=0; x<X; x++)
 | 
						|
    res[y+2][x+2] = '1';
 | 
						|
  add_border(res, 2+Y/2);
 | 
						|
  return res;
 | 
						|
  }
 | 
						|
 | 
						|
vector<string> genellipse(int D, ld alpha) {
 | 
						|
  vector<string> res(D+4, string (D+4, '0'));
 | 
						|
  ld R = (D-1.) / 2;
 | 
						|
  for(int y=0; y<D; y++)
 | 
						|
  for(int x=0; x<D; x++) {
 | 
						|
    ld ax = (x-R);
 | 
						|
    ld ay = (y-R);
 | 
						|
    ld bx = ax * cos(alpha) - ay * sin(alpha);
 | 
						|
    ld by = ay * cos(alpha) + ax * sin(alpha);
 | 
						|
    bx /= R;
 | 
						|
    by /= R;
 | 
						|
    res[y+2][x+2] = bx*bx+by*by*2 < 1 ? '1' : '0';
 | 
						|
    }
 | 
						|
  add_border(res, 2+R);
 | 
						|
  return res;
 | 
						|
  }
 | 
						|
 | 
						|
vector<string> gent(int X, int Y) {
 | 
						|
  vector<string> res(Y+X+4, string (Y+X+X+4, '0'));
 | 
						|
  for(int y=0; y<Y; y++)
 | 
						|
  for(int x=0; x<X+X+Y; x++)
 | 
						|
    res[y+2][x+2] = '1';
 | 
						|
  for(int y=0; y<Y; y++)
 | 
						|
  for(int x=0; x<X; x++)
 | 
						|
    res[x+2+Y][y+2+X] = '1';
 | 
						|
  add_border(res, 2+Y/2);
 | 
						|
  return res;
 | 
						|
  }
 | 
						|
 | 
						|
vector<string> fmap = gensquare(13, 13);
 | 
						|
 | 
						|
vector<string> snake = {
 | 
						|
  "00000000000000000000000000000000000",
 | 
						|
  "00444444444444444444444444444444400",
 | 
						|
  "04111111111111111111111111111111140",
 | 
						|
  "04111111111111111111111111111111140",
 | 
						|
  "06111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "00555555555555555555555555511111140",
 | 
						|
  "00000000000000000000000000051111140",
 | 
						|
  "00555555555555555555555555511111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111444444444444444444444444400",
 | 
						|
  "05111114000000000000000000000000000",
 | 
						|
  "05111111444444444444444444444444400",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111140",
 | 
						|
  "05111111111111111111111111111111170",
 | 
						|
  "05111111111111111111111111111111150",
 | 
						|
  "05111111111111111111111111111111150",
 | 
						|
  "00555555555555555555555555555555500",
 | 
						|
  "00000000000000000000000000000000000"
 | 
						|
  };
 | 
						|
 | 
						|
vector<string> apple = {
 | 
						|
  "0000000000000000000000000000000",
 | 
						|
  "0000000000000000440000000000000",
 | 
						|
  "0000000000000004114000000000000",
 | 
						|
  "0000000000000004140000000000000",
 | 
						|
  "0000000000000041140000000000000",
 | 
						|
  "0000000000000041140000000000000",
 | 
						|
  "0000004444444441144444440000000",
 | 
						|
  "0000041111111111111111114400000",
 | 
						|
  "0000411111111111111111111140000",
 | 
						|
  "0004111111111111111111111114000",
 | 
						|
  "0041111111111111111111111111400",
 | 
						|
  "0041111111111111111111111111140",
 | 
						|
  "0041111111111111111111111111140",
 | 
						|
  "0411111111111111111111111111140",
 | 
						|
  "0411111111111111111111111111140",
 | 
						|
  "0411111111111111111111111111140",
 | 
						|
  "0411111111111111111111111111140",
 | 
						|
  "0411111111111111111111111111140",
 | 
						|
  "0711111111111111111111111111160",
 | 
						|
  "0511111111111111111111111111150",
 | 
						|
  "0511111111111111111111111111150",
 | 
						|
  "0051111111111111111111111111150",
 | 
						|
  "0051111111111111111111111111500",
 | 
						|
  "0051111111111111111111111111500",
 | 
						|
  "0005111111111111111111111111500",
 | 
						|
  "0005111111111111111111111115000",
 | 
						|
  "0005111111111111111111111115000",
 | 
						|
  "0000511111111111111111111150000",
 | 
						|
  "0000051111111111111111111500000",
 | 
						|
  "0000051111111111111111115000000",
 | 
						|
  "0000005111111111111111150000000",
 | 
						|
  "0000000551111511111115500000000",
 | 
						|
  "0000000005555055555550000000000",
 | 
						|
  "0000000000000000000000000000000"
 | 
						|
  };
 | 
						|
 | 
						|
struct coord { 
 | 
						|
  int x, y; 
 | 
						|
  coord operator + (int d) {
 | 
						|
    coord res = *this;
 | 
						|
    d &= 3;
 | 
						|
    if(d == 0) res.x++;
 | 
						|
    if(d == 1) res.y++;
 | 
						|
    if(d == 2) res.x--;
 | 
						|
    if(d == 3) res.y--;
 | 
						|
    return res;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
char out = '-';
 | 
						|
 | 
						|
char& fmap_at(coord c) { return c.x >= 0 && c.x < isize(fmap[0]) && c.y >= 0 && c.y < isize(fmap) ? fmap[c.y][c.x] : out; }
 | 
						|
 | 
						|
ld vx[256][256], vy[256][256];
 | 
						|
 | 
						|
void reset_vxy() { for(int y=0; y<256; y++) for(int x=0; x<256; x++) vy[y][x] = vx[y][x] = 0; }
 | 
						|
 | 
						|
ld cscale;
 | 
						|
 | 
						|
bool pretty = true;
 | 
						|
 | 
						|
void iterate() {
 | 
						|
  int Y = isize(fmap);
 | 
						|
  int X = isize(fmap[0]);
 | 
						|
  for(int y=0; y<Y; y++) 
 | 
						|
  for(int x=0; x<X; x++) {
 | 
						|
    if(fmap[y][x] == '6')
 | 
						|
      vy[y][x] = 0, vx[y][x] = -1;
 | 
						|
    else if(fmap[y][x] == '7')
 | 
						|
      vy[y][x] = 0, vx[y][x] = +1;
 | 
						|
    else if(fmap[y][x] == '4')
 | 
						|
      vy[y][x] = -1;
 | 
						|
    else if(fmap[y][x] == '5')
 | 
						|
      vy[y][x] = +1;
 | 
						|
    else if(fmap[y][x] == '1')
 | 
						|
      vy[y][x] = (vy[y-1][x] + vy[y+1][x] + vy[y][x-1] + vy[y][x+1]) / 4;
 | 
						|
    if(among(fmap[y][x], '1', '4', '5')) {
 | 
						|
      int qty = 0;
 | 
						|
      ld total = 0;
 | 
						|
      auto in = [&] (char c) { return pretty ? c > '0' : among(c, '1', '6', '7'); };
 | 
						|
      if(y > 0 && in(fmap[y-1][x])) qty++, total += vx[y-1][x];
 | 
						|
      if(y < Y-1 && in(fmap[y+1][x])) qty++, total += vx[y+1][x];
 | 
						|
      if(x > 0 && in(fmap[y][x-1])) qty++, total += vx[y][x-1];
 | 
						|
      if(x < X-1 && in(fmap[y][x+1])) qty++, total += vx[y][x+1];
 | 
						|
      vx[y][x] = total / qty;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  vector<ld> xes;
 | 
						|
 | 
						|
  for(int y=0; y<Y-1; y++) for(int x=0; x<X-1; x++) 
 | 
						|
    if(fmap[y][x] == '1' && fmap[y+1][x] == '1' && fmap[y][x+1] == '1') {
 | 
						|
    
 | 
						|
    hyperpoint here = point2(vx[y][x], vy[y][x]);
 | 
						|
    hyperpoint v0   = point2(vx[y][x+1], vy[y][x+1]) - here;
 | 
						|
    hyperpoint v1   = point2(vx[y+1][x], vy[y+1][x]) - here;
 | 
						|
    
 | 
						|
    ld det = (v0 ^ v1)[2];
 | 
						|
    if(det == 0) continue;
 | 
						|
 | 
						|
    hyperpoint ba2 = point2(v1[1], -v0[1]) / det;
 | 
						|
    hyperpoint ca2 = point2(-v1[0], v0[0]) / det;
 | 
						|
    
 | 
						|
    ld d = (ba2|ba2);
 | 
						|
    if(d == 0) continue;
 | 
						|
  
 | 
						|
    ld good = (ca2^ba2)[2] / d;
 | 
						|
 | 
						|
    xes.push_back(good);
 | 
						|
    }
 | 
						|
  
 | 
						|
  sort(xes.begin(), xes.end());
 | 
						|
  if(isize(xes))
 | 
						|
    cscale = -xes[isize(xes) / 2];
 | 
						|
  
 | 
						|
  // println(hlog, "cscale = ", cscale);
 | 
						|
  }
 | 
						|
 | 
						|
#if CAP_NCONF
 | 
						|
void nconf_solve() {
 | 
						|
  nconf::SY = isize(fmap);
 | 
						|
  nconf::SX = isize(fmap[0]);
 | 
						|
  nconf::resize_pt();
 | 
						|
  for(int y=0; y<nconf::SY; y++) 
 | 
						|
  for(int x=0; x<nconf::SX; x++) {
 | 
						|
    auto& p = nconf::pts[y][x];
 | 
						|
    p.type = (nconf::ptype)(fmap[y][x] - '0');
 | 
						|
    p.side = 0;
 | 
						|
    }
 | 
						|
  nconf::pretty_borders = pretty;
 | 
						|
  nconf::draw_progress = false;
 | 
						|
  nconf::text_progress = false;
 | 
						|
  nconf::computemap(nconf::pts);
 | 
						|
  for(int y=0; y<nconf::SY; y++) 
 | 
						|
  for(int x=0; x<nconf::SX; x++) { 
 | 
						|
    if(fmap[y][x] == '1')
 | 
						|
    vx[y][x] = nconf::pts[y][x].x[0] * 2 - 1,
 | 
						|
    vy[y][x] = nconf::pts[y][x].x[1] * 2 - 1;
 | 
						|
    if(pretty && (fmap[y][x] == '4' || fmap[y][x] == '5'))
 | 
						|
      vx[y][x] = nconf::pts[y][x].x[0] * 2 - 1;
 | 
						|
    }
 | 
						|
 | 
						|
  printf("nconf solved\n");
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
basic_textureinfo nctinf, nctinf2;
 | 
						|
vector<glvertex> vs;
 | 
						|
 | 
						|
bool viewmap = true;
 | 
						|
 | 
						|
void fix_border() {
 | 
						|
  int Y = isize(fmap);
 | 
						|
  int X = isize(fmap[0]);
 | 
						|
  for(string& s: fmap) for(char& c: s) if(c == '5') c = '4';
 | 
						|
 | 
						|
  coord cc;
 | 
						|
  for(int y=0; y<Y; y++) for(int x=0; x<X; x++) if(fmap[y][x] == '6') cc = coord{x,y};
 | 
						|
  
 | 
						|
  int dir = 0;
 | 
						|
  while(fmap_at(cc+dir) != '1') dir++;
 | 
						|
  
 | 
						|
  cc = cc + dir;
 | 
						|
  dir += 2;
 | 
						|
  
 | 
						|
  while(true) {
 | 
						|
    if(fmap_at(cc+dir) == '1') cc = cc + dir, dir++;
 | 
						|
    else {
 | 
						|
      if(fmap_at(cc+dir) == '4') fmap_at(cc+dir) = '5';
 | 
						|
      if(fmap_at(cc+dir) == '7') break;
 | 
						|
      dir--;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
void doublemap() {
 | 
						|
  for(string& s: fmap) {
 | 
						|
    string res = "";
 | 
						|
    for(char c: s) res += c, res += c;
 | 
						|
    s = res;
 | 
						|
    }
 | 
						|
  fmap.resize(isize(fmap) * 2);
 | 
						|
  for(int y=isize(fmap)-1; y>=0; y--) fmap[y] = fmap[y/2];
 | 
						|
 | 
						|
  int Y = isize(fmap);
 | 
						|
  int X = isize(fmap[0]);
 | 
						|
  
 | 
						|
  for(int y=Y-1; y>=0; y--) for(int x=X-1; x>=0; x--)
 | 
						|
    vx[y][x] = vx[y/2][x/2], vy[y][x] = vy[y/2][x/2];
 | 
						|
 | 
						|
  for(int y=0; y<Y; y++) for(int x=0; x<X; x++) {
 | 
						|
    coord cc{x,y};
 | 
						|
    auto& us = fmap[y][x];
 | 
						|
    if(us >= '4') {
 | 
						|
      bool live = false;
 | 
						|
      for(int k=0; k<4; k++) if(fmap_at(cc+k) == '1') live = true;
 | 
						|
      if(!live) us = '0';
 | 
						|
      }
 | 
						|
    }
 | 
						|
  
 | 
						|
  bool found6 = false, found7 = false;
 | 
						|
  for(int y=0; y<Y; y++) for(int x=0; x<X; x++) {
 | 
						|
    if(fmap[y][x] == '6') {
 | 
						|
      if(found6) fmap[y][x] = '4'; else found6 = true;
 | 
						|
      }
 | 
						|
    if(fmap[y][x] == '7') {
 | 
						|
      if(found7) fmap[y][x] = '5'; else found7 = true;
 | 
						|
      }
 | 
						|
    fix_border();
 | 
						|
    }  
 | 
						|
  }
 | 
						|
 | 
						|
int pointmode;
 | 
						|
 | 
						|
bool show_mapping = true;
 | 
						|
bool show_mgrid = true;
 | 
						|
 | 
						|
ld mapping_split = .75;
 | 
						|
 | 
						|
char paintmode;
 | 
						|
 | 
						|
void changepoint(int x, int y, bool can_add) {
 | 
						|
  int Y = isize(fmap);
 | 
						|
  int X = isize(fmap[0]);
 | 
						|
  if(x < 0 || y < 0 || x >= X || y >= Y) return;
 | 
						|
  if(pointmode) {
 | 
						|
    if(fmap[y][x] < '4') return;
 | 
						|
    for(string& s: fmap) for(char& c: s) if(c == pointmode) c = '4';
 | 
						|
    fmap[y][x] = pointmode;
 | 
						|
    fix_border();
 | 
						|
    return;
 | 
						|
    }
 | 
						|
  if(y == 0) {
 | 
						|
    paintmode = 0;
 | 
						|
    fmap.emplace_back();
 | 
						|
    for(int i=Y-1; i>=0; i--) fmap[i+1] = fmap[i];
 | 
						|
    for(char& c: fmap[0]) c = '0';
 | 
						|
    }
 | 
						|
  if(y == Y-1) {
 | 
						|
    paintmode = 0;
 | 
						|
    fmap.push_back(fmap[0]);
 | 
						|
    for(char& c: fmap.back()) c = '0';
 | 
						|
    }
 | 
						|
  if(x == 0) {
 | 
						|
    paintmode = 0;
 | 
						|
    for(string& s: fmap) s = '0' + s;
 | 
						|
    }
 | 
						|
  if(x == X-1) {
 | 
						|
    paintmode = 0;
 | 
						|
    for(string& s: fmap) s = s + '0';
 | 
						|
    }
 | 
						|
  coord cc{x,y};
 | 
						|
  auto& us = fmap[y][x];
 | 
						|
  if(fmap[y][x] >= '4') {
 | 
						|
    if(fmap[y][x] > '5') {
 | 
						|
      int q = 0;        
 | 
						|
      for(int k=0; k<4; k++) if(fmap_at(cc+k) == '0') q++;
 | 
						|
      if(q != 1) return;
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      for(int k=0; k<4; k++) if(fmap_at(cc+k) == (us^ '1')) return;
 | 
						|
      int q = 0;
 | 
						|
      for(int k=0; k<4; k++) if(fmap_at(cc+k) >= '4') q++;
 | 
						|
      if(q > 2) return;
 | 
						|
      }
 | 
						|
    for(int k=0; k<4; k++) 
 | 
						|
      if(fmap_at(cc+k) != '1') 
 | 
						|
      if(fmap_at(cc+k+(k+1)) == '1') 
 | 
						|
      if(fmap_at(cc+(k+1)) != '1') 
 | 
						|
        return;
 | 
						|
 | 
						|
    for(int k=0; k<4; k++) 
 | 
						|
      if(fmap_at(cc+k) != '1') 
 | 
						|
      if(fmap_at(cc+k+k) == '1') 
 | 
						|
      if(fmap_at(cc+k+(k+1)) != '1') 
 | 
						|
      if(fmap_at(cc+k+(k-1)) != '1') 
 | 
						|
        return;
 | 
						|
    
 | 
						|
    if(fmap[y-1][x] == '0') fmap[y-1][x] = us;
 | 
						|
    if(fmap[y][x-1] == '0') fmap[y][x-1] = us;
 | 
						|
    if(fmap[y+1][x] == '0') fmap[y+1][x] = us;
 | 
						|
    if(fmap[y][x+1] == '0') fmap[y][x+1] = us;
 | 
						|
    us = '1';
 | 
						|
    }
 | 
						|
  else if(us == '1') {
 | 
						|
    int q = 0;
 | 
						|
    for(int k=0; k<4; k++) if(fmap_at(cc+k) == '1') q++;
 | 
						|
    if(q == 0) return;
 | 
						|
    if(q == 4) return;
 | 
						|
    if(q == 3) {
 | 
						|
      for(int k=0; k<4; k++) if(fmap_at(cc+k) != '1') {
 | 
						|
        int nei = 0;
 | 
						|
        if(fmap_at(cc+k+(k+1)) == '1') nei++;
 | 
						|
        if(fmap_at(cc+k+(k+3)) == '1') nei++;
 | 
						|
        if(nei == 2) return;
 | 
						|
        us = fmap_at(cc+k);
 | 
						|
        if(nei == 0) fmap_at(cc+k) = '0';
 | 
						|
        }
 | 
						|
      return;
 | 
						|
      }
 | 
						|
    if(q == 2 && fmap_at(cc+0) == '1' && fmap_at(cc+2) == '1') return;
 | 
						|
    if(q == 2 && fmap_at(cc+1) == '1' && fmap_at(cc+3) == '1') return;
 | 
						|
    for(int k=0; k<4; k++) if(fmap_at(cc+k) == '1' && fmap_at(cc+(k+1)) == '1' && fmap_at(cc+k+(k+1)) != '1') return;
 | 
						|
    bool have4 = false, kill6 = false, kill7 = false, live[4];
 | 
						|
    for(int k=0; k<4; k++) {
 | 
						|
      char ch = fmap_at(cc+k);
 | 
						|
 | 
						|
      live[k] = false;
 | 
						|
      for(int k=0; k<4; k++) {
 | 
						|
        for(int l=0; l<4; l++) if(k!=(l^2) && fmap_at(cc+k+l) == '1') live[k] = true;
 | 
						|
        }
 | 
						|
 | 
						|
      switch(ch) {
 | 
						|
        case '4': have4 = true; break;
 | 
						|
        case '5': break;
 | 
						|
        case '6': if(!live[k]) kill6 = true; break;
 | 
						|
        case '7': if(!live[k]) kill7 = true; break;
 | 
						|
        };
 | 
						|
      }
 | 
						|
    
 | 
						|
    if(kill6 && kill7) return;
 | 
						|
    
 | 
						|
    if(kill6) us = '6';
 | 
						|
    else if(kill7) us = '7';
 | 
						|
    else if(have4) us = '4';
 | 
						|
    else us = '5';
 | 
						|
    
 | 
						|
    for(int k=0; k<4; k++) if(!live[k]) fmap_at(cc+k) = '0';
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
bool showmenu = true;
 | 
						|
 | 
						|
void conf_shapes() {
 | 
						|
  cmode = 0;
 | 
						|
  dialog::init(XLAT("shapes"));
 | 
						|
  dialog::addItem("square 11x11", 'a');
 | 
						|
  dialog::add_action([] { fmap = gensquare(13, 13); reset_vxy(); popScreen(); });
 | 
						|
  dialog::addItem("rectangle 15x8", 'b');
 | 
						|
  dialog::add_action([] { fmap = gensquare(15, 8); reset_vxy(); popScreen(); });
 | 
						|
  dialog::addItem("T-shape", 'c');
 | 
						|
  dialog::add_action([] { fmap = gent(19, 7); reset_vxy(); popScreen(); });
 | 
						|
  dialog::addItem("snake", 'd');
 | 
						|
  dialog::add_action([] { fmap = snake; reset_vxy(); popScreen(); });
 | 
						|
  dialog::addItem("ellipse 50", 'e');
 | 
						|
  dialog::add_action([] { fmap = genellipse(50, hrand(180)); reset_vxy(); popScreen(); });
 | 
						|
  dialog::addItem("apple", 'f');
 | 
						|
  dialog::add_action([] { fmap = apple; reset_vxy(); popScreen(); });
 | 
						|
  dialog::addBreak(100);
 | 
						|
  dialog::addBack();
 | 
						|
  dialog::display();
 | 
						|
  }
 | 
						|
 | 
						|
int algo_speed = 10000;
 | 
						|
 | 
						|
int algo_ticks = 0;
 | 
						|
 | 
						|
bool in_visualization;
 | 
						|
int nconf_pos;
 | 
						|
ld steps_to_do;
 | 
						|
 | 
						|
#define DELTA [] { static int oldticks = ticks; int res = ticks - oldticks; oldticks = ticks; return res; }
 | 
						|
 | 
						|
auto nconf_delta = DELTA;
 | 
						|
 | 
						|
#if CAP_NCONF
 | 
						|
void nconf_prepare(bool fast) {
 | 
						|
  // pretend we are solving
 | 
						|
  nconf_solve();
 | 
						|
  build_equations(nconf::pts, 1, fast);
 | 
						|
  nconf_pos = 0;
 | 
						|
  in_visualization = true;
 | 
						|
  steps_to_do = 0;
 | 
						|
  algo_ticks = 0;
 | 
						|
  nconf_delta();
 | 
						|
  printf("points: %d\n", isize(nconf::allpoints));
 | 
						|
  }
 | 
						|
 | 
						|
void nconf_run() {
 | 
						|
  int d = nconf_delta();
 | 
						|
  algo_ticks += d;
 | 
						|
  steps_to_do += d * algo_speed / 1000.;
 | 
						|
  while(steps_to_do > 0) {
 | 
						|
    if(nconf_pos == isize(nconf::allpoints)) { in_visualization = false; break; }
 | 
						|
    auto co = nconf::allpoints[nconf_pos++];
 | 
						|
    auto &p = nconf::pts[co];
 | 
						|
    nconf::eliminate(nconf::pts, co);
 | 
						|
    printf("point #%d has %d equations\n", nconf_pos-1, hr::isize(p.eqs));
 | 
						|
    steps_to_do -= pow(hr::isize(p.eqs), 2);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
void pick_algorithm() {
 | 
						|
  cmode = 0;
 | 
						|
  dialog::init(XLAT("solving"));
 | 
						|
  dialog::addItem("iterative/reset", 'r');
 | 
						|
  dialog::add_action([] { reset_vxy(); algo_ticks = 0; popScreen(); });
 | 
						|
  dialog::addItem("solve linear equations", 's');
 | 
						|
  dialog::add_action([] { nconf_solve(); algo_ticks = 0; popScreen(); });
 | 
						|
  dialog::addItem("visualize (slow)", 'a');
 | 
						|
  dialog::add_action([] { nconf_prepare(false); popScreen(); });
 | 
						|
  dialog::addItem("visualize (fast)", 'b');
 | 
						|
  dialog::add_action([] { nconf_prepare(true); popScreen(); });
 | 
						|
  dialog::addSelItem("visualization speed", its(algo_speed), 'v');
 | 
						|
  dialog::add_action([] { dialog::editNumber(algo_speed, 100, 1000000, 0.1, 10000, "", ""), dialog::scaleLog(), dialog::dialogflags = sm::NOSCR; });
 | 
						|
  dialog::addBreak(50);
 | 
						|
  dialog::addBoolItem_action("pretty corners", pretty, 'p');
 | 
						|
  dialog::addBreak(50);
 | 
						|
  dialog::addBack();
 | 
						|
  dialog::display();
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
void ncee_work();
 | 
						|
 | 
						|
bool animated_pattern = false;
 | 
						|
 | 
						|
int redraws;
 | 
						|
 | 
						|
void redraw_texture() {
 | 
						|
  View = Id;
 | 
						|
  if(arcm::in()) View = View * spin(45._deg);
 | 
						|
  dynamicval<int> cgl(vid.cells_generated_limit, 9999999);
 | 
						|
  dynamicval<int> cdl(vid.cells_drawn_limit, 9999999);
 | 
						|
  dynamicval<bool> r(mousing, false);
 | 
						|
  rug::rugged = true;
 | 
						|
  rug::prepareTexture();
 | 
						|
  rug::rugged = false;
 | 
						|
  }
 | 
						|
 | 
						|
template<class T> void chg_pattern(const T& f) {
 | 
						|
  tactic::on = true;
 | 
						|
  autocheat = true;
 | 
						|
  reptilecheat = true;
 | 
						|
  stop_game();
 | 
						|
  set_geometry(gNormal);
 | 
						|
  set_variation(eVariation::bitruncated);
 | 
						|
  f();
 | 
						|
  start_game();
 | 
						|
  clearMessages();
 | 
						|
  redraws = 1;
 | 
						|
  }
 | 
						|
 | 
						|
void pick_pattern() {
 | 
						|
  cmode = sm::SIDE | sm::MAYDARK | sm::DIALOG_STRICT_X;
 | 
						|
  ncee_work();
 | 
						|
  dialog::init(XLAT("patterns"));
 | 
						|
 | 
						|
  dialog::addItem("green football", 'g');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      enable_canvas();
 | 
						|
      ccolor::which = &ccolor::sides;
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
  dialog::addItem("Goldberg football", 'G');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      gp::param.first = 9;
 | 
						|
      gp::param.second = 0;
 | 
						|
      set_variation(eVariation::goldberg);
 | 
						|
      enable_canvas();
 | 
						|
      ccolor::which = &ccolor::football;
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
  dialog::addItem("octagons", 'o');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      set_geometry(gOctagon);
 | 
						|
      enable_canvas();
 | 
						|
      ccolor::which = &ccolor::zebra_stripes;
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
  dialog::addItem("windy plains", 'w');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      firstland = specialland = laWhirlwind;
 | 
						|
      });
 | 
						|
    vid.smart_range_detail = 2.5;
 | 
						|
    });
 | 
						|
  
 | 
						|
  dialog::addItem("reptiles", 'r');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      firstland = specialland = laReptile;
 | 
						|
      });
 | 
						|
    });
 | 
						|
  
 | 
						|
  dialog::addItem("zebra", 'z');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      firstland = specialland = laZebra;
 | 
						|
      });
 | 
						|
    });
 | 
						|
  
 | 
						|
  dialog::addItem("colored squares", 's');
 | 
						|
  dialog::add_action([] { 
 | 
						|
    chg_pattern([] {
 | 
						|
      set_variation(eVariation::pure);
 | 
						|
      arcm::current.parse("4^5");
 | 
						|
      set_geometry(gArchimedean);
 | 
						|
      enable_canvas();
 | 
						|
      ccolor::which = &ccolor::shape;
 | 
						|
      });
 | 
						|
    });
 | 
						|
    
 | 
						|
  if(specialland == laWhirlwind) {
 | 
						|
    dialog::addBoolItem_action("animated", animated_pattern, 'a');
 | 
						|
    }
 | 
						|
  else dialog::addBreak(100);
 | 
						|
 | 
						|
  dialog::addBreak(50);
 | 
						|
  dialog::addBack();
 | 
						|
  dialog::display();
 | 
						|
  }
 | 
						|
 | 
						|
namespace ncee_scr {
 | 
						|
  int X, Y, xc, yc, x0, y0, siz;
 | 
						|
  }
 | 
						|
 | 
						|
void draw_ncee() {
 | 
						|
  using namespace ncee_scr;
 | 
						|
  auto cd = current_display;
 | 
						|
  
 | 
						|
  Y = isize(fmap);
 | 
						|
  X = isize(fmap[0]);
 | 
						|
  siz = min((cd->ysize / (show_mapping ? 2 : 1) - 5) / Y, showmenu ? (cd->xcenter -5 )*2/X : (cd->xsize - 5) / X);
 | 
						|
  
 | 
						|
  xc = 0;
 | 
						|
  yc = vid.yres * (show_mapping ? mapping_split : 1) / 2 - cd->ycenter;
 | 
						|
  
 | 
						|
  x0 = - int(siz * X / 2);
 | 
						|
  y0 = - int(siz * Y / 2);
 | 
						|
  
 | 
						|
  ld period;
 | 
						|
  
 | 
						|
  if(geometry == gNormal) {
 | 
						|
 | 
						|
    auto cw = heptspin(cwt.at->master, 0);
 | 
						|
    cw = cw + wstep + 3 + wstep + 5 + wstep;
 | 
						|
    period = hdist0(tC0(currentmap->relative_matrix(cwt.at, cw.at->c7, C0)));
 | 
						|
  
 | 
						|
    if(specialland == laWhirlwind)
 | 
						|
      period *= 9;
 | 
						|
    if(specialland == laZebra)
 | 
						|
      period *= 6;
 | 
						|
    if(specialland == laReptile)
 | 
						|
      period *= 3;
 | 
						|
    }
 | 
						|
 | 
						|
  else if(geometry == gOctagon) {
 | 
						|
    period = 2 * hdist0(tC0(currentmap->adj(cwt.at->master, 0)));
 | 
						|
    }
 | 
						|
 | 
						|
  else {
 | 
						|
    period = 2 * hdist0(tC0(currentmap->adj(cwt.at, 0)));
 | 
						|
    }
 | 
						|
 | 
						|
  period /= 90._deg;
 | 
						|
  
 | 
						|
  dynamicval<eModel> pm(pmodel, mdPixel);
 | 
						|
  dynamicval<eGeometry> pg(geometry, gEuclid);
 | 
						|
  
 | 
						|
  initquickqueue();
 | 
						|
  nctinf2.texture_id = rug::glbuf->renderedTexture;
 | 
						|
  nctinf2.tvertices.clear();
 | 
						|
  
 | 
						|
  ld map_ypos = vid.yres * (mapping_split + 1) / 2 - cd->ycenter;
 | 
						|
  ld sca2 = (vid.yres * (1-mapping_split) / 2 - 10)  / pconf.scale;
 | 
						|
 | 
						|
  if(show_mapping) {
 | 
						|
    for(int iter=-10; iter<=10; iter++) {
 | 
						|
      ld maxx = period * pconf.scale / 4;
 | 
						|
      ld scax = sca2 * maxx / 0.5;
 | 
						|
      ld xpos = scax * 2 * iter;
 | 
						|
      curvepoint(hpxy(xpos-scax, map_ypos-sca2));
 | 
						|
      nctinf2.tvertices.push_back(glhr::makevertex(0.5-maxx, 0, 0));
 | 
						|
      curvepoint(hpxy(xpos-scax, map_ypos+sca2));
 | 
						|
      nctinf2.tvertices.push_back(glhr::makevertex(0.5-maxx, 1, 0));
 | 
						|
      curvepoint(hpxy(xpos+scax, map_ypos-sca2));
 | 
						|
      nctinf2.tvertices.push_back(glhr::makevertex(0.5+maxx, 0, 0));
 | 
						|
      curvepoint(hpxy(xpos-scax, map_ypos+sca2));
 | 
						|
      nctinf2.tvertices.push_back(glhr::makevertex(0.5-maxx, 1, 0));
 | 
						|
      curvepoint(hpxy(xpos+scax, map_ypos-sca2));
 | 
						|
      nctinf2.tvertices.push_back(glhr::makevertex(0.5+maxx, 0, 0));
 | 
						|
      curvepoint(hpxy(xpos+scax, map_ypos+sca2));
 | 
						|
      nctinf2.tvertices.push_back(glhr::makevertex(0.5+maxx, 1, 0));
 | 
						|
      }
 | 
						|
    auto& q = queuecurve(shiftless(Id), 0, show_mgrid ? 0x404040FF : 0xFFFFFFFF, PPR::LINE);
 | 
						|
    q.tinf = &nctinf2;
 | 
						|
    q.flags |= POLY_TRIANGLES;
 | 
						|
    q.offset_texture = 0;
 | 
						|
    }
 | 
						|
    
 | 
						|
  auto h = [&] (int x, int y) { return hpxy(x0 + x * siz + xc, y0 + y * siz + yc); };
 | 
						|
  auto hc = [&] (int x, int y) { return hpxy(x0 + x * siz + siz/2 + xc, y0 + y * siz + siz/2 + yc); };
 | 
						|
  
 | 
						|
  color_t typecols[8] = {
 | 
						|
    0x101010FF, 0xD0D0D0FF, 0, 0, 0xF04040FF, 0x4040F0FF, 0xF0F040FF, 0x40F0F0FF
 | 
						|
    };
 | 
						|
 | 
						|
  for(int x=0; x<X; x++) for(int y=0; y<Y; y++) {
 | 
						|
    curvepoint(h(x,y));
 | 
						|
    curvepoint(h(x+1,y));
 | 
						|
    curvepoint(h(x+1,y+1));
 | 
						|
    curvepoint(h(x,y+1));
 | 
						|
    #if CAP_NCONF
 | 
						|
    bool ineq = 
 | 
						|
      in_visualization && fmap[y][x] == '1';
 | 
						|
    #endif
 | 
						|
    queuecurve(shiftless(Id), 0, 
 | 
						|
    #if CAP_NCONF
 | 
						|
      (ineq && nconf::pts[y][x].state == 1) ? 0xFF8000FF :
 | 
						|
      (ineq && nconf::pts[y][x].state == 2) ? 0x00FF00FF :
 | 
						|
    #endif
 | 
						|
      (fmap[y][x] == '1' && show_mgrid && show_mapping) ? 0x404040FF : typecols[fmap[y][x] - '0'], PPR::LINE);
 | 
						|
    }
 | 
						|
  
 | 
						|
  if(inHighQual) for(int x=0; x<X; x++) for(int y=0; y<Y; y++) {
 | 
						|
    curvepoint(h(x,y));
 | 
						|
    curvepoint(h(x,y+1));
 | 
						|
    curvepoint(h(x+1,y+1));
 | 
						|
    curvepoint(h(x+1,y));
 | 
						|
    queuecurve(shiftless(Id), 0, 
 | 
						|
      typecols[fmap[y][x] - '0'], PPR::LINE);
 | 
						|
    }
 | 
						|
 | 
						|
  quickqueue();
 | 
						|
  initquickqueue();
 | 
						|
 | 
						|
  nctinf.texture_id = rug::glbuf->renderedTexture;
 | 
						|
  nctinf.tvertices.clear();
 | 
						|
  
 | 
						|
  static int z = 0;
 | 
						|
 | 
						|
  auto tri = [&] (const array<coord,3>& c)  {
 | 
						|
    
 | 
						|
    int id = -1;
 | 
						|
    for(int i=0; i<3; i++) if(fmap_at(c[i])) id = i;
 | 
						|
    if(id == -1) return;
 | 
						|
    ld delta = (int((vx[c[id].y][c[id].x]) / cscale / period + 1000.5) - 1000) * period;
 | 
						|
    z = !z;
 | 
						|
    for(int s=0; s<3; s++) {
 | 
						|
      curvepoint(hc(c[s].x, c[s].y)); 
 | 
						|
      nctinf.tvertices.push_back(glhr::makevertex((vx[c[s].y][c[s].x]/cscale-delta)*pconf.scale/2+.5, vy[c[s].y][c[s].x]*pconf.scale/2+.5, 0));
 | 
						|
      }
 | 
						|
    };
 | 
						|
    
 | 
						|
  if(viewmap && !in_visualization) for(int x=0; x<X-1; x++) for(int y=0; y<Y-1; y++) {
 | 
						|
    if(fmap[y][x+1] > '0' && fmap[y+1][x] > '0') {
 | 
						|
      if(fmap[y][x] > '0') tri(make_array(coord{x,y}, coord{x+1,y}, coord{x,y+1}));
 | 
						|
      if(fmap[y+1][x+1] > '0') tri(make_array(coord{x+1,y+1}, coord{x+1,y}, coord{x,y+1}));
 | 
						|
      }
 | 
						|
    else if(fmap[y][x] > '0' && fmap[y+1][x+1] > '0') {
 | 
						|
      if(fmap[y][x+1] > '0') tri(make_array(coord{x,y}, coord{x+1,y}, coord{x+1,y+1}));
 | 
						|
      if(fmap[y+1][x] > '0') tri(make_array(coord{x,y}, coord{x,y+1}, coord{x+1,y+1}));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  
 | 
						|
  auto& q = queuecurve(shiftless(Id), 0, (show_mgrid && show_mapping) ? 0x404040FF : 0xFFFFFFFF, PPR::LINE);
 | 
						|
  q.tinf = &nctinf;
 | 
						|
  q.flags |= POLY_TRIANGLES;
 | 
						|
  q.offset_texture = 0;
 | 
						|
  
 | 
						|
  hyperpoint vmap[256][256];
 | 
						|
 | 
						|
  pair<int, int> mpt = {(mousex - xc - cd->xcenter - x0) / siz, (mousey - yc - cd->ycenter - y0) / siz};
 | 
						|
 | 
						|
  queueline1(h(0,0), h(0,-1), 0x1010101);
 | 
						|
  
 | 
						|
  const color_t gridcol = 0xFFFFFFFF;
 | 
						|
  if(inHighQual) ;
 | 
						|
  else if(show_mapping && show_mgrid && !in_visualization) {
 | 
						|
    for(int x=0; x<X-1; x++) for(int y=0; y<Y-1; y++) 
 | 
						|
      if(fmap[y][x] > '0')
 | 
						|
        vmap[y][x] = hpxy(vx[y][x]/cscale * sca2 / 2, vy[y][x] * sca2 / 2+ map_ypos);
 | 
						|
    for(int x=0; x<X-1; x++) for(int y=0; y<Y-1; y++) {
 | 
						|
      if(y < Y-2 && fmap[y][x] > '0' && fmap[y+1][x] > '0') {
 | 
						|
        color_t col = (make_pair(x,y) == mpt || make_pair(x,y+1) == mpt) ? 0xFFFF00FF : gridcol;
 | 
						|
        dynamicval<ld> lw(vid.linewidth, vid.linewidth * (col == 0xFFFF00FF ? 4 : 1));
 | 
						|
        queueline1(hc(x, y), hc(x, y+1), col, 0, PPR::CIRCLE);
 | 
						|
        queueline1(vmap[y][x], vmap[y+1][x], col, 0, PPR::CIRCLE);
 | 
						|
        }
 | 
						|
      if(x < X-2 && fmap[y][x] > '0' && fmap[y][x+1] > '0') {
 | 
						|
        color_t col = (make_pair(x,y) == mpt || make_pair(x+1,y) == mpt) ? 0xFFFF00FF : gridcol;
 | 
						|
        dynamicval<ld> lw(vid.linewidth, vid.linewidth * (col == 0xFFFF00FF ? 4 : 1));
 | 
						|
        queueline1(hc(x, y), hc(x+1, y), col, 0, PPR::CIRCLE);
 | 
						|
        queueline1(vmap[y][x], vmap[y][x+1], col, 0, PPR::CIRCLE);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  else {
 | 
						|
    int x = mpt.first;
 | 
						|
    int y = mpt.second;
 | 
						|
    vid.linewidth *= 3;
 | 
						|
    color_t col = 0;
 | 
						|
    if(x >= 0 && y >= 0 && x < X && y < Y) {
 | 
						|
      if(pointmode != 0) 
 | 
						|
        col = 0x00FF00FF;
 | 
						|
      else if(mousepressed)
 | 
						|
        col = paintmode == '1' ? 0xFF0000FF : 0xFFFF00FF;
 | 
						|
      else if(fmap[y][x] == '1')
 | 
						|
        col = 0xFF0000FF;
 | 
						|
      else if(fmap[y][x] == '4' || fmap[y][x] == '5')
 | 
						|
        col = 0xFFFF00FF;
 | 
						|
      }
 | 
						|
    queueline1(h(x,y), h(x,y+1), col);
 | 
						|
    queueline1(h(x,y), h(x+1,y), col);
 | 
						|
    queueline1(h(x+1,y), h(x+1,y+1), col);
 | 
						|
    queueline1(h(x,y+1), h(x+1,y+1), col);
 | 
						|
    vid.linewidth /= 3;
 | 
						|
    }
 | 
						|
  
 | 
						|
  for(int x=0; x<=X; x++) queueline1(h(x,0), h(x,Y), 0x80808080);
 | 
						|
  for(int y=0; y<=Y; y++) queueline1(h(0,y), h(X,y), 0x80808080);
 | 
						|
  
 | 
						|
  queueline1(h(0,0), h(0,-1), 0x1010101);
 | 
						|
 | 
						|
  quickqueue();
 | 
						|
  glflush();
 | 
						|
  }
 | 
						|
 | 
						|
int ncee_map_prepared;
 | 
						|
 | 
						|
void prepare_ncee_map() {
 | 
						|
  ncee_map_prepared = 5;
 | 
						|
  pmodel = mdBand;
 | 
						|
  dynamicval<int> cgl(vid.cells_generated_limit, 9999999);
 | 
						|
  dynamicval<bool> r(rug::display_warning, false);
 | 
						|
  // vid.consider_shader_projection = false;
 | 
						|
  pconf.scale = 0.5;
 | 
						|
  rug::init();
 | 
						|
  rug::prepareTexture();
 | 
						|
  rug::rugged = false;
 | 
						|
  }
 | 
						|
  
 | 
						|
void ncee_work() {
 | 
						|
 | 
						|
  if(specialland != laWhirlwind)
 | 
						|
    animated_pattern = false;
 | 
						|
 | 
						|
  if(redraws > 0) { 
 | 
						|
    redraws--; 
 | 
						|
    vid.consider_shader_projection = false;
 | 
						|
    redraw_texture(); 
 | 
						|
    }
 | 
						|
  if(animated_pattern) {
 | 
						|
    vid.consider_shader_projection = true;
 | 
						|
    redraw_texture();
 | 
						|
    }
 | 
						|
 | 
						|
  calcparam();
 | 
						|
  
 | 
						|
  if(ncee_map_prepared < 5) { cmode = sm::NORMAL | sm::DARKEN; ncee_map_prepared++; if(ncee_map_prepared == 5) prepare_ncee_map(); gamescreen(); return; }
 | 
						|
 | 
						|
  #if CAP_NCONF
 | 
						|
  if(in_visualization) 
 | 
						|
    nconf_run();
 | 
						|
  else 
 | 
						|
  #endif
 | 
						|
    iterate();
 | 
						|
  
 | 
						|
  draw_ncee();
 | 
						|
  }
 | 
						|
 | 
						|
void ncee() {
 | 
						|
  cmode = showmenu ? (sm::SIDE | sm::MAYDARK | sm::DIALOG_STRICT_X) : 0;
 | 
						|
  ncee_work();
 | 
						|
  using namespace ncee_scr;
 | 
						|
  auto cd = current_display;
 | 
						|
 | 
						|
  getcstat = '-';
 | 
						|
  
 | 
						|
  if(paintmode && mousepressed) {
 | 
						|
    int x = (mousex - cd->xcenter - xc - x0) / siz;
 | 
						|
    int y = (mousey - cd->ycenter - yc - y0) / siz;
 | 
						|
    if(fmap[y][x] == paintmode)
 | 
						|
      changepoint(x, y, false);
 | 
						|
    }
 | 
						|
  
 | 
						|
  if(showmenu) {
 | 
						|
    dialog::init(XLAT("newconformist"));
 | 
						|
    dialog::addBoolItem("edit shape", pointmode == 0, 'e');
 | 
						|
    dialog::addBoolItem("set left end", pointmode == '6', 'a');
 | 
						|
    dialog::addBoolItem("set right end", pointmode == '7', 'b');
 | 
						|
    dialog::addBreak(50);
 | 
						|
    dialog::addBoolItem("show the end result", viewmap, 'm');
 | 
						|
    dialog::addBoolItem("display the band model", show_mapping, 's');
 | 
						|
    if(show_mapping)
 | 
						|
      dialog::addBoolItem("display the grid on model", show_mgrid, 'g');
 | 
						|
    else
 | 
						|
      dialog::addBreak(100);
 | 
						|
    dialog::addBreak(50);
 | 
						|
    if(show_mapping)
 | 
						|
      dialog::addSelItem("mapping split", fts(mapping_split), 'y');
 | 
						|
    else
 | 
						|
      dialog::addBreak(100);
 | 
						|
    dialog::addSelItem("double precision", its(isize(fmap[0])) + "x" + its(isize(fmap)), 'd');
 | 
						|
    #if CAP_NCONF
 | 
						|
    dialog::addItem("solving method", 'l');
 | 
						|
    #endif
 | 
						|
    dialog::addItem("shapes", 't');
 | 
						|
    dialog::addItem("patterns", 'p');
 | 
						|
    dialog::addItem("hide the menu", 'v');
 | 
						|
    dialog::addItem("stop", 'x');
 | 
						|
    dialog::display();
 | 
						|
    }
 | 
						|
  else
 | 
						|
    displayButton(vid.xres - 8, 8 + vid.fsize, XLAT("(v) menu"), 'v', 16);
 | 
						|
 | 
						|
  if(algo_ticks)
 | 
						|
    displaystr(8, 8 + vid.fsize, 0, vid.fsize * 2, hr::format("%d.%03d", algo_ticks/1000, algo_ticks%1000), 0xFFFFFF, 0);
 | 
						|
  
 | 
						|
  keyhandler = [=] (int sym, int uni) {
 | 
						|
    // dialog::handleNavigation(sym, uni);
 | 
						|
    if(uni == 'z')
 | 
						|
      prepare_ncee_map();
 | 
						|
    
 | 
						|
    if(uni == 'x') {
 | 
						|
      popScreen();
 | 
						|
      // rug::rugged = true;
 | 
						|
      rug::close();
 | 
						|
      }
 | 
						|
    if(uni == 'e') pointmode = 0;
 | 
						|
    if(uni == 'a') pointmode = '6';
 | 
						|
    if(uni == 'b') pointmode = '7';
 | 
						|
    #if CAP_NCONF
 | 
						|
    if(uni == 'l') pushScreen(pick_algorithm);
 | 
						|
    #endif
 | 
						|
    if(uni == 'p') pushScreen(pick_pattern);
 | 
						|
    // if(uni == 'w') edit_whatever('f', 0);
 | 
						|
    if(uni == 'd') doublemap();
 | 
						|
    if(uni == 'm') viewmap = !viewmap;
 | 
						|
    if(uni == 's') show_mapping = !show_mapping;
 | 
						|
    if(uni == 'g') show_mgrid = !show_mgrid;
 | 
						|
    if(uni == 't') pushScreen(conf_shapes);
 | 
						|
    if(uni == 'y') {
 | 
						|
      dialog::editNumber(mapping_split, 0, 1, 0.05, 0.75, "", "");
 | 
						|
      dialog::get_di().dialogflags = sm::NOSCR;
 | 
						|
      }
 | 
						|
    if(uni == '-') {
 | 
						|
      int x = (mousex - cd->xcenter - xc - x0) / siz;
 | 
						|
      int y = (mousey - cd->ycenter - yc - y0) / siz;
 | 
						|
      if(x < 0 || y < 0 || x >= X || y >= Y) return;
 | 
						|
      paintmode = fmap[y][x];
 | 
						|
      changepoint(x, y, true);
 | 
						|
      }
 | 
						|
    if(uni == 'v') showmenu = !showmenu;
 | 
						|
    if(uni == 'X') {
 | 
						|
      int D = 100;
 | 
						|
  
 | 
						|
      fmap = genellipse(D, -10._deg), reset_vxy();
 | 
						|
      #if CAP_NCONF
 | 
						|
      nconf_solve(); 
 | 
						|
      #endif
 | 
						|
      iterate();
 | 
						|
      iterate();      
 | 
						|
      iterate();
 | 
						|
      
 | 
						|
      int slow = 2;
 | 
						|
  
 | 
						|
      for(int i=-100; i<180*slow; i++) {
 | 
						|
        ticks = anims::period * i / 180 / slow;
 | 
						|
        redraw_texture();
 | 
						|
        fmap = genellipse(D, i * degree / slow);
 | 
						|
        println(hlog, "i = ", i);
 | 
						|
        for(int a=0; a<10; a++) iterate();
 | 
						|
        if(i >= 0) shot::take(hr::format(rfname.c_str(), i), draw_ncee);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
extern "C" {
 | 
						|
  void nconf_view(int i) {
 | 
						|
    if(i == 1) 
 | 
						|
      show_mapping = false, viewmap = false;
 | 
						|
    else if(i == 2)
 | 
						|
      show_mapping = false, viewmap = true;
 | 
						|
    else if(i == 3)
 | 
						|
      show_mapping = true, viewmap = true, show_mgrid = true;
 | 
						|
    else if(i == 4)
 | 
						|
      showmenu = false;
 | 
						|
    else if(i == 5)
 | 
						|
      showmenu = true;
 | 
						|
    else if(i == 6)
 | 
						|
      reset_vxy(), algo_ticks = 0;
 | 
						|
    #if CAP_NCONF
 | 
						|
    else if(i == 7)
 | 
						|
      nconf_solve(), algo_ticks = 0;
 | 
						|
    else if(i == 8)
 | 
						|
      nconf_prepare(false);
 | 
						|
    else if(i == 9)
 | 
						|
      nconf_prepare(true);
 | 
						|
    #endif
 | 
						|
    else if(i == 10)
 | 
						|
      doublemap();
 | 
						|
    else if(i == 11)
 | 
						|
      fmap = gensquare(13, 13), reset_vxy();
 | 
						|
    else if(i == 12)
 | 
						|
      fmap = gensquare(15, 8), reset_vxy();
 | 
						|
    else if(i == 13)
 | 
						|
      fmap = gensquare(19, 7), reset_vxy();
 | 
						|
    else if(i == 14)
 | 
						|
      fmap = snake, reset_vxy();
 | 
						|
    else if(i == 15)
 | 
						|
      pushScreen(pick_pattern);
 | 
						|
    else if(i == 16)
 | 
						|
      fmap = apple, reset_vxy();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
int niceArgs() {
 | 
						|
  using namespace arg;
 | 
						|
           
 | 
						|
  if(0) ;
 | 
						|
  else if(argis("-ncee")) {
 | 
						|
    PHASE(3);
 | 
						|
    pushScreen(ncee);
 | 
						|
    showstartmenu = false;
 | 
						|
    clearMessages();
 | 
						|
    }
 | 
						|
  else if(argis("-ncv")) {
 | 
						|
    PHASE(3);
 | 
						|
    shift();
 | 
						|
    nconf_view(argi());
 | 
						|
    }
 | 
						|
  else if(argis("-ncvid")) {
 | 
						|
    shift(); rfname = args();
 | 
						|
    }
 | 
						|
    
 | 
						|
  else return 1;
 | 
						|
  return 0;
 | 
						|
  }
 | 
						|
 | 
						|
auto nhook = 
 | 
						|
  addHook(hooks_args, 100, niceArgs)
 | 
						|
+ 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
}
 |