2021-03-30 21:09:26 +00:00
# include "rogueviz.h"
namespace rogueviz {
namespace magic { void magic ( int i ) ; }
namespace colorpicker {
int current_step ;
color_t current_color ;
cell * current_center ;
color_t get_color_at ( cell * c ) {
crystal : : coord oldc = crystal : : get_coord ( current_center - > master ) ;
crystal : : coord newc = crystal : : get_coord ( c - > master ) ;
color_t res ;
for ( int i = 0 ; i < 3 ; i + + ) {
int val = part ( current_color , 2 - i ) + current_step * ( ( newc [ i ] - oldc [ i ] ) / 2 ) ;
if ( val < 0 ) val = 0 ;
if ( val > 255 ) val = 255 ;
part ( res , 2 - i ) = val ;
}
return res ;
}
bool color_markers ( cell * c , const shiftmatrix & V ) {
if ( ! centerover ) return false ;
if ( centerover ! = current_center ) {
current_color = get_color_at ( centerover ) ;
current_center = centerover ;
}
c - > landparam = get_color_at ( c ) ;
return false ;
}
bool color_key ( int sym , int uni ) {
2021-03-30 23:07:27 +00:00
if ( ( cmode & sm : : NORMAL ) & & ( uni > = ' 0 ' & & uni < = ' 6 ' ) ) {
2021-03-30 21:09:26 +00:00
current_step = ( 1 < < ( uni - ' 0 ' ) ) ;
return true ;
}
2021-03-30 23:07:27 +00:00
if ( ( cmode & sm : : NORMAL ) & & uni = = ' [ ' ) {
2021-03-30 21:09:26 +00:00
current_step = ( 1 + current_step ) / 2 ;
return true ;
}
2021-03-30 23:07:27 +00:00
if ( ( cmode & sm : : NORMAL ) & & uni = = ' ] ' ) {
2021-03-30 21:09:26 +00:00
current_step = 2 * current_step ;
return true ;
}
2021-03-30 23:07:27 +00:00
if ( ( cmode & sm : : NORMAL ) & & uni > = 1000 & & uni < 1010 ) {
2021-03-30 21:09:26 +00:00
current_step = 1 < < ( uni - 1000 ) ;
return true ;
}
return false ;
}
bool color_prestats ( ) {
nohelp = true ;
for ( int k = 0 ; k < = 6 ; k + + ) {
int v = 1 < < k ;
if ( displayButtonS ( 10 + k * vid . fsize * 2 , 10 + vid . fsize , its ( k ) , v = = current_step ? 0xFF2020 : 0xC0C0C0 , 0 , vid . fsize ) )
getcstat = 1000 + k ;
}
if ( mouseover ) {
displayButtonS ( 10 + 7 * vid . fsize * 2 , 10 + vid . fsize , itsh ( mouseover - > landparam & 0xFFFFFF ) , mouseover - > landparam , 0 , vid . fsize ) ;
}
return true ;
}
void run_cpick ( ) {
crystal : : compass_probability = 0 ;
stop_game ( ) ;
crystal : : set_crystal ( 6 ) ;
set_variation ( eVariation : : pure ) ;
firstland = specialland = laCanvas ;
patterns : : whichCanvas = ' g ' ;
patterns : : canvasback = 0 ;
check_cgi ( ) ;
start_game ( ) ;
current_center = currentmap - > gamestart ( ) ;
current_color = 0x808080 ;
current_step = 32 ;
mapeditor : : drawplayer = false ;
vid . smart_range_detail = 1 ;
vid . use_smart_range = 2 ;
2021-03-30 23:07:27 +00:00
rv_hook ( hooks_drawcell , 100 , color_markers ) ;
rv_hook ( hooks_handleKey , 50 , color_key ) ;
rv_hook ( hooks_prestats , 150 , color_prestats ) ;
2021-03-30 21:09:26 +00:00
}
auto cphook = addHook ( hooks_args , 100 , [ ] {
using namespace arg ;
if ( 0 ) ;
else if ( argis ( " -cpick " ) ) {
PHASEFROM ( 2 ) ;
run_cpick ( ) ;
}
else return 1 ;
return 0 ;
2021-03-30 23:07:27 +00:00
} ) ;
2021-03-30 21:09:26 +00:00
}
namespace sokoban {
bool on ;
bool created ;
hpcshape sokowall [ 10 ] [ 7 ] ;
hyperpoint tpoint [ 6 ] ;
void push3 ( hyperpoint h ) {
cgi . first = false ;
cgi . hpc . push_back ( h ) ;
}
void create_sokowalls ( cell * c ) {
for ( int a = 0 ; a < 6 ; a + + ) tpoint [ a ] = currentmap - > adj ( c , a ) * C0 ;
const int qfr = 8 ;
auto v = [ & ] ( int a , int b , int fr ) {
hyperpoint h0 = get_corner_position ( c , b ) ;
hyperpoint h1 = get_corner_position ( c , b + 1 ) ;
hyperpoint h2 = normalize ( h0 * ( qfr - fr ) + h1 * fr ) ;
return mscale ( h2 , 1 / ( 1 - a / 6.1 ) ) ;
} ;
for ( int a = 0 ; a < 9 ; a + + )
for ( int b = 0 ; b < 6 ; b + + ) {
cgi . bshape ( sokowall [ a ] [ b ] , PPR : : FLOOR + 2 * a + 1 ) ;
for ( int f = 0 ; f < = qfr ; f + + )
push3 ( v ( a , b , f ) ) ;
for ( int f = 0 ; f < = qfr ; f + + )
push3 ( v ( a + 1 , b , qfr - f ) ) ;
push3 ( v ( a , b , 0 ) ) ;
}
for ( int a = 0 ; a < 9 ; a + + ) {
cgi . bshape ( sokowall [ a ] [ 6 ] , PPR : : FLOOR + 2 * a ) ;
for ( int b = 0 ; b < 6 ; b + + )
for ( int f = 0 ; f < qfr ; f + + )
push3 ( v ( a , b , f ) ) ;
push3 ( v ( a , 0 , 0 ) ) ;
}
cgi . finishshape ( ) ;
cgi . extra_vertices ( ) ;
}
bool sokomap ( cell * c , const shiftmatrix & V ) {
if ( ! created ) {
created = true ;
create_sokowalls ( c ) ;
}
crystal : : coord v = crystal : : get_coord ( c - > master ) ;
bool high = ( v [ 0 ] ^ v [ 1 ] ^ v [ 2 ] ) & 2 ;
color_t col = 0x00C000FF ;
poly_outline = 0xFF ;
int lev = 0 ;
int phase = ( ( v [ 0 ] ^ v [ 2 ] ^ v [ 4 ] ) & 2 ) > > 1 ;
// high = v[0] >= 0 && v[0] <= 8 && v[1] >= 0 && v[1] <= 8 && v[2] == 0 && !(v[0] > 0 && v[0] < 8 && v[1] > 0 && v[1] < 8);
// if(high) col = 0xFFFF00FF, lev = 3;
high = true ;
lev = ( ( v [ 0 ] + v [ 1 ] + v [ 2 ] ) / 2 + 1 ) & 3 ;
if ( lev = = 0 ) col = 0x008000FF ;
if ( lev = = 1 ) col = 0x00C000FF ;
if ( lev = = 2 ) col = 0x40C000FF ;
if ( lev = = 3 ) col = 0x80FF00FF ;
// if(v[0] == 4 && v[1] == 4 && v[2] == 0) col = 0xFFFFFFFF;
c - > landparam = lev ;
if ( high ) {
ld d = hdist0 ( tC0 ( V ) ) ;
color_t dark1 = col - ( ( col & 0xFCFCFC00 ) > > 1 ) ;
color_t dark2 = col - ( ( col & 0xFCFCFC00 ) > > 2 ) ;
for ( int b = 0 ; b < 6 ; b + + )
for ( int a = c - > move ( b ) - > landparam ; a < lev ; a + + ) if ( hdist0 ( V * tpoint [ b ] ) < d ) {
/* auto& p = */
queuepoly ( V , sokowall [ a ] [ b ] , ( ( ( b + phase ) & 1 ) ? dark1 : dark2 ) ) ;
// p.flags |= POLY_PRECISE_WIDE;
// p.linewidth = 2;
}
queuepoly ( V , sokowall [ lev ] [ 6 ] , col ) ;
}
else {
queuepoly ( V , sokowall [ 0 ] [ 6 ] , col ) ;
}
c - > wall = waInvisibleFloor ;
return false ;
}
void run_sb ( ) {
crystal : : compass_probability = 0 ;
stop_game ( ) ;
crystal : : set_crystal ( 6 ) ;
set_variation ( eVariation : : pure ) ;
firstland = specialland = laCanvas ;
patterns : : whichCanvas = ' g ' ;
patterns : : canvasback = 0 ;
check_cgi ( ) ;
2021-03-30 23:07:27 +00:00
rv_hook ( hooks_drawcell , 100 , sokomap ) ;
2021-03-30 21:09:26 +00:00
start_game ( ) ;
mapeditor : : drawplayer = false ;
vid . smart_range_detail = 1 ;
vid . use_smart_range = 2 ;
}
auto sbhook = addHook ( hooks_args , 100 , [ ] {
using namespace arg ;
if ( 0 ) ;
else if ( argis ( " -sb " ) ) {
PHASEFROM ( 2 ) ;
sokoban : : run_sb ( ) ;
}
else return 1 ;
return 0 ;
2021-03-30 23:07:27 +00:00
} ) ;
2021-03-30 21:09:26 +00:00
}
const flagtype VC = 1 ;
const flagtype NO_VC = 2 ;
const flagtype PLAYER = 4 ;
void sync ( int mode , flagtype flags ) {
using namespace tour ;
if ( mode = = pmStart ) {
crystal : : compass_probability = 0 ;
crystal : : crystal_period = 0 ;
firstland = specialland = laCanvas ;
mapeditor : : drawplayer = ( flags & PLAYER ) ;
vid . smart_range_detail = 1 ;
vid . use_smart_range = 2 ;
crystal : : view_coordinates = ( flags & VC ) ;
smooth_scrolling = true ;
}
if ( mode = = pmKey & & ! ( flags & NO_VC ) )
crystal : : view_coordinates = ! crystal : : view_coordinates ;
if ( cwt . at ! = centerover & & ! playermoved & & ! ( flags & PLAYER ) ) {
cwt . at = centerover ;
current_display - > which_copy = gmatrix [ cwt . at ] . T ;
}
}
vector < tour : : slide > high_slides ;
int shapeid ;
int mycanvas ( cell * c ) {
int dim = crystal : : get_dim ( ) ;
auto d = crystal : : get_coord ( c - > master ) ;
for ( int i = 0 ; i < dim ; i + + ) d [ i ] > > = 1 ;
color_t col = 0 ;
d [ 0 ] + + ;
int ones = 0 ;
for ( int i = 0 ; i < dim ; i + + ) if ( ( d [ i ] & 1 ) = = 1 ) ones + + ;
switch ( shapeid ) {
case 0 : {
auto dx = d ; dx [ 0 ] - = 2 ;
bool grid = false ;
for ( int i = 1 ; i < dim ; i + + ) if ( ( dx [ i ] & 3 ) = = 2 ) grid = true ;
for ( int i = 0 ; i < 3 ; i + + ) part ( col , i ) = 0xFF + 0x30 * ( d [ i ] - 2 ) ;
if ( grid ) col | = 0x1000000 ;
if ( dx = = crystal : : c0 ) col = 0x1FFD500 ;
if ( dx [ 0 ] = = 2 & & dx [ 1 ] = = 0 & & dx [ 2 ] = = 0 & & dx [ 3 ] = = 0 & & dx [ 4 ] = = 0 & & dx [ 5 ] = = 0 ) col = 0 ;
if ( dx [ 0 ] = = 6 & & dx [ 1 ] = = 0 & & dx [ 2 ] = = 0 & & dx [ 3 ] = = 0 & & dx [ 4 ] = = 0 & & dx [ 5 ] = = 0 ) col = 0 ;
return col ;
}
case 1 : {
if ( d [ 1 ] = = 0 & & d [ 2 ] = = 0 & & d [ 3 ] = = 0 & & d [ 4 ] = = 0 & & d [ 5 ] = = 0 ) ;
else col = gradient ( 0x1FF0000 , 0x1FFFF00 , 9 , d [ 0 ] , 16 ) ;
part ( col , 0 ) = 0x80 + d [ 1 ] * 0x70 ;
return col ;
}
case 2 : {
col = gradient ( 0xFFFF00 , 0x00FF00 , 17 , d [ 0 ] , 24 ) ;
for ( int i = 0 ; i < 1 ; i + + ) part ( col , i ) = 0xFF + 0x30 * ( d [ i + 1 ] - 2 ) ;
c - > landparam = col ;
if ( ones = = dim - 1 ) col | = 0x1000000 ;
return col ;
}
case 3 : {
if ( d [ 3 ] = = 1 ) col = ( ones & 1 ) ? 0x1C0FFC0 : 0x180FF80 ;
if ( d [ 3 ] = = - 1 ) col = ( ones & 1 ) ? 0x18080FF : 0x14040FF ;
if ( d [ 2 ] = = 1 ) col = ( ones & 1 ) ? 0x1FFCC00 : 0x1FF8080 ;
if ( d [ 2 ] = = - 1 ) col = ( ones & 1 ) ? 0x180FFFF : 0x1408080 ;
if ( d [ 4 ] = = 1 ) col = 0x1FFFFFF ;
if ( d [ 4 ] = = - 1 ) col = 0x1FFFFFF ;
if ( d [ 5 ] = = 1 ) col = 0x1FFFFFF ;
if ( d [ 5 ] = = - 1 ) col = 0x1FFFFFF ;
return col ;
}
case 4 : {
if ( d [ 3 ] = = 1 ) col = ( ones & 1 ) ? 0x1C0FFC0 : 0x180FF80 ;
if ( d [ 3 ] = = - 1 ) col = ( ones & 1 ) ? 0x18080FF : 0x14040FF ;
if ( d [ 4 ] = = 1 ) col = 0x1FFFFFF ;
if ( d [ 4 ] = = - 1 ) col = 0x1FFFFFF ;
return col ;
}
case 5 : {
if ( d [ 3 ] = = 1 ) col = ( ones & 1 ) ? 0x1C0FFC0 : 0x180FF80 ;
if ( d [ 3 ] = = - 2 ) col = ( ones & 1 ) ? 0x180FFFF : 0x140FFFF ;
return col ;
}
case 6 : {
if ( d [ 3 ] = = 1 ) col = ( ones & 1 ) ? 0x1FF8080 : 0x1FF6060 ;
if ( d [ 2 ] = = - 1 ) col = ( ones & 1 ) ? 0x1FFFF70 : 0x1E0E060 ;
return col ;
}
case 7 : {
if ( d [ 1 ] = = 0 | | d [ 2 ] = = 0 ) ;
else if ( d [ 1 ] > 0 & & d [ 2 ] > 0 ) col = 0x1FF0000 ;
else if ( d [ 1 ] > 0 & & d [ 2 ] < 0 ) col = 0x1FFFF00 ;
else if ( d [ 1 ] < 0 & & d [ 2 ] < 0 ) col = 0x100FFFF ;
else if ( d [ 1 ] < 0 & & d [ 2 ] > 0 ) col = 0x10000FF ;
return col ;
}
case 8 : {
int s = d [ 1 ] + d [ 2 ] + d [ 3 ] + d [ 4 ] + d [ 5 ] ;
if ( s > 0 ) col = 0x1FFD500 ;
else if ( s < - 1 ) col = 0x17851a9 ;
return col ;
}
case 9 : {
int s = d [ 1 ] + d [ 2 ] + d [ 3 ] + d [ 4 ] + d [ 5 ] + d [ 0 ] ;
if ( s > 0 ) col = 0x1FF20FF ;
else if ( s < - 1 ) col = 0x1C0C0C0 ;
return col ;
}
case 10 : /* house */ {
d [ 0 ] - - ;
int is0 = 0 , is1 = 0 , is2 = 0 , ismore = 0 ;
for ( int a = 0 ; a < dim ; a + + ) {
int v = abs ( d [ a ] ) ;
if ( v = = 0 ) is0 + + ;
else if ( v = = 1 ) is1 + + ;
else if ( v = = 2 ) is2 + + ;
else if ( v > 2 ) ismore + + ;
}
println ( hlog , d , " -> " , tie ( is0 , is1 , is2 , ismore ) ) ;
if ( d [ dim - 1 ] ) return 0x101010 ;
else if ( ismore ) return 0x101010 ;
else if ( is2 ) return 0x1800000 ;
else if ( is1 ) return 0xFFFF00 ;
else return 0x1FFFFFF ;
}
case 11 : /* orthoplex */ {
int s = abs ( d [ 0 ] - 4 ) + abs ( d [ 1 ] - 3 ) + abs ( d [ 2 ] - 2 ) + abs ( d [ 3 ] - 3 ) ;
if ( s = = 0 ) return 0x1FFFFFF ;
else if ( s = = 12 ) return 0x1FF0000 ;
else if ( s < 12 ) return 0x800000 ;
// else if(s == 13) return 0x1FF8000;
else return 0x202020 ;
}
default :
return - 1 ;
}
}
2021-03-30 23:07:27 +00:00
void enable ( ) {
rv_hook ( patterns : : hooks_generate_canvas , 100 , mycanvas ) ;
}
2021-03-30 21:09:26 +00:00
auto explore_structure ( int _shapeid ) {
using namespace tour ;
return [ = ] ( presmode mode ) {
sync ( mode , NO_VC ) ;
if ( mode = = pmStart ) {
tour : : slide_backup ( mapeditor : : drawplayer , false ) ;
tour : : slide_backup ( smooth_scrolling , true ) ;
stop_game ( ) ;
set_geometry ( geometry = = gCrystal534 ? gCrystal534 : gCrystal344 ) ;
firstland = specialland = laCanvas ;
patterns : : whichCanvas = ' ' ;
shapeid = _shapeid ;
2021-03-30 23:07:27 +00:00
enable ( ) ;
2021-03-30 21:09:26 +00:00
crystal : : crystal_period = 4 ;
start_game ( ) ;
ray : : max_cells = 4096 ;
}
if ( mode = = pmKey | | mode = = pmGeometrySpecial ) {
stop_game ( ) ;
set_geometry ( geometry = = gCrystal534 ? gCrystal344 : gCrystal534 ) ;
2021-03-30 23:07:27 +00:00
enable ( ) ;
2021-03-30 21:09:26 +00:00
start_game ( ) ;
}
} ;
}
void add_explore_structure ( vector < tour : : slide > & v , int id , string nshort , string nlong ) {
string hds = " high-dimensional shapes/ " ;
v . emplace_back (
tour : : slide { hds + nshort , 999 , tour : : LEGAL : : SPECIAL ,
nlong + " \n \n "
" In these slides, press 5 to switch between 4-dimensional and 6-dimensional space. "
" Press End/Home to move forward/backward. " ,
explore_structure ( id )
} ) ;
}
void house ( int sides , int shape = 10 ) {
stop_game ( ) ;
if ( sides < 0 )
set_geometry ( gCrystal344 ) ;
else
crystal : : set_crystal ( sides ) ;
set_variation ( eVariation : : pure ) ;
firstland = specialland = laCanvas ;
patterns : : whichCanvas = ' ' ;
shapeid = shape ;
check_cgi ( ) ;
2021-03-30 23:07:27 +00:00
enable ( ) ;
2021-03-30 21:09:26 +00:00
start_game ( ) ;
}
tour : : slide * gen_high_demo ( ) {
high_slides . clear ( ) ;
using namespace tour ;
auto & v = high_slides ;
v . emplace_back (
slide { " Introduction/Three-dimensional space " , 999 , LEGAL : : NONE ,
" This is our 2D visualization of 3-dimensional space. \n \n "
" In most slides you can press '5' to enable or disable the coordinate display. "
" You can move the focus with numpad, arrowkeys, or clicking cells with mouse. "
,
[ ] ( presmode mode ) {
sync ( mode , VC ) ;
if ( mode = = pmStart ) {
crystal : : set_crystal ( 6 ) ;
patterns : : whichCanvas = ' K ' ;
start_game ( ) ;
}
}
} ) ;
v . emplace_back (
slide { " Introduction/Four-dimensional space " , 999 , LEGAL : : NONE ,
" This is our 2D visualization of 4-dimensional space. " ,
[ ] ( presmode mode ) {
sync ( mode , VC ) ;
if ( mode = = pmStart ) {
crystal : : set_crystal ( 8 ) ;
patterns : : whichCanvas = ' K ' ;
start_game ( ) ;
}
}
} ) ;
v . emplace_back (
slide { " Introduction/Color picker " , 999 , LEGAL : : NONE ,
" Color picker. You can press '0' to '6' to adjust how fast the colors change. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart )
colorpicker : : run_cpick ( ) ;
}
} ) ;
v . emplace_back (
slide { " games and puzzles/house 3D " , 999 , LEGAL : : NONE ,
" A house in three dimensions. This is a 5x5 square, its center is white, rest of its interior is yellow, and its perimeter is red. "
" By using the third dimension, you can leave the square, or enter it back. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
house ( 6 ) ;
}
}
} ) ;
v . emplace_back (
slide { " games and puzzles/house 4D " , 999 , LEGAL : : NONE ,
" A house in four dimensions. This is a 5x5x5 cube. "
,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
house ( 8 ) ;
}
}
} ) ;
v . emplace_back (
slide { " games and puzzles/house, 3D visualization " , 999 , LEGAL : : NONE ,
" A house in four dimensions, using the 3D version of our visualization. This visualization is harder to understand. Press End/Home to move forward/backward. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
house ( - 1 ) ;
}
}
} ) ;
v . emplace_back (
slide { " games and puzzles/4D orthoplex using 2D " , 999 , LEGAL : : NONE ,
" Try to find the center of the orthoplex in four dimensions. This is a 4D analog of the octahedron. \n \n "
" The faces of the orthoplex are bright red, the outside is dark gray, and the center is white. "
,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
house ( 8 , 11 ) ;
}
}
} ) ;
v . emplace_back (
slide { " games and puzzles/4D orthoplex using 3D " , 999 , LEGAL : : NONE ,
" The same visualization in 3D. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
house ( 8 , 11 ) ;
}
}
} ) ;
v . emplace_back (
slide { " games and puzzles/basic roguelike " , 999 , LEGAL : : NONE ,
" This is a basic roguelike in three dimensions. Even though it appears that it should be possible to move in such a way that "
" one of the enemies is no longer adjacent to us, it turns out that one of its other 'copies' will always manage "
" to chase us. This is clear when we imagine the actual higher-dimensional space. " ,
[ ] ( presmode mode ) {
sync ( mode , NO_VC | PLAYER ) ;
if ( mode = = pmStart ) {
crystal : : set_crystal ( 6 ) ;
patterns : : whichCanvas = ' c ' ;
colortables [ ' c ' ] [ 0 ] = 0x208020 ;
colortables [ ' c ' ] [ 1 ] = 0x105010 ;
patterns : : canvasback = 0x101010 ;
start_game ( ) ;
auto & us = vid . cs ;
us . charid = 4 ;
/* us.skincolor = 0xB55239FF;
us . haircolor = 0xB55239FF ;
us . dresscolor = 0xB55239FF ; */
us . skincolor = 0x202020FF ;
us . haircolor = 0x202020FF ;
us . dresscolor = 0x202020FF ;
us . eyecolor = 0xC000FF ;
cwt . at - > move ( 0 ) - > monst = moRedFox ;
cwt . at - > move ( 1 ) - > monst = moLavaWolf ;
minf [ moLavaWolf ] . color = 0x909090 ;
minf [ moLavaWolf ] . name = " Wolf " ;
minf [ moRedFox ] . name = " Fox " ;
}
}
} ) ;
v . emplace_back (
slide { " games and puzzles/gravity mockup " , 999 , LEGAL : : NONE ,
" A mockup of a 4D game with gravity. We use the 3D version of our visualization, while the gravity dimension is shown using perspective. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
sokoban : : run_sb ( ) ;
}
}
} ) ;
add_explore_structure ( v , 0 , " Cage " , " In this series of slides we show various structures in four-dimensional space, using the three-dimensional variant of our visualization. \n \n We start with a 4x4x4x4 cage with a golden point in the center. " ) ;
add_explore_structure ( v , 1 , " Tunnel " , " One-dimensional tunnel " ) ;
add_explore_structure ( v , 2 , " Skeleton " , " The 1-skeleton of the tessellation of Z^4 with cubes of edge 2 " ) ;
add_explore_structure ( v , 3 , " Tunnel2 " , " Two-dimensional tunnel " ) ;
add_explore_structure ( v , 4 , " Hyperplanes " , " Two hyperplanes in distance 2, i.e., three-dimensional tunnel. " ) ;
add_explore_structure ( v , 5 , " Far hyperplanes " , " Two hyperplanes in distance 3. " ) ;
add_explore_structure ( v , 6 , " Orthogonal " , " Two orthogonal hyperplanes. " ) ;
add_explore_structure ( v , 7 , " Quarterspaces " , " Four quarterspaces. " ) ;
add_explore_structure ( v , 8 , " Diagonal " , " Diagonal tunnel in all coordinates except one. " ) ;
add_explore_structure ( v , 9 , " Diagonal " , " Diagonal tunnel in all coordinates. " ) ;
v . emplace_back (
slide { " Magic cube/Standard magic cube " , 999 , LEGAL : : NONE ,
" Magic Cube (aka Rubik's Cube) using two dimensions. This is an example of a visualization which is difficult for our method, because we are moving complex objects in the 3D space. "
" Press 'r' to rotate the face (while the mouse pointer is on its center -- two coodinates must be 0 and one must be non-zero), Shift+R to reset. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
magic : : magic ( 6 ) ;
}
}
} ) ;
v . emplace_back (
slide { " Magic cube/Four-dimensional magic cube " , 999 , LEGAL : : NONE ,
" Magic Cube (4D) using two dimensions. Keys are the same as in the previous slide. \n \n "
" Use 'r' to rotate the 2D face under the mouse pointer (two coodinates must be 0 and two must be non-zero). "
,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
magic : : magic ( 8 ) ;
}
}
} ) ;
v . emplace_back (
slide { " Magic cube/Four-dimensional magic cube, 3D visualization " , 999 , LEGAL : : NONE ,
" Magic Cube (4D) using three dimensions. " ,
[ ] ( presmode mode ) {
sync ( mode , 0 ) ;
if ( mode = = pmStart ) {
magic : : magic ( - 1 ) ;
}
}
} ) ;
callhooks ( pres : : hooks_build_rvtour , " highdim " , high_slides ) ;
pres : : add_end ( v ) ;
return & high_slides [ 0 ] ;
}
auto highdim_hooks =
addHook ( hooks_welcome_message , 100 , [ ] ( ) {
addMessage ( XLAT ( " Welcome to the %1-dimensional space! " , its ( crystal : : get_dim ( ) ) ) ) ;
return true ;
} )
+ addHook ( tour : : ss : : hooks_extra_slideshows , 120 , [ ] ( tour : : ss : : slideshow_callback cb ) {
if ( high_slides . empty ( ) ) gen_high_demo ( ) ;
cb ( XLAT ( " visualizing higher-dimensional spaces " ) , & high_slides [ 0 ] , ' h ' ) ;
} ) ;
}