2022-04-24 17:48:45 +00:00
namespace nilrider {
2022-05-03 20:08:17 +00:00
bool all ( checkerparam c ) { return c . t - > collected_triangles = = Flag ( isize ( c . l - > triangles ) ) - 1 ; }
goalchecker basic_check ( ld time_limit , ld rev_limit ) {
return [ = ] ( checkerparam c ) {
2022-05-06 14:05:29 +00:00
if ( c . t - > timer > time_limit | | c . rev > rev_limit ) return grFailed ;
2022-05-03 20:08:17 +00:00
if ( all ( c ) ) return grSuccess ;
return grNone ;
} ;
}
goalchecker get_any ( ld time_limit , ld rev_limit ) {
return [ = ] ( checkerparam c ) {
2022-05-06 14:05:29 +00:00
if ( c . t - > timer > time_limit | | c . rev > rev_limit ) return grFailed ;
2022-05-03 20:08:17 +00:00
if ( c . t - > collected_triangles ) return grSuccess ;
return grNone ;
} ;
}
goalchecker get_ordered ( ld time_limit , ld rev_limit ) {
return [ = ] ( checkerparam c ) {
2022-05-06 14:05:29 +00:00
if ( c . t - > timer > time_limit | | c . rev > rev_limit ) return grFailed ;
2022-05-03 20:08:17 +00:00
if ( c . t - > collected_triangles & ( c . t - > collected_triangles + 1 ) ) return grFailed ;
if ( all ( c ) ) return grSuccess ;
return grNone ;
} ;
}
goalchecker yplus_check ( ld time_limit , ld rev_limit ) {
return [ = ] ( checkerparam c ) {
2022-05-06 14:05:29 +00:00
if ( c . t - > timer > time_limit | | c . rev > rev_limit ) return grFailed ;
2022-05-03 20:08:17 +00:00
if ( c . t - > where [ 1 ] < 0 ) return grFailed ;
if ( all ( c ) ) return grSuccess ;
return grNone ;
} ;
}
goalchecker fullstop_check ( ld time_limit , ld rev_limit ) {
return [ = ] ( checkerparam c ) {
2022-05-06 14:05:29 +00:00
if ( c . t - > timer > time_limit | | c . rev > rev_limit ) return grFailed ;
2022-05-03 20:08:17 +00:00
if ( all ( c ) & & c . t - > vel = = 0 ) return grSuccess ;
return grNone ;
} ;
}
2024-08-18 19:43:28 +00:00
ld f_heisenberg0 ( hyperpoint h ) { return nilv : : convert_bonus ( h , nilv : : nmHeis , nilv : : model_used ) ; }
2022-04-24 17:48:45 +00:00
2024-08-18 19:43:28 +00:00
ld rot_plane ( hyperpoint h ) { return nilv : : convert_bonus ( h , nilv : : nmSym , nilv : : model_used ) ; }
2022-04-24 17:48:45 +00:00
ld f_rot_well ( hyperpoint h ) {
2024-08-18 19:43:28 +00:00
return rot_plane ( h ) + h [ 0 ] * h [ 0 ] + h [ 1 ] * h [ 1 ] ;
2022-04-24 17:48:45 +00:00
}
ld long_x ( hyperpoint h ) {
2024-08-18 19:43:28 +00:00
return rot_plane ( h ) + h [ 0 ] * h [ 1 ] / 2 ;
2022-04-24 17:48:45 +00:00
}
2024-08-17 23:30:10 +00:00
ld cycloid ( ld x ) {
// for x from 0 to TAU, returns y from 0 to 2
ld alpha = binsearch ( 0 , TAU , [ x ] ( ld a ) {
ld ax = a - sin ( a ) ;
return ax > = x ;
} , 20 ) ;
return 1 - cos ( alpha ) ;
}
ld cycloid_wave ( ld x ) {
/* static bool test = true;
if ( test ) {
for ( ld a = 0 ; a < TAU ; a + = 0.01 ) printf ( " %5.3f : %5.3f \n " , a , cycloid ( a ) ) ;
exit ( 1 ) ;
} */
int i = floor ( x ) ;
ld xf = x - i ;
return cycloid ( xf * TAU ) * ( ( i & 1 ) ? - 1 : 1 ) / TAU ;
}
ld brachistochrone ( hyperpoint h ) {
2024-08-18 19:43:28 +00:00
return long_x ( h ) - cycloid_wave ( h [ 0 ] / 63 ) * 63 + h [ 1 ] * h [ 1 ] / 5 ;
2024-08-17 23:30:10 +00:00
}
2022-04-24 17:48:45 +00:00
ld geodesics_0 ( hyperpoint h ) {
ld r = hypot_d ( 2 , h ) ;
ld phi = atan2 ( h [ 1 ] , h [ 0 ] ) ;
2022-11-12 21:38:45 +00:00
ld z = ( phi / TAU ) * ( M_PI * r * r + TAU ) ;
2022-04-24 17:48:45 +00:00
return z + rot_plane ( h ) ;
}
ld geodesics_at_4 ( hyperpoint h ) {
ld r = 4 ;
ld phi = atan2 ( h [ 1 ] , h [ 0 ] ) ;
2022-11-12 21:38:45 +00:00
ld z = ( phi / TAU ) * ( M_PI * r * r + TAU ) ;
2022-04-24 17:48:45 +00:00
return z + rot_plane ( h ) ;
}
map < char , color_t > bcols = {
{ ' ' , 0xFF101010 } ,
{ ' W ' , 0xFFFFFFFF } ,
{ ' g ' , 0xFF008000 } ,
{ ' h ' , 0xFF20A020 } ,
{ ' r ' , 0xFFFF4040 } ,
{ ' u ' , 0xFF4040FF } ,
{ ' b ' , 0xFF804000 } ,
{ ' l ' , 0xFF0000C0 } ,
{ ' f ' , 0xFF603000 } ,
{ ' F ' , 0xFF804000 } ,
{ ' 2 ' , 0xFF404040 } ,
{ ' 4 ' , 0xFF808080 } ,
{ ' 6 ' , 0xFFC0C0C0 } ,
2024-08-18 11:56:03 +00:00
{ ' ! ' , 0xFF000000 } ,
{ ' Y ' , 0xFFFFFF80 } ,
{ ' y ' , 0xFFC0C040 } ,
2022-04-24 17:48:45 +00:00
} ;
2022-05-05 20:37:05 +00:00
const int pixel_per_block = 16 ;
map < char , array < string , pixel_per_block > > submaps = {
2022-04-24 17:48:45 +00:00
{ ' o ' , {
" WWWWWWWWWWWWWWWW " ,
" W22222222222222W " ,
" W22222666622222W " ,
" W22266222266222W " ,
" W22622222222622W " ,
" W22622222222622W " ,
" W26222222222262W " ,
" W262222WW222262W " ,
" W262222WW222262W " ,
" W26222222222262W " ,
" W22622222222622W " ,
" W22622222222622W " ,
" W22266222266222W " ,
" W22222666622222W " ,
" W22222222222222W " ,
" WWWWWWWWWWWWWWWW "
} } ,
{ ' x ' , {
" WWWWWWWWWWWWWWWW " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222622622222W " ,
" W222222rW222222W " ,
" W222222Wr222222W " ,
" W22222622622222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" W22222222222222W " ,
" WWWWWWWWWWWWWWWW "
} } ,
{ ' b ' , {
" " ,
" rrr rrr rrr rrr " ,
" " ,
" rr rrr rrr rrr r " ,
" " ,
" rrr rrr rrr rrr " ,
" " ,
" rr rrr rrr rrr r " ,
" " ,
" rrr rrr rrr rrr " ,
" " ,
" rr rrr rrr rrr r " ,
" " ,
" rrr rrr rrr rrr " ,
" " ,
" rr rrr rrr rrr r " ,
} } ,
{ ' f ' , {
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
" FfFfFfFfFfFfFfFf " ,
" fFfFfFfFfFfFfFfF " ,
} } ,
{ ' l ' , {
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
" llllllllllllllll " ,
} } ,
{ ' g ' , {
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
} } ,
{ ' G ' , {
" ghghghghghghghgh " ,
" hghghghghghWhghg " ,
" ghghrhghghWlWhgh " ,
" hghrWrhghghWhghg " ,
" ghghrhghghghghgh " ,
" hghghghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghlhghghghg " ,
" ghghghlWlhghghgh " ,
" hghghghlhghghghg " ,
" ghghghghghghgrgh " ,
" hghglghghghgrWrg " ,
" ghglWlghghghgrgh " ,
" hghglghghghghghg " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
} } ,
{ ' r ' , {
" rrrrrrrrrrrrrrru " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" ubbbbbbbbbbbbbbu " ,
" urrrrrrrrrrrrrrr " ,
} } ,
{ ' * ' , {
" WWWWWW WW WWWWWW " ,
" W W " ,
" W W " ,
" W W " ,
" W W " ,
" W rr W " ,
" rr " ,
" W r r W " ,
" W r r W " ,
" r r " ,
" W r r W " ,
" W rrrrrrrr W " ,
" W W " ,
" W W " ,
" W W " ,
" WWWWWW WW WWWWWW " ,
} } ,
{ ' + ' , {
" gh WW gh " ,
" hg WW hg " ,
" WW " ,
" " ,
" " ,
" WW " ,
" WW " ,
" WWW WWWWWW WWW " ,
" WWW WWWWWW WWW " ,
" WW " ,
" WW " ,
" " ,
" " ,
" WW " ,
" gh WW gh " ,
" hg WW hg " ,
} } ,
{ ' - ' , {
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" WWW WWWWWW WWW " ,
" WWW WWWWWW WWW " ,
" " ,
" " ,
" " ,
" " ,
" " ,
" ghghghghghghghgh " ,
" hghghghghghghghg " ,
} } ,
{ ' | ' , {
" gh WW gh " ,
" hg WW hg " ,
" gh WW gh " ,
" hg hg " ,
" gh gh " ,
" hg WW hg " ,
" gh WW gh " ,
" hg WW hg " ,
" gh WW gh " ,
" hg WW hg " ,
" gh WW gh " ,
" hg hg " ,
" gh gh " ,
" hg WW hg " ,
" gh WW gh " ,
" hg WW hg " ,
} } ,
2024-08-18 13:50:06 +00:00
{ ' T ' , { /* trampoline */
2024-08-18 11:56:03 +00:00
" WWWWWWWWWWWWWWWW " ,
" WYYYYYYYYYYYYYYW " ,
" WYyyyyyyyyyyyyYW " ,
" WYyYYYYYYYYYYyYW " ,
" WYyYyyyyyyyyYyYW " ,
" WYyYyYYYYYYyYyYW " ,
" WYyYyYyyyyYyYyYW " ,
" WYyYyYyYYyYyYyYW " ,
" WYyYyYyYYyYyYyYW " ,
" WYyYyYyyyyYyYyYW " ,
" WYyYyYYYYYYyYyYW " ,
" WYyYyyyyyyyyYyYW " ,
" WYyYYYYYYYYYYyYW " ,
" WYyyyyyyyyyyyyYW " ,
" WYYYYYYYYYYYYYYW " ,
" WWWWWWWWWWWWWWWW " ,
} } ,
2024-08-18 13:50:06 +00:00
{ ' V ' , { /* velocity converter */
" WWWWWWWWWWWWWWWW " ,
" WrrrrrrrrrrrrrrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrrrrrrrrrrrrrrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrrrrrrrrrrrrrrW " ,
" WrrrrrrrrrrrrrrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrrrrrrrrrrrrrrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrbbrbbrrbbrbbrW " ,
" WrrrrrrrrrrrrrrW " ,
" WWWWWWWWWWWWWWWW " ,
} } ,
2022-04-24 17:48:45 +00:00
} ;
level rotplane (
2022-05-06 17:12:51 +00:00
" Trying to be horizontal " , ' r ' , 0 ,
" Collect all the triangles! \n \n "
" All the lines going through the center are horizontal. \n "
2024-08-18 19:17:01 +00:00
" However, this is Nil geometry. The other lines are NOT horizontal! Clockwise ones slope upwards, and counterclockwise ones slope downwards. \n "
2022-05-06 17:12:51 +00:00
" Your unicycle is powered only by the gravity. Use that to your advantage! "
,
2024-08-19 10:38:37 +00:00
- 7.5 * dft_block , 7.5 * dft_block , 7.5 * dft_block , - 7.5 * dft_block ,
2022-04-24 17:48:45 +00:00
{
2024-08-19 10:38:37 +00:00
" ggggggggggggggg " ,
" ggggggfffgggggg " ,
" ggggggfffgggggg " ,
" gggg|ggggg|gggg " ,
" ggg-*-----*-ggg " ,
" gggg|ggggf|gggg " ,
" ggGg|g+ggg|grgG " ,
" gGgg|g|xgo|gggg " ,
" ggGg|g|ggg|grgg " ,
" gggg|g|ggg|gggg " ,
" gg--*-+---*--gg " ,
" gggg|ggggg|gggg " ,
" gggggggGGgggggg " ,
" ggggggggggggggg " ,
" ggggggggggggggg "
2022-04-24 17:48:45 +00:00
} ,
2024-08-18 11:56:46 +00:00
6 , 6 , { } ,
2022-05-03 20:08:17 +00:00
rot_plane ,
{
// the solver[0.25] result is 36.92
goal { 0x40FF40 , " Collect all the triangles in below 60 seconds " , basic_check ( 60 , 999 ) } ,
goal { 0xFFD500 , " Collect all the triangles in below 38 seconds " , basic_check ( 38 , 999 ) }
}
2022-04-24 17:48:45 +00:00
) ;
level longtrack (
" A Long Track " , ' l ' , 0 ,
" The main street is horizontal, as well as the lines orthogonal to it. " ,
2022-05-03 09:28:59 +00:00
0 * dft_block , + 6.5 * dft_block , 64 * dft_block , - 1.5 * dft_block ,
2022-04-24 17:48:45 +00:00
{
2022-05-03 09:28:59 +00:00
" Ggggggggr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " ,
" Ggggggggr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " ,
" Ggggggggr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!x! " ,
" Ggggxgggr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " ,
2022-04-24 17:48:45 +00:00
" gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg " ,
2022-04-30 10:01:18 +00:00
" ggggggggrggggggrggggggggrGggggggggGGggggGGGgggggGGGGggggggggggGG " ,
2022-05-06 11:14:15 +00:00
" --------------------------------------------------------------*G " ,
2022-04-24 17:48:45 +00:00
" gggggfffffggggggggggggggggggggggggggggggggggggggggggggggggggggGG "
} ,
2024-08-18 11:56:46 +00:00
0 , 5 , { } ,
2022-05-03 20:08:17 +00:00
long_x ,
{
// the solver[0.25] result is 1:08.56 (reduced to 1:08.45 by removing some points)
goal { 0xFFD500 , " Collect the triangle in below 1:15 " , basic_check ( 75 , 999 ) } ,
// the solver[0.25] + some manual modifications achieves 1:37.44
goal { 0xFF4040 , " Stop where the triangle is in below 1:45 " , fullstop_check ( 75 , 999 ) } ,
// the solver[0.25] result is 1:45.52
goal { 0x303030 , " Reach the triangle without going on the right side of the road below 2:00 " , yplus_check ( 120 , 999 ) } ,
}
2022-04-24 17:48:45 +00:00
) ;
level geodesical (
" Roads are Geodesics " , ' g ' , nrlPolar ,
2022-05-06 17:12:51 +00:00
" Geodesics are the lines that are (locally) shortest. In the default settings, "
" the space in Nil Rider is rendered according to the Fermat's principle, that is, "
" light rays are assumed to be geodesics. \n \n "
" Geodesics in Nil are horizontal, vertical, and helical. "
" In this level, all the roads are (fragments of) helical geodesics. " ,
2022-11-12 21:38:45 +00:00
- 45. _deg , 3 * dft_block , 225. _deg , 0 ,
2022-04-24 17:48:45 +00:00
// -8*dft_block, +8*dft_block, +8*dft_block, 0,
{
" ffffffffffffffff " ,
" ---------------- " ,
" ---------------- " ,
2022-05-03 09:56:53 +00:00
" *--------------* " ,
2022-04-24 17:48:45 +00:00
" ---------------- " ,
" ---------------- " ,
" ---------------- " ,
" bbbbbbbbbbbbbbbb " ,
} ,
2024-08-18 11:56:46 +00:00
0 , 6 , { } ,
2022-05-03 20:08:17 +00:00
geodesics_0 ,
{
// the solver[0.25] result is 26.10
goal { 0xFFD500 , " Collect both triangles in below 30 seconds " , basic_check ( 30 , 999 ) }
}
2022-04-24 17:48:45 +00:00
) ;
level geodesical4 (
" Helical Geodesic " , ' s ' , nrlPolar ,
" The main road here is a helical geodesic. Orthogonal lines are horizontal. " ,
2022-11-12 21:38:45 +00:00
- 80. _deg , 8.5 * dft_block , 260. _deg , 0.5 * dft_block ,
2022-04-24 17:48:45 +00:00
// -8*dft_block, +8*dft_block, +8*dft_block, 0,
{
" !!!!!!!!!!!!!!!! " ,
" ffffffffffffffff " ,
" gggggggggggggggg " ,
" ggGggggggggGgggg " ,
2022-05-03 09:53:29 +00:00
" +--------------* " ,
2022-04-24 17:48:45 +00:00
" gggggGggggGggggg " ,
" gggGgggggGgggggg " ,
" ffffffffffffffff " ,
} ,
2024-08-18 11:56:46 +00:00
0 , 5 , { } ,
2022-05-03 20:08:17 +00:00
geodesics_at_4 ,
{
// the solver[0.25] result is 32.04
goal { 0xFFD500 , " Collect the triangle in below 35 seconds " , basic_check ( 35 , 999 ) }
}
2022-04-24 17:48:45 +00:00
) ;
level heisenberg0 (
" Heisenberg Zero " , ' z ' , 0 ,
" This is the plane z=0 in the Heisenberg group model of Nil. The roads are x=0, y=0 axes. " ,
2024-08-19 10:38:37 +00:00
- 7.5 * dft_block , 7.5 * dft_block , 7.5 * dft_block , - 7.5 * dft_block ,
2022-04-24 17:48:45 +00:00
{
2024-08-19 10:38:37 +00:00
" ggggggg|ggggggg " ,
" grggggg|gggggrg " ,
" gg*gggg|gggg*gg " ,
" gggffgg|ggggggg " ,
" gggffgg|ggfrggg " ,
" ggggggg|gggggGg " ,
" ggggggg|ggggggg " ,
" -------+------- " ,
" ggggggg|ggggggg " ,
" gggGgog|ggggggg " ,
" ggggggg|ggrgrgg " ,
" gggGgGg|ggggggg " ,
" gg*gggg|gggg*gg " ,
" grggggg|gggggrg " ,
" ggggggg|ggggggg "
2022-04-24 17:48:45 +00:00
} ,
2024-08-18 11:56:46 +00:00
8 , 8 , { } ,
2022-05-03 20:06:21 +00:00
f_heisenberg0 ,
{
// the solver[0.25] result is 49:15
goal { 0x40FFd0 , " Collect all triangles in below 0:55 " , basic_check ( 55 , 999 ) }
}
2022-04-24 17:48:45 +00:00
) ;
level rotwell (
2022-05-03 20:06:21 +00:00
" Deep Well " , ' d ' , nrlOrder ,
2022-05-06 17:12:51 +00:00
" Can you escape this well? \n \n "
" The sculpture in the center is built around eight helical geodesics which start in a point on the floor, and all cross in a point in the sky. Try to find that point and "
" look below! \n \n "
" Note: you can move the camera freely (using the arrow keys and PageUp/Down/Home/End) while the game is paused. "
,
2024-08-19 10:38:37 +00:00
- 7.5 * dft_block , 7.5 * dft_block , 7.5 * dft_block , - 7.5 * dft_block ,
2022-04-24 17:48:45 +00:00
{
2024-08-19 10:38:37 +00:00
" ggggggggggggggg " ,
" gogggggggggggog " ,
" ggggg--*--ggggg " ,
" gggg*ggggg*gggg " ,
" ggg*ggGfGgg*ggg " ,
" gg|ggfgggfgg|gg " ,
" gg|gGgggggGg|gg " ,
" gg*gfggxggfg*gg " ,
" gg|gGgggggGg|gg " ,
" gg|ggfgggfgg|gg " ,
" ggg*ggGfGgg*ggg " ,
" gggg*ggggg*gggg " ,
" ggggg--*--ggggg " ,
" gogggggggggggog " ,
" ggggggggggggggg "
2022-04-24 17:48:45 +00:00
} ,
2024-08-18 11:56:46 +00:00
8 , 8 , { } ,
2022-05-03 20:08:17 +00:00
f_rot_well ,
{
// the solver[0.5] result is 1:19.54 (obtained using get_ordered)
goal { 0xFFD500 , " Collect all triangles below 1:25 " , basic_check ( 85 , 999 ) }
}
2022-04-24 17:48:45 +00:00
) ;
level labyrinth (
" Labyrinth " , ' l ' , 0 ,
2022-05-06 17:12:51 +00:00
" You will have to go clockwise this time! \n \n "
" The squares of this level have half of their usual length. " ,
2024-08-19 10:38:37 +00:00
- 7.5 * dft_block / 2 , 7.5 * dft_block / 2 , 7.5 * dft_block / 2 , - 7.5 * dft_block / 2 ,
2022-04-24 17:48:45 +00:00
{
2024-08-19 10:38:37 +00:00
" ogggrfffffffffo " ,
" g*ggrgggggggggg " ,
" ggggrgggggggggg " ,
" ggggrgggggggggg " ,
" ggggrgggrrggggg " ,
" ggggrgGGGrrgggg " ,
" ggggrGgggGrgggg " ,
" ggggrGgxgGrgggg " ,
" ggggrGgggGrgggg " ,
" ggggrrGGGrrgggg " ,
" gggggrrrrrggggg " ,
" ggggggggggggggg " ,
" ggggggggggggggg " ,
" ggggggggggggggg " ,
" offfffffffffffo " ,
2022-04-24 17:48:45 +00:00
} ,
2024-08-18 11:56:46 +00:00
8 , 8 , { } ,
2022-05-03 20:08:17 +00:00
rot_plane ,
{
// the solver[0.1] result is 1:03.53
// the solver[0.15] result is 1:06.58
// the solver[0.24] result is 1:08.54
// the solver[0.25] result is 1:22.09 (it goes north for some reason)
goal { 0xFFD500 , " Collect the triangle in below 1:15 " , basic_check ( 75 , 999 ) }
}
2022-04-24 17:48:45 +00:00
) ;
2022-05-09 12:44:39 +00:00
level obstacle (
" Obstacle Course " , ' o ' , 0 ,
" The main street is horizontal, as well as the lines orthogonal to it. " ,
2024-08-19 10:38:37 +00:00
0 * dft_block , 2.5 * dft_block , 64 * dft_block , - 2.5 * dft_block ,
2022-05-09 12:44:39 +00:00
{
" ggggggGrggGrgggggggggggggggggggggGrxgggggggggGrggggggggGrggggggo " ,
" ggggggGrggGrgggGrgggggGrgggggggggGrgggggggggggggGrgggggGrggggggo " ,
" -----------r----r------r----r-----r--r---------r---------------* " ,
" ggggggGrgggggggGrgggggGrggggggggggggGrggggggGrgggggggggGrggggggo " ,
2024-08-19 10:38:37 +00:00
" ggggggGrgggggggGrgggggggggggggggggggGrgggggggggGrggggggGrggggggo "
2022-05-09 12:44:39 +00:00
} ,
2024-08-18 11:56:46 +00:00
0 , 4 , { } ,
2022-05-09 12:44:39 +00:00
long_x ,
{
goal { 0xFFFFC0 , " Collect the triangle in below 1:25, reversing time at most 3 times " , basic_check ( 85 , 3 ) } ,
goal { 0xFFD500 , " Collect the triangle in below 1:10, reversing time at most 3 times " , basic_check ( 70 , 3 ) } ,
}
) ;
2022-04-24 17:48:45 +00:00
level * curlev = & rotplane ;
2022-08-14 17:23:18 +00:00
struct complex_surface {
hyperpoint cur ;
map < pair < int , int > , surface_fun > blocks ;
2024-08-18 19:43:28 +00:00
static transmatrix flatpush ( hyperpoint h ) { return rgpushxto0 ( nilv : : convert ( point31 ( h [ 0 ] , h [ 1 ] , 0 ) , nilv : : nmSym , nilv : : model_used ) ) ; }
2022-08-14 17:23:18 +00:00
static transmatrix hpush ( hyperpoint h ) { h [ 1 ] = 0 ; h [ 2 ] = 0 ; return flatpush ( h ) ; }
static transmatrix vpush ( hyperpoint h ) { h [ 0 ] = 0 ; h [ 2 ] = 0 ; return flatpush ( h ) ; }
static hyperpoint spin_around ( hyperpoint h , hyperpoint start , hyperpoint ctr , ld dir ) {
auto h1 = h - ctr ;
auto d = hypot_d ( 2 , h1 ) ;
ld r = 2 ;
h1 = h1 * ( r / d ) ;
2022-11-12 21:38:45 +00:00
ld phi = atan2 ( h1 [ 1 ] , h1 [ 0 ] ) + 90. _deg ;
ld phis = atan2 ( ( start - ctr ) [ 1 ] , ( start - ctr ) [ 0 ] ) + 90. _deg ;
cyclefix ( phi , phis ) ;
2022-08-14 17:23:18 +00:00
h1 + = ctr ;
auto z = [ & ] ( ld a ) { return point31 ( r * sin ( a ) , - r * cos ( a ) , ( r * r / 2 ) * ( a - sin ( a ) * cos ( a ) ) ) ; } ;
if ( 0 ) {
// not smooth enough ....
transmatrix q = gpushxto0 ( z ( phis ) ) * rgpushxto0 ( z ( phi ) ) ;
hyperpoint arc = rgpushxto0 ( start ) * q * flatpush ( h - h1 ) * C0 ;
return arc ;
}
hyperpoint h2 = h ; if ( start [ 0 ] = = ctr [ 0 ] ) h2 [ 1 ] = start [ 1 ] ; else h2 [ 0 ] = start [ 0 ] ;
hyperpoint pre = rgpushxto0 ( start ) * flatpush ( h2 - start ) * flatpush ( h - h2 ) * C0 ;
2022-11-12 21:38:45 +00:00
hyperpoint last = rgpushxto0 ( start ) * gpushxto0 ( z ( phis ) ) * rgpushxto0 ( z ( phis + dir * 90. _deg ) ) * C0 ;
2022-08-14 17:23:18 +00:00
hyperpoint h3 = h ; if ( start [ 0 ] ! = ctr [ 0 ] ) h3 [ 1 ] = last [ 1 ] ; else h3 [ 0 ] = last [ 0 ] ;
hyperpoint post = rgpushxto0 ( last ) * flatpush ( h3 - last ) * flatpush ( h - h3 ) * C0 ;
2022-11-12 21:38:45 +00:00
ld p = ( 1 + sin ( ( phi - phis ) * 2 - 90. _deg ) ) / 2. ;
2022-08-14 17:23:18 +00:00
pre [ 2 ] = pre [ 2 ] + ( post [ 2 ] - pre [ 2 ] ) * p ;
// println(hlog, "START = ", start, " LAST = ", last, " h = ", h, " h2 = ", h2, " h3 = ", h3, " p = ", p, " pre = ", pre);
// exit(1);
return pre ;
// flatpush(h1 - start) * flatpush(h - h1) * C0;
}
static hyperpoint rel ( int x , int y ) { return point30 ( x , y , 0 ) ; } ;
surface_fun & at ( hyperpoint h ) {
int ax = int ( floor ( h [ 0 ] / 4 ) ) ;
int ay = int ( floor ( h [ 1 ] / 4 ) ) ;
return blocks [ { ax , ay } ] ;
} ;
void right_block ( ) {
auto c = cur ;
println ( hlog , " RIGHT at " , c ) ;
auto f = [ c ] ( hyperpoint h ) { return rgpushxto0 ( c ) * hpush ( h - c ) * vpush ( h - c ) * C0 ; } ;
at ( c + rel ( 2 , 0 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 4 , 0 ) ) ;
}
void left_block ( ) {
auto c = cur ;
println ( hlog , " LEFT at " , c ) ;
auto f = [ c ] ( hyperpoint h ) { return rgpushxto0 ( c ) * hpush ( h - c ) * vpush ( h - c ) * C0 ; } ;
at ( c + rel ( - 2 , 0 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( - 4 , 0 ) ) ;
}
void up_block ( ) {
auto c = cur ;
println ( hlog , " UP at " , c ) ;
auto f = [ c ] ( hyperpoint h ) { return rgpushxto0 ( c ) * vpush ( h - c ) * hpush ( h - c ) * C0 ; } ;
at ( c + rel ( 0 , 2 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 0 , 4 ) ) ;
}
void down_block ( ) {
auto c = cur ;
println ( hlog , " DOWN at " , c ) ;
auto f = [ c ] ( hyperpoint h ) { return rgpushxto0 ( c ) * vpush ( h - c ) * hpush ( h - c ) * C0 ; } ;
at ( c + rel ( 0 , - 2 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 0 , - 4 ) ) ;
}
/* counterclockwise */
void turn_up_block ( ) {
auto c = cur ;
println ( hlog , " TURN UP at " , c ) ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( 0 , 2 ) , 1 ) ) ; } ;
at ( c + rel ( 2 , 0 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 2 , 2 ) ) ;
} ;
void turn_left_block ( ) {
auto c = cur ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( - 2 , 0 ) , 1 ) ) ; } ;
at ( c + rel ( 0 , 2 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( - 2 , 2 ) ) ;
} ;
void turn_down_block ( ) {
auto c = cur ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( 0 , - 2 ) , 1 ) ) ; } ;
at ( c + rel ( - 2 , 0 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( - 2 , - 2 ) ) ;
} ;
void turn_right_block ( ) {
auto c = cur ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( 2 , 0 ) , 1 ) ) ; } ;
at ( c + rel ( 0 , - 2 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 2 , - 2 ) ) ;
} ;
/* clockwise */
void turn_up_block2 ( ) {
auto c = cur ;
println ( hlog , " TURN UP at " , c ) ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( 0 , 2 ) , - 1 ) ) ; } ;
at ( c + rel ( - 2 , 0 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( - 2 , 2 ) ) ;
} ;
void turn_left_block2 ( ) {
auto c = cur ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( - 2 , 0 ) , - 1 ) ) ; } ;
at ( c + rel ( 0 , - 2 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( - 2 , - 2 ) ) ;
} ;
void turn_down_block2 ( ) {
auto c = cur ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( 0 , - 2 ) , - 1 ) ) ; } ;
at ( c + rel ( 2 , 0 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 2 , - 2 ) ) ;
} ;
void turn_right_block2 ( ) {
auto c = cur ;
auto f = [ c ] ( hyperpoint h ) { return ( spin_around ( h , c , c + rel ( 2 , 0 ) , - 1 ) ) ; } ;
at ( c + rel ( 0 , 2 ) ) = [ f ] ( hyperpoint h ) { return f ( h ) [ 2 ] ; } ;
cur = f ( c + rel ( 2 , 2 ) ) ;
} ;
ld get ( hyperpoint h ) {
int ax = int ( floor ( h [ 0 ] / 4 ) ) ;
int ay = int ( floor ( h [ 1 ] / 4 ) ) ;
2024-08-18 19:43:28 +00:00
if ( blocks . count ( { ax , ay } ) ) return blocks [ { ax , ay } ] ( h ) ;
2022-08-14 17:23:18 +00:00
return 0 ;
}
complex_surface ( hyperpoint h ) : cur ( h ) { }
} ;
complex_surface * spiral , * hilbert ;
ld spiral_level ( hyperpoint h ) {
if ( ! spiral ) {
spiral = new complex_surface ( point31 ( - 4 , 2 , 0 ) ) ;
spiral - > right_block ( ) ;
spiral - > right_block ( ) ;
spiral - > right_block ( ) ;
spiral - > right_block ( ) ;
spiral - > turn_up_block ( ) ;
spiral - > up_block ( ) ;
spiral - > up_block ( ) ;
spiral - > turn_left_block ( ) ;
spiral - > left_block ( ) ;
spiral - > left_block ( ) ;
spiral - > turn_down_block ( ) ;
spiral - > down_block ( ) ;
spiral - > turn_right_block ( ) ;
spiral - > right_block ( ) ;
spiral - > turn_up_block ( ) ;
spiral - > turn_left_block ( ) ;
spiral - > left_block ( ) ;
}
return spiral - > get ( h ) ;
}
ld hilbert_level ( hyperpoint h ) {
if ( ! hilbert ) {
hilbert = new complex_surface ( point31 ( 2 , 0 , 0 ) ) ;
hilbert - > up_block ( ) ;
hilbert - > turn_right_block2 ( ) ;
hilbert - > turn_down_block2 ( ) ;
hilbert - > turn_right_block ( ) ;
hilbert - > right_block ( ) ;
hilbert - > turn_up_block ( ) ;
hilbert - > turn_left_block ( ) ;
hilbert - > turn_up_block2 ( ) ;
hilbert - > turn_right_block2 ( ) ;
hilbert - > turn_up_block ( ) ;
hilbert - > turn_left_block ( ) ;
hilbert - > left_block ( ) ;
hilbert - > turn_down_block ( ) ;
hilbert - > turn_left_block2 ( ) ;
hilbert - > turn_up_block2 ( ) ;
hilbert - > up_block ( ) ;
}
return hilbert - > get ( h ) ;
}
level spirallev (
" Square Spiral " , ' s ' , 0 ,
" The projection of this track is shaped like a square spiral. " ,
0.5 * dft_block , 16.5 * dft_block , 16.5 * dft_block , 0.5 * dft_block ,
{
" !!!!!!!!!!!!!!!! " ,
" rgggggggggggggr! " ,
" g+-----------+g! " ,
" g|gGgggggggGg|g! " ,
" g|G!!!!!!!!!G|g! " ,
" g|g!rgggggr!g|g! " ,
" g|g!g*---+g!g|g! " ,
" g|g!rgggg|g!g|g! " ,
" g|G!!!!!x|g!g|g! " ,
" g|gGgggGg|g!g|g! " ,
" g+-------+g!g|g! " ,
" rgggggggggr!g|g! " ,
" !!!!!!!!!!!!G|g! " ,
" fffggggggggGg|g! " ,
" -------------+g! " ,
" ggggggggggggggr! "
} ,
2024-08-18 11:56:46 +00:00
1 , 15.4 , { } , spiral_level ,
2022-08-14 17:23:18 +00:00
{
// the solver result is 55.239
goal { 0xFFD500 , " Collect the triangle in below 60 seconds " , basic_check ( 60 , 999 ) } ,
goal { 0xFF4040 , " Collect the triangle in below 70 seconds " , basic_check ( 70 , 999 ) } ,
}
) ;
level hilbertlev (
" Hilbert's Curve " , ' s ' , 0 ,
" The projection of this track is shaped like the Hilbert curve. " ,
0.5 * dft_block , 16.5 * dft_block , 16.5 * dft_block , 0.5 * dft_block ,
{
" !!!!!!!!!!!!!!!! " ,
" ggg!rgggGGGgggr! " ,
" g*g!gf-------fg! " ,
" g|g!g|ggGGGgg|g! " ,
" g|g!g|g!!!!!g|g! " ,
" g|gxg|g!rgggg|g! " ,
" gf---fg!gf---fg! " ,
" rgggggr!g|ggggr! " ,
" !!!!!!!!g|o!!!!! " ,
" rgggggr!g|ggggr! " ,
" gf---fg!gf---fg! " ,
" g|ggg|g!rgggg|g! " ,
" g|g!x|g!!!!!g|g! " ,
" g|g!g|ggGGGgg|g! " ,
" g|g!gf-------fg! " ,
" g|g!rgggGGGgggr! "
} ,
2024-08-18 11:56:46 +00:00
2.4 , 15.4 , { } , hilbert_level ,
2022-08-14 17:23:18 +00:00
{
// the solver result is 50.94
goal { 0xFFD500 , " Collect the triangle in below 55 seconds " , basic_check ( 55 , 999 ) } ,
goal { 0xFF4040 , " Collect the triangle in below 60 seconds " , basic_check ( 60 , 999 ) } ,
}
) ;
2024-08-17 23:30:10 +00:00
level cycloid_slalom (
" Cycloid slalom " , ' c ' , nrlSwapTriangleOrder ,
" The main street is a brachistochrone. If you were not moving north/south, "
" it would be the fastest path to get to the goal. Is it still the case "
" in these physics? Definitely not if you have to collect on the way! " ,
2024-08-19 10:38:37 +00:00
- 0.5 * dft_block , 2.5 * dft_block , 63.5 * dft_block , - 2.5 * dft_block ,
2024-08-17 23:30:10 +00:00
{
" gggggggG*GggggrgggggG*GgggggrggggggG*GgggggrggggG*Rgggggrggggggo " ,
" gggggggGGGggggggggggGGGggggggggggggGGGggggggggggGGGggggggggggggo " ,
" ---------------------------------------------------------------* " ,
" gggggggggggggGGGgggggggggggGGGggggggggggggGGGggggggggggGGGgggggo " ,
2024-08-19 10:38:37 +00:00
" ggggggggrggggG*GgggggrgggggG*GggggggrgggggG*GggggrgggggG*Ggggggo "
2024-08-17 23:30:10 +00:00
} ,
2024-08-18 11:56:46 +00:00
0 , 2 , { } ,
2024-08-17 23:30:10 +00:00
brachistochrone ,
{
goal { 0xFFFFC0 , " Collect all triangles in below 1:25, reversing time at most 3 times " , basic_check ( 85 , 3 ) } ,
goal { 0xFFD500 , " Collect all triangles in below 1:10, reversing time at most 3 times " , basic_check ( 70 , 3 ) } ,
}
) ;
2024-08-18 19:22:20 +00:00
level multifloor (
" Multi-floor " , ' m ' , 0 ,
" There are triangles on the floors below. I mean, DIRECTLY below. \n \n Hopefully, you can abuse how straight lines work in this geometry to reach them! "
2024-08-18 11:56:46 +00:00
,
2024-08-19 10:38:37 +00:00
- 1.5 * dft_block , 1.5 * dft_block , 1.5 * dft_block , - 1.5 * dft_block ,
2024-08-18 11:56:46 +00:00
{
2024-08-19 10:38:37 +00:00
" ggg " ,
" ggg " ,
" ggg " } ,
2024-08-18 19:22:20 +00:00
0 , 1 , { } ,
2024-08-18 11:56:46 +00:00
rot_plane ,
{
2024-08-18 19:22:20 +00:00
goal { 0x40FF40 , " Collect all the triangles in below 300 seconds, reversing time at most 3 times " , basic_check ( 300 , 3 ) } ,
goal { 0xFFD500 , " Collect all the triangles in below 150 seconds, reversing time at most once " , basic_check ( 150 , 1 ) }
2024-08-18 11:56:46 +00:00
}
) ;
2022-04-24 17:48:45 +00:00
vector < level * > all_levels = {
2024-08-18 19:22:20 +00:00
& rotplane , & longtrack , & geodesical , & geodesical4 , & heisenberg0 , & rotwell , & labyrinth , & obstacle , & spirallev , & hilbertlev , & cycloid_slalom ,
& multifloor
2022-04-24 17:48:45 +00:00
} ;
}