2021-02-23 03:56:23 +00:00
# ifdef NOTKNOT
# include "../hyper.cpp"
# endif
2021-03-31 13:19:13 +00:00
# include "rogueviz.h"
2021-02-18 15:16:11 +00:00
2021-06-25 11:54:17 +00:00
# if CAP_RAY
2021-02-18 15:16:11 +00:00
/**
2021-02-19 13:42:39 +00:00
* mg 2 in old video
Blocky Knot Portal :
2021-02-18 15:16:11 +00:00
compile with : mymake rogueviz / notknot
the video has been created with the following options :
2021-02-19 13:42:39 +00:00
2021-03-21 09:46:50 +00:00
older Euclidean
2021-02-19 13:42:39 +00:00
https : //youtu.be/1TMY2U4_9Qg
nk_margin = 2 - noplayer - canvas - random 20 - geo notknot - sight3 0.5 - ray - cells 600000 smooth_scrolling = 1 camspd = 10 panini_alpha = 1 fov = 150 - shot - hd ray_exp_decay_poly = 30 ray_fixed_map = 1
2021-03-21 09:46:50 +00:00
better Euclidean
2021-02-19 13:42:39 +00:00
https : //youtu.be/eb2DhCcGH7U
nk_margin = 4 - noplayer - canvas - random 20 - geo notknot - sight3 0.5 - ray - cells 600000 smooth_scrolling = 1 camspd = 10 panini_alpha = 1 fov = 150 - shot - hd ray_exp_decay_poly = 30 ray_fixed_map = 1 - ray - iter 100 ray_reflect_val = 0.30
2021-02-18 15:16:11 +00:00
2021-03-21 09:46:50 +00:00
self - hiding Euclidean
2021-02-23 03:56:23 +00:00
https : //youtu.be/vFLZ2NGtuGw
2021-03-21 09:46:50 +00:00
selfhide = 1 nk_loop = 4 nk_margin = 4 - noplayer - canvas - random 20 - geo notknot - sight3 0.5 - ray - cells 600000 smooth_scrolling = 1 camspd = 10 panini_alpha = 1 fov = 150 - shot - hd ray_exp_decay_poly = 30 ray_fixed_map = 1 - ray - iter 100 ray_reflect_val = 0.30
penrose staircase in Nil
- noplayer nk_loop = 6 nk_secondary = 0 nk_terminate = 9999999 - geo Nil - nilperiod 8 8 8 - nilwidth .25 - canvas - random 20 - nkbase - geo notknot ray_fixed_map = 1 - ray - cells 600000 - sight3 1 - ray - range 1 3 - ray - random 1 - shot - 1000
self - hiding knotted portal in S3
selfhide = 1 - run nk_secondary = 0 nk_terminate = 9999999 nk_loop = 4 - canvas - random 10 - load spherknot . lev - nkbase - nkbasemap spherknot . lev - PM nativ - fov 270 panini_alpha = 1 - nk - volumetric - noplayer ray_fixed_map = 1 - ray - cells 600000 - ray - iter 600
basic portal in S3 :
nk_secondary = 0 nk_terminate = 99999 nk_loop = 0 - nk - unloop 60 7 - canvas - random 10 - load spherring . lev - nkbase - nkbasemap spherring . lev - PM nativ - fov 270 panini_alpha = 1 - nk - volumetric - noplayer
2021-02-23 03:56:23 +00:00
2021-02-18 15:16:11 +00:00
The algorithm here is as follows :
* create the map without portals ( this is just the cube with the trifoil knot in it )
This is done with a program ( function create_trifoil_knot ) .
The general algorithm should work with any map , and it would be possible to make it so that the user can create the map using HyperRogue map editor .
* the universal cover can be seen as the set of all paths , where two paths are identified if they are homotopic . So we generate all paths
from the chosen starting point ; when we generate extensions from path . . . A , we check if we have a situation where we could go . . . A - > B - > D or . . . A - > C - > D - -
if so , the two paths are homotopic , so we identify them ( that is , all the references to one of the paths are replaced with the references to the other path ,
possibly propagating to all known extensions of these paths )
* since the universal cover of the trifoil knot complement is infinite , we also identify two paths if they differ by three loops around the knot ( around any point of the knot ) .
( If we did not do that , the algorithm would never terminate , or we could terminate it at some point ( terminate_at ) , but then we easily run into ugly unfinished areas . )
* this result in a relatively standard HyperRogue map representation ( cubes connected via glued faces ) which is rendered using HyperRogue ' s raycaster .
*/
namespace hr {
2021-02-19 13:42:39 +00:00
namespace notknot {
2021-03-21 09:46:50 +00:00
void create_notknot ( ) ;
2021-02-19 13:42:39 +00:00
/* how many times we need to loop around the portal frame to get back to the same space */
/* the number of the worlds is: 1 (loop=1), 6 (loop=2), 24, 96, 600, infinity (loop>5) */
int loop = 3 ;
2021-03-21 09:46:50 +00:00
/* any loop repeated loop_any times */
int loop_any = 0 ;
2021-02-19 13:42:39 +00:00
/* extra space around the knot */
int margin = 4 ;
/* the scale factor for the knot */
int knotsize = 3 ;
2021-03-21 09:46:50 +00:00
int secondary_percentage = 10 ;
2021-02-19 13:42:39 +00:00
int terminate_at = 500000000 ;
2021-02-18 15:16:11 +00:00
2021-03-21 09:46:50 +00:00
string base_map = " " ;
2021-02-23 03:56:23 +00:00
/* make a self-hiding knot */
bool self_hiding = false ;
2021-02-18 15:16:11 +00:00
eGeometry gNotKnot ( eGeometry ( - 1 ) ) ;
/** It was easier to generate a program to design the trifoil knot than to generate it manually.
* This function does generate the instructions for trifoil knot , although they have been adjusted manually
* The generated instructions is the weird array in create_trifoil_knot ( )
*/
2021-03-21 09:46:50 +00:00
vector < vector < int > > to_unloop ;
2021-02-18 15:16:11 +00:00
void gen_trifoil ( ) {
for ( int len = 2 ; len < = 12 ; len + = 2 ) {
println ( hlog , " trying len = " , len ) ;
int pos = 1 ;
for ( int l = 0 ; l < len ; l + + ) pos * = 6 ;
for ( int p = 0 ; p < pos ; p + + ) {
vector < int > lst ;
int a = p ;
int bal = 0 ;
for ( int p = 0 ; p < len ; p + + ) {
if ( a % 6 < 3 ) bal + + ; else bal - - ;
lst . push_back ( a % 6 ) ;
a / = 6 ;
}
if ( bal ) continue ;
array < int , 3 > start = { 0 , 0 , 0 } ;
array < int , 3 > where = start ;
set < array < int , 3 > > ful ;
map < array < int , 2 > , int > proj ;
int steps = 0 ;
vector < pair < int , int > > crosses ;
for ( int i = 0 ; i < 3 ; i + + ) {
for ( auto d : lst ) {
if ( ful . count ( where ) ) goto next ;
ful . insert ( where ) ;
auto pco = array < int , 2 > { { where [ 0 ] - where [ 2 ] , where [ 1 ] - where [ 2 ] } } ;
if ( proj . count ( pco ) ) crosses . emplace_back ( proj [ pco ] , steps ) ;
else proj [ pco ] = steps ;
where [ ( d + i ) % 3 ] + = ( d < 3 ? 1 : - 1 ) ;
steps + + ;
}
}
if ( where ! = start ) { println ( hlog , " bad loop " ) ; continue ; }
if ( isize ( ful ) ! = 3 * len ) continue ;
if ( isize ( proj ) ! = 3 * len - 3 ) continue ;
println ( hlog , " len= " , len , " ful= " , isize ( ful ) , " proj= " , isize ( proj ) , " for " , lst ) ;
println ( hlog , " crosses = " , crosses ) ;
if ( 1 ) {
set < int > crosval ;
for ( auto c : crosses ) crosval . insert ( c . first ) , crosval . insert ( c . second ) ;
vector < int > cvs ;
for ( auto s : crosval ) cvs . push_back ( s ) ;
bool wrong = false ;
for ( auto c : crosses ) if ( c . first = = cvs [ 0 ] & & c . second = = cvs [ 1 ] ) wrong = true ;
for ( auto c : crosses ) if ( c . first = = cvs [ 1 ] & & c . second = = cvs [ 2 ] ) wrong = true ;
if ( wrong ) continue ;
}
println ( hlog , " result: " , lst ) ;
exit ( 3 ) ;
next : ;
}
}
exit ( 2 ) ;
}
2021-03-21 09:46:50 +00:00
eGeometry base = gCubeTiling ;
const int arrsize = 12 ;
2021-02-18 15:16:11 +00:00
struct hrmap_notknot : hrmap {
/* represents a path (may be partially identified) */
struct ucover {
/* the heptagon of the underlying map */
heptagon * where ;
/* the heptagon of the result map */
heptagon * result ;
/* what is has been merged into */
ucover * merged_into ;
/* connections in every direction */
2021-03-21 09:46:50 +00:00
ucover * ptr [ arrsize ] ;
2021-02-18 15:16:11 +00:00
/* used for painting walls in a single color */
ucover * wall_merge ;
color_t wallcolor , wallcolor2 ;
2021-03-21 10:08:10 +00:00
/* 0 = live, 1 = wall, 2 = merged, 4 = overflow, 8 = to hide */
2021-03-21 09:46:50 +00:00
char state ;
/* direction to the parent */
char parentdir ;
2021-02-18 15:16:11 +00:00
/* index in the table `all` */
int index ;
2021-03-21 09:46:50 +00:00
ucover ( heptagon * w , int s ) { where = w ; for ( int i = 0 ; i < arrsize ; i + + ) ptr [ i ] = nullptr ; state = s ; merged_into = nullptr ; result = nullptr ; wall_merge = this ; }
bool iswall ( ) { return state & 1 ; }
bool nowall ( ) { return ! iswall ( ) ; }
2021-03-21 10:08:10 +00:00
bool ismerged ( ) { return state & 2 ; }
bool isover ( ) { return state & 4 ; }
bool tohide ( ) { return state & 8 ; }
2021-02-18 15:16:11 +00:00
} ;
/* find-union algorithm for wall_merge */
ucover * ufind ( ucover * at ) {
if ( at - > wall_merge = = at ) return at ;
return at - > wall_merge = ufind ( at - > wall_merge ) ;
}
void funion ( ucover * a , ucover * b ) {
ufind ( b ) - > wall_merge = ufind ( a ) ;
}
/* the vector of all paths */
vector < ucover * > all ;
/* the stack of known unifications */
vector < pair < ucover * , ucover * > > unify ;
/* the underlying map */
hrmap * euc ;
heptagon * getOrigin ( ) override {
// return hepts[0];
return all [ 0 ] - > result ;
}
heptagon * at ( int x , int y , int z ) {
2021-03-21 09:46:50 +00:00
dynamicval < eGeometry > g ( geometry , base ) ;
2021-02-18 15:16:11 +00:00
dynamicval < hrmap * > m ( currentmap , euc ) ;
euc : : coord co = euc : : basic_canonicalize ( { x , y , z } ) ;
return euc : : get_at ( co ) ;
}
/* make sure that where->move(d) and where->c.spin(d) are known */
void cmov ( heptagon * where , int d ) {
if ( where - > move ( d ) ) return ;
2021-03-21 09:46:50 +00:00
dynamicval < eGeometry > g ( geometry , base ) ;
2021-02-18 15:16:11 +00:00
dynamicval < hrmap * > m ( currentmap , euc ) ;
createStep ( where , d ) ;
}
heptagon * create_trifoil_knot ( ) {
euc : : coord cmin { 99 , 99 , 99 } , cmax { - 99 , - 99 , - 99 } , cat { 0 , 0 , 0 } ;
heptagon * h = at ( 0 , 0 , 0 ) ;
vector < heptagon * > trifoil ;
2021-02-19 13:42:39 +00:00
int step = knotsize ;
2021-02-18 15:16:11 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
for ( auto m : { 3 , 3 , 3 , 3 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 0 } ) for ( int rep = 0 ; rep < step ; rep + + ) {
trifoil . push_back ( h ) ;
int d = ( i + m ) % 3 + ( m < 3 ? 0 : 3 ) ;
cmov ( h , d ) ;
h = h - > move ( d ) ;
if ( m < 3 ) cat [ ( i + m ) % 3 ] + + ; else cat [ ( i + m ) % 3 ] - - ;
for ( int k = 0 ; k < 3 ; k + + ) cmin [ k ] = min ( cmin [ k ] , cat [ k ] ) , cmax [ k ] = max ( cmax [ k ] , cat [ k ] ) ;
}
}
2021-02-19 13:42:39 +00:00
int & mg = margin ;
2021-02-18 15:16:11 +00:00
for ( int i = cmin [ 0 ] - mg ; i < = cmax [ 0 ] + mg ; i + + )
for ( int j = cmin [ 1 ] - mg ; j < = cmax [ 1 ] + mg ; j + + )
for ( int k = cmin [ 2 ] - mg ; k < = cmax [ 2 ] + mg ; k + + )
if ( among ( i , cmin [ 0 ] - mg , cmax [ 0 ] + mg ) | | among ( j , cmin [ 1 ] - mg , cmax [ 1 ] + mg ) | | among ( k , cmin [ 2 ] - mg , cmax [ 2 ] + mg ) )
at ( i , j , k ) - > zebraval = 1 ;
else
at ( i , j , k ) - > zebraval = 0 ;
for ( auto h : trifoil )
2021-02-23 03:56:23 +00:00
h - > zebraval = 9 ;
2021-02-18 15:16:11 +00:00
return at ( cmax [ 0 ] , cmax [ 1 ] , cmax [ 2 ] ) ;
}
2021-03-21 09:46:50 +00:00
heptagon * create_nil_knot ( ) {
dynamicval < eGeometry > g ( geometry , base ) ;
dynamicval < hrmap * > m ( currentmap , euc ) ;
auto ac = currentmap - > allcells ( ) ;
for ( cell * c : ac ) c - > master - > zebraval = 0 ;
2021-02-18 15:16:11 +00:00
2021-03-21 09:46:50 +00:00
auto hept = [ & ] ( int x , int y , int z ) {
x = zgmod ( x , nilv : : nilperiod [ 0 ] ) ;
y = zgmod ( y , nilv : : nilperiod [ 1 ] ) ;
z = zgmod ( z , nilv : : nilperiod [ 2 ] ) ;
return nilv : : get_heptagon_at ( nilv : : mvec ( x , y , z ) ) ;
} ;
hept ( - 3 , - 3 , - 4 ) - > zebraval | = 16 ;
heptagon * h0 = hept ( - 2 , - 2 , 0 ) ;
auto h = h0 ;
for ( int d : { 4 , 3 , 1 , 0 } )
for ( int i = 0 ; i < 4 ; i + + ) {
h - > zebraval | = 1 ;
h = h - > cmove ( d ) ;
h - > zebraval | = 1 ;
h = h - > cmove ( 5 ) ;
}
if ( h ! = h0 ) { println ( hlog , " not looped " ) ; exit ( 1 ) ; }
hept ( 0 , 0 , 2 ) - > zebraval | = 1 ;
hept ( 1 , 0 , 2 ) - > zebraval | = 1 ;
hept ( - 1 , 0 , 2 ) - > zebraval | = 1 ;
for ( int z = 0 ; z < 8 ; z + + )
for ( int x = - 3 ; x < 4 ; x + + )
for ( int y = - 3 ; y < 4 ; y + + )
if ( ! ( x > = - 1 & & x < = 1 & & y > = - 1 & & y < = 1 ) )
if ( ! ( hept ( x , y , z ) - > zebraval & 1 ) )
hept ( x , y , z ) - > zebraval | = 32 ;
return ac [ 0 ] - > master ;
}
2021-03-25 09:36:07 +00:00
2021-06-25 11:54:17 +00:00
# if CAP_SOLV
2021-03-25 09:36:07 +00:00
heptagon * create_solv_knot ( ) {
dynamicval < eGeometry > g ( geometry , base ) ;
dynamicval < hrmap * > m ( currentmap , euc ) ;
auto ac = currentmap - > allcells ( ) ;
for ( cell * c : ac ) c - > master - > zebraval = 0 ;
auto hept = [ & ] ( int x , int y , int z ) {
asonov : : coord co ( x , y , z ) ;
return asonov : : get_at ( co ) ;
} ;
auto h = hept ( 0 , 0 , 0 ) ;
h - > zebraval | = 16 ;
int top = asonov : : period_xy ;
top + = 2 - margin ;
for ( int x = 1 ; x < top - 1 ; x + + )
for ( int y = 1 ; y < top - 1 ; y + + )
if ( x = = 1 | | y = = 1 | | x = = top - 2 | | y = = top - 2 )
hept ( x , y , 0 ) - > zebraval | = 9 ;
hept ( 0 , 0 , ( asonov : : period_z + 1 ) / 2 ) - > c7 - > wall = waFloorA ;
hept ( 2 , 2 , 0 ) - > zebraval | = 128 ;
// if(top > 4) hept(3, 3, 1)->zebraval |= 9;
return ac [ 0 ] - > master ;
}
2021-06-25 11:54:17 +00:00
# endif
2021-03-21 09:46:50 +00:00
heptagon * interpret_basemap ( ) {
dynamicval < eGeometry > g ( geometry , base ) ;
dynamicval < hrmap * > m ( currentmap , euc ) ;
auto ac = currentmap - > allcells ( ) ;
for ( cell * c : ac ) {
auto & m = c - > master - > zebraval ;
m = 0 ;
if ( c - > wall = = waPlatform )
m | = 9 ;
}
return ac [ 0 ] - > master ;
}
heptagon * create_under ( ) {
if ( base_map ! = " " )
return interpret_basemap ( ) ;
if ( base = = gCubeTiling )
return create_trifoil_knot ( ) ;
else if ( base = = gNil )
return create_nil_knot ( ) ;
2021-06-25 11:54:17 +00:00
# if CAP_SOLV
2021-03-25 09:36:07 +00:00
else if ( base = = gArnoldCat )
return create_solv_knot ( ) ;
2021-06-25 11:54:17 +00:00
# endif
2021-03-21 09:46:50 +00:00
throw hr_exception ( ) ;
}
bool remove_marked_walls ;
ucover * gen_adj ( ucover * u , int d ) {
if ( u - > ptr [ d ] ) return u - > ptr [ d ] ;
cmov ( u - > where , d ) ;
auto x = u - > where - > move ( d ) ;
auto d1 = u - > where - > c . spin ( d ) ;
auto z = x - > zebraval ;
if ( z & 6 ) {
2021-03-21 21:56:38 +00:00
throw hr_exception ( " zebraval failure! " ) ;
2021-03-21 09:46:50 +00:00
exit ( 3 ) ;
x - > zebraval = 0 ;
}
if ( remove_marked_walls & & ( z & 8 ) )
z & = ~ 9 ;
u - > ptr [ d ] = new ucover ( x , z & 15 ) ;
u - > ptr [ d ] - > ptr [ d1 ] = u ;
u - > ptr [ d ] - > index = isize ( all ) ;
u - > ptr [ d ] - > parentdir = d1 ;
all . push_back ( u - > ptr [ d ] ) ;
return u - > ptr [ d ] ;
} ;
void add_to_unify ( ucover * a , ucover * b ) {
if ( a - > where ! = b - > where )
2021-03-21 21:56:38 +00:00
throw hr_exception ( " unification error " ) ;
2021-03-21 09:46:50 +00:00
unify . emplace_back ( a , b ) ;
} ;
2021-03-25 10:41:24 +00:00
map < heptagon * , vector < vector < int > > > uloops ;
bool collapse_loop ( ucover * u , int loopcount , const vector < int > & looplist ) {
2021-03-21 09:46:50 +00:00
auto ux = u ;
for ( int iter = 0 ; iter < loopcount ; iter + + )
for ( int w : looplist ) {
ux = gen_adj ( ux , w ) ;
if ( ux - > iswall ( ) ) return false ;
}
add_to_unify ( u , ux ) ;
return true ;
} ;
2021-03-25 10:41:24 +00:00
bool verify_loop ( ucover * u , int loopcount , const vector < int > & looplist ) {
auto ux = u ;
for ( int iter = 0 ; iter < loopcount ; iter + + )
for ( int w : looplist ) {
ux = gen_adj ( ux , w ) ;
if ( ux - > iswall ( ) ) return false ;
}
return true ;
}
2021-03-21 09:46:50 +00:00
2021-03-25 10:41:24 +00:00
void record_loop ( ucover * u , int loopcount , const vector < int > & looplist ) {
vector < int > repeated ;
for ( int l = 0 ; l < loopcount ; l + + )
for ( auto v : looplist ) repeated . push_back ( v ) ;
uloops [ u - > where ] . push_back ( repeated ) ;
} ;
void record_loop_if_nowall ( ucover * u , int loopcount , const vector < int > & looplist ) {
if ( verify_loop ( u , loopcount , looplist ) )
record_loop ( u , loopcount , looplist ) ;
}
void record_loop_verify ( ucover * u , int loopcount , const vector < int > & looplist , const hr_exception & ex ) {
if ( ! verify_loop ( u , loopcount , looplist ) ) throw ex ;
record_loop ( u , loopcount , looplist ) ;
}
2021-03-21 09:46:50 +00:00
transmatrix adj ( ucover * u , int k ) {
dynamicval < eGeometry > g ( geometry , base ) ;
dynamicval < hrmap * > m ( currentmap , euc ) ;
return currentmap - > adj ( u - > where , k ) ;
}
bool adjacent_matrix ( const transmatrix & Tk , const transmatrix & Tl ) {
2021-07-13 20:46:55 +00:00
for ( auto vk : cgi . heptshape - > vertices_only )
for ( auto vl : cgi . heptshape - > vertices_only )
2021-03-21 09:46:50 +00:00
if ( hdist ( Tk * vk , Tl * vl ) < .01 )
return true ;
return false ;
}
bool adjacent_face ( ucover * u , int k , int l ) {
if ( base = = gCubeTiling ) return abs ( k - l ) ! = 3 ;
if ( base = = gNil ) return abs ( k - l ) ! = 3 ;
return adjacent_matrix ( adj ( u , k ) , adj ( u , l ) ) ;
}
void unify_homotopies ( ucover * u ) {
/* unify homotopies */
if ( base = = gNil ) {
2021-03-25 10:41:24 +00:00
collapse_loop ( u , 1 , { 0 , 2 , 3 , 5 } ) ;
collapse_loop ( u , 1 , { 1 , 2 , 4 , 5 } ) ;
collapse_loop ( u , 1 , { 0 , 1 , 3 , 4 , 2 } ) ;
2021-03-21 09:46:50 +00:00
return ;
}
if ( base = = gCubeTiling ) {
2021-03-25 10:41:24 +00:00
collapse_loop ( u , 1 , { 0 , 1 , 3 , 4 } ) ;
collapse_loop ( u , 1 , { 0 , 2 , 3 , 5 } ) ;
collapse_loop ( u , 1 , { 1 , 2 , 4 , 5 } ) ;
2021-03-21 09:46:50 +00:00
return ;
}
2021-07-13 20:46:55 +00:00
for ( auto & v : cgi . heptshape - > vertices_only ) {
2021-03-21 09:46:50 +00:00
map < heptagon * , ucover * > visited ;
vector < pair < ucover * , transmatrix > > q ;
auto visit = [ & ] ( ucover * u , const transmatrix & T ) {
if ( visited . count ( u - > where ) ) {
add_to_unify ( u , visited [ u - > where ] ) ;
return ;
}
visited [ u - > where ] = u ;
q . emplace_back ( u , T ) ;
} ;
hyperpoint h = v ;
visit ( u , Id ) ;
for ( int i = 0 ; i < isize ( q ) ; i + + ) {
auto u1 = q [ i ] . first ;
transmatrix T0 = q [ i ] . second ;
for ( int i = 0 ; i < u1 - > where - > type ; i + + ) {
auto u2 = gen_adj ( u1 , i ) ;
if ( u2 - > state ! = 0 ) continue ;
auto T1 = T0 * adj ( u1 , i ) ;
bool adjacent = false ;
2021-07-13 20:46:55 +00:00
for ( auto & v2 : cgi . heptshape - > vertices_only )
2021-03-21 09:46:50 +00:00
if ( hdist ( T1 * v2 , h ) < 1e-5 )
adjacent = true ;
if ( adjacent )
visit ( u2 , T1 ) ;
}
}
}
}
void unify_loops_general ( ucover * u ) {
int t = u - > where - > type ;
for ( int i = 0 ; i < t ; i + + ) {
auto u1 = gen_adj ( u , i ) ;
2021-03-21 10:08:10 +00:00
if ( u1 - > nowall ( ) ) continue ;
2021-03-21 09:46:50 +00:00
if ( u1 - > where - > zebraval ! = 9 ) continue ;
transmatrix M = adj ( u , i ) ;
map < heptagon * , int > camefrom ;
vector < pair < ucover * , transmatrix > > visited ;
auto visit = [ & ] ( ucover * from , ucover * at , int ldir , const transmatrix & T ) {
// println(hlog, from ? from->where : (heptagon*)nullptr, " -> ", at->where, " (", i, ")", " (reverse ", at->where->c.spin(i), ")");
if ( camefrom . count ( at - > where ) ) {
vector < int > path ;
vector < int > rpath ;
while ( at - > where ! = u - > where ) {
int d = camefrom [ at - > where ] ;
// println(hlog, "from ", at->where, " going back ", d);
rpath . push_back ( at - > where - > c . spin ( d ) ) ;
at = gen_adj ( at , d ) ;
}
while ( ! rpath . empty ( ) ) { path . push_back ( rpath . back ( ) ) ; rpath . pop_back ( ) ; }
path . push_back ( ldir ) ;
int st = 0 ;
while ( from - > where ! = u - > where ) {
int d = camefrom [ from - > where ] ;
// println(hlog, "from ", from->where, " going ", d);
st + + ; if ( st = = 10 ) exit ( 1 ) ;
path . push_back ( d ) ;
from = gen_adj ( from , d ) ;
}
2021-03-25 10:16:52 +00:00
if ( false ) {
println ( hlog , " path = " , path ) ;
2021-03-21 09:46:50 +00:00
}
2021-03-25 10:41:24 +00:00
record_loop_verify ( u , loop , path , hr_exception ( " wall in loops_general " ) ) ;
2021-03-21 09:46:50 +00:00
}
else {
camefrom [ at - > where ] = ldir ;
visited . emplace_back ( at , T ) ;
}
} ;
visit ( nullptr , u , - 1 , Id ) ;
for ( int vi = 0 ; vi < isize ( visited ) ; vi + + ) {
auto at = visited [ vi ] . first ;
auto Ti = visited [ vi ] . second ;
for ( int j = 0 ; j < at - > where - > type ; j + + ) {
if ( j = = camefrom [ at - > where ] ) continue ;
auto u2 = gen_adj ( at , j ) ;
2021-03-21 10:08:10 +00:00
if ( u2 - > iswall ( ) ) continue ;
2021-03-21 09:46:50 +00:00
transmatrix Tj = Ti * adj ( at , j ) ;
bool adj = false ;
2021-07-13 20:46:55 +00:00
for ( auto v : cgi . heptshape - > vertices_only ) for ( auto v1 : cgi . heptshape - > vertices_only )
2021-03-21 09:46:50 +00:00
if ( hdist ( M * v1 , Tj * v ) < 1e-3 ) adj = true ;
if ( adj ) visit ( at , u2 , at - > where - > c . spin ( j ) , Tj ) ;
}
}
}
}
void unify_loops ( ucover * u ) {
/* try to make it finite */
bool special = false ;
if ( base_map = = " " & & base = = gNil ) {
special = true ;
2021-03-25 10:41:24 +00:00
record_loop_if_nowall ( u , loop , { 0 , 0 , 2 , 2 , 2 , 3 , 3 , 5 , 5 , 5 } ) ;
if ( u - > where - > zebraval & 16 ) {
for ( int dir : { 0 , 1 , 2 } )
record_loop_verify ( u , nilv : : nilperiod [ dir ] , { dir } , hr_exception ( " 16 failed " ) ) ;
2021-03-21 09:46:50 +00:00
}
}
2021-03-25 09:36:07 +00:00
2021-06-25 11:54:17 +00:00
# if CAP_SOLV
2021-03-25 09:36:07 +00:00
if ( base_map = = " " & & base = = gArnoldCat ) {
2021-03-25 10:41:24 +00:00
if ( u - > where - > zebraval & 16 ) {
for ( int dir : { 0 , 4 , 5 } ) {
int steps = dir ? asonov : : period_xy : asonov : : period_z ;
if ( dir ) steps * = 2 ;
record_loop_verify ( u , steps , { dir } , hr_exception ( " 16 failed " ) ) ;
2021-03-25 09:36:07 +00:00
}
}
if ( u - > where - > zebraval & 128 ) {
for ( int a = 0 ; a < 2 ; a + + ) {
vector < int > myloop ;
myloop . push_back ( 0 ) ;
auto add_shift = [ & ] ( int x , int y , int lev ) {
if ( a ) swap ( x , y ) ;
while ( lev > 0 ) lev - - , tie ( x , y ) = make_pair ( x * 2 - y , y - x ) ;
while ( lev < 0 ) lev + + , tie ( x , y ) = make_pair ( x + y , x + 2 * y ) ;
while ( x > 0 ) x - - , myloop . push_back ( 4 ) ;
while ( y > 0 ) y - - , myloop . push_back ( 5 ) ;
while ( x < 0 ) x + + , myloop . push_back ( 10 ) ;
while ( y < 0 ) y + + , myloop . push_back ( 11 ) ;
} ;
auto p = asonov : : period_xy ;
add_shift ( p - 2 , 0 , 1 ) ;
myloop . push_back ( 6 ) ;
myloop . push_back ( 6 ) ;
add_shift ( 2 , 0 , - 1 ) ;
myloop . push_back ( 0 ) ;
myloop . push_back ( 0 ) ;
add_shift ( - 2 , 0 , 1 ) ;
myloop . push_back ( 6 ) ;
myloop . push_back ( 6 ) ;
add_shift ( 2 - p , 0 , - 1 ) ;
myloop . push_back ( 0 ) ;
2021-03-25 10:41:24 +00:00
record_loop_verify ( u , 1 , myloop , hr_exception ( " 128 failed " ) ) ;
2021-03-25 09:36:07 +00:00
}
}
}
2021-06-25 11:54:17 +00:00
# endif
2021-03-21 09:46:50 +00:00
if ( base = = gCubeTiling ) {
special = true ;
2021-03-25 10:41:24 +00:00
record_loop_if_nowall ( u , loop , { 0 , 0 , 1 , 1 , 3 , 3 , 4 , 4 } ) ;
2021-03-21 09:46:50 +00:00
}
if ( base = = gCell120 ) {
special = true ;
int t = u - > where - > type ;
for ( int i = 0 ; i < t ; i + + )
for ( int j = 0 ; j < i ; j + + ) {
auto u1 = u - > ptr [ i ] ;
auto u2 = u - > ptr [ j ] ;
2021-03-21 10:08:10 +00:00
if ( u1 - > nowall ( ) ) continue ;
if ( u2 - > nowall ( ) ) continue ;
2021-03-21 09:46:50 +00:00
auto ucur = u ;
auto ulast = ( ucover * ) nullptr ;
2021-03-25 10:41:24 +00:00
vector < int > myloop ;
for ( int step = 0 ; step < 5 ; step + + ) {
2021-03-21 09:46:50 +00:00
for ( int i = 0 ; i < t ; i + + ) {
auto ucand = ucur - > ptr [ i ] ;
2021-03-21 10:08:10 +00:00
if ( ucand & & isNeighbor ( ucand - > where - > c7 , u1 - > where - > c7 ) & & isNeighbor ( ucand - > where - > c7 , u2 - > where - > c7 ) & & ucand ! = ulast ) {
2021-03-25 10:41:24 +00:00
myloop . push_back ( i ) ;
2021-03-21 09:46:50 +00:00
ulast = ucur , ucur = ucand ;
goto next_step ;
}
}
goto fail ;
next_step : ;
}
2021-03-25 10:41:24 +00:00
record_loop ( u , loop , myloop ) ;
2021-03-21 09:46:50 +00:00
fail : ;
}
}
if ( loop & & ! special )
unify_loops_general ( u ) ;
if ( u - > where = = all [ 0 ] - > where )
2021-03-25 10:41:24 +00:00
for ( auto & lo : to_unloop ) {
record_loop_verify ( u , 1 , lo , hr_exception ( " loop-to-unloop goes through a wall " ) ) ;
2021-03-21 09:46:50 +00:00
}
}
map < heptagon * , int > indices ;
2021-02-18 15:16:11 +00:00
hrmap_notknot ( ) {
2021-03-21 09:46:50 +00:00
try {
if ( base_map ! = " " ) {
dynamicval < eGeometry > dg ( geometry , geometry ) ;
mapstream : : loadMap ( base_map ) ;
base = geometry ;
create_notknot ( ) ;
euc = currentmap ;
for ( hrmap * & m : allmaps ) if ( m = = euc ) m = NULL ;
}
else {
dynamicval < eGeometry > dg ( geometry , base ) ;
2021-02-18 15:16:11 +00:00
initcells ( ) ; euc = currentmap ;
for ( hrmap * & m : allmaps ) if ( m = = euc ) m = NULL ;
}
int i = 0 ;
2021-03-21 09:46:50 +00:00
all . emplace_back ( new ucover ( create_under ( ) , 0 ) ) ;
2021-02-23 04:21:08 +00:00
all [ 0 ] - > index = 0 ;
2021-03-21 09:46:50 +00:00
all [ 0 ] - > parentdir = - 1 ;
if ( all [ 0 ] - > where - > zebraval & 1 )
2021-03-21 21:56:38 +00:00
throw hr_exception ( " error: starting inside a wall " ) ;
2021-02-18 15:16:11 +00:00
2021-03-21 09:46:50 +00:00
remove_marked_walls = false ;
2021-02-23 03:56:23 +00:00
bool first = true ;
back :
2021-02-18 15:16:11 +00:00
while ( true ) {
/* handle all known unifications */
if ( ! unify . empty ( ) ) {
ucover * uf , * ut ;
tie ( uf , ut ) = unify . back ( ) ;
unify . pop_back ( ) ;
while ( uf - > merged_into ) uf = uf - > merged_into ;
while ( ut - > merged_into ) ut = ut - > merged_into ;
if ( uf = = ut ) continue ;
if ( ! uf | | ! ut ) println ( hlog , " null unified " ) ;
/* we always keep the one with the lower index */
2021-02-23 03:56:23 +00:00
if ( uf - > index < ut - > index ) swap ( uf , ut ) ;
/* if a knot is removed, remove the other copy */
2021-03-21 10:08:10 +00:00
if ( uf - > iswall ( ) & & ut - > nowall ( ) )
2021-02-23 03:56:23 +00:00
uf - > state & = ~ 1 ;
2021-02-19 01:37:03 +00:00
uf - > state | = 2 ; uf - > merged_into = ut ;
2021-02-18 15:16:11 +00:00
if ( uf - > where ! = ut - > where )
2021-03-21 21:56:38 +00:00
throw hr_exception ( " where confusion " ) ;
2021-03-21 09:46:50 +00:00
for ( int d = 0 ; d < uf - > where - > type ; d + + ) {
2021-02-18 15:16:11 +00:00
cmov ( uf - > where , d ) ;
auto d1 = uf - > where - > c . spin ( d ) ;
if ( uf - > ptr [ d ] ) {
if ( ! ut - > ptr [ d ] ) {
/* was a known connection in uf, but not in ut -- reconnect it to ut */
uf - > ptr [ d ] - > ptr [ d1 ] = ut ;
ut - > ptr [ d ] = uf - > ptr [ d ] ;
uf - > ptr [ d ] = nullptr ;
}
else {
/* in some direction, connections for both uf and ut are already known, so unify them too */
2021-03-21 09:46:50 +00:00
add_to_unify ( uf - > ptr [ d ] , ut - > ptr [ d ] ) ;
2021-02-18 15:16:11 +00:00
uf - > ptr [ d ] - > ptr [ d1 ] = nullptr ;
uf - > ptr [ d ] = nullptr ;
}
}
}
continue ;
}
/* handle creation and loops */
if ( i > = isize ( all ) ) break ;
auto u = all [ i + + ] ;
if ( u - > state ! = 0 ) continue ;
2021-02-19 01:37:03 +00:00
if ( i > terminate_at ) { u - > state | = 4 ; continue ; }
2021-02-18 15:16:11 +00:00
2021-03-21 09:46:50 +00:00
for ( int k = 0 ; k < u - > where - > type ; k + + ) gen_adj ( u , k ) ;
2021-03-25 10:41:24 +00:00
unify_homotopies ( u ) ;
if ( ! uloops . count ( u - > where ) ) {
uloops [ u - > where ] = { } ;
2021-03-21 09:46:50 +00:00
unify_loops ( u ) ;
2021-04-07 17:58:23 +00:00
// println(hlog, "loops recorded for ", u->where, ": ", isize(uloops[u->where]));
2021-03-21 09:46:50 +00:00
}
2021-03-25 10:41:24 +00:00
for ( auto & myloop : uloops [ u - > where ] )
if ( ! collapse_loop ( u , 1 , myloop ) )
throw hr_exception ( " invalid loop recorded " ) ;
if ( u - > where = = all [ 0 ] - > where ) {
vector < int > pathback ;
auto uc = u ;
while ( uc - > parentdir ! = - 1 ) {
pathback . push_back ( uc - > parentdir ) ;
uc = uc - > ptr [ ( int ) uc - > parentdir ] ;
}
2021-04-07 17:58:23 +00:00
// println(hlog, "pathback = ", pathback);
2021-03-25 10:41:24 +00:00
if ( loop_any ) {
auto us = all [ 0 ] ;
for ( int it = 1 ; it < loop_any ; it + + ) {
uc = u ;
while ( uc - > parentdir ! = - 1 ) {
us = gen_adj ( us , uc - > parentdir ) ;
uc = uc - > ptr [ ( int ) uc - > parentdir ] ;
}
}
add_to_unify ( us , u ) ;
}
}
2021-02-19 01:37:03 +00:00
}
/* make the walls single-colored */
2021-03-21 09:46:50 +00:00
println ( hlog , " single-colored " ) ;
2021-02-19 01:37:03 +00:00
for ( int i = 0 ; i < isize ( all ) ; i + + ) {
auto u = all [ i ] ;
if ( u - > state ! = 0 ) continue ;
2021-03-21 09:46:50 +00:00
if ( u - > where - > zebraval & 32 ) {
for ( int k = 0 ; k < u - > where - > type ; k + + ) {
auto uk = gen_adj ( u , k ) ;
if ( uk - > state ! = 0 ) continue ;
if ( uk - > where - > zebraval & 32 )
funion ( u , uk ) ;
}
}
2021-02-19 01:37:03 +00:00
/* convex corners */
2021-03-21 09:46:50 +00:00
for ( int k = 0 ; k < u - > where - > type ; k + + )
for ( int l = 0 ; l < u - > where - > type ; l + + ) {
2021-02-19 01:37:03 +00:00
auto uk = gen_adj ( u , k ) ;
if ( uk - > state ! = 0 ) continue ;
auto ul = gen_adj ( u , l ) ;
if ( ul - > state ! = 0 ) continue ;
2021-03-25 10:17:24 +00:00
if ( base = = gCubeTiling | | base = = gNil ) {
2021-03-21 09:46:50 +00:00
auto ukl = gen_adj ( uk , l ) ;
auto ulk = gen_adj ( ul , k ) ;
if ( ukl - > where = = ulk - > where & & ukl - > state ! = 0 )
funion ( ukl , ulk ) ;
}
else {
for ( int k1 = 0 ; k1 < u - > where - > type ; k1 + + )
for ( int l1 = 0 ; l1 < u - > where - > type ; l1 + + ) {
auto ukl = gen_adj ( uk , l1 ) ;
auto ulk = gen_adj ( ul , k1 ) ;
2021-03-25 09:36:07 +00:00
if ( ukl - > where = = ulk - > where & & ukl - > state ! = 0 & &
eqmatrix ( adj ( u , k ) * adj ( uk , l1 ) , adj ( u , l ) * adj ( ul , k1 ) )
)
2021-03-21 09:46:50 +00:00
funion ( ukl , ulk ) ;
if ( base = = gCell600 & & isNeighbor ( ukl - > where - > c7 , ulk - > where - > c7 ) & & ukl - > state ! = 0 & & ulk - > state ! = 0 )
funion ( ukl , ulk ) ;
if ( base = = gCell600 & & ulk - > nowall ( ) & & ukl - > iswall ( ) ) {
for ( int m1 = 0 ; m1 < u - > where - > type ; m1 + + ) {
auto ulkm = gen_adj ( ulk , m1 ) ;
if ( ulkm - > where = = ukl - > where ) funion ( ulkm , ukl ) ;
}
}
}
}
2021-02-19 01:37:03 +00:00
}
/* flat areas */
2021-06-25 11:54:17 +00:00
# if CAP_SOLV
2021-03-25 09:36:07 +00:00
if ( ! asonov : : in ( ) )
2021-06-25 11:54:17 +00:00
# endif
2021-03-21 09:46:50 +00:00
for ( int k = 0 ; k < u - > where - > type ; k + + )
for ( int l = 0 ; l < u - > where - > type ; l + + ) {
2021-02-18 15:16:11 +00:00
auto uk = gen_adj ( u , k ) ;
if ( uk - > state ! = 0 ) continue ;
auto ul = gen_adj ( u , l ) ;
2021-03-21 10:08:10 +00:00
if ( ul - > nowall ( ) ) continue ;
2021-02-18 15:16:11 +00:00
auto ukl = gen_adj ( uk , l ) ;
2021-03-21 10:08:10 +00:00
if ( ukl - > nowall ( ) ) continue ;
2021-02-18 15:16:11 +00:00
funion ( ul , ukl ) ;
}
2021-02-19 01:37:03 +00:00
/* concave corners */
2021-03-21 09:46:50 +00:00
for ( int k = 0 ; k < u - > where - > type ; k + + )
for ( int l = 0 ; l < u - > where - > type ; l + + )
if ( adjacent_face ( u , k , l ) ) {
2021-02-18 15:16:11 +00:00
auto uk = gen_adj ( u , k ) ;
2021-03-21 10:08:10 +00:00
if ( uk - > nowall ( ) ) continue ;
2021-02-18 15:16:11 +00:00
auto ul = gen_adj ( u , l ) ;
2021-03-21 10:08:10 +00:00
if ( ul - > nowall ( ) ) continue ;
2021-03-21 09:46:50 +00:00
funion ( ul , uk ) ;
2021-02-19 01:37:03 +00:00
}
2021-03-21 09:46:50 +00:00
if ( base = = gCell600 )
for ( int k = 0 ; k < u - > where - > type ; k + + )
for ( int l = 0 ; l < u - > where - > type ; l + + )
if ( adjacent_face ( u , k , l ) ) {
auto uk = gen_adj ( u , k ) ;
if ( uk - > nowall ( ) ) continue ;
auto ul = gen_adj ( u , l ) ;
if ( ul - > iswall ( ) ) continue ;
for ( int m = 0 ; m < u - > where - > type ; m + + )
if ( adjacent_matrix ( adj ( u , k ) , adj ( u , l ) * adj ( ul , m ) ) ) {
auto um = gen_adj ( ul , m ) ;
if ( um - > nowall ( ) ) continue ;
funion ( um , uk ) ;
}
}
2021-02-18 15:16:11 +00:00
}
/* statistics */
int lives = 0 , walls = 0 , overflow = 0 , merged = 0 ;
for ( auto v : all ) {
if ( v - > state = = 0 ) lives + + ;
2021-03-21 10:08:10 +00:00
if ( v - > iswall ( ) ) walls + + ;
if ( v - > ismerged ( ) ) merged + + ;
if ( v - > isover ( ) ) overflow + + ;
2021-02-18 15:16:11 +00:00
}
set < heptagon * > wheres ;
println ( hlog , " lives = " , lives ) ;
println ( hlog , " walls = " , walls ) ;
println ( hlog , " merged = " , merged ) ;
println ( hlog , " overflow = " , overflow ) ;
println ( hlog , " total = " , isize ( all ) ) ;
/* create the result map */
for ( int i = 0 ; i < isize ( all ) ; i + + ) {
auto u = all [ i ] ;
2021-03-21 10:08:10 +00:00
if ( u - > ismerged ( ) ) continue ;
2021-02-18 15:16:11 +00:00
if ( u - > state = = 0 ) wheres . insert ( all [ i ] - > where ) ;
2021-03-21 10:08:10 +00:00
u - > result = tailored_alloc < heptagon > ( S7 ) ;
2021-02-18 15:16:11 +00:00
u - > result - > c7 = newCell ( S7 , u - > result ) ;
2021-03-21 09:46:50 +00:00
indices [ u - > result ] = i ;
2021-02-18 15:16:11 +00:00
}
println ( hlog , " wheres = " , isize ( wheres ) , " : " , lives * 1. / isize ( wheres ) ) ;
for ( int i = 0 ; i < isize ( all ) ; i + + ) {
auto u = all [ i ] ;
2021-03-21 10:08:10 +00:00
if ( u - > ismerged ( ) ) continue ;
2021-02-18 15:16:11 +00:00
for ( int d = 0 ; d < S7 ; d + + ) {
cmov ( u - > where , d ) ;
auto d1 = u - > where - > c . spin ( d ) ;
2021-03-21 10:08:10 +00:00
if ( u - > ptr [ d ] & & u - > ptr [ d ] - > result = = nullptr )
2021-03-21 21:56:38 +00:00
throw hr_exception ( lalign ( 0 , " connection to null in state " , u - > ptr [ d ] - > state , " from state " , u - > state , " i= " , i , " .. " , u - > ptr [ d ] - > index ) ) ;
2021-02-18 15:16:11 +00:00
if ( u - > ptr [ d ] & & u - > ptr [ d ] - > ptr [ d1 ] ! = u )
2021-03-21 21:56:38 +00:00
throw hr_exception ( " wrong connection " ) ;
2021-02-18 15:16:11 +00:00
if ( u - > ptr [ d ] )
u - > result - > c . connect ( d , u - > ptr [ d ] - > result , d1 , false ) ;
else
2021-04-04 12:25:21 +00:00
u - > result - > c . connect ( d , u - > result , d , false ) ;
2021-02-18 15:16:11 +00:00
}
}
for ( int k = 0 ; k < 23 ; k + + ) hrand ( 5 ) ;
2021-02-19 01:37:03 +00:00
int colors_used = 0 ;
for ( int i = 0 ; i < isize ( all ) ; i + + )
all [ i ] - > wallcolor = 0 ;
2021-02-18 15:16:11 +00:00
for ( int i = 0 ; i < isize ( all ) ; i + + )
2021-03-21 10:08:10 +00:00
if ( all [ i ] - > iswall ( ) & & ! all [ i ] - > ismerged ( ) )
2021-02-19 01:37:03 +00:00
ufind ( all [ i ] ) - > wallcolor + + ;
map < int , int > sizes ;
for ( int i = 0 ; i < isize ( all ) ; i + + )
2021-03-21 10:08:10 +00:00
if ( all [ i ] - > iswall ( ) & & ufind ( all [ i ] ) = = all [ i ] & & all [ i ] - > wallcolor )
2021-02-19 01:37:03 +00:00
colors_used + + ,
sizes [ all [ i ] - > wallcolor ] + + ;
2021-03-21 10:08:10 +00:00
2021-02-19 01:37:03 +00:00
for ( auto p : sizes )
println ( hlog , " size = " , p . first , " times " , p . second ) ;
2021-03-21 10:08:10 +00:00
2021-02-19 01:37:03 +00:00
println ( hlog , " colors_used = " , colors_used ) ;
2021-03-21 10:08:10 +00:00
2021-02-23 03:56:23 +00:00
if ( first & & self_hiding ) {
ucover * what = nullptr ;
for ( int i = 0 ; i < isize ( all ) ; i + + )
2021-03-21 10:08:10 +00:00
if ( all [ i ] - > iswall ( ) & & all [ i ] - > tohide ( ) & & ! all [ i ] - > ismerged ( ) )
2021-02-23 03:56:23 +00:00
what = ufind ( all [ i ] ) ;
for ( int i = 0 ; i < isize ( all ) ; i + + )
2021-03-21 10:08:10 +00:00
if ( all [ i ] - > iswall ( ) & & ufind ( all [ i ] ) = = what )
2021-02-23 03:56:23 +00:00
all [ i ] - > state & = ~ 9 ;
println ( hlog , " removed one knot! " ) ;
2021-03-21 09:46:50 +00:00
first = false ; i = 0 ; remove_marked_walls = true ;
2021-02-23 03:56:23 +00:00
goto back ;
}
2021-02-19 01:37:03 +00:00
for ( int i = 0 ; i < isize ( all ) ; i + + )
2021-03-31 08:55:16 +00:00
if ( all [ i ] - > iswall ( ) & & ufind ( all [ i ] ) = = all [ i ] & & all [ i ] - > wallcolor ) {
2021-02-18 15:16:11 +00:00
all [ i ] - > wallcolor = hrand ( 0x1000000 ) | 0x404040 ,
all [ i ] - > wallcolor2 = hrand ( 0x1000000 ) | 0x404040 ;
2021-02-19 01:37:03 +00:00
}
2021-03-21 09:46:50 +00:00
for ( int i = 0 ; i < isize ( all ) ; i + + )
if ( ( all [ i ] - > where - > zebraval & 32 ) & & ufind ( all [ i ] ) = = all [ i ] ) {
auto & w = all [ i ] - > wallcolor ;
all [ i ] - > wallcolor = ( hrand ( 0x1000000 ) < < 8 ) | 0x01 ;
switch ( hrand ( 6 ) ) {
case 0 : w | = 0xFF000000 ; break ;
case 1 : w | = 0x00FF0000 ; break ;
case 2 : w | = 0x0000FF00 ; break ;
case 3 : w | = 0xC0C00000 ; break ;
case 4 : w | = 0x00C0C000 ; break ;
case 5 : w | = 0xC000C000 ; break ;
}
}
2021-02-18 15:16:11 +00:00
for ( int i = 0 ; i < isize ( all ) ; i + + ) {
auto u = all [ i ] ;
if ( ! u - > result ) continue ;
cell * c = u - > result - > c7 ;
setdist ( c , 7 , c ) ;
c - > land = laCanvas ;
2021-03-21 10:08:10 +00:00
if ( u - > iswall ( ) ) {
2021-02-18 15:16:11 +00:00
c - > wall = waWaxWall ;
2021-03-21 09:46:50 +00:00
c - > landparam = hrand ( 100 ) < secondary_percentage ? ufind ( u ) - > wallcolor2 : ufind ( u ) - > wallcolor ;
2021-03-21 10:08:10 +00:00
if ( ufind ( u ) - > nowall ( ) ) println ( hlog , " connected to state " , ufind ( u ) - > state ) ;
2021-02-19 01:37:03 +00:00
// if(!(c->landparam & 0x404040)) println(hlog, "color found ", c->landparam);
2021-02-18 15:16:11 +00:00
}
2021-03-21 10:08:10 +00:00
else if ( u - > isover ( ) )
2021-02-18 15:16:11 +00:00
c - > wall = waBigTree ;
else
c - > wall = waNone ;
2021-03-21 09:46:50 +00:00
if ( all [ i ] - > where - > zebraval & 32 )
ray : : volumetric : : vmap [ c ] = ufind ( u ) - > wallcolor ^ ( ( hrand ( 0x1000000 ) & 0x3F3F3F ) < < 8 ) ;
else
ray : : volumetric : : vmap [ c ] = 0x00000001 ;
}
2021-03-21 21:56:38 +00:00
} catch ( const hr_exception & s ) {
println ( hlog , " exception: " , s . what ( ) ) ;
2021-03-21 09:46:50 +00:00
throw ;
}
}
void add_fog ( ) {
int id = 0 ;
map < cell * , pair < int , int > > dist ;
vector < cell * > lst ;
auto color = [ & ] ( cell * c , color_t col , int d ) {
if ( ! dist . count ( c ) ) dist [ c ] = { d , 0 } ;
auto & p = dist [ c ] ;
if ( p . first = = d ) {
if ( ! p . second ) lst . push_back ( c ) ;
p . second + + ;
auto & vm = ray : : volumetric : : vmap [ c ] ;
if ( p . second = = 1 ) vm = col ;
else vm = gradient ( vm , col , 0 , 1 , p . second ) ;
}
} ;
2021-03-25 10:18:13 +00:00
int qty = 0 ;
2021-03-21 09:46:50 +00:00
for ( int i = 0 ; i < isize ( all ) ; i + + )
if ( all [ i ] - > result )
2021-03-25 10:18:13 +00:00
if ( all [ i ] - > where - > c7 - > wall = = waFloorA )
qty + + ;
for ( int i = 0 ; i < isize ( all ) ; i + + )
if ( all [ i ] - > result )
if ( all [ i ] - > where - > c7 - > wall = = waFloorA ) {
cell * c = all [ i ] - > result - > c7 ;
if ( dist . count ( c ) ) continue ;
2022-04-21 10:35:18 +00:00
int idd = ( id + + ) ;
2021-03-25 10:18:13 +00:00
color_t col = rainbow_color ( 1 , idd * 1. / qty ) ;
col < < = 8 ; col | = 1 ;
2022-04-21 10:35:18 +00:00
color ( c , col , 0 ) ;
2021-03-25 10:18:13 +00:00
}
2021-03-21 09:46:50 +00:00
for ( int i = 0 ; i < isize ( lst ) ; i + + ) {
auto c = lst [ i ] ;
auto col = ray : : volumetric : : vmap [ c ] ;
int d = dist [ c ] . first ;
forCellCM ( c1 , c )
if ( c1 - > wall = = waNone )
color ( c1 , col , d + 1 ) ;
}
for ( int i = 0 ; i < isize ( lst ) ; i + + ) {
auto c = lst [ i ] ;
ray : : volumetric : : vmap [ c ] ^ = ( ( hrand ( 0x1000000 ) & 0x3F3F3F ) < < 8 ) ;
2021-02-18 15:16:11 +00:00
}
2021-03-21 09:46:50 +00:00
ray : : volumetric : : enable ( ) ;
2021-02-18 15:16:11 +00:00
}
2021-07-12 13:20:04 +00:00
transmatrix relative_matrixh ( heptagon * h2 , heptagon * h1 , const hyperpoint & hint ) override {
2021-02-18 15:16:11 +00:00
return Id ;
}
transmatrix adj ( heptagon * h , int i ) override {
2021-03-21 09:46:50 +00:00
return adj ( all [ indices [ h ] ] , i ) ;
}
transmatrix adj ( cell * c , int i ) override {
return adj ( c - > master , i ) ;
2021-02-18 15:16:11 +00:00
}
2021-02-23 04:22:22 +00:00
~ hrmap_notknot ( ) {
for ( auto uc : all ) {
if ( uc & & uc - > result ) {
tailored_delete ( uc - > result - > c7 ) ;
tailored_delete ( uc - > result ) ;
}
if ( uc ) delete uc ;
}
delete euc ;
}
2021-02-18 15:16:11 +00:00
} ;
auto h = addHook ( hooks_newmap , 0 , [ ] {
// gen_trifoil();
if ( geometry = = gNotKnot ) {
return ( hrmap * ) new hrmap_notknot ;
}
return ( hrmap * ) nullptr ;
} ) ;
void create_notknot ( ) {
2021-03-21 11:47:32 +00:00
if ( true ) {
dynamicval < eGeometry > b ( geometry , base ) ;
2022-08-13 20:45:10 +00:00
dynamicval < eVariation > bv ( variation , eVariation : : pure ) ;
2021-03-21 11:47:32 +00:00
check_cgi ( ) ;
cgi . require_basics ( ) ;
cgi . require_shapes ( ) ;
cgi . require_usershapes ( ) ;
}
2021-03-21 09:46:50 +00:00
if ( gNotKnot = = eGeometry ( - 1 ) ) {
ginf . push_back ( ginf [ base ] ) ;
gNotKnot = eGeometry ( isize ( ginf ) - 1 ) ;
}
else ginf [ gNotKnot ] = ginf [ base ] ;
2021-02-18 15:16:11 +00:00
auto & gi = ginf . back ( ) ;
2022-05-21 11:08:42 +00:00
gi . flags | = qANYQ | qCLOSED | qEXPERIMENTAL | qPORTALSPACE ;
2021-02-18 15:16:11 +00:00
gi . quotient_name = " notknot " ;
gi . shortname = " notknot " ;
gi . menu_displayed_name = " notknot " ;
}
2021-02-23 03:56:53 +00:00
void regenerate ( ) {
if ( geometry = = gNotKnot & & game_active ) {
stop_game ( ) ;
start_game ( ) ;
}
}
2021-02-23 04:22:22 +00:00
2021-03-21 11:47:32 +00:00
bool show_selfhiding = true ;
2021-03-31 13:19:03 +00:00
void launch_euc ( ) {
stop_game ( ) ;
set_geometry ( gCubeTiling ) ;
base = gCubeTiling ;
base_map = " " ;
to_unloop . clear ( ) ;
create_notknot ( ) ;
loop = 3 ;
secondary_percentage = 10 ;
show_selfhiding = true ;
set_geometry ( gNotKnot ) ;
start_game ( ) ;
ray : : reset_raycaster ( ) ;
ray : : volumetric : : on = false ;
ray : : exp_decay_poly = 30 ;
pmodel = mdPerspective ;
}
void launch_nil ( ) {
stop_game ( ) ;
set_geometry ( gNil ) ;
base_map = " " ;
base = geometry ;
to_unloop . clear ( ) ;
secondary_percentage = 0 ;
nilv : : nilwidth = .25 ;
nilv : : nilperiod = make_array ( 8 , 8 , 8 ) ;
nilv : : set_flags ( ) ;
create_notknot ( ) ;
show_selfhiding = false ;
loop = 6 ;
set_geometry ( gNotKnot ) ;
start_game ( ) ;
ray : : reset_raycaster ( ) ;
ray : : volumetric : : on = true ;
ray : : exp_decay_poly = 3 ;
camera_speed = 1 ;
pmodel = mdGeodesic ;
}
void launch_sphere ( ) {
stop_game ( ) ;
set_geometry ( gCell120 ) ;
base_map = " spherring.lev " ;
to_unloop . clear ( ) ;
vector < int > v ; for ( int i = 0 ; i < 60 ; i + + ) v . push_back ( 7 ) ;
to_unloop . emplace_back ( v ) ;
show_selfhiding = true ;
secondary_percentage = 0 ;
loop = 0 ;
set_geometry ( gNotKnot ) ;
start_game ( ) ;
ray : : reset_raycaster ( ) ;
ray : : volumetric : : on = false ;
ray : : exp_decay_poly = 10 ;
camera_speed = 1 ;
mapeditor : : drawplayer = false ;
pmodel = mdPerspective ;
( ( hrmap_notknot * ) currentmap ) - > add_fog ( ) ;
}
void launch_sphereknot ( ) {
stop_game ( ) ;
set_geometry ( gCell600 ) ;
base_map = " spherknot.lev " ;
to_unloop . clear ( ) ;
secondary_percentage = 0 ;
show_selfhiding = true ;
loop = 3 ;
set_geometry ( gNotKnot ) ;
start_game ( ) ;
ray : : reset_raycaster ( ) ;
ray : : volumetric : : on = false ;
ray : : exp_decay_poly = 10 ;
camera_speed = 1 ;
mapeditor : : drawplayer = false ;
pmodel = mdPerspective ;
( ( hrmap_notknot * ) currentmap ) - > add_fog ( ) ;
}
2021-06-25 11:54:17 +00:00
# if CAP_SOLV
2021-03-31 13:19:03 +00:00
void launch_solv ( ) {
stop_game ( ) ;
set_geometry ( gArnoldCat ) ;
base_map = " " ;
base = geometry ;
to_unloop . clear ( ) ;
secondary_percentage = 0 ;
vid . binary_width = .25 ;
margin = 3 ;
asonov : : period_xy = 8 ;
asonov : : period_z = 3 ;
loop = 6 ;
asonov : : set_flags ( ) ;
create_notknot ( ) ;
show_selfhiding = false ;
set_geometry ( gNotKnot ) ;
start_game ( ) ;
ray : : reset_raycaster ( ) ;
ray : : exp_decay_poly = 10 ;
camera_speed = 1 ;
pmodel = mdGeodesic ;
( ( hrmap_notknot * ) currentmap ) - > add_fog ( ) ;
}
2021-06-25 11:54:17 +00:00
# endif
2021-03-31 13:19:03 +00:00
2021-02-23 04:22:22 +00:00
void show ( ) {
cmode = sm : : SIDE | sm : : MAYDARK ;
2022-07-05 14:03:12 +00:00
gamescreen ( ) ;
2021-02-23 04:22:22 +00:00
dialog : : init ( XLAT ( " notknot " ) , 0xFFFFFFFF , 150 , 0 ) ;
2021-03-21 11:47:32 +00:00
dialog : : addItem ( " available scenes " , ' a ' ) ;
dialog : : add_action_push ( [ ] {
cmode = sm : : SIDE | sm : : MAYDARK ;
2022-07-05 14:03:12 +00:00
gamescreen ( ) ;
2021-03-21 11:47:32 +00:00
dialog : : init ( XLAT ( " notknot scenes " ) , 0xFFFFFFFF , 150 , 0 ) ;
dialog : : addItem ( " knot portal in Euclidean geometry " , ' a ' ) ;
2021-03-31 13:19:03 +00:00
dialog : : add_action ( launch_euc ) ;
2021-03-21 11:47:32 +00:00
dialog : : addItem ( " Penrose staircase portal in Nil geometry " , ' b ' ) ;
2021-03-31 13:19:03 +00:00
dialog : : add_action ( launch_nil ) ;
2021-03-21 11:47:32 +00:00
dialog : : addItem ( " great circle portal in spherical geometry " , ' c ' ) ;
2021-03-31 13:19:03 +00:00
dialog : : add_action ( launch_sphere ) ;
2021-03-21 11:47:32 +00:00
dialog : : addItem ( " knotted portal in spherical geometry " , ' d ' ) ;
2021-03-31 13:19:03 +00:00
dialog : : add_action ( launch_sphereknot ) ;
2021-03-21 11:47:32 +00:00
2021-06-25 11:54:17 +00:00
# if CAP_SOLV
2021-03-25 11:40:04 +00:00
dialog : : addItem ( " a portal in Solv geometry " , ' e ' ) ;
2021-03-31 13:19:03 +00:00
dialog : : add_action ( launch_solv ) ;
2021-06-25 11:54:17 +00:00
# endif
2021-03-25 11:40:04 +00:00
2021-03-21 11:47:32 +00:00
dialog : : display ( ) ;
} ) ;
if ( loop ) add_edit ( loop ) ;
if ( base = = gCubeTiling & & base_map = = " " ) {
add_edit ( margin ) ;
add_edit ( knotsize ) ;
}
if ( show_selfhiding ) add_edit ( self_hiding ) ;
if ( nil ) menuitem_nilwidth ( ' w ' ) ;
2021-03-25 11:40:04 +00:00
if ( sol ) menuitem_binary_width ( ' w ' ) ;
2021-03-21 11:47:32 +00:00
if ( base ! = gCubeTiling ) {
dialog : : addBoolItem ( " fog enabled " , ray : : volumetric : : on , ' f ' ) ;
dialog : : add_action ( [ ] {
ray : : volumetric : : on = ! ray : : volumetric : : on ;
ray : : reset_raycaster ( ) ;
if ( sphere & & ray : : volumetric : : on )
( ( hrmap_notknot * ) currentmap ) - > add_fog ( ) ;
} ) ;
}
2021-02-23 04:22:22 +00:00
dialog : : addBreak ( 100 ) ;
dialog : : addItem ( XLAT ( " configure raycasting " ) , ' A ' ) ;
dialog : : add_action_push ( ray : : configure ) ;
2021-03-21 11:47:32 +00:00
add_edit_fov ( ' f ' ) ;
2021-02-23 04:22:22 +00:00
# if CAP_VR
dialog : : addBoolItem ( XLAT ( " VR settings " ) , vrhr : : active ( ) , ' v ' ) ;
dialog : : add_action_push ( vrhr : : show_vr_settings ) ;
# endif
dialog : : addBack ( ) ;
dialog : : display ( ) ;
}
void o_key ( o_funcs & v ) {
if ( geometry = = gNotKnot ) v . push_back ( named_dialog ( " notknot " , show ) ) ;
}
2021-03-21 09:46:50 +00:00
2021-03-21 10:09:19 +00:00
bool do_check_cycle ;
2021-03-21 09:46:50 +00:00
cell * startcell , * current ;
vector < int > dirs ;
void check_cycle ( ) {
2021-03-21 10:09:19 +00:00
if ( ! do_check_cycle ) return ;
2021-03-21 09:46:50 +00:00
if ( ! current ) {
auto s = currentmap - > allcells ( ) [ 0 ] ;
println ( hlog , " starting the cycle, " , cwt . at = = s ) ;
startcell = current = cwt . at = s ;
}
if ( cwt . at ! = current ) {
forCellIdEx ( c1 , i , current )
if ( c1 = = cwt . at ) {
dirs . push_back ( i ) ;
current = cwt . at ;
startcell - > item = itGold ;
println ( hlog , " dirs = " , dirs , " finished = " , startcell = = current ) ;
2021-03-21 10:09:19 +00:00
string dirstr ;
for ( int d : dirs )
if ( d < 10 )
dirstr + = char ( ' 0 ' + d ) ;
else
dirstr + = char ( ' a ' + d - 10 ) ;
addMessage ( " this loop can be identified with identity using: -nk-unloop 1 " + dirstr ) ;
2021-03-21 09:46:50 +00:00
}
}
}
void gen_knot ( ) {
for ( cell * c : currentmap - > allcells ( ) )
c - > wall = waNone ;
cell * last = nullptr ;
2021-02-18 15:16:11 +00:00
2021-03-21 09:46:50 +00:00
for ( int i = 0 ; i < 3600 ; i + + ) {
ld alpha = i * degree / 10 ;
ld q = sqrt ( 2 ) / 2 ;
hyperpoint h = hyperpoint ( q * cos ( alpha * 2 ) , q * sin ( alpha * 2 ) , q * cos ( alpha * 3 ) , q * sin ( alpha * 3 ) ) ;
cell * b = currentmap - > gamestart ( ) ;
virtualRebase ( b , h ) ;
b - > wall = waPlatform ;
if ( b ! = last ) {
if ( ! last ) println ( hlog , " start at " , b ) ;
if ( last ) println ( hlog , " i= " , i , " : to " , b , " isN = " , isNeighbor ( last , b ) ) ;
last = b ;
}
}
}
2021-03-21 11:47:32 +00:00
void nk_launch ( ) {
margin = 4 ;
mapeditor : : drawplayer = false ;
stop_game ( ) ;
2021-09-30 08:49:12 +00:00
enable_canvas ( ) ;
2021-03-21 11:47:32 +00:00
set_geometry ( gNotKnot ) ;
sightranges [ geometry ] = .5 ;
ray : : max_cells = 600000 ;
smooth_scrolling = 1 ;
2022-08-05 18:34:56 +00:00
game_keys_scroll = true ;
2021-03-21 11:47:32 +00:00
camera_speed = 10 ;
// panini_alpha = 1;
// fov = 150;
ray : : exp_decay_poly = 30 ;
ray : : fixed_map = true ;
ray : : max_iter_iso = 80 ;
showstartmenu = false ;
# if CAP_VR
vrhr : : hsm = vrhr : : eHeadset : : holonomy ;
vrhr : : eyes = vrhr : : eEyes : : truesim ;
vrhr : : cscr = vrhr : : eCompScreen : : eyes ;
vrhr : : absolute_unit_in_meters = 0.2 ;
# endif
}
2022-02-27 13:53:22 +00:00
void portal_slideshow ( tour : : ss : : slideshow_callback cb ) {
using namespace rogueviz : : pres ;
using namespace tour ;
static vector < slide > portal_slides ;
if ( portal_slides . empty ( ) ) {
portal_slides . emplace_back ( slide { " portal collection " , 100 , LEGAL : : NONE | QUICKSKIP ,
" This is a collection of portals. We start with knotted portals in Euclidean geometry, "
" then we visit portals in other geometries, and finally, we explore portals between different "
" geometries. \n \n Loading these may take some time, so you need to press 'r' to run them. In most slides you can also press '5' to change various parameters. " ,
[ ] ( presmode mode ) { }
} ) ;
auto add = [ & ] ( string s , string text , string youtube , reaction_t act ) {
portal_slides . emplace_back (
2022-08-12 07:09:38 +00:00
tour : : slide { s , 100 , LEGAL : : NONE | QUICKGEO | QUICKSKIP | ALWAYS_TEXT , text ,
2022-02-27 13:53:22 +00:00
[ = ] ( presmode mode ) {
setCanvas ( mode , ' 0 ' ) ;
if ( youtube ! = " " )
slide_url ( mode , ' y ' , " YouTube link " , youtube ) ;
2022-08-05 18:34:56 +00:00
non_game_slide_scroll ( mode ) ;
2022-02-27 13:53:22 +00:00
slide_action ( mode , ' r ' , " run " , [ = ] {
slide_backup ( margin ) ;
slide_backup ( mapeditor : : drawplayer ) ;
slide_backup ( firstland ) ;
slide_backup ( specialland ) ;
slide_backup ( ray : : max_cells , 600000 ) ;
slide_backup ( camera_speed , 10 ) ;
slide_backup ( ray : : exp_decay_poly , 30 ) ;
slide_backup ( ray : : fixed_map , true ) ;
slide_backup ( ray : : max_iter_iso , 80 ) ;
2022-03-01 07:45:21 +00:00
slide_backup ( vid . cells_drawn_limit , 100 ) ;
# if CAP_VR
2022-02-27 13:53:22 +00:00
slide_backup ( vrhr : : hsm ) ;
slide_backup ( vrhr : : eyes ) ;
slide_backup ( vrhr : : cscr ) ;
slide_backup ( vrhr : : absolute_unit_in_meters ) ;
# endif
on_restore ( [ ] { nilv : : set_flags ( ) ; asonov : : set_flags ( ) ; } ) ;
slide_backup ( nilv : : nilwidth ) ;
slide_backup ( nilv : : nilperiod ) ;
slide_backup ( vid . binary_width ) ;
slide_backup ( asonov : : period_xy ) ;
slide_backup ( asonov : : period_z ) ;
act ( ) ;
start_game ( ) ;
loop = 2 ;
2022-08-07 13:44:49 +00:00
popScreenAll ( ) ;
2022-02-27 13:53:22 +00:00
} ) ;
2022-03-01 08:32:39 +00:00
slidecommand = " notknot options " ;
2022-02-27 13:53:22 +00:00
if ( mode = = tour : : pmKey ) pushScreen ( show ) ;
} } ) ;
} ;
auto launch_euc_with = [ ] ( bool b ) {
return [ b ] {
self_hiding = b ;
launch_euc ( ) ;
} ;
} ;
add ( " knotted portal " , " This is a knotted portal in Euclidean space. " , " https://www.youtube.com/watch?v=eb2DhCcGH7U " , launch_euc_with ( false ) ) ;
add ( " self-hiding portal " , " This knotted portal is 'self-hiding'. It appears that the portal enters itself and disappears! " , " https://www.youtube.com/watch?v=vFLZ2NGtuGw " , launch_euc_with ( true ) ) ;
add ( " non-Euclidean portal in Nil " , " A portal in Nil geometry. " , " https://www.youtube.com/watch?v=2K-v8tK68AE " , launch_nil ) ;
2022-08-07 13:44:49 +00:00
add ( " spherical portal " , " A portal in spherical geometry. Such a portal lets us create a space with spherical geometry that has more volume than the sphere. " , " https://www.youtube.com/watch?v=PerPeQFu5gw " , launch_sphere ) ;
2022-08-12 07:09:38 +00:00
add ( " knotted spherical portal " , " A knotted portal in spherical geometry. " , " https://www.youtube.com/watch?v=PerPeQFu5gw " , launch_sphereknot ) ;
2022-02-27 13:53:22 +00:00
add ( " Cat Portal in Solv " , " A portal in Solv geometry. The honeycomb is based on the mapping torus of Arnold's cat mapping. " , " https://www.youtube.com/watch?v=CGiSxC9B6i0 " , launch_solv ) ;
callhooks ( rogueviz : : pres : : hooks_build_rvtour , " portal " , portal_slides ) ;
add_end ( portal_slides ) ;
}
cb ( XLAT ( " portal collection " ) , & portal_slides [ 0 ] , ' p ' ) ;
}
2021-02-19 13:42:39 +00:00
auto shot_hooks = addHook ( hooks_initialize , 100 , create_notknot )
2021-02-23 04:22:22 +00:00
+ addHook ( hooks_welcome_message , 100 , [ ] {
if ( geometry = = gNotKnot ) {
addMessage ( " Welcome to Notknot! Press 'o' for options " ) ;
return true ;
}
return false ;
} )
2021-03-21 09:46:50 +00:00
+ addHook ( hooks_args , 100 , [ ] {
using namespace arg ;
if ( 0 ) ;
else if ( argis ( " -nkbase " ) ) {
base = geometry ;
create_notknot ( ) ;
}
else if ( argis ( " -nkbasemap " ) ) {
shift ( ) ; base_map = args ( ) ;
set_geometry ( gNotKnot ) ;
}
else if ( argis ( " -nk-volumetric " ) ) {
start_game ( ) ;
( ( hrmap_notknot * ) currentmap ) - > add_fog ( ) ;
}
else if ( argis ( " -nk-genknot " ) ) {
start_game ( ) ;
gen_knot ( ) ;
}
2022-04-21 10:36:03 +00:00
else if ( argis ( " -nk-solv " ) )
launch_solv ( ) ;
2021-03-21 10:09:19 +00:00
else if ( argis ( " -nk-findloop " ) ) {
do_check_cycle = true ;
}
2021-03-21 09:46:50 +00:00
else if ( argis ( " -nk-unloop " ) ) {
shift ( ) ;
int copies = argi ( ) ;
shift ( ) ;
vector < int > v ;
for ( int i = 0 ; i < copies ; i + + )
for ( char c : args ( ) )
if ( c > = ' 0 ' & & c < = ' 9 ' ) v . push_back ( c - ' 0 ' ) ;
else v . push_back ( c - ' a ' + 10 ) ;
to_unloop . push_back ( v ) ;
println ( hlog , " pushed to to_unloop: " , v ) ;
}
2021-03-21 11:47:32 +00:00
else if ( argis ( " -nk-launch " ) )
nk_launch ( ) ;
2021-03-21 09:46:50 +00:00
else return 1 ;
return 0 ;
} )
2021-02-23 04:22:22 +00:00
+ addHook ( hooks_o_key , 80 , o_key )
2021-03-21 09:46:50 +00:00
+ addHook ( hooks_frame , 100 , check_cycle )
2021-03-21 10:35:11 +00:00
+ addHook ( hooks_cgi_string , 100 , [ ] ( string & s ) {
if ( geometry = = gNotKnot ) {
s + = " base: " ;
dynamicval < eGeometry > b ( geometry , base ) ;
s + = cgi_string ( ) ;
}
} )
2021-02-19 13:42:39 +00:00
+ addHook ( hooks_configfile , 100 , [ ] {
2021-02-23 04:22:22 +00:00
param_i ( loop , " nk_loop " )
- > editable ( 1 , 5 , 1 , " notknot order " , " How many times do we need to go around the knot to get back. " , ' o ' )
- > set_sets ( [ ] { dialog : : bound_low ( 1 ) ; dialog : : bound_up ( 5 ) ; } )
- > set_reaction ( regenerate ) ;
param_i ( margin , " nk_margin " )
- > editable ( 0 , 10 , 1 , " notknot margins " , " Empty space close to the walls. " , ' m ' )
- > set_sets ( [ ] { dialog : : bound_low ( 0 ) ; dialog : : bound_up ( 10 ) ; } )
- > set_reaction ( regenerate ) ;
param_i ( knotsize , " nk_knotsize " )
- > editable ( 0 , 10 , 1 , " notknot size " , " Size of the knot. " , ' s ' )
- > set_sets ( [ ] { dialog : : bound_low ( 2 ) ; dialog : : bound_up ( 5 ) ; } )
- > set_reaction ( regenerate ) ;
2021-02-23 03:56:53 +00:00
param_i ( terminate_at , " nk_terminate " ) - > set_reaction ( regenerate ) ;
2021-03-21 09:46:50 +00:00
param_i ( secondary_percentage , " nk_secondary " ) ;
2021-02-23 04:22:22 +00:00
param_b ( self_hiding , " selfhide " )
- > editable ( " self-hiding knot " , ' h ' )
- > set_reaction ( regenerate ) ;
2021-03-21 09:46:50 +00:00
param_i ( loop_any , " nk_loopany " ) ;
2021-03-31 13:19:13 +00:00
} )
# ifndef NOTKNOT
2022-02-27 13:53:22 +00:00
+ addHook_slideshows ( 120 , portal_slideshow )
2021-03-31 13:19:13 +00:00
# endif
2022-02-27 13:53:22 +00:00
;
2021-02-19 13:42:39 +00:00
2021-02-23 04:22:22 +00:00
# ifdef NOTKNOT
auto hook1 =
addHook ( hooks_config , 100 , [ ] {
if ( arg : : curphase = = 1 )
conffile = " notknot.ini " ;
2021-03-21 11:47:32 +00:00
if ( arg : : curphase = = 2 )
nk_launch ( ) ;
2021-02-23 04:22:22 +00:00
} ) ;
# endif
2021-02-19 13:42:39 +00:00
}
2021-02-18 15:16:11 +00:00
}
2021-06-25 11:54:17 +00:00
# endif