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 ;
} ;
}
2022-04-24 17:48:45 +00:00
ld f_heisenberg0 ( hyperpoint h ) { return 0 ; }
ld rot_plane ( hyperpoint h ) {
return h [ 0 ] * h [ 1 ] / 2 ;
}
ld f_rot_well ( hyperpoint h ) {
return h [ 0 ] * h [ 1 ] / 2 + h [ 0 ] * h [ 0 ] + h [ 1 ] * h [ 1 ] ;
}
ld long_x ( hyperpoint h ) {
return h [ 0 ] * h [ 1 ] ;
}
ld geodesics_0 ( hyperpoint h ) {
ld r = hypot_d ( 2 , h ) ;
ld phi = atan2 ( h [ 1 ] , h [ 0 ] ) ;
ld z = ( phi / 2 / M_PI ) * ( M_PI * r * r + 2 * M_PI ) ;
return z + rot_plane ( h ) ;
}
ld geodesics_at_4 ( hyperpoint h ) {
ld r = 4 ;
ld phi = atan2 ( h [ 1 ] , h [ 0 ] ) ;
ld z = ( phi / 2 / M_PI ) * ( M_PI * r * r + 2 * M_PI ) ;
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 } ,
2022-05-05 20:37:05 +00:00
{ ' ! ' , 0xFF000000 }
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 " ,
} } ,
} ;
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 "
" However, this is Nil geometry. The other lines are NOT horizontal! Clockwise ones slope upwards, and counterclockwise ones slop edownwards. \n "
" Your unicycle is powered only by the gravity. Use that to your advantage! "
,
2022-04-24 17:48:45 +00:00
- 7.5 * dft_block , 7.5 * dft_block , 8.5 * dft_block , - 8.5 * dft_block ,
{
" ggggggggggggggg! " ,
" ggggggfffgggggg! " ,
" ggggggfffgggggg! " ,
" gggg|ggggg|gggg! " ,
2022-04-30 10:01:18 +00:00
" ggg-*-----*-ggg! " ,
2022-04-24 17:48:45 +00:00
" gggg|ggggf|gggg! " ,
" ggGg|g+ggg|grgG! " ,
" gGgg|g|xgo|gggg! " ,
" ggGg|g|ggg|grgg! " ,
" gggg|g|ggg|gggg! " ,
2022-04-30 10:01:18 +00:00
" gg--*-+---*--gg! " ,
2022-04-24 17:48:45 +00:00
" gggg|ggggg|gggg! " ,
" gggggggGGgggggg! " ,
" ggggggggggggggg! " ,
" ggggggggggggggg! " ,
" !!!!!!!!!!!!!!!! "
} ,
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 "
} ,
2022-05-03 09:28:59 +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-04-24 17:48:45 +00:00
- 45 * degree , 3 * dft_block , 225 * degree , 0 ,
// -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 " ,
} ,
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. " ,
- 80 * degree , 8.5 * dft_block , 260 * degree , 0.5 * dft_block ,
// -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 " ,
} ,
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. " ,
- 7.5 * dft_block , 7.5 * dft_block , 8.5 * dft_block , - 8.5 * dft_block ,
{
" ggggggg|ggggggg! " ,
" grggggg|gggggrg! " ,
2022-05-03 09:56:53 +00:00
" gg*gggg|gggg*gg! " ,
2022-04-24 17:48:45 +00:00
" gggffgg|ggggggg! " ,
" gggffgg|ggfrggg! " ,
" ggggggg|gggggGg! " ,
" ggggggg|ggggggg! " ,
" -------+-------! " ,
" ggggggg|ggggggg! " ,
" gggGgog|ggggggg! " ,
" ggggggg|ggrgrgg! " ,
" gggGgGg|ggggggg! " ,
2022-05-03 09:56:53 +00:00
" gg*gggg|gggg*gg! " ,
2022-04-24 17:48:45 +00:00
" grggggg|gggggrg! " ,
" ggggggg|ggggggg! " ,
" !!!!!!!!!!!!!!!! "
} ,
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. "
,
2022-04-24 17:48:45 +00:00
- 7.5 * dft_block , 7.5 * dft_block , 8.5 * dft_block , - 8.5 * dft_block ,
{
" 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! " ,
" !!!!!!!!!!!!!!!! "
} ,
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. " ,
2022-04-24 17:48:45 +00:00
- 7.5 * dft_block / 2 , 7.5 * dft_block / 2 , 8.5 * dft_block / 2 , - 8.5 * dft_block / 2 ,
{
" ogggrfffffffffo! " ,
" g*ggrgggggggggg! " ,
" ggggrgggggggggg! " ,
" ggggrgggggggggg! " ,
" ggggrgggrrggggg! " ,
" ggggrgGGGrrgggg! " ,
" ggggrGgggGrgggg! " ,
" ggggrGgxgGrgggg! " ,
" ggggrGgggGrgggg! " ,
" ggggrrGGGrrgggg! " ,
" gggggrrrrrggggg! " ,
" ggggggggggggggg! " ,
" ggggggggggggggg! " ,
" ggggggggggggggg! " ,
" offfffffffffffo! " ,
" !!!!!!!!!!!!!!!! "
} ,
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
) ;
level * curlev = & rotplane ;
vector < level * > all_levels = {
& rotplane , & longtrack , & geodesical , & geodesical4 , & heisenberg0 , & rotwell , & labyrinth
} ;
}