Compare commits

...

3055 Commits

Author SHA1 Message Date
Zeno Rogue 7af403490a fixed the bug with smart range 2024-05-31 19:18:08 +02:00
Zeno Rogue 2314eaba29 fixed non-enterable characters 2024-05-29 14:22:44 +02:00
Zeno Rogue 5d34760290 v13.0l 2024-05-29 13:58:21 +02:00
Zeno Rogue 50d70097cb fixup to another fix 2024-05-29 13:52:12 +02:00
Zeno Rogue c16c064b21 fixed loading used model 2024-05-29 13:52:02 +02:00
Zeno Rogue 448397ab1d fixed Orb Energy orb desc and Air charges 2024-05-29 13:51:53 +02:00
Zeno Rogue b482dabb84 fixed crashes when apply_settings_light with no cgip 2024-05-29 13:51:35 +02:00
Zeno Rogue 478be692de do not exit on sfc if save not even loaded 2024-05-29 13:51:20 +02:00
Zeno Rogue dda979ad14 delayed start in config file 2024-05-29 13:51:09 +02:00
Zeno Rogue 9485495e48 v13.0k 2024-05-28 20:21:45 +02:00
Zeno Rogue d4a610c2b6 fixed orb change display 2024-05-28 20:21:07 +02:00
Zeno Rogue 003ca36ee5 fixed backward incompatible color reading from config 2024-05-28 20:20:56 +02:00
Zeno Rogue 9752cdede1 fixed symbol changed enable archimedean unexpectedly 2024-05-28 20:20:28 +02:00
Zeno Rogue fbd2cc6b9d v13.0j 2024-05-28 19:35:48 +02:00
Zeno Rogue 5324d3d068 fixed parameters in VR 2024-05-28 18:55:22 +02:00
Zeno Rogue d34070f709 fixed atomic 2024-05-28 17:18:39 +02:00
Zeno Rogue 5d576c3344 display charge count for all orbs, and activation costs for frog-like orbs 2024-05-28 15:45:31 +02:00
Zeno Rogue c6c040eead testing in menu_format 2024-05-28 15:35:42 +02:00
Zeno Rogue aec2463f2f more explanation to menu format 2024-05-28 15:26:45 +02:00
Zeno Rogue ba44e111ca fixed string_parameter editors forgetting the edited text 2024-05-28 15:26:10 +02:00
Zeno Rogue 43d1fd3db8 known keynames for all F1-F10 2024-05-28 15:15:41 +02:00
Zeno Rogue 727ae8a260 gametime available in formulas 2024-05-28 15:09:18 +02:00
Zeno Rogue 99bc842c57 generalized show_turns to menu_format 2024-05-28 15:09:00 +02:00
Zeno Rogue a9d6def718 string parameters are now correctly editable 2024-05-28 15:08:30 +02:00
Zeno Rogue 0d5723dd69 config:: pre reactions 2024-05-28 15:07:29 +02:00
Zeno Rogue ab0ca74328 fixed the font file name, also fixed the problem in rawdisplaystr 2024-05-28 13:41:30 +02:00
Zeno Rogue e66f071521
Merge pull request #378 from jlmjlm/fakemob-font
Make fake-mobile fail cleanly if font missing.
2024-05-28 13:36:01 +02:00
Zeno Rogue b7bfe746cb updated the font name in fake-mobile 2024-05-28 13:34:42 +02:00
Zeno Rogue 093044ba83 Orb of Luck now removes the blue bug bias 2024-05-28 13:33:19 +02:00
Zeno Rogue 3c29b987ce fixup to shape pattern 2024-05-28 13:08:08 +02:00
Zeno Rogue a755f26075 make exception text available for parse errors 2024-05-28 13:05:55 +02:00
Zeno Rogue c1bacb0695 catch exception in case if failed to convert 2024-05-28 13:05:07 +02:00
Zeno Rogue e2c81eeae7 size of the world in arcm now can be pressed just like in geom_exp 2024-05-28 13:04:52 +02:00
Zeno Rogue fcc3cae938 fixed the shape pattern for converted tilings 2024-05-28 13:04:24 +02:00
Zeno Rogue 3b3e9e2de6 fixed arb::convert to take 'step' into account, not only 'next' 2024-05-28 13:02:12 +02:00
Zeno Rogue 5901d9598d faster joystick intiialization 2024-05-28 11:59:03 +02:00
Zeno Rogue 6bf198946c chainspilling lava slimes 2024-05-28 11:58:41 +02:00
Zeno Rogue a3261b21da throw color parse error if wrong length 2024-05-27 22:24:20 +02:00
Zeno Rogue 3da7e4c020 removed debug spam 2024-05-27 20:29:31 +02:00
Zeno Rogue ce09e4910e display smaller mouseover help if there is too much text 2024-05-27 15:54:12 +02:00
Zeno Rogue 95d7ffee08 provided some more help to bool parameters 2024-05-27 15:53:59 +02:00
Zeno Rogue 82a7077019 in bool dialog items, display help text as mouseover 2024-05-27 15:53:37 +02:00
Zeno Rogue 1cc90a6f76 added help to some bool parameters 2024-05-27 15:21:57 +02:00
Zeno Rogue 1323ec446a fixed a crash when changing 3D always 2024-05-27 15:21:44 +02:00
Zeno Rogue 8db11dc683 bool dialogs 2024-05-27 15:21:31 +02:00
Zeno Rogue 502469a54a innerwall is now a param 2024-05-27 14:38:29 +02:00
Zeno Rogue 0df75589ca phi now available in formulas 2024-05-27 14:20:54 +02:00
Zeno Rogue 358554d60e sides and shape now available in color formula 2024-05-27 14:20:54 +02:00
Zeno Rogue c594aea40e windmap and cdata available in color formula 2024-05-27 14:20:54 +02:00
Zeno Rogue 03c549b010 hsv color definition 2024-05-27 14:20:54 +02:00
Zeno Rogue 937a291485 atan2 function in parser 2024-05-27 14:20:54 +02:00
Zeno Rogue 0e09775669 clamp function 2024-05-27 14:20:54 +02:00
Zeno Rogue 5c03f9c7fe fixed wallif 2024-05-27 14:20:54 +02:00
Zeno Rogue 8321751cb0 'single color' now works better with live canvas 2024-05-27 14:20:54 +02:00
Zeno Rogue bfacda7207 ccolor:: live_canvas feature 2024-05-27 14:20:54 +02:00
Zeno Rogue 4f761c70cb Wax walls in Canvas now not only in 3D 2024-05-27 14:20:53 +02:00
Zeno Rogue 3ca75bec8e parsecolortable 2024-05-27 14:20:53 +02:00
Zeno Rogue 54443e365d argcolor now uses parsecolor 2024-05-27 14:20:53 +02:00
Zeno Rogue 6ca2051c96 bugfix in parsecolor 2024-05-27 14:20:53 +02:00
Zeno Rogue e5e89c4800 all color names are now accepted in parsecolor 2024-05-27 14:20:53 +02:00
Zeno Rogue bb6df35bf2 moved wallif to parsecolor from general parse 2024-05-27 14:20:53 +02:00
Zeno Rogue ba05c94d7b parse color: fixed color formula doc 2024-05-27 14:20:53 +02:00
Zeno Rogue 90c7f6e927 fixed 'formula' pattern to use RGB correctly 2024-05-27 14:20:53 +02:00
Zeno Rogue e6417951de fixed rgb color passing 2024-05-27 14:20:53 +02:00
Zeno Rogue f823a53f84 fixed hex color parsing 2024-05-27 14:20:53 +02:00
Zeno Rogue 83575d9d7d color parser 2024-05-27 14:20:53 +02:00
Zeno Rogue d381caba1f better a/b anim pars 2024-05-27 14:20:53 +02:00
Zeno Rogue 78cd26f456 fixed char_paremeter edit_option, added edit_option for string_parameters, improved warning for lack of edit_option 2024-05-27 14:20:53 +02:00
Zeno Rogue 96be05484a tau can be now used in formulas 2024-05-27 14:20:53 +02:00
Zeno Rogue 4d57041c9f angles now can be given in quarterturns 2024-05-27 14:20:53 +02:00
Zeno Rogue 5022b76d75 use turncount, framecount and illegal_moves in formulas 2024-05-27 14:20:53 +02:00
Zeno Rogue 8caf343390 track illegal moves 2024-05-27 14:20:53 +02:00
Zeno Rogue 203c11f6e1 fixed used_model parameter 2024-05-27 14:20:53 +02:00
Zeno Rogue 322b21e999 hardcore now can use a formula 2024-05-27 14:20:53 +02:00
Zeno Rogue f445d02707 specialized exceptions for param errors 2024-05-27 02:18:22 +02:00
Zeno Rogue 888a34dea6 fixed unused lambda capture 2024-05-26 23:26:49 +02:00
Zeno Rogue a20158ab65 fixed overzealous override 2024-05-26 23:22:40 +02:00
Zeno Rogue a703448144 added missing override 2024-05-26 23:20:50 +02:00
Zeno Rogue 480916e4db added missing split_string to repo 2024-05-26 23:19:19 +02:00
Zeno Rogue 998a74800c colortables are now saved correctly 2024-05-26 21:15:26 +02:00
Zeno Rogue f4796a10f4 config:: provided custom_reset 2024-05-26 20:57:32 +02:00
Zeno Rogue aa4bf4d818 removed set_default method from parameters 2024-05-26 20:55:39 +02:00
Zeno Rogue ff8bb20a55 config:: custom parameters now have custom_do_save 2024-05-26 20:51:33 +02:00
Zeno Rogue 57691737f0 fixed rwalls not being set in nilrider 2024-05-26 20:42:47 +02:00
Zeno Rogue a4b9b9b0a5 ccolor::which is now a parameter 2024-05-26 20:38:31 +02:00
Zeno Rogue 1c74774bfa refactored the parameter (saver/setting) system 2024-05-26 20:22:29 +02:00
Zeno Rogue a80a73458a fixed product rendering 2024-05-25 22:46:47 +02:00
Zeno Rogue d7bde6f175 fixup to CR 2024-05-25 12:04:11 +02:00
Zeno Rogue 9f711627f1 export to_square 2024-05-25 11:46:53 +02:00
Zeno Rogue 89763be7d2 when drawing circle_around_center, be more precise, and also use POLY_FORCEWIDE 2024-05-25 11:46:37 +02:00
Zeno Rogue 03b89f053b do not draw Safety in high-qual screenshots 2024-05-25 11:46:11 +02:00
Zeno Rogue 441f825566 export achievement data 2024-05-25 11:45:47 +02:00
Zeno Rogue f2d8b4d95e Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-05-24 20:58:32 +02:00
Zeno Rogue 73dbccbb0e made Bringris, Nil Rider, and Relative Hell compile after changes 2024-05-24 20:57:53 +02:00
Jacob Mandelson efc2ce90e0 Make fake-mobile fail cleanly if font missing. 2024-05-16 19:33:24 -07:00
Zeno Rogue 7b3d2c2626
Merge pull request #377 from jlmjlm/prune_tab
Prune table of new land candidates.
2024-05-16 22:04:51 +02:00
Zeno Rogue 126f45a714
Merge pull request #376 from jlmjlm/nows1
Remove trailing whitespace from system.cpp
2024-05-16 21:56:25 +02:00
Jacob Mandelson 11837d9614 Check for having pruned all land candidates. 2024-05-16 12:46:06 -07:00
Zeno Rogue 64569f1818 debug removed 2024-05-16 21:42:49 +02:00
Jacob Mandelson cd2152ffad Prune table of getNewLand() candidates. 2024-05-16 12:41:19 -07:00
Zeno Rogue eee39b0340 fixed fake-mobile 2024-05-16 21:21:42 +02:00
Zeno Rogue 937c830571 fixed model orientation for spiral 2024-05-16 21:21:14 +02:00
Zeno Rogue 4ec627b1a1 fixed errors about underlying_map uninitialized 2024-05-16 21:21:14 +02:00
Zeno Rogue 1a70e54e24 hopefully fixed yet another C++20 bug 2024-05-16 21:21:13 +02:00
Zeno Rogue a70a9dc663 fixed a bug causing not compiling in C++20 2024-05-16 21:21:13 +02:00
Zeno Rogue 879549ca5d fixed 'race angle' setting: no crash, rotates immediately 2024-05-16 21:21:13 +02:00
Zeno Rogue 7982ea0e58 Removed references to private/daily.cpp and private/hypersteam.cpp. Also removed HAVE_ACHIEVEMENTS as it was redundant to CAP_ACHIEVE 2024-05-16 21:21:13 +02:00
Zeno Rogue 7b99248c06
Merge pull request #374 from jlmjlm/time2
Fix minor menu glitches.
2024-05-16 20:28:22 +02:00
Zeno Rogue dc136cc937
Merge pull request #375 from jlmjlm/time5
Make option to show turns on the main screen.
2024-05-16 20:27:16 +02:00
Jacob Mandelson 3f78c11e6c Remove trailing whitespace from system.cpp 2024-05-16 09:13:48 -07:00
Jacob Mandelson 1dd4da5135 Make option to show turns on the main screen.
"Liberal" version that shows the turncount unguarded by
nomenukey and ISMOBILE.  Hopefully this means that it'll
display properly on mobile, outside the map region's "DRAG" area.
But this display mode is only used by the mobile builds which I
don't have toolchains for, so can't test it.  :(
2024-05-16 08:31:45 -07:00
Jacob Mandelson 601274e67a Fix minor menu glitches.
Currently, if CAP_TOUR is not set then "(v) menu" is displayed
unconditionally, because the "else" statement which suppresses its
display when nomenukey is set is guarded by CAP_TOUR.  That "else"
statement is moved outside the guard.

Currently, the "timeline" -- containing the elapsed time, turn count,
and YASC code -- is not displayed if cheats are active, because it's
replaced by a cheats count line.  Since these lines don't conflict
and the timeline contains useful information, changed to display both.
2024-05-16 07:12:28 -07:00
Zeno Rogue 7581ba887b 13.0i 2024-05-10 20:40:54 +02:00
Zeno Rogue 6b03aca3c0 threecolor now uses its own ctab, not nestcolors 2024-05-10 19:34:01 +02:00
Zeno Rogue 80df589bd2 reverted numlock on MAC 2024-05-10 19:29:14 +02:00
Zeno Rogue 159b47e72a full_rotate_camera no longer reacts to val==0 2024-05-10 19:29:01 +02:00
Zeno Rogue 9a33e63f53 unflipped mine_zero_display 2024-05-10 19:28:47 +02:00
Zeno Rogue 10184f9087 edit minefield colors in minefield config 2024-05-10 19:28:26 +02:00
Zeno Rogue 6b0dd547bd fixed rosebush/crystal world interaction 2024-05-10 19:10:44 +02:00
Zeno Rogue 542e2520c1 changed the guarding in Power landscape 2024-05-10 18:52:23 +02:00
Zeno Rogue f2d81746a7 fixed crash on adding/deleting colors to colortables 2024-05-10 18:37:05 +02:00
Zeno Rogue a130fbbc50 display Compass beason on radar 2024-05-09 21:10:53 +02:00
Zeno Rogue 2097fde609 display Orb of Yendor beacon on radar 2024-05-09 21:07:44 +02:00
Zeno Rogue bc5e1d78c9 always checkTide 2024-05-09 20:44:25 +02:00
Zeno Rogue e324ae07f3 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-05-09 20:42:43 +02:00
Zeno Rogue 215be1ea17
Merge pull request #372 from jlmjlm/tidefix2
Check tide before drawing cells.
2024-05-09 20:42:03 +02:00
Zeno Rogue 53461e6c5a removed yendor debug 2024-05-09 20:21:55 +02:00
Zeno Rogue 7a81b6b0de version 13.0h 2024-05-09 10:50:02 +02:00
Zeno Rogue 723422e137 disable custom_land_list in princess 2024-05-09 10:44:37 +02:00
Zeno Rogue 50881f519f do not count achievements if custom_land_list is used 2024-05-09 10:44:37 +02:00
Zeno Rogue df67249ec0 fixup to distance 534 2024-05-09 10:44:37 +02:00
Zeno Rogue 0a9714e657 cleanup of LB_ constants 2024-05-09 10:44:37 +02:00
Zeno Rogue 5eb7cfc17a LB_PRINCESS instead of magic value 36 2024-05-09 10:44:37 +02:00
Zeno Rogue 000bfd4b97 fixed a bug in celldistance_534 2024-05-09 10:44:37 +02:00
Zeno Rogue 0b0ad4abe3 made bfs in 3D always know nearby cells even if gmatrix not known 2024-05-09 10:44:37 +02:00
Zeno Rogue 305d546ae1 fixed the Yendor beacon to appear in the correct place (usually on the boundary, not the closest visible tile) 2024-05-09 10:44:37 +02:00
Zeno Rogue c369c08bc9 fixed CR3 generated in CR2 layout 2024-05-09 10:44:37 +02:00
Zeno Rogue 52f9cc820b fixed CR2 generated in CR3/CR4 layouts 2024-05-09 10:44:37 +02:00
Zeno Rogue 4c81c0cc5d fixed single wrong tile of the first land when safetying in landscape etc 2024-05-09 10:44:37 +02:00
Zeno Rogue 51ecd882e1 Orb of Summoning now works on deep water, shallow water, and Camelot moat tiles 2024-05-09 10:44:37 +02:00
Zeno Rogue 9ba9797068 fixed CLI -picload 2024-05-09 10:44:37 +02:00
Zeno Rogue ba972ea8d8 more settings for minefield graphics 2024-05-09 10:44:37 +02:00
Zeno Rogue e4b0ebbd89 removed Haunted and Elemental from the landscape mode 2024-05-09 10:44:37 +02:00
Zeno Rogue 35ddcf6fe1 stone gargoyles and statues are now non-blocking for missiles 2024-05-09 10:44:37 +02:00
Zeno Rogue 7c2aca91a4 Orb of Earth now cancels Invisibility only if it is doing something 2024-05-09 10:44:37 +02:00
Zeno Rogue 43702b82a1 clear boats from removed Orbs of Water 2024-05-09 10:44:37 +02:00
Zeno Rogue 43a3e8f030 color change in rogueviz 2024-05-09 10:44:37 +02:00
Zeno Rogue ce825db2c0 redone the canvas coloring system 2024-05-09 10:44:37 +02:00
Zeno Rogue b8a7e6e093 line patterns easier to reach 2024-05-05 17:09:34 +02:00
Zeno Rogue 962efb3152 new linepattern 'wall highlight' 2024-05-05 17:09:13 +02:00
Zeno Rogue 84666ade8c fixed a crash setting landscape_div to 0 2024-05-05 15:19:52 +02:00
Zeno Rogue 9aa15f96e1 fixed a crash with irregular spherical maps 2024-05-05 15:11:07 +02:00
Zeno Rogue bc22d17a16 fixed a possible crash with bad Steam data 2024-05-05 15:10:45 +02:00
Zeno Rogue d9a03ab1d3 renamed tehora to Tehora Rogue in credits 2024-05-05 14:59:07 +02:00
Zeno Rogue 5ae3bc02d1 rogueviz:: dhrg:: removed %Lf 2024-04-28 02:49:53 +02:00
Zeno Rogue aafced83aa rogueviz:: dhrg:: Ld to lld 2024-04-28 02:49:24 +02:00
Zeno Rogue 33aacfa289 disabled simple test 2024-04-28 02:40:43 +02:00
Zeno Rogue d074606cae rogueviz:: sag:: Ld to lld 2024-04-28 02:36:42 +02:00
Zeno Rogue 6aecf921bf rogueviz:: dhrg:: Lf to llf 2024-04-28 02:35:49 +02:00
Zeno Rogue fa99e83019 added the Discord link to README 2024-04-28 02:34:39 +02:00
Zeno Rogue 1003808999 removed badges from README 2024-04-28 02:34:32 +02:00
Zeno Rogue 5085853fb4 removed Emscripten CI 2024-04-28 02:26:24 +02:00
Zeno Rogue 9372ecb8f8 github_ci:: removed Android CI for now 2024-04-28 02:25:27 +02:00
Zeno Rogue 690b2164db github_ci: disabled macos-latest 2024-04-28 02:18:18 +02:00
Zeno Rogue 16e3daeab5 rogueviz:: dhrg:: fixed format 2024-04-28 02:16:28 +02:00
Zeno Rogue 0a16e53561 rogueviz:: fixed missing virtual destructor in model 2024-04-28 02:13:42 +02:00
Zeno Rogue 443be1acda rogueviz:: dhrg:: fixed warning on %p 2024-04-28 02:11:14 +02:00
Zeno Rogue ba9c41bed2 rogueviz:: dhrg:: fixed incorrect initialization 2024-04-28 02:10:22 +02:00
Zeno Rogue 329ad76c3c rogueviz:: dhrg:: fixed VLA 2024-04-28 02:09:19 +02:00
Zeno Rogue de20daf708 rogueviz:: undef IF_ macros 2024-04-28 02:04:40 +02:00
Zeno Rogue f229c489cd rogueviz:: antidesitter:: fixed uninitialized variable 2024-04-28 02:03:13 +02:00
Zeno Rogue 1e3347590b rogueviz:: sag:: fixed unini variable 2024-04-28 02:01:30 +02:00
Zeno Rogue fd1960191e rogueviz:: fixed pedantic error in embedded-chess 2024-04-28 01:52:20 +02:00
Zeno Rogue 942fd9dafb rogueviz::dhrg:: fixed VLA 2024-04-28 01:47:50 +02:00
Zeno Rogue f1e91a1614 rogueviz::dhr:: fixed unused result 2024-04-28 01:46:47 +02:00
Zeno Rogue e71ddf1140 rogueviz::som:: string cannot be constexpr 2024-04-28 01:46:13 +02:00
Zeno Rogue a0ba84d70c Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-04-28 01:41:46 +02:00
Zeno Rogue 404b964f28 fixed unused-result error 2024-04-28 01:41:25 +02:00
Jacob Mandelson b56d2d21bf Check tide before drawing cells. 2024-04-22 15:48:08 -07:00
Zeno Rogue 27fb2d92d7
Merge pull request #370 from jlmjlm/build1
Fix the build.
2024-04-22 18:44:02 +02:00
Zeno Rogue ec9be47a83
Merge pull request #371 from jlmjlm/geom_wmark
Show weapon watermark with geometric xbow.
2024-04-22 18:42:57 +02:00
Jacob Mandelson 14519dc258 Show weapon watermark with geometric xbow. 2024-04-22 09:26:29 -07:00
Jacob Mandelson c3ef9c2733 Include the GCC compiler's install too. 2024-04-20 15:29:31 -07:00
Jacob Mandelson c29517b5b0 Fix the build.
Explain how to install the required dev libraries for Windows.
Update C++ std to use from C++11 to C++14.
Put the MSYS2 SDL include dir in the include files path.
2024-04-20 15:13:01 -07:00
Zeno Rogue e91c11ffb7
Merge pull request #368 from jlmjlm/srfix3
Record asteroids_generated and asteroid_orbs_generated in the saveline.
2024-04-17 11:53:03 +02:00
Zeno Rogue 7d3d3a0869
Merge pull request #369 from Tokarak/pr-mac-build
Fix Mac Build
2024-04-17 11:51:56 +02:00
Tokarak d0d4b24f91 Update README.md with up-to-date build info 2024-04-17 10:27:02 +01:00
Tokarak 2659d08b78 Add message about using glew and libpng to Makefile 2024-04-17 10:23:40 +01:00
Tokarak 45db9977a0 Fix SDL include from sdl_gfx
Resolves #332; for MacOS only.
2024-04-17 10:16:55 +01:00
Tokarak aa78aacdf3 Update MacOS Makefile comments to match README
Also fix an unintentially modified Linux comment in parrent commit
2024-04-17 08:49:17 +01:00
Tokarak fd128d24c6 Fix MacOS-silicon compile
Use the right Homebrew prefix — not hard-coded any more.
2024-04-16 17:09:59 +01:00
Jacob Mandelson d756224f8d Record asteroids_generated and asteroid_orbs_generated in the saveline. 2024-04-13 15:43:44 -07:00
Zeno Rogue fbea2d91ce 13.0g 2024-04-09 02:52:01 +02:00
Zeno Rogue d4f449d994 since the Aether users now see adjacent items in water, they can also pick them up 2024-04-09 02:42:25 +02:00
Zeno Rogue 9807b1b3ba simplified the boat logic 2024-04-09 02:34:30 +02:00
Zeno Rogue 4d761385ac a new pseudopept pattern in Binary4 and Ternary 2024-04-08 19:14:01 +02:00
Zeno Rogue 05b6cdea3e fixed a bug ion Ternary emeraldval 2024-04-08 19:13:48 +02:00
Zeno Rogue 10646933db fixed the West Wall being not inaccessible from some lands 2024-04-08 00:58:34 +02:00
Zeno Rogue 521b452436 auto-pause game when it loses focus 2024-04-08 00:45:20 +02:00
Zeno Rogue 0323e4100e fixed the key being generated on ivy 2024-04-08 00:45:03 +02:00
Zeno Rogue 0708c0e2bc fixed a possible crash when using Orb of Space on Orb of Safety 2024-04-07 23:48:49 +02:00
Zeno Rogue b7db56812e fixed a possible freeze in Ocean in the chaos modes 2024-04-07 23:37:28 +02:00
Zeno Rogue 7fc90f116b fixed a possible crash after killing 400 mutants 2024-04-07 23:37:00 +02:00
Zeno Rogue 824fa9a732 push an exploding barrel on a mine now causes an explosion 2024-04-07 23:36:06 +02:00
Zeno Rogue 92603dddcc fixed pressing numpad keys with numpad on acting both as moves and quick-keys 2024-04-07 23:35:33 +02:00
Zeno Rogue 32d329d81e fixed a possible crash when generating YASC message 2024-04-07 23:35:08 +02:00
Zeno Rogue b9608dcd4c save the Halloween stuff 2024-04-06 18:36:14 +02:00
Zeno Rogue 977bd8ca9d ls:: cursed walls 2024-04-06 18:33:29 +02:00
Zeno Rogue 869c63cb88 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-04-06 11:48:06 +02:00
Zeno Rogue 5377147b1a new land structure, CR2-like 2024-04-06 11:45:51 +02:00
Zeno Rogue e83d38e267 new land structure: excessive crossing walls 2024-04-06 10:36:51 +02:00
Zeno Rogue 1fc02631c8 fixed CR4 still appearing in 'landscape' land structure, and when disabled via custom land list 2024-04-06 09:50:41 +02:00
Zeno Rogue edff317759
Merge pull request #367 from jlmjlm/srfix2
Record fuel collected and space rocks killed.
2024-03-28 17:47:58 +01:00
Jacob Mandelson b8de8155da Record fuel collected and space rocks killed. 2024-03-27 21:07:20 -07:00
Zeno Rogue 9bc4e21f10 13.0f 2024-03-27 23:52:22 +01:00
Zeno Rogue a328568ee5 new messages on Orb of Phasing, Slaying, and Weakness 2024-03-27 23:52:22 +01:00
Zeno Rogue 494fc4ec11 more accurate messages on dice pushing 2024-03-27 23:52:22 +01:00
Zeno Rogue 6f7e5b4d6a load_mode_data error checking 2024-03-27 23:52:22 +01:00
Zeno Rogue ccea416237 when loading save, load full mode data including custom lands 2024-03-27 23:52:22 +01:00
Zeno Rogue 4a908273d0 irregular maps no longer save a different modeline every time due to floating point precision 2024-03-27 23:52:22 +01:00
Zeno Rogue 5efacd787d save_cheats option, also fixed buffer overflow 2024-03-27 23:52:22 +01:00
Zeno Rogue b07987b2f4 removed debug displayed by irregular 2024-03-27 23:52:22 +01:00
Zeno Rogue 84ada5184f Space Rock monsters now drop treasure only if in Space Rock land 2024-03-27 23:52:22 +01:00
Zeno Rogue 14b68f0b64 ineligible starting land also if land is not in game 2024-03-27 23:52:22 +01:00
Zeno Rogue 960485ec8e autocheat now circumvents the lock on the Princess Challenge 2024-03-27 23:52:22 +01:00
Zeno Rogue e032e619c0 do not crash if no New Sealand is available 2024-03-27 23:52:22 +01:00
Zeno Rogue 57f6fb5f71 in countHyperstones, two variants of Mirror are counted once 2024-03-27 23:52:22 +01:00
Zeno Rogue d2cd6fa2c1 Princess Quest now marked as 'ingame' when in Princess Challenge 2024-03-27 23:52:22 +01:00
Zeno Rogue 8a407f4505 specially generated lands now respect Unlocked and LandIngame rules 2024-03-27 23:52:22 +01:00
Zeno Rogue 6abb82174e fixed some more crashes related to SDL2 (e.g., right-click in shmup) 2024-03-27 16:28:37 +01:00
Zeno Rogue dea9fea67f mention custom mode in watermark 2024-03-24 21:41:52 +01:00
Zeno Rogue d618b10889 fixed crashes in 'shift to target' option 2024-03-24 21:22:58 +01:00
Zeno Rogue d250abf1a4 added Pasu4 to the credits 2024-03-24 20:43:46 +01:00
Zeno Rogue 89563ebde9 in 3D, rosebushes now blink if they are close to going off 2024-03-24 20:03:02 +01:00
Zeno Rogue 445c240c79 rosebushes now show up on the radar 2024-03-24 20:02:31 +01:00
Zeno Rogue 15b711e099 if you are in water (and have no Fish), you can now see Orbs of Fish and Aether in adjacent water tiles, and also you can move there and pick them up 2024-03-24 19:29:44 +01:00
Zeno Rogue 8002f42d71 added AntiRogue to knight names 2024-03-24 19:28:02 +01:00
Zeno Rogue 79f2940683 crossbow bolt now ignore rose restrictions on attack 2024-03-24 19:12:42 +01:00
Zeno Rogue 0ec4e46bf0 SDL2 bugfix to shmup and game_keys_scroll 2024-03-24 13:15:58 +01:00
Zeno Rogue c55550de57 13.0d 2024-03-24 12:18:40 +01:00
Zeno Rogue 886a7ff43e fixed on older compiler 2024-03-24 11:36:22 +01:00
Zeno Rogue deb207e4c3 load_mode_data now resets creature scale in shmup 2024-03-24 11:15:33 +01:00
Zeno Rogue 819d815d59 mode now includes specialland, creature_scale and global_boundary_ratio parameters 2024-03-24 11:15:13 +01:00
Zeno Rogue b20288557e specialland now has param 2024-03-24 11:14:49 +01:00
Zeno Rogue 4a8eb08340 fixed face_the_player in VR 2024-03-24 11:14:28 +01:00
Zeno Rogue 007a111eab compass/Yendor targets now should be displayed in VR 2024-03-24 11:14:05 +01:00
Zeno Rogue 65e9f68bc7 disable achievements on custom land list 2024-03-24 00:56:15 +01:00
Zeno Rogue 3e30a7ded1 test command in custom land list 2024-03-24 00:51:20 +01:00
Zeno Rogue 5f8d250940 refactored gen_landvisited 2024-03-24 00:51:00 +01:00
Zeno Rogue dee90f8d7c creature_scale saved to modedata 2024-03-24 00:41:36 +01:00
Zeno Rogue d43b19625e scale now always can be changed, but cheater flag is set in shmup 2024-03-24 00:39:02 +01:00
Zeno Rogue f32a2708b4 do not call auto_creator when loading valid irregular save 2024-03-24 00:30:50 +01:00
Zeno Rogue be27fc0fce protect save_map_bin and load_map_bin from possible lacking base 2024-03-24 00:30:04 +01:00
Zeno Rogue 61720cec5e nicer plain floorshapes in IRREGULAR maps 2024-03-24 00:29:45 +01:00
Zeno Rogue 7cf1643c5d ls:: removed debug from landscape 2024-03-23 23:48:48 +01:00
Zeno Rogue 3791daf9e3 map editor now can save irregular maps (also should save modes too) 2024-03-23 21:21:16 +01:00
Zeno Rogue e9941d29d3 hstream_exception now can contain explanation 2024-03-23 21:19:04 +01:00
Zeno Rogue afd4a3f4e3 custom mode manager and custom welcome messages 2024-03-22 01:22:34 +01:00
Zeno Rogue 66a79fe2cd ls:: no 'better_mirror' in Patched Chaos, Total Chaos, or Landscape 2024-03-21 22:51:13 +01:00
Zeno Rogue 350963852c landscape structure is now based on BCC honeycomb 2024-03-21 22:50:42 +01:00
Zeno Rogue a650fe7faf YASC codes work better if killed on a 10+ tile 2024-03-21 22:49:50 +01:00
Zeno Rogue fdf83820f2 ls:: landscape land structure 2024-03-21 20:15:45 +01:00
Zeno Rogue 6b723977dd in grid mode, don't try to draw greatwall lines outside of normal geometry pure/bitruncated 2024-03-21 19:40:07 +01:00
Zeno Rogue 1b3aecc10c better pseudohept in INVERSE tilings 2024-03-21 19:35:22 +01:00
Zeno Rogue e762da439c fixed the lack of non-trapdoors in Zebra 435 2024-03-21 19:17:12 +01:00
Zeno Rogue 7f023b2459 better Emerald in Octagon chamfered 2024-03-21 19:13:05 +01:00
Zeno Rogue 2a9ae3071d fixed Emerald Mine and Vineyard generating very bad in {n,oo} and binary tiling 2024-03-21 19:07:15 +01:00
Zeno Rogue de21375f40 clear more walls when generating Wild West in high GP 2024-03-21 18:56:12 +01:00
Zeno Rogue 7bc2715a43 debug_voronoi works in horo too 2024-03-21 18:44:28 +01:00
Zeno Rogue 04c15fc9c6 mapfontscale setting 2024-03-21 18:44:19 +01:00
Zeno Rogue 9430c26970 fixed a crash when running away from Clearing in single-land mode. 2024-03-21 18:19:28 +01:00
Zeno Rogue 616607dc8e hv:: fixed troll nests 2024-03-19 19:58:45 +01:00
Zeno Rogue 86f5a040c9 fixed dice hints over different heights 2024-03-19 19:36:28 +01:00
Zeno Rogue 37b498203c item movement animations for Orb of Space and Curse of Repulsion 2024-03-19 19:25:08 +01:00
Zeno Rogue 77a4bb4160 items moved by Orb of Water, Magnetism, and Winter are now animated 2024-03-19 19:19:23 +01:00
Zeno Rogue 5bdade94b6 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-03-19 18:54:04 +01:00
Zeno Rogue 0b526cbdfb rulegen:: no crash if no giver 2024-03-19 18:53:37 +01:00
Zeno Rogue a82d9b2266 rulegen:: optimize in 2D, also debug information during optimize is toggleable 2024-03-19 18:53:09 +01:00
Zeno Rogue 0e018df878 Void Beasts are now pulled by Orb of Air 2024-03-19 18:52:16 +01:00
Zeno Rogue 1c5709a3c9 slight change to Charged/Grounded wall temperature 2024-03-19 18:50:52 +01:00
Zeno Rogue c230e03a0a trees etc are now mentioned as blockers in YASC messages 2024-03-19 18:39:09 +01:00
Zeno Rogue b71cd1e44d
Merge pull request #365 from jlmjlm/ec-elec
Change some walls' electrical properties.
2024-03-14 20:41:21 +01:00
Zeno Rogue ef936d7b0e Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-03-14 20:39:34 +01:00
Zeno Rogue 97f8c5ed72 CA does not count for hyperstones 2024-03-14 20:27:01 +01:00
Zeno Rogue 94bf06f7dc custom:: disable/enable all option, and don't srestart the game when customizing 2024-03-14 20:20:33 +01:00
Zeno Rogue 261800d765 Cellular Automaton now works when enabled in land_list 2024-03-14 20:20:01 +01:00
Zeno Rogue 2b2cc4e8a9 in getNewLand, do not freeze if no land is valid 2024-03-14 20:19:27 +01:00
Zeno Rogue cbccf4936d Asteroids now has some gameplay in non-shmup 2024-03-14 19:52:22 +01:00
Zeno Rogue 68f5ad6e92 custom: Wild West now enablable 2024-03-14 19:38:26 +01:00
Zeno Rogue 9f44f98b0a fixup to Halloween 2024-03-14 19:37:24 +01:00
Zeno Rogue 5bb4b69c23 fixup to Halloween 2024-03-14 19:36:21 +01:00
Zeno Rogue 9cc370a2d2 enabling Halloween in infinite geometries now produces something that makes sense 2024-03-14 19:34:51 +01:00
Zeno Rogue 26e61783b2 in getNewLand, both laMirrorOld and laMirror are now options, so both are supported in custom land list 2024-03-14 19:31:19 +01:00
Zeno Rogue d0d354b53a removed debug from intra 2024-03-14 19:29:36 +01:00
Zeno Rogue 78a1615c6c nicer boundaries used for archimedean 2024-03-14 19:29:10 +01:00
Zeno Rogue 125b271889 hooks for do_draw 2024-03-14 19:28:44 +01:00
Zeno Rogue c85b4d2f2b save/load mode data, via CLI 2024-03-14 19:28:33 +01:00
Zeno Rogue 424186b10d horodisk_from and randomwalk_size saved to save_mode_data 2024-03-14 19:27:50 +01:00
Zeno Rogue 4421143ae5 customize land mode 2024-03-14 19:27:08 +01:00
Jacob Mandelson ee293310b6 Consider red rock & rubble to electrically insulate. 2024-03-11 18:41:41 -07:00
Jacob Mandelson a40e72f1d8 Mark trees as grounded walls. 2024-03-11 18:41:33 -07:00
Jacob Mandelson 3bd67f466a Remove trees and red rock from conductive walls. 2024-03-11 18:41:26 -07:00
Zeno Rogue ddb9fbd58e
Merge pull request #363 from jlmjlm/save-xbow-reload
Record the ranged weapons' state in the savefile
2024-02-28 15:25:35 +01:00
Zeno Rogue b152bac377
Merge pull request #362 from jlmjlm/save_fa-so-fg
Track more missing game state in saves.
2024-02-28 15:25:26 +01:00
Jacob Mandelson a626ede2bf Record the amount of revolver ammunition in save file. 2024-02-27 21:31:57 -08:00
Jacob Mandelson 1f2692a4fb Record crossbow reload time in savefile. 2024-02-26 17:18:57 -08:00
Jacob Mandelson e31c9dc263 Record moFriendlyGhost kills in savefile. 2024-02-24 16:36:48 -08:00
Jacob Mandelson 7d04b0c717 Record snake oil in savefile. 2024-02-24 16:36:40 -08:00
Jacob Mandelson 0f84812d15 Track fatigue across save/load. 2024-02-24 16:36:33 -08:00
Jacob Mandelson 80f90dec52 Remove spurious semicolon. 2024-02-24 16:36:16 -08:00
Zeno Rogue e840e39ba0 13.0c 2024-02-24 09:56:30 +01:00
Zeno Rogue fa9c2da41d fixed tide/lava help counters 2024-02-24 09:53:31 +01:00
Zeno Rogue f291bbb1d1 fixed a bug with rusalka-cursing the first tile when you shoot 2024-02-24 09:47:53 +01:00
Zeno Rogue 2de61962f9 special YASC message for pinches 2024-02-24 03:19:38 +01:00
Zeno Rogue 43fc692b47 in YASC messages, 'on the Round Table' replaced by 'being polite' 2024-02-24 03:13:48 +01:00
Zeno Rogue 87ac19febe in YASC messages, mention the knights blocking the way, and also mention their names 2024-02-24 03:13:15 +01:00
Zeno Rogue 2379228ab4 display yasc message in gameover 2024-02-24 03:00:42 +01:00
Zeno Rogue 5aac5fd2a3 missing override added 2024-02-23 01:38:32 +01:00
Zeno Rogue 46eaee44ef 13.0b 2024-02-23 01:35:48 +01:00
Zeno Rogue 21d3f8bec4 IFINGAME is now undefined 2024-02-23 01:35:35 +01:00
Zeno Rogue c2d06dc05b missed offside parameters 2024-02-23 01:35:17 +01:00
Zeno Rogue 21a782cd28 improved in/on messages, also for Brownian III 2024-02-23 01:22:30 +01:00
Zeno Rogue bf512e39ce YASC messages in shmup 2024-02-23 01:09:22 +01:00
Zeno Rogue de5ddc3034 YASC messages in hardcore mode 2024-02-23 00:48:17 +01:00
Zeno Rogue b4b00baa5e apply_chaos removed baby tortoise move since we are using moveItem 2024-02-23 00:40:13 +01:00
Zeno Rogue 648dd67dc7 fixed Curse of Repulsion to use moveItem 2024-02-23 00:39:48 +01:00
Zeno Rogue 30f6fbc16c added A human to credits 2024-02-23 00:39:27 +01:00
Zeno Rogue 00b5fe3a22 save the YASC messages in save file, and display them in score list; also auto-width and zoom 2024-02-23 00:39:12 +01:00
Zeno Rogue 55493cc364 shmup:: boat can go thru non-adjacent using Orb of Warp 2024-02-23 00:37:41 +01:00
Zeno Rogue 3b1918535f fixed Orb of Chaos not calling moveItem 2024-02-22 21:08:39 +01:00
Zeno Rogue 650108bad3 gp:: goldberg x/y limit is now based on what the engine allows 2024-02-22 20:42:17 +01:00
Zeno Rogue 79e74e8d53 gp:: 'dual of current' no longer can circumvent the limits 2024-02-22 20:41:54 +01:00
Zeno Rogue 3ed43b8c7d fixed a freeze when computing distance in INVERSE 2024-02-22 20:30:35 +01:00
Zeno Rogue 5508fb7183 fixed sizes_known returning true incorrectly in INVERSE 2024-02-22 20:30:06 +01:00
Zeno Rogue 6c682510bc fixed the Yard bug 2024-02-22 20:21:08 +01:00
Zeno Rogue 6d9f7e791b Trollheim does not generate adjacent non-unlocked troll lands 2024-02-22 18:59:08 +01:00
Zeno Rogue e343ed9c3f alternative land unlock rules when monster/item requested is not available due to geometry etc 2024-02-22 18:57:41 +01:00
Zeno Rogue 8af2a43f5e fixed a crash with too large band 2024-02-22 18:41:52 +01:00
Zeno Rogue e33f26d51f opening inventory mode when you can just shoot should be fixed 2024-02-22 18:16:27 +01:00
Zeno Rogue 60980bcb8b bow:: rusalka curses now work 2024-02-22 18:11:12 +01:00
Zeno Rogue bcc026173e fixed tricking Pikemen with a bow 2024-02-22 18:03:50 +01:00
Zeno Rogue d86f70886d bow:: while rosed, you can now only shoot when this kills a monster at point blank in the rose direction 2024-02-22 17:49:45 +01:00
Zeno Rogue 2a7e2e96ca fixed crashes when e.g. entering 'ma' as a value 2024-02-22 17:29:58 +01:00
Zeno Rogue a91f74c86c fixed a crash bug when editing custom_settings 2024-02-22 17:21:57 +01:00
Zeno Rogue 285c71e10f yasc messages 2024-02-22 17:12:49 +01:00
Zeno Rogue a28c62416f restarting a race now resets pause counter 2024-02-22 16:47:20 +01:00
Zeno Rogue bfd1945d7b classified kills[moNone] 2024-02-22 12:33:49 +01:00
Zeno Rogue f271ba6b4d Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-02-22 12:30:33 +01:00
Zeno Rogue f87a7c5f1c
Merge pull request #361 from jlmjlm/save-wtkill
Record World Turtle kills.
2024-02-22 12:30:13 +01:00
Zeno Rogue 9ce5c63708 new projection: polar coordinates 2024-02-22 01:16:43 +01:00
Jacob Mandelson 56c8838101 Record World Turtle kills. 2024-02-21 11:23:08 -08:00
Zeno Rogue 9a590ecc42 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2024-02-21 10:25:29 +01:00
Zeno Rogue eb1488b24f rogueviz:: updated reverb to compile 2024-02-21 10:24:46 +01:00
Zeno Rogue 26328f5493
Merge pull request #359 from jlmjlm/tidefix1
Calculate tidalsize before using it in mouseovers.
2024-02-19 14:22:49 +01:00
Zeno Rogue 52081a916a
Merge pull request #360 from jlmjlm/oofishfix
Record Orb of Fish in savefile.
2024-02-19 14:22:00 +01:00
Jacob Mandelson 08a774dfd4 Record Orb of Fish in savefile. 2024-02-17 20:50:10 -08:00
Jacob Mandelson acd88377a9 Calculate tidalsize before using it in mouseovers.
This way the game doesn't immediately crash when restoring a save
in tidal areas.
2024-02-14 11:13:16 -08:00
Zeno Rogue 51f59cc2fa version 13.0a 2024-01-13 09:03:12 +01:00
Zeno Rogue 5f552799e5 added fisheye_alpha to hyper.h 2024-01-13 09:02:57 +01:00
Zeno Rogue f883322ecd new Princess message 2024-01-13 08:56:41 +01:00
Zeno Rogue 8c06e184c8 added a message for not caring about roses 2024-01-11 17:51:18 +01:00
Zeno Rogue b8a5c7528b crossbow leaderboards should be fixed 2024-01-11 17:26:45 +01:00
Zeno Rogue 11aa7d5216 fixed button placement on Android once more 2024-01-11 17:23:01 +01:00
Zeno Rogue 0ea461fa7e fixed constant name 2024-01-11 17:22:20 +01:00
Zeno Rogue bdd2b5e9fd bow:: fixed mirrors in fire mode 2024-01-11 17:01:46 +01:00
Zeno Rogue 8ce805372d savemem:: larger allh array 2024-01-11 15:23:18 +01:00
Zeno Rogue 072041db06 savemem:: make sure it is not the same altmap 2024-01-11 15:23:05 +01:00
Zeno Rogue 4c6c44cc26 variant fisheye projection 2024-01-07 12:52:50 +01:00
Zeno Rogue 31471fc6c5 The bump_to_shoot flag now actually works 2024-01-07 12:52:11 +01:00
Zeno Rogue 7ad46d8e80 fixed tides in shmup and when scrolling 2024-01-07 09:33:29 +01:00
Zeno Rogue 34ab44d1e1 dipping rule no longer affects Tiger's Eyes 2024-01-07 09:23:14 +01:00
Zeno Rogue 66a3a3df6c screenshots centered 2024-01-07 09:13:44 +01:00
Zeno Rogue 0c34e9fd34 'cylidrical' stereo mode 2024-01-07 09:13:31 +01:00
Zeno Rogue cb8a3f5424 fixed changing the high-FOV mode to reset shaders 2024-01-07 09:09:18 +01:00
Zeno Rogue fc808d448b fixed FOV menu to automatically change its upper bound on high-fov modes 2024-01-07 09:08:44 +01:00
Zeno Rogue 7ad955dcff fixed two-eye rendering in stereo modes which should not cause that 2024-01-07 09:07:54 +01:00
Zeno Rogue 17b84bb4fb hyperroid updated to 13.0 2023-12-30 08:27:47 +01:00
Zeno Rogue 902986d473 vertical sliders work on Android 2023-12-30 08:10:52 +01:00
Zeno Rogue 9bc978ce16 added some CAP_ guards so Android compiles 2023-12-30 08:10:34 +01:00
Zeno Rogue 6f81743488 Android:: prevent android buttons from being too close from the center 2023-12-30 08:10:07 +01:00
Zeno Rogue f4607b63f4 moved game_keys_scroll so that it exists on Android 2023-12-30 08:08:33 +01:00
Zeno Rogue 6e3be8a92c version 13.0 2023-12-27 17:45:09 +01:00
Zeno Rogue 02efdec4b7 export daily::historical 2023-12-27 16:32:47 +01:00
Zeno Rogue 18247ec98f rogueviz:: made gobot compile without video 2023-12-27 16:32:36 +01:00
Zeno Rogue eb4b7177f3 rogueviz:: extra projection 2023-12-27 16:28:08 +01:00
Zeno Rogue 517f4af193 small fixes to gentrans 2023-12-27 16:27:05 +01:00
Zeno Rogue 2f1bb092b8 rogueviz:: list of portal scenes in portal collection 2023-12-27 16:25:33 +01:00
Zeno Rogue ffda562f7c geom3:: fixed Sol, NIH and SolN embeddings being always displayed as legal 2023-12-27 10:58:55 +01:00
Zeno Rogue c5a4cc2255 bow:: geometric crossbow can now hit monsters on the edge of vision 2023-12-27 10:50:01 +01:00
Zeno Rogue dbc51d2f94 bow:: fixed the geometric crossbow not hitting monsters inside walls 2023-12-27 10:45:24 +01:00
Zeno Rogue 3da65f4cd5 translation update: CZ 13.0 included and some fixes 2023-12-27 10:40:04 +01:00
Zeno Rogue 0c7aa7cbe3 fixed NUMLEADER in hyper.h 2023-12-27 10:23:26 +01:00
Zeno Rogue 79527688cf ls:: fixed Caribbean in ideal Voronoi 2023-12-22 11:30:09 +01:00
Zeno Rogue 364a563423 fixed the name displayed on mouseover for slime 2023-12-22 01:14:41 +01:00
Zeno Rogue a6b30fa564 fixed checkmove giving wrong answer when bow::fire_mode is active 2023-12-22 01:07:12 +01:00
Zeno Rogue eb3406d7dc fixed the bug where tides may move on orb use 2023-12-22 00:51:07 +01:00
Zeno Rogue 95ed035180 fixed typo in PL translation 2023-12-22 00:28:29 +01:00
Zeno Rogue 3d01ce808f bow:: disabled blade-only achievements 2023-12-22 00:28:11 +01:00
Zeno Rogue 558b8d7aff crossbow achievements 2023-12-21 19:51:05 +01:00
Zeno Rogue 0de012923a pressing ESC key while in fire mode now disables the fire mode 2023-12-21 19:50:01 +01:00
Zeno Rogue 7a352ccf43 in eligibility, mark that leaderboards are separate 2023-12-17 22:03:35 +01:00
Zeno Rogue 98831aff7e
Merge pull request #353 from jlmjlm/fproof_key
Make the Key fireproof.
2023-12-17 17:58:50 +01:00
Zeno Rogue 17c254e2b4
Merge pull request #352 from jlmjlm/gal21b
Make tortoise if first 21/21 tile created in > 100 turns.
2023-12-17 17:58:10 +01:00
Zeno Rogue 4fbce2ae5a a debug function added 2023-12-17 17:47:05 +01:00
Zeno Rogue cdc1696929 fixed the drawing of half-vines and mirror walls in spatial 2023-12-17 17:46:46 +01:00
Zeno Rogue 2fc42cb114 ls:: in Voronoi, made Rlyeh and Temple appear, and Haunted and Free Fall are now unavailable 2023-12-17 17:43:59 +01:00
Zeno Rogue 73884482aa using -lands option no longer enforces cheat mode 2023-12-17 17:42:47 +01:00
Zeno Rogue 8c57e8b746 in achievement eligiblity, a message if not in this version 2023-12-17 17:42:28 +01:00
Zeno Rogue f5c5a5f876 ls:: better land compatibility in Voronoi 2023-12-17 17:42:03 +01:00
Jacob Mandelson 12c464eb99 Make the Key fireproof. 2023-12-16 18:31:12 -08:00
Zeno Rogue 8e31c51bc9 achievement eligiblity added to translation 2023-12-15 11:04:47 +01:00
Zeno Rogue 71cbc8e221 achievement eligibility display 2023-12-15 11:00:41 +01:00
Zeno Rogue bce07e5914 hv:: fixed CR2 2023-12-15 11:00:41 +01:00
Zeno Rogue ed8b7d5d1d ls:: fixed Land of Storms in Horodisk and Voronoi 2023-12-15 11:00:41 +01:00
Zeno Rogue 5c24213092 fixed restoring golems in casual 2023-12-15 11:00:41 +01:00
Zeno Rogue a282ac314e shmup:: crossbow bolts now pierce multi-tile monsters 2023-12-15 11:00:41 +01:00
Zeno Rogue 5ab9bf8f11 shmup:: disabled fire-on-mouse 2023-12-15 11:00:41 +01:00
Zeno Rogue 61303fcab6 remove crossbow paths on orb use 2023-12-15 11:00:41 +01:00
Zeno Rogue 517f4a833c changelog/version number update to 12.1z was missing 2023-12-15 11:00:41 +01:00
Jacob Mandelson 27db11064c Make tortoise if first 21/21 tile created in > 100 turns. 2023-12-12 11:53:14 -08:00
Zeno Rogue 062fb577b2 fixed a bug with clicking lists in some dialogs 2023-12-12 20:09:19 +01:00
Zeno Rogue 4338ec2b43 racing:: exception on reading bad ghostmoments 2023-12-12 20:03:59 +01:00
Zeno Rogue cd7af38e2e fixed loading pre-bow character styles (fixes crashes on loading races) 2023-12-12 20:03:42 +01:00
Zeno Rogue 24c196db15 limit setland errors 2023-12-12 20:02:53 +01:00
Zeno Rogue 548e2609ce geom3:: fixed a bug with embedded maps being destroyed on restart 2023-12-12 19:18:26 +01:00
Zeno Rogue d2d6167eb9 updated Polish translation to 13.0 2023-12-03 14:50:06 +01:00
Zeno Rogue 86402cf979 fixup to honeycomb 2023-12-03 14:48:10 +01:00
Zeno Rogue 38825f3a31 added missing honeycombs to translations 2023-12-03 14:30:54 +01:00
Zeno Rogue 560cc91e95 fixed a translation bug with infinite squares 2023-12-03 14:30:08 +01:00
Zeno Rogue ffc06b981f used the same string in some places for easier translation 2023-12-03 14:29:50 +01:00
Zeno Rogue 0cdd6f8d5d hyperweb:: use XLAT1 not XLAT 2023-12-03 14:29:26 +01:00
Zeno Rogue c63969a21b fix typo 2023-12-03 14:29:08 +01:00
Zeno Rogue 7802194248 deconfused translation checker 2023-12-03 14:29:02 +01:00
Zeno Rogue a79a7f63a1 added XLAT in some places where it was missing 2023-12-03 14:28:30 +01:00
Zeno Rogue 928ab73fff menu_item_name_modified to help with translation 2023-12-03 14:10:03 +01:00
Zeno Rogue ac33354358 bow:: fix shooting bolts in blade mode 2023-12-02 21:10:11 +01:00
Zeno Rogue 39ddc3dc33 fix compile bug 2023-12-02 19:34:06 +01:00
Zeno Rogue 68a3d20d83 rug mouseover:: fix incorrect points in perspective; fix points behind eye in perspective; fix reverse Z in non-perspective (VR presumed fine) 2023-12-02 12:27:04 +01:00
Zeno Rogue 6ef4a8a5e9 draw:: fixed drawing mode on quotient spaces 2023-12-02 12:07:23 +01:00
Zeno Rogue 16cb1090e8 reduced CR3 land requirement to 20 in casual 2023-12-02 11:34:51 +01:00
Zeno Rogue 176ea28a24 bow:: mouse_fire_mode 2023-12-02 11:30:51 +01:00
Zeno Rogue 9bebbd8f4e clarified that only direct melee attacks trigger Storms/Flash 2023-12-02 11:05:28 +01:00
Zeno Rogue 4ca8a7e394 the unarmed Princess is now able to use Empathy+Thorns and Empathy+Horns 2023-12-02 11:04:47 +01:00
Zeno Rogue 8946317475 bow:: press 'f' + direction for auto fire at distant enemies in the given direction 2023-12-02 10:37:07 +01:00
Zeno Rogue 9ca0993d6f bulls are now enraged by crossbow shots 2023-12-02 09:32:50 +01:00
Zeno Rogue 2a892012b2 bow:: The warped space distracts you from reloading while staying in place 2023-12-02 09:32:34 +01:00
Zeno Rogue 53b0701d95 ratlings no longer react to useless shoots 2023-12-02 08:47:11 +01:00
Zeno Rogue 439040c90c bow:: bolts do not go through Warped 2023-12-02 08:46:31 +01:00
Zeno Rogue a840b96104 fixed VR demos 2023-12-02 08:27:38 +01:00
Zeno Rogue fe7e122613 ray:: improved ODS 2023-11-30 12:38:30 +01:00
Zeno Rogue 2dccf0d3ab reg3:: fix_stretch now can be disabled to make older recordings work 2023-11-30 12:35:06 +01:00
Zeno Rogue c69bed4d12 intra:: cleaner scale changing 2023-11-30 12:34:41 +01:00
Zeno Rogue c94e927929 intra:: in screenshot, do not call twice 2023-11-30 12:33:49 +01:00
Zeno Rogue 2dd4ef868b export record_frame_id 2023-11-30 12:32:50 +01:00
Zeno Rogue 34d3d67ace cleaned up stereo/high-FOV projections 2023-11-30 12:32:24 +01:00
Zeno Rogue 2add515fbf config:: add_edit accepts key parameter 2023-11-30 12:25:13 +01:00
Zeno Rogue 79165ae014 intra:: fixed product spaces 2023-11-23 22:11:15 +01:00
Zeno Rogue 9d4d085973 equirectangular projection in raycasting 2023-11-23 22:10:59 +01:00
Zeno Rogue 45a9e0c85a 12.1y 2023-10-29 11:05:21 +01:00
Zeno Rogue c336e9d385 crossbow:: geometric lines option 2023-10-29 11:02:58 +01:00
Zeno Rogue 8984cd8cd2 list settings may now be configured to need confirmation to change 2023-10-29 11:00:19 +01:00
Zeno Rogue f76ccef90f clear bow memory 2023-10-29 10:14:18 +01:00
Zeno Rogue 858db697d8 crossbow:: no time passes when shooting while unstable 2023-10-29 10:13:00 +01:00
Zeno Rogue 8185657768 crossbow:: fixed Z-fighting and arrow paths not visible in FPP 2023-10-29 09:57:19 +01:00
Zeno Rogue 0c6d286fa8 crossbow:: shrubs are no longer blocking 2023-10-29 09:23:57 +01:00
Zeno Rogue 76c6195d19 fixed fire_mode not disabling correctly 2023-10-29 09:22:40 +01:00
Zeno Rogue 95dc72a582 mirror:: fixed a but with target_at not cleared 2023-10-29 09:22:11 +01:00
Zeno Rogue c91dc341ae crossbow:: no more mimics attacking in melee, or swinging at mirrors 2023-10-29 09:21:49 +01:00
Zeno Rogue b84e751d96 crossbow:: crossbow moves are no longer considered valid moves for the checkmate rule when the crossbow is not loaded 2023-10-29 08:19:40 +01:00
Zeno Rogue ed9081cfd5 fixup 2023-10-29 08:06:26 +01:00
Zeno Rogue da0bf9a035 crossbow:: changed peek to cpeek just in case 2023-10-29 08:01:43 +01:00
Zeno Rogue 6030402441 crossbow:: changed start message 2023-10-29 08:00:27 +01:00
Zeno Rogue 4b97f300ff crossbow:: in fire mode, no longer display ranged orb icons on mousing 2023-10-29 08:00:19 +01:00
Zeno Rogue 0c0bf1dd84 crossbow:: reverse shoot order 2023-10-29 07:59:44 +01:00
Zeno Rogue 1926fd8434 crossbow:: improved texts 2023-10-29 07:59:19 +01:00
Zeno Rogue 6b8adfde9e crossbow:: fire_mode can now be enabled even while reloading 2023-10-29 07:58:55 +01:00
Zeno Rogue 85fc2773b1 clarify Water Elemental special case 2023-10-29 07:58:00 +01:00
Zeno Rogue 669814efce ambush:: nicer guard_attack message 2023-10-29 07:57:20 +01:00
Zeno Rogue 1f6bee5701 crossbow:: piercing dragons 2023-10-29 07:57:05 +01:00
Zeno Rogue b2c8bb96d6 crossbow:: saving tortoises now possible 2023-10-29 00:06:40 +02:00
Zeno Rogue 87f7b2a593 attacking guarding dogs now wakes up all other existing guarding dogs, and causes a small ambush -- also affects shmup mode and other ranged attacks 2023-10-28 23:44:05 +02:00
Zeno Rogue f7a25ff2d1 fixed crossbow mode not changing legacy_modecode 2023-10-28 23:34:02 +02:00
Zeno Rogue a163c80ba1 crossbow:: graves and Round Table are non-blocking, thruVine is blocking 2023-10-28 23:33:38 +02:00
Zeno Rogue b3b1611f33 v12.1x 2023-10-28 10:04:15 +02:00
Zeno Rogue 89a46a8cd1 more constexpr fixes 2023-10-28 10:04:15 +02:00
Zeno Rogue a50a87f095 another constexpr changed to const in textures.cpp 2023-10-28 10:04:15 +02:00
Zeno Rogue 33060a884c array initializer did not compile on Steam 2023-10-28 10:04:15 +02:00
Zeno Rogue 9caa4daa62 crossbow flags constexpr 2023-10-28 10:04:15 +02:00
Zeno Rogue 8e55cc9ebd movei(nullptr_t) not compiling on OSX Clang 2023-10-28 09:51:27 +02:00
Zeno Rogue 4e134c56b6 crossbow:: constexpr 2023-10-28 09:51:27 +02:00
Zeno Rogue 8129cfd726 crossbow: better mimic bowpaths, mimic bowpaths colored, mimic bowpaths slay mirror spirits 2023-10-28 09:51:27 +02:00
Zeno Rogue 3645a9b85e better optimal shoot counting 2023-10-28 09:51:27 +02:00
Zeno Rogue b0d117e646 crossbow:: checkmate rule 2023-10-28 09:51:27 +02:00
Zeno Rogue 4f82c3eb8e last_bowpath changed to more efficient bowpath_map 2023-10-28 09:51:27 +02:00
Zeno Rogue c36da1985c crossbow:: peace, dual, and non-shmup multiplayer are incompatible 2023-10-28 09:51:27 +02:00
Zeno Rogue e8ecccdf53 crossbow:: explain hedgehogs better 2023-10-28 09:51:27 +02:00
Zeno Rogue 11869c796b crossbow:: disable fire_mode on move 2023-10-28 09:51:27 +02:00
Zeno Rogue a012e6103a crossbow:: do not try shooting on stay 2023-10-28 09:51:27 +02:00
Zeno Rogue ddc7cddb91 side attacks for bows 2023-10-28 09:51:27 +02:00
Zeno Rogue daebe28d4f helpful comment for mirror::mirrors 2023-10-28 09:51:27 +02:00
Zeno Rogue 3ef09bded2 crossbow:: more detailed attack 2023-10-28 09:51:27 +02:00
Zeno Rogue f99a473720 fixed some bug wiht fire mode 2023-10-28 09:51:27 +02:00
Zeno Rogue dd37a1c6c7 crossbow:: change bow color via menu 2023-10-28 09:51:27 +02:00
Zeno Rogue 41e28c34b2 crossbow:: mimics shoot too 2023-10-28 09:51:27 +02:00
Zeno Rogue 9da8206a9f crossbow:: can hit hedgehogs 2023-10-28 09:51:27 +02:00
Zeno Rogue a233d3a7a6 crossbow:: display crossbow in shmup and on mimics 2023-10-28 09:51:27 +02:00
Zeno Rogue 3a35d351c4 crossbow:: crossbow in shmup 2023-10-28 09:51:27 +02:00
Zeno Rogue 079094799d bow changes mode, disables achievements, displayed in rich presence and bottom line 2023-10-28 09:51:27 +02:00
Zeno Rogue 4ddccfed8e system:: applyBoxEnum 2023-10-28 09:51:27 +02:00
Zeno Rogue 44265f6d61 gobot:: sphere 2023-10-28 09:51:27 +02:00
Zeno Rogue ddb06573df crossbow:: weapon selection in menu 2023-10-28 09:51:27 +02:00
Zeno Rogue 1924a03d7a crossbow:: draw crossbow on PC 2023-10-28 09:51:27 +02:00
Zeno Rogue 33d48a76b3 crossbow:: crossbow icon works 2023-10-28 09:51:27 +02:00
Zeno Rogue f3398e70c3 crossbow:: draw crossbow paths 2023-10-28 09:51:27 +02:00
Zeno Rogue c81e2bf7e8 crossbow:: crossbow colors 2023-10-28 09:51:27 +02:00
Zeno Rogue e5458c5f80 crossbow:: shapes 2023-10-28 09:51:27 +02:00
Zeno Rogue e6a4d987bb first version of crossbow 2023-10-28 09:51:27 +02:00
Zeno Rogue f8fb7d5950 locations:: null movei 2023-10-28 09:51:27 +02:00
Zeno Rogue 7e46b4b5bb config:: set_value_to for enum settings 2023-10-28 09:51:27 +02:00
Zeno Rogue 845237c756
Merge pull request #343 from Quuxplusone/constexpr
Change `static const` to `static constexpr` wherever possible
2023-10-19 12:31:56 +02:00
Zeno Rogue 9f5b13dfab
Merge pull request #348 from jlmjlm/undead_frghst
Flag moFriendlyGhost as non-living.
2023-10-19 12:31:13 +02:00
Zeno Rogue 63b6576eb6
Merge pull request #349 from jlmjlm/nosemi-postfunc
Remove semicolons from after } that close functons.
2023-10-19 12:30:48 +02:00
Jacob Mandelson db72295775 Remove semicolons from after } that close functons. 2023-10-16 21:02:54 -07:00
Jacob Mandelson 36bdc5d3f0 Flag moFriendlyGhost as non-living. 2023-10-16 20:53:24 -07:00
Zeno Rogue 5fb0099fbb v12.1w 2023-10-05 14:15:01 +02:00
Zeno Rogue ff19ceb438 modelcolor taken into account in sphere mdDisk alpha <= 1 2023-10-05 13:58:13 +02:00
Zeno Rogue 99f4b8698b fixed relative_matrix_recursive in some geoms 2023-10-05 13:55:12 +02:00
Zeno Rogue 67a77befb9 Prairie fixup 2023-10-05 13:55:00 +02:00
Zeno Rogue 1c0bf5def3 ls:: Prairie in Horodisk 2023-10-05 13:53:24 +02:00
Zeno Rogue 0ab6974cd9 fixed Hives missing in Voronoi 2023-10-05 13:10:48 +02:00
Zeno Rogue fb1f3d8f13 fixed some tiles pre-marked as mines in Minefield next to Ivory Tower in Voronoi LS 2023-10-05 12:10:34 +02:00
Zeno Rogue 72029b3fbe setland_randomwalk now takes cheat dest list into account 2023-10-05 11:51:01 +02:00
Zeno Rogue c63eebc15f fixed burial mounds not appearing in chaos/h/v land structures 2023-10-05 11:48:43 +02:00
Zeno Rogue b9d8aaee13 reverted the unintentional change which caused holes to appear in the platforms on Ivory Tower 2023-10-05 11:43:02 +02:00
Zeno Rogue ef93305313 ls:: randomwalk_size parameter added 2023-09-22 12:55:17 +02:00
Zeno Rogue fb5e4d25bb ls:: horocyclic variant of Warped Coast 2023-09-22 12:50:39 +02:00
Zeno Rogue 2c171f7be4 also made laElementalWall available 2023-09-22 12:37:30 +02:00
Zeno Rogue 64a89e732f horocycle-based Elemental Plains 2023-09-22 12:36:27 +02:00
Zeno Rogue 7b3532a594 ls:: fixed dragons not appearing in hv 2023-09-22 12:18:09 +02:00
Zeno Rogue 70b7e24e96 ls:: fixed roses not appearing in horodisk 2023-09-22 12:13:22 +02:00
Zeno Rogue 9326220310 fixed some lands not appearing in horodisk (Caribbean, Kraken, Whirlpool, Rlyeh, Temple, Haunted) 2023-09-22 12:13:06 +02:00
Zeno Rogue c2f1f4371c fixed land generation becoming glitched in standard modes when Lost Mountain or Clearing becomes unlocked 2023-09-22 11:58:56 +02:00
Zeno Rogue 9e4c883001 v12.1u 2023-09-20 23:13:46 +02:00
Zeno Rogue eeb6373338 hive is valid 2023-09-19 08:00:15 +02:00
Zeno Rogue 6db4adb91c ls:: fixed hole in H/V Ivory Tower (still a hole in Dungeon but not available anyway) 2023-09-19 07:51:13 +02:00
Zeno Rogue ec4b02d754 ls:: Hive in H/V 2023-09-18 15:41:53 +02:00
Zeno Rogue d4247e7b13 ls:: (reverse) ivory tower joins the game again in H/V 2023-09-18 14:34:46 +02:00
Zeno Rogue a74cdeeacc ls:: Galapagos now works and is fun in H/V 2023-09-18 13:02:17 +02:00
Zeno Rogue 2239d72bc8 ls:: better Brown island in h/v (but still not correct so not officially in list) 2023-09-18 12:12:13 +02:00
Zeno Rogue 4d680e13c4 dice help no longer drawn in high-quality screenshots 2023-09-18 12:07:29 +02:00
Zeno Rogue 23423e4016 ls:: fixed Ocean and some other lands generating errors when restarted in Safety in h/v mode 2023-09-18 12:07:05 +02:00
Zeno Rogue 7a7af2a536 ls:: fixed Safety in Ocean/Lost Memory/Space Rocks/Eclectic destroying land generation everywhere 2023-09-18 11:26:46 +02:00
Zeno Rogue 9fbc73025e ls:: fixed the generation of various lands in horodisk/voronoi 2023-09-18 11:24:45 +02:00
Zeno Rogue 66ea0804cf ls:: more careful incompatibility handling in voronoi 2023-09-18 11:10:41 +02:00
Zeno Rogue cab3cfe2f9 ls:: fixed some land validity rules 2023-09-18 11:09:35 +02:00
Zeno Rogue f62fcc12fc ls:: horodisk mode now has a parameter controlling perfection vs density 2023-09-18 11:09:06 +02:00
Zeno Rogue 9031b32cf4 ls:: fixed Krakens not appearing in hv_structure 2023-09-18 10:58:15 +02:00
Zeno Rogue 5076343223 12.1t 2023-09-15 08:13:12 +02:00
Zeno Rogue dd5e9dbc6e ls:: fixed Camelot in horodisk_structure 2023-09-14 21:15:00 +02:00
Zeno Rogue 1d4dac0a50 fixed voronoi crash on clearmemory -- might need better fix 2023-09-14 17:46:11 +02:00
Zeno Rogue 4aa707f197 renamed horodisk_la* to hv_la* 2023-09-14 17:37:37 +02:00
Zeno Rogue 3670be5700 debug_voronoi option 2023-09-14 17:36:31 +02:00
Zeno Rogue 78b75baf3a ls:: clearmemory clears horodisk_last_land 2023-09-14 17:36:19 +02:00
Zeno Rogue b617bc12a7 hprint:: added index_pointer_int 2023-09-14 17:36:07 +02:00
Zeno Rogue 6e695b5262 ls:: in voronoi, more varied relative distances on cross 2023-09-14 17:26:08 +02:00
Zeno Rogue 2668841e5a ls:: in voronoi, eliminate bugs when new root goes through known area 2023-09-14 17:25:55 +02:00
Zeno Rogue 283fe020fc added Dylan to credits 2023-09-14 16:38:43 +02:00
Zeno Rogue e1a78fe1ac ls:: fixed weird trees in ideal Voronoi 2023-09-14 16:29:06 +02:00
Zeno Rogue f9b8551529 ls:: firstland now taken into account in Voronoi 2023-09-14 16:20:51 +02:00
Zeno Rogue 8ac3bb29ab ls:: fixed frog park in hv 2023-09-14 15:51:36 +02:00
Zeno Rogue 8568f6489c get_child, right_child, left_child 2023-09-14 15:07:13 +02:00
Zeno Rogue 49ca18aef3 more specific 'cannot load parameter' 2023-09-14 15:07:01 +02:00
Zeno Rogue 3b341bb34b better -L option 2023-09-14 15:06:49 +02:00
Zeno Rogue 77e5efa28f ideal Voronoi implemented 2023-09-14 15:06:39 +02:00
Zeno Rogue 50e5cc2c5a ls:: horodisk implemented 2023-09-14 11:41:51 +02:00
Zeno Rogue 0293680ea1 horodisk land structure 2023-09-14 11:38:39 +02:00
Zeno Rogue f3d28c9105 fixed a crash on projection changing 2023-09-14 09:49:13 +02:00
Arthur O'Dwyer 62629f3e70 Change `static const` to `static constexpr` wherever possible
Since we require C++11, most of these consts can be constexpr.

Two `static const ld` remain non-compile-time-evaluable because
they depend on the runtime `log` function. One `static const cld`
remains non-compile-time because `std::complex<T>` doesn't become
constexpr until C++14.
2023-08-23 09:47:28 -08:00
Zeno Rogue b70b339f52 removed unused variable buf2 in mobile.cpp 2023-08-22 22:38:11 +02:00
Zeno Rogue 529e27ea2f gobot:: Discord bot token set via env variable 2023-08-22 20:20:46 +02:00
Zeno Rogue c89d98e832 rogueviz::som::adjusted to the new dialog system 2023-08-22 20:12:34 +02:00
Zeno Rogue 089db20356 play this track / quit Nil Rider in Nil Rider selection 2023-08-22 20:11:46 +02:00
Zeno Rogue 572866b67a rogueviz:: rv_keep 2023-08-22 20:06:52 +02:00
Zeno Rogue b2668e4cf5 gobot:: disk-gp and bring-gp 2023-08-22 20:06:38 +02:00
Zeno Rogue 01ede9681e gobot:: lighter owner marks 2023-08-22 20:06:28 +02:00
Zeno Rogue bb22d363c8 improved dhrg::logistic 2023-08-22 20:03:17 +02:00
Zeno Rogue fd1be4beb8
Merge pull request #341 from Quuxplusone/override
Consistently apply `override` (and not `virtual`) to overriding virtuals
2023-08-22 19:56:17 +02:00
Zeno Rogue 04f31aa637
Merge pull request #340 from Quuxplusone/format-sprintf
Avoid sprintf, in favor of hr::format and snprintf
2023-08-22 19:54:52 +02:00
Arthur O'Dwyer 28880f2985 Consistently apply `override` (and not `virtual`) to overriding virtuals
Three functions were missing `override`, triggering `-Wsuggest-override` on Clang.
Many functions had redundant `virtual ... override`.
2023-08-21 10:23:48 -07:00
Arthur O'Dwyer 10d0ed8900 Eliminate calls to `sprintf`
Apple Xcode has started giving `-Wdeprecated-declarations` warnings
for `sprintf`, and suggesting that people migrate to `snprintf` instead.
This is silly, but the warnings are spam and need to be silenced
somehow. Migrating to `snprintf` and/or `hr::format` is the path of
least resistance.
2023-08-21 10:18:44 -07:00
Arthur O'Dwyer ced3bbcad4 Qualify calls to `format`
C++20 introduces `std::format` and we `using namespace std`,
so some of these would be ambiguous in C++20.
2023-08-21 10:18:44 -07:00
Zeno Rogue a250a4d430 version 12.s 2023-08-16 10:49:39 +02:00
Zeno Rogue c1584e9ece added some missing 'override' 2023-08-16 10:36:16 +02:00
Zeno Rogue e3357c9b26 added missing override in hyper_function.h 2023-08-16 10:27:27 +02:00
Zeno Rogue 29d50a9f21 fix ori() setting in multi::two_focus 2023-08-16 10:25:57 +02:00
Zeno Rogue 0b2aee0b40 fixup hyper.h was not pushed 2023-08-16 09:54:48 +02:00
Zeno Rogue 4b5a1621e8 also fixed the use normalize_flat in celldrawer 2023-08-16 09:35:38 +02:00
Zeno Rogue 6a9ed169eb fixed normalize_flat in emb_none -- this fixes centering in multiplayer 2023-08-16 09:33:25 +02:00
Zeno Rogue 838b34762e animation rug angle fixes 2023-08-15 20:35:29 +02:00
Zeno Rogue 18d042b9eb fixed a crash when changing sight range while in rug 2023-08-15 20:29:09 +02:00
Zeno Rogue 0e1d7c024e dialog:: display crosshair when changing crosshair 2023-08-15 20:28:36 +02:00
Zeno Rogue 73e98644d3 fixed crash on kill setting change 2023-08-15 20:28:06 +02:00
Zeno Rogue 9e999ef30f cell count is now displayed while editing range/detail; range is now editable in 3D even if smart range is on 2023-08-15 19:53:29 +02:00
Zeno Rogue b7f55e9f87 made -d:param display side dialog 2023-08-15 17:54:12 +02:00
Zeno Rogue 01748ac77b more elegant matrix display 2023-08-15 17:25:00 +02:00
Zeno Rogue 610d64d22a dialog:: more intuitive rotation hotkeys 2023-08-15 17:08:41 +02:00
Zeno Rogue a5ada45164 dialog:: isitem now knows diMatrixItems 2023-08-15 17:08:25 +02:00
Zeno Rogue 442a7d3c74 fixed matrix_setting::show_edit_option to display dim 2023-08-15 17:08:12 +02:00
Zeno Rogue b123900b52 fixed camera angle: aura and shader projection 2023-08-15 16:01:38 +02:00
Zeno Rogue 37d558944e fixed bandspin explorable to use band, not Joukowsky Inverted 2023-08-15 15:49:47 +02:00
Zeno Rogue 56b5d52534 start animations were too fast 2023-08-15 15:49:25 +02:00
Zeno Rogue 42c47d0388 fixed bandshift to work with mori correctly 2023-08-15 15:49:10 +02:00
Zeno Rogue 36607319fd fixed models::rotation parameter name 2023-08-15 15:45:54 +02:00
Zeno Rogue f37c4ba165 fixed band boundary 2023-08-15 15:45:43 +02:00
Zeno Rogue b9eac3f6ae fixed addInfo to addHelp in matrix_dialog 2023-08-15 15:39:00 +02:00
Zeno Rogue 933361d394 config:: list_setting::show_edit_option won't crash if value is illegal 2023-08-15 15:28:25 +02:00
Zeno Rogue 83b49caa5f fixed multiply transmatrix * trans23 2023-08-15 15:20:46 +02:00
Zeno Rogue f2f62cf296 fixed sides in Euclidean hemisphere 2023-08-15 15:20:29 +02:00
Zeno Rogue 27bedb19ed fixed a bug which caused the screen to disappear on switch-to-fpp 2023-08-15 15:19:50 +02:00
Zeno Rogue 27b572a44a fix mdBall 2023-08-15 14:39:52 +02:00
Zeno Rogue cfa01d878c draw boundary correctly in hemisphere Euclidean 2023-08-15 14:33:53 +02:00
Zeno Rogue 937da384e7 better ring drawing in hyperboloid/hemisphere 2023-08-15 14:29:42 +02:00
Zeno Rogue f3a0855df2 queuecurve_reuse 2023-08-15 14:28:38 +02:00
Zeno Rogue e22c34b343 hemisphere in spherical 2023-08-15 14:21:19 +02:00
Zeno Rogue b018582f44 fixed mdHyperboloid in spherical geometry 2023-08-15 11:00:43 +02:00
Zeno Rogue ccb5068964 fixed draw_boundary in hyperbolic geometry in mdHemisphere and mdHyperboloid 2023-08-15 10:56:39 +02:00
Zeno Rogue 63fc2c9c92 fixed get_side 2023-08-15 10:55:01 +02:00
Zeno Rogue 53324a9eeb dialog:: made editNumber return number_dialog 2023-08-15 10:54:36 +02:00
Zeno Rogue 1b76ab495e config:: added set_cld back 2023-08-15 10:54:17 +02:00
Zeno Rogue 97be7618e6 gobot:: scores on screenshot 2023-08-14 21:17:06 +02:00
Zeno Rogue 74f1a93dc3 save_geometry now saves disksize and diskshape 2023-08-14 21:10:44 +02:00
Zeno Rogue 246034f4cb gobot:: csc command 2023-08-14 20:36:09 +02:00
Zeno Rogue 260c30c218 gobot:: last move marker 2023-08-14 20:35:58 +02:00
Zeno Rogue 394f8052b4 oauto now takes shot 2023-08-14 20:24:05 +02:00
Zeno Rogue 44e9c3e317 gobot:: clear uninitialized indices on init_go_board 2023-08-14 20:23:54 +02:00
Zeno Rogue 000726f450 gobot:: call init_go_board not init_go 2023-08-14 20:15:42 +02:00
Zeno Rogue 535d86a1c8 gobot:: fix uninitialized variable 2023-08-14 20:15:31 +02:00
Zeno Rogue a70940b3ee gobot:: clear the board in init_go_board 2023-08-14 20:15:18 +02:00
Zeno Rogue 590d8021c6 rogueviz:: use_brm only for closed_manifold, not bounded 2023-08-14 20:14:17 +02:00
Zeno Rogue 07857e612a rogueviz adjusted to the changes 2023-08-14 20:13:52 +02:00
Zeno Rogue beb679ccab dual_angle now also matrix 2023-08-14 18:11:48 +02:00
Zeno Rogue 67d38feabd camera_angle now uses matrix dialog 2023-08-14 18:08:28 +02:00
Zeno Rogue 3e1228b7c7 dialog:: in 2D matrix dialog, show degree unit, and do not negate 2023-08-14 17:44:22 +02:00
Zeno Rogue dff8db44b0 rotate immediately when editing models::rotation 2023-08-14 17:42:15 +02:00
Zeno Rogue 757579fb18 matrix dialog now used for models::rotation 2023-08-14 17:02:34 +02:00
Zeno Rogue 3eb2813667 extra_options and reaction now work in matrix dialog 2023-08-14 16:59:46 +02:00
Zeno Rogue cb05649732 pconf.ball now a matrix (but not implemented draw_boundary yet) 2023-08-14 16:18:44 +02:00
Zeno Rogue 3069dbd316 moved the constructor of projection_configuration to models 2023-08-14 13:49:07 +02:00
Zeno Rogue a7cf3c4d1c renaming also applied to drawing.cpp 2023-08-14 13:28:48 +02:00
Zeno Rogue e4562be1f5 nicer edit dialog for mori 2023-08-14 11:25:29 +02:00
Zeno Rogue d9d92bfd84 scr_to_ori functions applied in shifted bands 2023-08-14 11:25:09 +02:00
Zeno Rogue b98ac1c487 models:: fix to halfplane 2023-08-14 11:24:29 +02:00
Zeno Rogue 6806a0e7e3 renamed apply_ori to more intuitive scr_to_ori, also invert the matrix 2023-08-14 11:08:37 +02:00
Zeno Rogue ea193d23b1 dialog:: made dialog matrix more intuitive for anims::movement_angle 2023-08-14 10:52:17 +02:00
Zeno Rogue 9ab2b2bbd8 dialog:: mouse control in matrix dialog 2023-08-14 04:50:13 +02:00
Zeno Rogue 3a3317d0be dialog:: fixed crash in editingDetail 2023-08-14 04:37:01 +02:00
Zeno Rogue e666faba31 dialog:: new options for matrix dialog 2023-08-14 04:36:39 +02:00
Zeno Rogue 392d3c075f dialog:: fixed 3D matrix viz 2023-08-14 04:36:23 +02:00
Zeno Rogue c9a9a38188 dialog:: cleaned string dialog 2023-08-14 04:36:14 +02:00
Zeno Rogue f50964d576 CLI option -d:param 2023-08-13 13:54:08 +02:00
Zeno Rogue 22636060dc no more pop when number dialog calls another 2023-08-13 13:45:25 +02:00
Zeno Rogue b4e280c43f modernized animation parameters 2023-08-13 13:38:36 +02:00
Zeno Rogue dc95d4c3e6 anim:: removed obsolete skiprope_rotation, joukowsky_rotation and ballangle_rotation 2023-08-13 13:37:20 +02:00
Zeno Rogue d8f64b62ac enum settings are now animatable, and option names are recognized 2023-08-13 13:34:14 +02:00
Zeno Rogue 5cc7a4e527 matrix editor and saver are now transmatrix, not trans23 2023-08-10 14:38:59 +02:00
Zeno Rogue fe6d7abec2 improved matrix parser 2023-08-09 14:35:47 +02:00
Zeno Rogue f212f6173b commandline:: replaced legacy rotation with -sview 2023-08-09 14:35:18 +02:00
Zeno Rogue 8a124f6890 dialog:: removed debug from visualize_matrix 2023-08-09 14:23:10 +02:00
Zeno Rogue 563d16c9c1 hyper.h was missing for trans23 use 2023-08-09 14:22:51 +02:00
Zeno Rogue 4668321e4e dialog:: more fixes 2023-08-09 14:22:32 +02:00
Zeno Rogue b6f13b953b more OOP-style standard dialogs 2023-08-09 14:01:24 +02:00
Zeno Rogue 4d4874f7ac dialog:: visualize matrix items 2023-08-09 09:07:53 +02:00
Zeno Rogue 234a691ab6 more parameter improvements and fixes 2023-08-09 01:11:44 +02:00
Zeno Rogue 5057f10358 improved parameter animation 2023-08-09 01:01:32 +02:00
Zeno Rogue a13ba9bdbe param_matrix 2023-08-08 17:20:39 +02:00
Zeno Rogue c914bf86e0 fixed units in matrix parser 2023-08-08 16:30:27 +02:00
Zeno Rogue e658a471da ray:: want_use as param_i 2023-08-08 16:28:13 +02:00
Zeno Rogue a088d46e6d config:: made it work in c++14 2023-08-08 16:28:04 +02:00
Zeno Rogue 1554caa7b4 rotations are now represented as matrices, not angles 2023-08-08 16:27:52 +02:00
Zeno Rogue c896b3ecd6 bringris:: more solid lps 2023-08-08 12:12:19 +02:00
Zeno Rogue debdcae057 bringris:: fix quit 2023-08-08 12:06:25 +02:00
Zeno Rogue 22947c7fd1 ads:: do not load earth textures if already loaded 2023-08-08 12:05:33 +02:00
Zeno Rogue 522436ba96 ads:: more solid lps use 2023-08-08 12:05:18 +02:00
Zeno Rogue 4ca3d41ad5 config:: added some more param_b's 2023-08-08 12:04:19 +02:00
Zeno Rogue 7a09ab2cb0 fixes to savers 2023-08-08 12:01:36 +02:00
Zeno Rogue c42a06772b adjusted nilrider and bringris to improved lps 2023-08-08 11:50:55 +02:00
Zeno Rogue 4c59d87a34 fixed param_custom in models 2023-08-08 11:49:49 +02:00
Zeno Rogue fb3b526ae6 simplified lps 2023-08-08 11:47:08 +02:00
Zeno Rogue 301236d154 ultimate nil Christoffel formulas in model 2023-08-07 20:48:55 +02:00
Zeno Rogue d2c601834a nil Christoffel formulas in model 2023-08-07 20:46:45 +02:00
Zeno Rogue 097ded1bd0 fix for nil model-changed christoffel 2023-08-07 20:04:17 +02:00
Zeno Rogue 07aa843f18 nilrider:: fixup to default settings 2023-08-07 17:59:50 +02:00
Zeno Rogue 0cdbb0f8f4 fixup default whichCanvas is 0 2023-08-07 17:59:30 +02:00
Zeno Rogue b31ceaf3df nilrider:: adjust to collection 2023-08-07 17:16:44 +02:00
Zeno Rogue 108f4fb437 bringris:: adjust to collection 2023-08-07 17:16:17 +02:00
Zeno Rogue 38baf6605a ads:: use lps 2023-08-07 17:15:50 +02:00
Zeno Rogue 861543b9e5 config:: lps_add_enum 2023-08-07 17:15:21 +02:00
Zeno Rogue 1211de5603 config:: char settings 2023-08-07 17:14:39 +02:00
Zeno Rogue bcc86e7b30 nilrider:: using the lps system 2023-08-06 22:17:20 +02:00
Zeno Rogue 9e46638733 added some values as params 2023-08-06 22:16:29 +02:00
Zeno Rogue ec5e774613 config:: lps fixup 2023-08-06 22:13:57 +02:00
Zeno Rogue c75f7b9cd4 config:: color_setting fixup 2023-08-06 22:13:48 +02:00
Zeno Rogue 919725eabb config:: new setting type color_setting 2023-08-06 22:07:08 +02:00
Zeno Rogue 9ecd621fe8 config:: local_parameter_set 2023-08-06 22:06:39 +02:00
Zeno Rogue 56be838b40 gobot:: -go-video command 2023-08-06 12:04:30 +02:00
Zeno Rogue 32911e2b67 gobot:: improved save/load 2023-08-06 12:04:18 +02:00
Zeno Rogue 4b61d63ef5 gobot:: import/export feature 2023-08-06 11:58:16 +02:00
Zeno Rogue a830fa73b3 gobot:: ko rule checking 2023-08-06 11:58:06 +02:00
Zeno Rogue 0167e284cc gobot:: better own information 2023-08-06 11:57:48 +02:00
Zeno Rogue 9a9ecd3c8c gobot: change geometry 2023-08-06 11:57:06 +02:00
Zeno Rogue 286f98fb49 gobot: upgraded from aegis to dpp 2023-08-06 11:53:44 +02:00
Zeno Rogue 2c0afce4ca gobot: CAP_THREAD not CAP_THREADS 2023-08-06 11:52:09 +02:00
Zeno Rogue dfb3626568 used separate keyconfigs in bringris, nilrider and ads 2023-08-06 11:51:43 +02:00
Zeno Rogue 34574ad050 multi:: can now use separate key configurations for separate games in collection 2023-08-06 11:48:48 +02:00
Zeno Rogue 0168e4c7a8 hooks_control added 2023-08-06 11:47:21 +02:00
Zeno Rogue 92cf27a056 version 12.1r 2023-07-21 09:34:51 +02:00
Zeno Rogue ac336f7035 fixed some bugs with anisotropic mdDisk 2023-07-21 09:29:49 +02:00
Zeno Rogue aebcabb99c tes:: fixed a bug with apeirogonal tiles 2023-07-21 09:28:20 +02:00
Zeno Rogue 754e774bcf in adj_minefield_cells_full, change forCellIdEx to forCellIdCM 2023-07-11 17:35:54 +02:00
Zeno Rogue c6ccee56f9 representation experiments 2023-06-21 15:10:42 +02:00
Zeno Rogue 554e9c5cfc kz for array 2023-06-21 15:09:46 +02:00
Zeno Rogue a041016446 CLI -center-vertex to center on vertex; still needs i=2 to rotate the camera 2023-06-10 11:07:49 +02:00
Zeno Rogue f972170869 fixed hat-animations for spectre 2023-06-10 11:06:13 +02:00
Zeno Rogue e218b0b19f pipes for anisotropic geometries 2023-06-10 11:05:57 +02:00
Zeno Rogue 901521631f inverse_exp_newton 2023-06-10 11:05:13 +02:00
Zeno Rogue 41fda7545e new param fake_multiple 2023-06-10 10:35:27 +02:00
Zeno Rogue aa729c912c fixed stereo_alpha in some geometries 2023-06-10 10:35:09 +02:00
Zeno Rogue 59dd09173a fixed the combinations of Archimedean, fake, and embedding 2023-06-10 10:33:42 +02:00
Zeno Rogue e68cd6736e changelog for 12.1q 2023-05-31 02:19:00 +02:00
Zeno Rogue 31976a1994 12.1q 2023-05-31 02:11:14 +02:00
Zeno Rogue 51fc7b6573 improved hat_param desc 2023-05-31 02:10:31 +02:00
Zeno Rogue 965996b3fb retitled hat parameter 2023-05-31 02:09:27 +02:00
Zeno Rogue 5054b12b93 one more fix for plain floors 2023-05-30 18:44:03 +02:00
Zeno Rogue 61610282ca correct ordering of plain floors when z-ordering cannot be trusted in SVG or with alpha 2023-05-30 18:44:03 +02:00
Zeno Rogue 2153626309 patterns2:: 'big triangular grid' should now work in meuclid 2023-05-30 18:44:03 +02:00
Zeno Rogue 03b0a80be0 patterns2:: pattern 'L' to show mastery 2023-05-30 18:44:03 +02:00
Zeno Rogue 3850d8dbeb 3D floors now should work in SVG 2023-05-30 18:44:03 +02:00
Zeno Rogue 20546133c3 Berger sphere should now work correctly in subdivided 2023-05-30 18:44:03 +02:00
Zeno Rogue e069a2cd46 default_flooralpha and plainfloors 2023-05-30 18:44:03 +02:00
Zeno Rogue d587f29a91 Aperiodic Spectre tiling 2023-05-30 18:44:03 +02:00
Zeno Rogue 3e8dd6f549 arcm:: fixed a stupid bug 2023-05-30 18:44:03 +02:00
Zeno Rogue 3fdd6d4967 a new option for pseudohedral 2023-05-30 18:44:03 +02:00
Zeno Rogue 09a43c5646 cview sets playermoved to false 2023-05-23 20:21:36 +02:00
Zeno Rogue 6aed2c58e8 auxiliary function atmod 2023-05-23 20:21:20 +02:00
Zeno Rogue b808d78e7f auxiliary functions adjmod and iadjmod 2023-05-23 20:20:55 +02:00
Zeno Rogue c6b27c5b27 fixed Archimedean embeddings 2023-05-23 11:46:05 +02:00
Zeno Rogue da687e8874 12.1p 2023-05-19 01:35:05 +02:00
Zeno Rogue d179976281 rogueviz:: embedded-chess:: added CAP_VIDEO guards 2023-05-19 01:35:05 +02:00
Zeno Rogue bde2025ce3 rogueviz:: embedded-chess:: fixed default hmul 2023-05-19 01:35:05 +02:00
Zeno Rogue 9658950e6a set_char_by_name 2023-05-19 01:18:02 +02:00
Zeno Rogue a5e327f67f rogueviz:: embedded-chess:: disable reversal, it is general now 2023-05-19 01:09:21 +02:00
Zeno Rogue ccf9abc2b6 automatic reversal in swapmatrix when wallheight changes 2023-05-19 01:09:02 +02:00
Zeno Rogue d1d06b9941 rogueviz:: embedded-chess improvements 2023-05-19 01:07:48 +02:00
Zeno Rogue 02d1fbd1e7 made embedded-chess more accessible 2023-05-18 14:18:46 +02:00
Zeno Rogue 949ee1b382 fixed bucketer 2023-05-18 13:58:02 +02:00
Zeno Rogue 2d74cfe6c4 euclid::in() returns false for experimental (this is for visualizing other connections) 2023-05-18 13:22:12 +02:00
Zeno Rogue f2cb72aaeb findfont debug only with DF_INIT 2023-05-15 19:36:10 +02:00
Zeno Rogue 24cd670de0 improvement to fontconfig support 2023-05-15 19:33:32 +02:00
Zeno Rogue c03e9cfeb4
Merge pull request #300 from dulsi/master
Add optional fontconfig support.
2023-05-15 19:16:18 +02:00
Zeno Rogue d9f01c67d1 added the 3D models for embedded-chess 2023-05-15 02:50:41 +02:00
Zeno Rogue 4bcd23af08 rogueviz:: embedded-chess added 2023-05-15 02:50:41 +02:00
Zeno Rogue 71d49b7198 rogueviz:: rename nodes via color file 2023-05-15 02:50:41 +02:00
Zeno Rogue 1f834d3def popScreenAll in presentation -slide command 2023-05-15 02:50:41 +02:00
Zeno Rogue 9932a034fc improvements to objmodels: better debugging, better performance on geometry change 2023-05-15 02:50:41 +02:00
Zeno Rogue c95395f574 rogueviz::smoothcam:: export some functions 2023-05-15 02:50:41 +02:00
Zeno Rogue 494a65d16e config:: semidirect_rendering as parameter 2023-05-15 02:50:41 +02:00
Zeno Rogue 1359784e65 forced_center_down parameter 2023-05-15 02:50:41 +02:00
Zeno Rogue fd3cc72508 added bucket_scale to fix bucketing problems 2023-05-15 02:50:41 +02:00
Zeno Rogue a70e799081 raycaster:: should now work in plane embedded as Solv 2023-05-15 02:50:41 +02:00
Zeno Rogue a9d76c861c vnear_default and vfar_default are now changeable 2023-05-15 02:50:41 +02:00
Zeno Rogue 56916e8bc6 better console output in -animvideo 2023-05-15 02:50:41 +02:00
Zeno Rogue b76db976f0 periodwidth parameter 2023-05-15 02:50:41 +02:00
Zeno Rogue 60d7d1da7e sky:: fixed stars 2023-05-15 02:50:41 +02:00
Zeno Rogue e6738f6c20 semidirect rendering 2023-05-15 02:50:41 +02:00
Zeno Rogue 2e1e14c1a2 config:: set_cld function 2023-05-15 02:50:41 +02:00
Zeno Rogue f22abb7def embeddings:: fixed with center_z 2023-05-15 02:50:41 +02:00
Zeno Rogue c77a5cef22 embeddings:: removed height_limit for Clifford torus since it seems buggy 2023-05-15 02:50:41 +02:00
Zeno Rogue a0aeb6f792 rogueviz::smoothcam:: fixes for some geometries 2023-05-15 02:50:41 +02:00
Zeno Rogue 37fa49aab8 rogueviz::smoothcam:: fixed the angle unit to be degrees indeed 2023-05-15 02:50:41 +02:00
Zeno Rogue 17fc76c0eb rogueviz::smoothcam:: should now work with mirroring 2023-05-15 02:50:41 +02:00
Zeno Rogue d5064db846 rogueviz::smoothcam:: spinEdge_full called if needed 2023-05-15 02:50:41 +02:00
Zeno Rogue fccf07a07d spinEdge_full function 2023-05-15 02:50:41 +02:00
Zeno Rogue 542ce23b76 smoothcam:: smoothcam_param added 2023-05-15 02:50:41 +02:00
Zeno Rogue 97c24d7dfe smoothcam:: export functions for append, save and load animation 2023-05-15 02:50:41 +02:00
Zeno Rogue 58a1b085c7 smoothcam:: moved to namespace rogueviz 2023-05-15 02:50:41 +02:00
Zeno Rogue 3692ef68b9 placeSidewalls now set PPR::TRANSPARENT_WALL priority for walls with alpha 2023-05-15 02:50:41 +02:00
Zeno Rogue 894252caf2 sky:: draw_ceiling should not be restricted to non-sphere 2023-05-15 02:50:41 +02:00
Zeno Rogue 07c6a596e0 better wall shading in EuclidSquare embeddings 2023-05-15 02:50:41 +02:00
Zeno Rogue 227b4a15f7 sky:: simple_sky 2023-05-15 02:50:41 +02:00
Zeno Rogue 882fecf792 sky:: fixed for changed depth 2023-05-15 02:50:41 +02:00
Zeno Rogue a6c3ea03e4 embeddings:: fixed swapmatrix_iview for center_z changes 2023-05-15 02:50:41 +02:00
Zeno Rogue cca6b1b721 embeddings:: fixed a typo in emb_same_in_same::actual_to_base 2023-05-15 02:50:41 +02:00
Zeno Rogue 043fc38dc6 made euc_in_hyp scalable 2023-05-15 02:50:41 +02:00
Zeno Rogue cad46dc16f gp:: fixed wrong gp_adj on embedded 2023-05-01 15:46:42 +02:00
Zeno Rogue f9a951a2d1 hooks added for draw_ceiling 2023-04-27 22:49:15 +02:00
Zeno Rogue 9c462b2334 prevented crashes while using incorrect gpside 2023-04-27 22:48:58 +02:00
Zeno Rogue f9b0dcf8a0 fixed some crashes on out_of_bounds 2023-04-27 22:48:36 +02:00
Zeno Rogue 557166c561 embeddings:: fixed LAKE, SHALLOW, HELLSPIKE and BOTTOM to no longer exhibit extra sgn 2023-04-27 22:48:13 +02:00
Zeno Rogue 3541a39119 added hooks for generate_floorshapes 2023-04-27 22:47:50 +02:00
Zeno Rogue 7dc21f32de changed some prepare_basics to require_basics 2023-04-27 22:47:32 +02:00
Zeno Rogue 8ede45cb12 embeddings:: break cylinder feature 2023-04-27 22:46:31 +02:00
Zeno Rogue b49a52d6af changing Euclid scale now applies settings 'light' 2023-04-27 22:46:07 +02:00
Zeno Rogue d4e71b78c6 rogueviz:: use CAP_PORTALS 2023-04-15 01:30:05 +02:00
Zeno Rogue 3f1dc8a4c4 introduced new CAP, CAP_PORTALS 2023-04-15 01:30:05 +02:00
Zeno Rogue 0410f54d43 rogueviz:: added some guards 2023-04-15 01:30:05 +02:00
Zeno Rogue 782b6ab4f8 mousexs and mouseys variables in formulae 2023-04-15 01:29:59 +02:00
Zeno Rogue 921ec7ff8d removed debug message 2023-04-15 01:29:59 +02:00
Zeno Rogue 6a1601becf CAP_HOLDKEYS guard added 2023-04-15 01:29:59 +02:00
Zeno Rogue a8b75c317a mymake:: improved the web compilation 2023-04-15 01:29:59 +02:00
Zeno Rogue 9f85af3068 prevent current_linewidth from causing extra GL calls 2023-04-15 01:29:59 +02:00
Zeno Rogue f57157435e fixed a bug in rel_log 2023-04-15 01:29:59 +02:00
Zeno Rogue 0c473559f3 fixed get_value to be exported by hyperweb 2023-04-15 01:29:59 +02:00
Zeno Rogue e63feddb7c added MAXMDIM guards in various places 2023-04-15 01:29:59 +02:00
Zeno Rogue 804c3897b8 number of step reported in crystal::build_shortest_path 2023-04-15 01:29:59 +02:00
Zeno Rogue 70842eb6e9 fixup to minimize improve 2023-04-15 01:15:35 +02:00
Zeno Rogue 1271c9162a embeddings:: fixed for MAXMDIM == 3 2023-04-15 01:15:15 +02:00
Zeno Rogue d389a40bd9 removed unused variables 2023-04-15 01:14:56 +02:00
Zeno Rogue 5a4f6595e1 improved performance with MINIMIZE_GL_CALLS 2023-04-15 01:14:29 +02:00
Zeno Rogue 9832285260 fixed a warning on array indexed by char 2023-04-15 01:13:49 +02:00
Zeno Rogue 31cce8aa2c added addsaver to be exported without CAP_CONFIG 2023-04-15 01:13:31 +02:00
Zeno Rogue b5343d5696 fixed dice for MDIM==3 2023-04-15 01:13:05 +02:00
Zeno Rogue 79cde326af aperiodic-hat:: fixed a warning 2023-04-13 16:26:05 +02:00
Zeno Rogue a02cfe2062 fixed a possible crash in aperiodic hat 2023-04-13 16:25:03 +02:00
Zeno Rogue 3ded56524d silenced warnings by replacing \& with \&\& 2023-04-12 01:56:09 +02:00
Zeno Rogue 5b47779028 fixes to nofont.cpp 2023-04-11 18:13:38 +02:00
Zeno Rogue e9c2278e8e embeddings:: virtual destructor added for embedding_method 2023-04-11 17:25:21 +02:00
Zeno Rogue a471025346 guards fixup 2023-04-11 17:14:19 +02:00
Zeno Rogue 3b2c87838d fixup to more guards 2023-04-11 17:10:40 +02:00
Zeno Rogue 8760ac4cfb more guards added 2023-04-11 17:10:04 +02:00
Zeno Rogue 3e81697164 rv:: snow:: snow_not_player parameter 2023-04-11 16:50:07 +02:00
Zeno Rogue 0b6be1caff rv:: smoothcam:: works in isotropic again 2023-04-11 16:49:54 +02:00
Zeno Rogue d5e7f22073 rv:: added some guards 2023-04-11 16:48:57 +02:00
Zeno Rogue e93187a81f rv:: intra-demos improvements 2023-04-11 16:47:58 +02:00
Zeno Rogue decdfc7806 bounded_mine_percentage now configurable via CLI, also renamed to freq in config file 2023-04-11 16:46:18 +02:00
Zeno Rogue dfcfee087d added missing guard for intra 2023-04-11 16:44:22 +02:00
Zeno Rogue 7806f1cb70 boundary drawing improvements 2023-04-11 16:44:11 +02:00
Zeno Rogue 1c2dbcc7d9 fixup to hat_param_imag 2023-04-11 16:43:53 +02:00
Zeno Rogue 2576918b8a added missing override 2023-04-11 16:43:34 +02:00
Zeno Rogue 2a05642198 hat:: hat_param_imag 2023-04-11 16:41:05 +02:00
Zeno Rogue d04a015bd0 hat:: fixed typo 2023-04-04 17:57:05 +02:00
Zeno Rogue 5a33967711 missing push of rogueviz.h 2023-04-01 22:56:33 +02:00
Zeno Rogue f0b52b7034 hat skeleton animation 2023-03-30 11:26:36 +02:00
Zeno Rogue 14aaa7ecea hat:: export get_long_transform 2023-03-30 11:26:05 +02:00
Zeno Rogue 7dbb60d3f8 version 12.1o 2023-03-29 09:35:43 +02:00
Zeno Rogue 25fb183059 fixed regenerate hat in seo 2023-03-29 09:34:18 +02:00
Zeno Rogue f822d5b215 hat:: auto-fill transform levels as needed 2023-03-29 09:10:38 +02:00
Zeno Rogue 0a9141d940 fixed variation not showing 2023-03-29 09:02:41 +02:00
Zeno Rogue d1813b5ad1 fixed hat orientation 2023-03-29 09:02:28 +02:00
Zeno Rogue 8c3b073e0e version 12.1n 2023-03-28 23:43:29 +02:00
Zeno Rogue d4e264bc9b hat:: special welcome message 2023-03-28 23:09:23 +02:00
Zeno Rogue f99e95b914 fixed crashes in Zebra in Hat and some other geometries 2023-03-28 23:09:11 +02:00
Zeno Rogue a9b6452d25 fixed Zebra floor graphics in hat 2023-03-28 23:08:54 +02:00
Zeno Rogue 511ffe8498 fractal geometry 2023-03-28 22:54:46 +02:00
Zeno Rogue 121df0d9c7 fixed Terracotta in Euclidean disk 2023-03-28 22:53:31 +02:00
Zeno Rogue e3a4ca5aa7 hat:: animations:: changed the hat-atoms-colored line 2023-03-28 14:50:31 +02:00
Zeno Rogue 86838ac307 hat:: hat-animations:: shift parameter 2023-03-28 14:36:38 +02:00
Zeno Rogue 1dac5c731b fixed rainbow_color for hue == 6 2023-03-28 14:35:22 +02:00
Zeno Rogue 3baf09be25 more levels of long_transformations 2023-03-28 14:24:33 +02:00
Zeno Rogue 014f88132a fixed auto-orientation to work with adj_memo 2023-03-28 14:24:25 +02:00
Zeno Rogue e906cb985b hat:: interesting value for hat parameter 2023-03-28 14:10:36 +02:00
Zeno Rogue 7e023e8092 square root symbol 2023-03-28 14:10:13 +02:00
Zeno Rogue eaaeac8624 cleaned unused variable in 3d-models 2023-03-28 13:38:57 +02:00
Zeno Rogue 610338329b added the source code of hat animations 2023-03-28 13:32:53 +02:00
Zeno Rogue 3793bb00c3 hat: Frog Park is now OK 2023-03-28 12:48:30 +02:00
Zeno Rogue 06d250e6a5 hat:: Orb of Vaulting now works correctly 2023-03-28 12:47:03 +02:00
Zeno Rogue a0343f6108 hat:: arrow trap graphical lines shown 2023-03-28 12:46:50 +02:00
Zeno Rogue e61321aea3 hat:: full arrow trap lines shown 2023-03-28 12:46:10 +02:00
Zeno Rogue 968dfb1aac hat:: relative_matrix computation 2023-03-28 12:45:50 +02:00
Zeno Rogue e2c5420c96 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2023-03-28 11:11:55 +02:00
Zeno Rogue 17579d8301 hat:: dualpoint now reflects the tiles correctly 2023-03-28 11:11:46 +02:00
Zeno Rogue b085426f2c hat:: memoize adj for speed 2023-03-28 11:11:23 +02:00
Zeno Rogue 342c7c4484
Merge pull request #335 from jlmjlm/aip_text3
Only use 'texture' in editAt guard when CAP_TEXTURE is set.
2023-03-26 12:35:36 +02:00
Zeno Rogue fe4786d768
Merge pull request #336 from jlmjlm/ortroll3
Swap the Red Troll's hair & fur colors.
2023-03-26 12:34:26 +02:00
Zeno Rogue 759de3274a version 12.1m 2023-03-26 09:42:49 +02:00
Zeno Rogue a47dbc5dd5 fixed some crashes in embedding+arb 2023-03-26 00:37:08 +01:00
Zeno Rogue a3c861ec9e hat:: fake now actually appears in menu 2023-03-25 23:43:43 +01:00
Zeno Rogue f8b6b28c75 hat:: fixed crashes when changing hat param with mouse, also works with embedded_plane now 2023-03-25 23:43:26 +01:00
Zeno Rogue d13c939ff6 version 12.1l 2023-03-25 09:31:28 +01:00
Zeno Rogue 314a7af3fd dual_point only in aperiodic 2023-03-25 09:25:16 +01:00
Zeno Rogue cd391412aa do not display relativistic modes in model list 2023-03-25 09:25:06 +01:00
Zeno Rogue 08bf3fe3d6 an option to not display default help 2023-03-25 09:24:47 +01:00
Zeno Rogue 7e79661ce0 dual linepattern now accepts parameter 2023-03-25 00:36:20 +01:00
Zeno Rogue 4c10fd6aae hat:: keep orientation while changing parameter 2023-03-25 00:35:44 +01:00
Zeno Rogue 44454c479a minor fixes to hat parameter 2023-03-24 23:55:24 +01:00
Zeno Rogue defeaf2cc6 hat:: hat parameter 2023-03-24 23:53:13 +01:00
Zeno Rogue 56ca00df82 fixed naming conflict -W3 to -W4 2023-03-24 23:20:31 +01:00
Zeno Rogue fa9365466c hat:: disable horo and use clueless just in case 2023-03-24 23:19:53 +01:00
Zeno Rogue 9fa2ba72fe hat:: better pseudohept 2023-03-24 23:19:32 +01:00
Zeno Rogue 15623fd84d CLI -land-info to list validity for every land 2023-03-24 23:18:30 +01:00
Zeno Rogue a0f91faf67 land_validity for hat 2023-03-24 23:18:16 +01:00
Zeno Rogue 1e68511d46 patched chaos now uses cheatdest_list 2023-03-24 23:17:43 +01:00
Zeno Rogue d3da7dddc9 hat:: Jungle 2023-03-24 23:17:16 +01:00
Zeno Rogue 2ec531e056 hat:: Land of Storms 2023-03-24 23:17:09 +01:00
Zeno Rogue 9d483b1442 hat:: Palace 2023-03-24 23:17:00 +01:00
Zeno Rogue 39dcaa9e15 hat:: removed debug 2023-03-24 23:16:37 +01:00
Zeno Rogue e1ec1ef5b9 hat:: fixed tiles 2023-03-24 23:16:25 +01:00
Zeno Rogue 1a97becdf0 fake geometry for hat 2023-03-24 23:16:03 +01:00
Zeno Rogue 8dfa0efbcf aperiodic hat: formulas for the shape, better centering 2023-03-24 19:12:07 +01:00
Zeno Rogue 8efec97b24 devmods:: included a tool to generate the hat rules 2023-03-24 17:02:01 +01:00
Jacob Mandelson 7470b6996d Swap the Red Troll's hair & fur colors. 2023-03-23 13:30:07 -07:00
Zeno Rogue de0e51412c version 12.1k 2023-03-23 09:38:22 +01:00
Zeno Rogue 3faedc295b min_scale now changed to 1e-6 2023-03-23 09:29:46 +01:00
Zeno Rogue de6f5ba97a patched chaos in aperiodic tilings 2023-03-23 09:29:07 +01:00
Zeno Rogue 3416f09381 fixed a crash in hat reversing 2023-03-23 09:14:06 +01:00
Zeno Rogue bf6220913c no more repetitions in hat minesweeper 2023-03-23 02:04:39 +01:00
Zeno Rogue 9c0ff85a98 alt mine rule for aperiodic 2023-03-23 02:04:15 +01:00
Zeno Rogue 76d432aa9c arb-borders are now also used for aperiodic tilings 2023-03-23 01:37:52 +01:00
Zeno Rogue 426c350a59 conformal square improved on sphere 2023-03-23 01:37:52 +01:00
Zeno Rogue b854f68a88 aperiodic hat tiling 2023-03-23 01:37:52 +01:00
Zeno Rogue acfa454114 aperiodic is now distinct from kite::in 2023-03-23 01:37:52 +01:00
Zeno Rogue 732d80965f fixup: version 2023-03-23 01:37:52 +01:00
Zeno Rogue f9d28371b7 fixup: axial_angle 2023-03-23 01:37:52 +01:00
Zeno Rogue 15540e91e6 fixed a bug in mdBandAny 2023-03-19 12:21:15 +01:00
Zeno Rogue 1b7f4b869e new Conformal Square projection (with transition and shader and Euclidean form) 2023-03-19 12:21:05 +01:00
Zeno Rogue 02f0b1e714 bugfix 2023-03-16 23:18:45 +01:00
Zeno Rogue 4bface6860 removed name nullptr too 2023-03-16 23:18:16 +01:00
Zeno Rogue 2527398a3e availability checks configurable 2023-03-16 23:15:26 +01:00
Zeno Rogue 5986f02025 rogueviz:: adjusted extra-projections to changes 2023-03-16 23:13:55 +01:00
Zeno Rogue a434f3b063 axial angle now can be set for axial models 2023-03-16 23:13:27 +01:00
Zeno Rogue 631e44f871 fixed model flags 2023-03-16 23:12:20 +01:00
Zeno Rogue 2370084b11 two extra projections in RogueViz 2023-03-16 15:18:02 +01:00
Zeno Rogue eb867ecccc fog color is now model color if the projection is not perspective 2023-03-16 14:48:16 +01:00
Zeno Rogue 2a45504580 fixed the shader ID 2023-03-16 14:47:39 +01:00
Zeno Rogue 12a9ba163f more detailed 3D pipes 2023-03-16 14:47:23 +01:00
Zeno Rogue c862a94e46 svg:: make smaller SVG files by not including things out of the region 2023-03-16 14:47:04 +01:00
Zeno Rogue e0e1182d97 added jennlbw to the credits 2023-03-16 14:46:14 +01:00
Zeno Rogue e898c61921 improved glhr debugging 2023-03-16 14:46:05 +01:00
Zeno Rogue b6503f0059 CLI: noplayer now removes the player as the name suggests, and -drawplayer 1 draws the player 2023-03-16 14:45:29 +01:00
Zeno Rogue b8f916df3a more configuration for meridian/parallel patterns 2023-03-16 14:45:11 +01:00
Zeno Rogue 0f9b30f51b draw boundary in fisheye Euclidean 2023-03-16 14:44:44 +01:00
Zeno Rogue ef556185db X symbol from the two-point models is now configurable 2023-03-16 14:44:31 +01:00
Zeno Rogue 7bd5abbdd6 reset shaders on panini/stereo changes 2023-03-16 14:43:29 +01:00
Zeno Rogue 5473c1645c CLI option -grotatei 2023-03-16 14:43:14 +01:00
Zeno Rogue ad90aecee7 fixed crash in edgelen 2023-03-16 14:42:10 +01:00
Zeno Rogue 2a354786e4 new projection: horocyclic equal-area 2023-03-16 14:42:02 +01:00
Zeno Rogue b8059c0528 new linepattern Tri Walls 2023-03-16 14:41:00 +01:00
Zeno Rogue 66671145a9 refactored grid drawing 2023-03-16 14:40:26 +01:00
Jacob Mandelson 9982f88a41 Only use 'texture' in editAt guard when CAP_TEXTURE is set. 2023-03-11 08:27:03 -08:00
Zeno Rogue 999b26e818 embeddings:: NFC, just using more lines 2023-02-21 18:55:07 +01:00
Zeno Rogue fa528e75d2 removed floorshape warnings unless DF_GEOM 2023-02-21 18:54:14 +01:00
Zeno Rogue cf90d4e3c4 fixed a bug causing spinning in VR 2023-02-21 18:53:42 +01:00
Zeno Rogue 16e1e0d516 fixed cell boundaries key 2023-02-21 18:53:01 +01:00
Zeno Rogue b708391dd2 embeddings:: fixed emb_product_embedding::actual_to_intermediate 2023-02-21 18:52:00 +01:00
Zeno Rogue 7aa11a83ec embeddings:: fixed emb_same_in_same::actual_to_logical 2023-02-21 18:51:30 +01:00
Zeno Rogue 19fbb43bab vr:: fixed apply_movement to be geodesic-based not embedded-based in H2.5; also added new eHeadset holonomy_z 2023-02-21 18:50:36 +01:00
Zeno Rogue a07dac637b vr:: spinEdge for embedded 2023-02-21 18:48:19 +01:00
Zeno Rogue fa03b4f275 fixed an error computing distances in bitruncated {5,4} causing crashes 2023-02-21 18:47:43 +01:00
Zeno Rogue 65883a53cf embeddings:: better explained altitudes 2023-02-19 01:00:15 +01:00
Zeno Rogue 5a40534c85 embeddings:: star probability configurable 2023-02-18 19:33:27 +01:00
Zeno Rogue f73660c801 fixed a possible crash when changing -seo options when OpenGL not yet initialized 2023-02-18 19:16:21 +01:00
Zeno Rogue acdac858a3 embedded:: shFloor is now changed to shFullFloor by default; also whichShape has other options 2023-02-18 18:43:30 +01:00
Zeno Rogue a3b815741d fixed the possible crashes when changing settings 2023-02-18 18:32:54 +01:00
Zeno Rogue 5764e46bbe fixed orthogonal_move for euclidean same_in_same 2023-02-18 18:32:37 +01:00
Zeno Rogue 573304faab more detailed 3D depth settings 2023-02-18 18:32:01 +01:00
Zeno Rogue 1eaa6d4dd9 better changing embedded settings 2023-02-18 12:55:33 +01:00
Zeno Rogue e40bd436af racing:: fixed death in racing mode 2023-02-18 12:54:16 +01:00
Zeno Rogue d108f27dcf added some missing CAP_ guards 2023-02-18 12:53:52 +01:00
Zeno Rogue 53483005cf fixed ads compilation line 2023-02-18 12:42:01 +01:00
Zeno Rogue 9bda1ecbf3 rogueviz::smoothcam:: -smoothcam-anim-on 2023-02-15 14:57:57 +01:00
Zeno Rogue 9853de5775 rogueviz:: sag:: -sagfull and dofullsa now accept times as float 2023-02-15 14:57:57 +01:00
Zeno Rogue c53972c4b0 rogueviz:: objmodels:: OO design of the model class 2023-02-15 14:57:57 +01:00
Zeno Rogue f252456578 embeddings:: actually implemented emb_euc_cylinder_sl2 2023-02-15 14:57:57 +01:00
Zeno Rogue 37aa0dadee embeddings:: fixed actual_to_logical and logical_to_actual in emb_same_in_same Euclidean 2023-02-15 14:57:57 +01:00
Zeno Rogue 23f8be380d fixed a bug with configure_cylinder not knowing the correct tessf 2023-02-15 14:57:57 +01:00
Zeno Rogue 7cf7c6b216 embeddings:: 3d model fixes 2023-02-15 14:57:57 +01:00
Zeno Rogue f820f356b1 embeddings:: fixed rotation in swapmatrix_iview 2023-02-15 14:57:57 +01:00
Zeno Rogue ec4ceb5347 embeddings:: fixed items size in euc_in_hyp 2023-02-15 14:57:57 +01:00
Zeno Rogue c5e05bd199 embeddings:: fixed setting changing 2023-02-15 14:57:57 +01:00
Zeno Rogue 1295ea7920 setting eye level now affects vid.tc_camera as it should 2023-02-15 14:57:57 +01:00
Zeno Rogue 03336ecae0 rogueviz:: smoothcam:: debug removed, set last_segment on swapdim hook to recompute 2023-02-15 14:57:57 +01:00
Zeno Rogue 5bdae71879 rogueviz/smoothcam: used swapmatrix_iview and swapmatrix_view 2023-02-10 19:05:47 +01:00
Zeno Rogue 29d1a0c191 never_invert flag, mainly for debugging 2023-02-10 19:05:05 +01:00
Zeno Rogue fb2a3a7931 embeddings:: switching should now keep as much as possible 2023-02-10 19:04:32 +01:00
Zeno Rogue c2070a6fd6 embeddings:: fix euc_in_nil 2023-02-10 19:03:24 +01:00
Zeno Rogue c7de7df6fe rogueviz/smoothcam:: better smoothcam for embedded_plane 2023-02-10 15:37:10 +01:00
Zeno Rogue d0f6a94418 rogueviz/smoothcam:: kz in interpolate 2023-02-10 15:36:11 +01:00
Zeno Rogue 903c654c44 fixup correct order and detailed comment 2023-02-10 15:13:16 +01:00
Zeno Rogue 597d95ccc2 rogueviz/smoothcam:: interpolate factored out 2023-02-10 15:02:25 +01:00
Zeno Rogue 6115e5a96d texture pattern no longer affects map editor pattern 2023-02-05 22:00:29 +01:00
Zeno Rogue b104cc0361 on_dim_change clears where on sphere 2023-02-05 21:59:45 +01:00
Zeno Rogue 7d600ecdfe fixed singletile pattern 2023-02-05 21:59:35 +01:00
Zeno Rogue 472443a6d2 embeddings:: noshadow disables monster shadows 2023-02-05 21:58:56 +01:00
Zeno Rogue 0fd676e6d3 goldberg:: embeddings:: fixes 2023-02-05 21:58:38 +01:00
Zeno Rogue fe6ae71990 version 12.1i 2023-02-05 11:45:57 +01:00
Zeno Rogue 60c041e397 phi cannot be constexpr on some compilers 2023-02-05 11:38:14 +01:00
Zeno Rogue 9fd7d94af2 embeddings:: added missing override 2023-02-05 11:38:14 +01:00
Zeno Rogue c900d6823e set floor col for radar/ASCII 2023-02-05 11:24:19 +01:00
Zeno Rogue e1ed7284dd Euclidean quotient spaces no longer display as quotient OFF, and can be edited while embedded 2023-02-05 11:19:19 +01:00
Zeno Rogue ce90bb6db2 embeddings:: better info about wrong options and how to change them 2023-02-05 11:18:13 +01:00
Zeno Rogue 23e4f90685 embeddings:: reset view option in menu to fix errors 2023-02-05 10:44:36 +01:00
Zeno Rogue b89ba69fd9 local_perspective_used now known better 2023-02-05 10:31:58 +01:00
Zeno Rogue 6a1cb13c11 embeddings:: fixed emb_euc_in_nil 2023-02-05 10:30:11 +01:00
Zeno Rogue 73fc9192ce invert option listed for cylinders 2023-02-05 10:30:00 +01:00
Zeno Rogue 52d38665ae fixed crashes in 3D mode 2023-02-05 10:09:36 +01:00
Zeno Rogue 2d4cb637f2 set_view in product uses inverse_exp 2023-02-04 23:07:43 +01:00
Zeno Rogue e29b28ddb9 embeddings:: fixed default parameters for cylinders 2023-02-04 23:06:38 +01:00
Zeno Rogue e3b87792aa walking mode adds 'make_actual_view' to know whether local_perspective_used 2023-02-04 23:05:49 +01:00
Zeno Rogue e8c03acf07 reverted final_coords for now 2023-02-04 23:01:41 +01:00
Zeno Rogue 2aafe6829c embeddings:: fixed goldberg 2023-02-04 20:16:52 +01:00
Zeno Rogue f9fb1b9e84 fixed a bug generating Dice in some tessellations 2023-02-04 20:03:32 +01:00
Zeno Rogue cd673b2fd2 disabling frustum_culling option now also disables smart-range frustum culling 2023-02-04 19:44:06 +01:00
Zeno Rogue dea0c5cc58 fixed euc::in 2023-02-04 19:42:20 +01:00
Zeno Rogue 334c4715af fix_rotation compactized 2023-02-04 19:41:10 +01:00
Zeno Rogue 2fe39a6613 embeddings:: shmup fixes 2023-02-04 19:40:49 +01:00
Zeno Rogue d67b157904 embeddings:: fixed animation facing in more cylinders 2023-02-04 12:59:51 +01:00
Zeno Rogue d4eb33cd71 embeddings:: fixed radar in hyp_in_solnih 2023-02-04 12:44:33 +01:00
Zeno Rogue a48f255c17 embeddings:: fixed lmirror in hyp_in_solnih 2023-02-04 12:30:53 +01:00
Zeno Rogue 53bc23e280 embeddings: fixed sphere_in_low 2023-02-04 12:30:38 +01:00
Zeno Rogue 3183e10168 embeddings:: fixed product embedding 2023-02-04 12:29:55 +01:00
Zeno Rogue caf5b5dc8e fixed facing during animation in Cylinder -- although does not seem to be the correct fix 2023-02-04 11:56:39 +01:00
Zeno Rogue 01a3f620b0 embeddings:: fixed leg animation in product 2023-02-04 11:50:48 +01:00
Zeno Rogue 5b89cfdecf embeddings:: removed smESL2 method -- smEmbedded works fine now for all non-product embeddings 2023-02-04 11:44:42 +01:00
Zeno Rogue 793ae6fcd9 embeddings:: fixed monster movement animations in euc_in_hyp 2023-02-04 11:28:41 +01:00
Zeno Rogue 3f44c71fea draw_ceiling adds 0 to sky by default 2023-02-04 11:04:07 +01:00
Zeno Rogue db6d9c0245 embeddings:: correct ASCII in euc_in_hyp radar 2023-02-04 10:56:21 +01:00
Zeno Rogue 373c0fe152 embeddings:: fixed snake chaining 2023-02-04 10:19:13 +01:00
Zeno Rogue a14bceb681 embeddings:: simplifications 2023-02-04 10:18:01 +01:00
Zeno Rogue 32491d6425 fixed product (non-embedding) 2023-02-04 09:35:04 +01:00
Zeno Rogue de9149a8cd embeddings:: fixed Makefile 2023-02-04 09:24:06 +01:00
Zeno Rogue 3811eebc8f rogueviz:: darken_a fixed 2023-02-04 09:21:16 +01:00
Zeno Rogue 3e615d3c53 safer face_the_player 2023-02-04 09:17:10 +01:00
Zeno Rogue 4ee2c9faa3 embeddings:: editing euclid_embed parameters no longer edits them back 2023-02-04 09:17:10 +01:00
Zeno Rogue 13a90006b8 fixed remaining zpush to lzpush 2023-02-04 09:17:10 +01:00
Zeno Rogue 21e399648f 3d-models:: yet another fix to make_revolution_cut 2023-02-04 09:17:10 +01:00
Zeno Rogue d868548fa2 embeddings:: fixed xspinpush 2023-02-04 09:17:10 +01:00
Zeno Rogue 8e004230a7 embeddings:: 3d-models:: fixed animate_bird 2023-02-04 09:17:10 +01:00
Zeno Rogue 93ebe337b5 embeddings:: 3d-models:: fixed revolutions cut 2023-02-04 09:17:10 +01:00
Zeno Rogue 6056fce41a embeddings:: better yzspin 2023-02-04 09:17:10 +01:00
Zeno Rogue d8a0023c54 fixed add_texture in 3d models 2023-02-04 09:17:10 +01:00
Zeno Rogue 7ffa2a3806 fixed slime 3D model too high 2023-02-04 09:17:10 +01:00
Zeno Rogue 941379ba2a embeddings:: fixed scalefactor for euc_in_noniso 2023-02-04 09:17:10 +01:00
Zeno Rogue f09b94bfcd fixed the initialization of hpcshape 2023-02-04 09:17:10 +01:00
Zeno Rogue a536a3bc61 fixed missing shadows 2023-02-03 23:44:55 +01:00
Zeno Rogue 43f345234a embeddings:: do not try to display model boundary in perspective 2023-02-03 16:20:26 +01:00
Zeno Rogue 6950e0e1ba embeddings:: fixed vertical_vector 2023-02-03 16:11:13 +01:00
Zeno Rogue 5e0d05f10b embeddings:: fixed set_radar_transform to correctly rotate if eyelevel not 0, and also when euclid_embed_rotate is used 2023-02-03 16:08:11 +01:00
Zeno Rogue 6be7951187 ads:: demo feature (not enablable) 2023-02-03 15:28:48 +01:00
Zeno Rogue 9c04b39ed3 ads:: reverse replay feature 2023-02-03 15:28:37 +01:00
Zeno Rogue bc3b4841b7 makeradar fixes 2023-02-03 02:53:55 +01:00
Zeno Rogue 5f3c638653 fixed radar_transform in product spaces and Z clearing 2023-02-02 19:27:22 +01:00
Zeno Rogue e4c775b986 embeddings:: fixed map over itself in spherical product embedding 2023-02-02 19:26:51 +01:00
Zeno Rogue d305896c96 embedding:: fixed leaving mdGeodesic 2023-02-02 19:07:02 +01:00
Zeno Rogue dc1aa2c4c0 embeddings:: made itls and itl matrices correct in 4x4 2023-02-02 19:06:34 +01:00
Zeno Rogue bccb7b1d5d embeddings:: fixed Clifford torus 2023-02-02 19:06:06 +01:00
Zeno Rogue 637feb315a rogueviz::ads:: screenshot option 2023-01-31 16:40:29 +01:00
Zeno Rogue 8e17338585 rogueviz/ads:: adjusted to changes 2023-01-31 16:40:09 +01:00
Zeno Rogue a84596a355 better isometry in Nil cylinder 2023-01-30 17:16:35 +01:00
Zeno Rogue 0b11c9388b TAU and other constants are now declared as constexpr 2023-01-30 15:37:03 +01:00
Zeno Rogue 9ce2a90c33 embedding: Nil cylinder, also fixed the product cylinder 2023-01-30 15:36:44 +01:00
Zeno Rogue ad93a6db0b triangles in Nil Rider are now rotating 2023-01-30 01:25:40 +01:00
Zeno Rogue 98690c225c new Nil model used in Nil Rider 2023-01-30 01:20:12 +01:00
Zeno Rogue 439850f74c fixup to simple_impossible 2023-01-30 01:02:02 +01:00
Zeno Rogue c21d5373e5 simple-impossible now works with the new model, and also rotates 2023-01-30 00:46:55 +01:00
Zeno Rogue c468c90463 rogueviz/simple-impossible.cpp 2023-01-30 00:46:18 +01:00
Zeno Rogue 395cbf3668 nilv:: the Nil model is now changeable 2023-01-30 00:02:13 +01:00
Zeno Rogue 80c0b4bb0c rogueviz:: adjusted flocking to interface changes 2023-01-29 17:03:53 +01:00
Zeno Rogue b11e270eb5 chasmifyPoly now uses logical coordinates 2023-01-29 17:03:25 +01:00
Zeno Rogue 40ad4f04d2 walk parameters are now prefixed by walk -- eye_level vs eyelevel was confusing 2023-01-29 17:03:12 +01:00
Zeno Rogue ba03d33959 embedding:: a simple general implementation of radar 2023-01-29 16:09:00 +01:00
Zeno Rogue 5c2b206433 final_coords now refers to cgi.emb->logical_to_base 2023-01-29 14:17:41 +01:00
Zeno Rogue a6d53944cd fixup to coordinates 2023-01-29 14:17:03 +01:00
Zeno Rogue c0c6f44c19 moved kleinize from floorshapes to hyperpoint 2023-01-29 14:16:50 +01:00
Zeno Rogue 31a5a9e5c7 floor tiles are now constructed based on logical coordinates 2023-01-29 14:14:58 +01:00
Zeno Rogue 1e6e75c7d4 embeddings:: clarified the meaning of various coordinate systems, both in a comment and in idea 2023-01-29 14:13:30 +01:00
Zeno Rogue ce72e55353 fixup to -seo CLI option 2023-01-29 14:11:56 +01:00
Zeno Rogue 8e577bc2de embeddings:: fixup apply_always3 for CliffordTorus 2023-01-29 14:10:59 +01:00
Zeno Rogue 43b3a13dc4 embeddings:: fixed the ordering 2023-01-29 14:10:41 +01:00
Zeno Rogue 9ca8f20dc3 fixup to nicer apply_always3 2023-01-29 11:56:26 +01:00
Zeno Rogue fd55d4de89 CLI option -seo 2023-01-28 04:08:32 +01:00
Zeno Rogue 3af71864c7 embeddings:: seCylinderSL2 2023-01-28 03:56:08 +01:00
Zeno Rogue c155491ca2 fixup to last 2023-01-28 03:47:33 +01:00
Zeno Rogue 0873fe2088 cleaner apply_always3 2023-01-28 03:47:02 +01:00
Zeno Rogue a45ae2cd21 embeddings:: cylinder_horo 2023-01-27 16:46:54 +01:00
Zeno Rogue d7fe4af1e9 embeddings:: implemented the cylinderHE embedding 2023-01-27 11:16:34 +01:00
Zeno Rogue 9e2059e72b embeddings:: moved functions outside class 2023-01-27 11:15:42 +01:00
Zeno Rogue a73f85c88a fixup to simplified and fixed 2023-01-27 10:18:39 +01:00
Zeno Rogue 9e6e8e02b0 fixup to new embeddings, pointer cgi1 in sky 2023-01-27 10:18:19 +01:00
Zeno Rogue 56f5fee8dd embeddings:: simplified and fixed euc_in_sl2 2023-01-27 10:17:54 +01:00
Zeno Rogue e4239a11a4 embeddings:: emb_euc_cylinder simplified and generalized to hyperbolic 2023-01-27 10:07:40 +01:00
Zeno Rogue 85dffdbeff rewritten the embeddings more nicely 2023-01-27 00:27:10 +01:00
Zeno Rogue 8744420504 new embedding: Euclidean cylinder 2023-01-24 15:17:09 +01:00
Zeno Rogue bab78c8179 fixed configure_product_cylinder 2023-01-24 14:54:19 +01:00
Zeno Rogue 146c075210 removed functions which were moved elsewhere 2023-01-23 22:14:59 +01:00
Zeno Rogue 02e8dec195 12.1h changelog 2023-01-08 16:44:42 +01:00
Zeno Rogue 3013e956b9 12.1h 2023-01-08 16:44:28 +01:00
Zeno Rogue 2d21e9122a fixed list sliders not working correctly when quickmouse is off 2023-01-08 16:20:59 +01:00
Zeno Rogue 8a5e768b51 rogueviz::dhrg::loglik:: max steps 2023-01-08 16:03:20 +01:00
Zeno Rogue 4ff8f4b68a rogueviz::sag:: added CAP_SDL guards 2023-01-08 16:02:32 +01:00
Zeno Rogue b6c257a264 rogueviz:: newconf:: apple default shape 2023-01-08 16:02:02 +01:00
Zeno Rogue a7f95cfe3d SAG shuift_object is now geodesic 2023-01-08 16:00:42 +01:00
Zeno Rogue faee70ec3e radar in euc_in_sl2 (not great) 2023-01-08 15:59:28 +01:00
Zeno Rogue 763a932aca fixed radar in euc_in_sph (no animate), radar in euc_in_product (somewhat), fixed_YZ in euc_in_sph 2023-01-08 15:59:28 +01:00
Zeno Rogue 742355433a shallow water is no longer glitched when the 3D settings are illegal 2023-01-08 15:59:28 +01:00
Zeno Rogue ce93910f0f fixed context help getting stuck in corner stats mode 2023-01-08 15:59:28 +01:00
Zeno Rogue 5f3c58154c fixed Princess using boat 2023-01-08 15:59:28 +01:00
Zeno Rogue 8118ecd4f3 fixed the spin functions in hyp_in_solnih and euc_in_sl2 2023-01-08 15:59:28 +01:00
Zeno Rogue 6259815f7f refactored animation, and should now work in every embedded 2023-01-08 15:59:28 +01:00
Zeno Rogue 5dcddc9365 shift_view functions refactored 2023-01-08 15:59:28 +01:00
Zeno Rogue 5c1ab36b16 auto-configure S2xR embedding for Euclidean cylinder 2023-01-08 15:59:28 +01:00
Zeno Rogue 351ef88df7 improved embedded_space diagnostic help text 2023-01-07 23:21:03 +01:00
Zeno Rogue 4351f99432 fixed shmup in euc_in_nil and euc_in_sl2 2023-01-07 22:51:46 +01:00
Zeno Rogue 8e49baef0e shmup should work in euc_in_product 2023-01-07 22:19:31 +01:00
Zeno Rogue 6d0c0daa40 fixed shmup in euc_in_sph 2023-01-07 21:50:13 +01:00
Zeno Rogue 88ca5c920f fixed treasure rendering in euc_in_sph and euc_vertical 2023-01-07 21:49:04 +01:00
Zeno Rogue 14d6e33768 fixed wolf shape in Clifford torus 2023-01-07 20:40:57 +01:00
Zeno Rogue 64b5c52b80 simplified embedded shift 2023-01-07 19:47:19 +01:00
Zeno Rogue 8136d9b554 fixed camera movement in ESL2 2023-01-07 19:41:42 +01:00
Zeno Rogue f02073a35f fixed fixed_YZ in euc_in_sl2 2023-01-07 18:56:12 +01:00
Zeno Rogue e4839a19b7 fixed the coordinate system naming, and added a comment on these names 2023-01-07 16:52:24 +01:00
Zeno Rogue 8dede9f8a0 fixed bucketing for euc_in_sl2 2023-01-07 12:55:28 +01:00
Zeno Rogue 0e2b9d07ee set correct parameters for euc_in_nil and euc_in_sl2 2023-01-07 12:55:12 +01:00
Zeno Rogue b7a4997509 fixed camera movement in euc_in_sl2 2023-01-07 12:22:14 +01:00
Zeno Rogue 3f2a84be5f refactored get_logical_z 2023-01-07 11:45:40 +01:00
Zeno Rogue 57b762dfe8 fixed shift_view_towards in smLie 2023-01-07 11:44:44 +01:00
Zeno Rogue 63032a42a2 debug removed in lie_exp 2023-01-07 11:44:31 +01:00
Zeno Rogue f5f6bdcf3b euc_in_sl2 (still buggy) 2023-01-07 11:44:13 +01:00
Zeno Rogue dfb73bbdaa fixed the matrix multiplication order in prepare_lta 2023-01-07 11:33:39 +01:00
Zeno Rogue d32b0855a0 kz added for shiftmatrix and shiftpoint 2023-01-06 00:24:58 +01:00
Zeno Rogue 1fc48be781 fixed lta 2023-01-06 00:24:45 +01:00
Zeno Rogue 4b3bfb9932 euc_in_product 2023-01-06 00:09:12 +01:00
Zeno Rogue 28146b13f7 Rug option in 3D settings 2023-01-05 16:57:08 +01:00
Zeno Rogue 3052a9f29b Clifford Torus now attempts something if not a torus 2023-01-05 16:41:23 +01:00
Zeno Rogue 2d5bfc7b5a fixed reset 2023-01-05 16:37:31 +01:00
Zeno Rogue dd01cd9af4 auto-configure Clifford Torus embedding 2023-01-05 16:12:23 +01:00
Zeno Rogue 2182f442d9 more detailed Euclidean embedding parameters 2023-01-05 14:01:23 +01:00
Zeno Rogue 731fcee7ce a and b are now param_f 2023-01-04 23:31:55 +01:00
Zeno Rogue 82ce9914c5 one fixe with lie_exp 2023-01-04 23:31:12 +01:00
Zeno Rogue 601457ebc2 fixed non-shader band with shifts 2023-01-04 23:30:54 +01:00
Zeno Rogue 32546cee4a Clifford torus embedding (needs to be configured manually and on a straight square for now) 2023-01-04 23:30:36 +01:00
Zeno Rogue bc96b7fba9 CLI option -each-random 2023-01-04 23:27:27 +01:00
Zeno Rogue 1dced09f71 min_cells_drawn setting 2023-01-04 23:26:46 +01:00
Zeno Rogue 502e2c6102 fixed a crash when no last 2023-01-04 23:24:52 +01:00
Zeno Rogue a55ed32fa1 adjusted bringris to use mproduct and mhybrid 2023-01-03 20:51:29 +01:00
Zeno Rogue 016b0a95bc fixed a bug in hybrid gp 2023-01-03 20:50:48 +01:00
Zeno Rogue 7d0235b459 fixed in_smart_range for perspective 2022-12-29 21:49:43 +01:00
Zeno Rogue 7068b41d28 fixes to Lie log/exp in SL2 2022-12-29 21:19:08 +01:00
Zeno Rogue 78fb0cca20 fixed apply_perspective to use the actual z to keep z-ordering correct 2022-12-29 20:50:47 +01:00
Zeno Rogue 2999818eaf fixed rotate view 2022-12-29 20:50:17 +01:00
Zeno Rogue 86492d1181 Improved the UI for 'geodesic movement' setting, and also make it work correctly in SL2 and hyperbolic geometries 2022-12-25 12:14:36 +01:00
Zeno Rogue 080e853364 adjusted RogueViz to name changes 2022-12-18 14:06:38 +01:00
Zeno Rogue 176d5b76c1 one more change from 12.1g which was not pushed somehow 2022-12-18 01:12:28 +01:00
Zeno Rogue 868ffba2d4 fixed changelog 2022-12-18 01:11:55 +01:00
Zeno Rogue 978d9d6eda 12.1g 2022-12-18 01:01:13 +01:00
Zeno Rogue 09ae23b310 fixes to product radar 2022-12-18 00:31:41 +01:00
Zeno Rogue 9dee000a6a display error when Euclidean nonisotropic used incorrectly 2022-12-18 00:31:07 +01:00
Zeno Rogue 8ca0ef23fa dialog:: fixed coloring of info items 2022-12-18 00:29:28 +01:00
Zeno Rogue 272523d185 fixed Euler char shown in geom-exp 2022-12-18 00:21:57 +01:00
Zeno Rogue 0bedb56296 better display geometry names in geom-exp 2022-12-18 00:21:50 +01:00
Zeno Rogue 1f3db08ac4 fixed default eye levels 2022-12-18 00:16:49 +01:00
Zeno Rogue 006a325d36 fixed resetview in embedded_plane in product 2022-12-18 00:16:32 +01:00
Zeno Rogue 547c0785ef radar fixes 2022-12-18 00:16:18 +01:00
Zeno Rogue c2dc16f8ca made radar work in new embedded_planes, with some glitches 2022-12-17 23:59:39 +01:00
Zeno Rogue c252e8f51e fixed radar thrashing 2022-12-17 21:39:31 +01:00
Zeno Rogue 9793ebbff8 fixup one more isotropic 2022-12-17 21:29:25 +01:00
Zeno Rogue a5ff327ef3 fixed get_shift_view_embedded_of 2022-12-17 21:29:15 +01:00
Zeno Rogue 22d4a49b68 no, that was wrong, but still renamed 2022-12-17 21:09:20 +01:00
Zeno Rogue 1ac28797de fixed autocentering in same_in_same; also renamed smIsometric to smIsotropic 2022-12-17 21:07:32 +01:00
Zeno Rogue 14ac186fe2 Lower and Much Lower curvature settings are now respecting even if it was hyperbolic anyway 2022-12-17 20:57:08 +01:00
Zeno Rogue 8884fbc11f fixed monster facing displayed in embedded_in product 2022-12-17 20:37:07 +01:00
Zeno Rogue e68c807f68 euc_in_hyp won't be standarized 2022-12-17 20:21:33 +01:00
Zeno Rogue 8e726d1231 fixed the roof (hiding incorrectly) in gproduct 2022-12-17 20:18:49 +01:00
Zeno Rogue 534448967f fixed the roof (hiding incorrectly) in hyp_in_solnih 2022-12-17 20:06:39 +01:00
Zeno Rogue d623593392 fixed the sky in hyp_in_solnih 2022-12-17 19:59:53 +01:00
Zeno Rogue 72c1cf300e fixed binary tiling embedded in product 2022-12-17 19:34:03 +01:00
Zeno Rogue be747b7a44 yet another fix to adjust_eye in nonisotropic space 2022-12-17 19:03:36 +01:00
Zeno Rogue 805cb4dc0c fixed the computation of camera_level in sph_in_low 2022-12-17 18:40:33 +01:00
Zeno Rogue 014b4a8b23 fixed rebase in sph_in_low 2022-12-17 18:36:30 +01:00
Zeno Rogue 0e83580199 fixup to logical_to_actual 2022-12-17 18:36:05 +01:00
Zeno Rogue a3b8cdb149 fixed fix_to_2 and also renamed it to full_fix 2022-12-17 18:13:33 +01:00
Zeno Rogue 8de0f4e2e4 fixup: test removed 2022-12-17 18:00:01 +01:00
Zeno Rogue d5e5e65745 fixed shift_object in embedded 2022-12-17 17:58:55 +01:00
Zeno Rogue 2e0b3c5811 fixed hyp_in_noniso to keep the correct orientation 2022-12-17 17:57:57 +01:00
Zeno Rogue 6b337bc262 shmup:: cspin01 not spin 2022-12-17 17:41:02 +01:00
Zeno Rogue 14fd283dd2 fixed shmup with wall_height < 0 to correctly swap the 'X' coordinate 2022-12-17 17:40:42 +01:00
Zeno Rogue 436f782541 fixed shmup::fix_to_2 2022-12-17 17:38:04 +01:00
Zeno Rogue 5f645f2f25 fixed reset and auto centering 2022-12-17 17:37:26 +01:00
Zeno Rogue b2f9038cd4 fixed default eyepos in sph_in_low 2022-12-17 17:31:05 +01:00
Zeno Rogue 814467082f shift_method gets more possible arguments 2022-12-17 11:47:10 +01:00
Zeno Rogue 5da1b8f88e removed obsolete CLI options -solgeo and -solnogeo 2022-12-17 11:35:46 +01:00
Zeno Rogue 4da63f57dc renamed parallel_transport to shift_object, made it use shift_method, and made it correct for Lie movement 2022-12-17 11:35:28 +01:00
Zeno Rogue e1301e10bd fixup to shift: moved the shift methods to hyperpoint, also removed _auto 2022-12-17 11:16:47 +01:00
Zeno Rogue 70718b2602 switching nisot::geodesic_movement now automatically switches the perspective -- basically, light also moves as chosen 2022-12-16 23:08:54 +01:00
Zeno Rogue 1210de672e fixed shift in nonisotropic embeddings; also you can now choose between geodesic or embed-aware, for both manual and auto camera movement 2022-12-16 23:03:00 +01:00
Zeno Rogue dfbf553608 euc_in_nil has sky errors too 2022-12-16 01:26:28 +01:00
Zeno Rogue 78356114c1 Euclid embed scale editable 2022-12-16 01:26:11 +01:00
Zeno Rogue 4f0d16f9ed faster bt grid rendering, and also works correctly in embedded_plane 2022-12-16 01:05:18 +01:00
Zeno Rogue a525de9759 shmup works in embedded_plane product 2022-12-16 01:00:08 +01:00
Zeno Rogue e1ce20cabe correct map geometry displayed in welcome message, and both displayed in EwG 2022-12-16 00:41:17 +01:00
Zeno Rogue db43ea9de8 fixed sky over irregular map 2022-12-16 00:36:44 +01:00
Zeno Rogue 68b7beb753 simplified a bit 2022-12-15 23:16:49 +01:00
Zeno Rogue d61e498d4b kite-and-dart working correctly in embedded_plane 2022-12-15 23:13:38 +01:00
Zeno Rogue 5edb1dba04 fixup to tes working 2022-12-15 23:13:00 +01:00
Zeno Rogue 16a2aa0f4b removed debug from full-screen dialog display 2022-12-15 23:00:40 +01:00
Zeno Rogue 7195d688d0 also fixed kite-and-dart in standard spatial embedding 2022-12-15 22:58:43 +01:00
Zeno Rogue ad7cbac338 fixed tes in standard spatial embedding 2022-12-15 22:48:29 +01:00
Zeno Rogue 90977aacaf minor style changes 2022-12-15 21:18:39 +01:00
Zeno Rogue 74b59d3331 fixed raycaster in sph_in_low; seems to still need fixing in non-regular 2022-12-15 21:17:08 +01:00
Zeno Rogue 9b91d46f47 list_setting::show_edit_option for very large lists 2022-12-15 21:14:36 +01:00
Zeno Rogue 735db2bcc4 fixed horo_ok to use mhyperbolic 2022-12-15 21:03:36 +01:00
Zeno Rogue 6473ff8b45 sph_in_low function 2022-12-15 21:03:20 +01:00
Zeno Rogue a20ee8e716 fixed the euc_in_noniso function 2022-12-15 19:21:16 +01:00
Zeno Rogue 585ab12e4f reverted sky fixup 2022-12-15 19:20:56 +01:00
Zeno Rogue a67081adf8 fixed slime size 2022-12-15 19:20:49 +01:00
Zeno Rogue e8b93600f7 fixup to last: euc in sol actually works 2022-12-15 19:00:41 +01:00
Zeno Rogue 33380fba89 noniso skies 2022-12-15 18:59:20 +01:00
Zeno Rogue 839beabbc9 vertical_vector in same-in-same 2022-12-15 18:20:13 +01:00
Zeno Rogue 6b262104fd fixed vertical in embedded_plane in noniso 2022-12-15 18:15:26 +01:00
Zeno Rogue 3233ecbfde fixup inverse/flat flags no longer set to true by default 2022-12-15 18:14:09 +01:00
Zeno Rogue 91ac8a600b flat and invert are now separate flags 2022-12-15 13:11:23 +01:00
Zeno Rogue 9498a1de03 more intuitive 3D setting 2022-12-15 12:48:25 +01:00
Zeno Rogue 18cc8cbba3 small fix in euc_in_noniso 2022-12-15 11:43:43 +01:00
Zeno Rogue 10e543a44e binary-like tilings can now be embedded in Solv and variants 2022-12-15 11:43:26 +01:00
Zeno Rogue 7dac26a85a fixed wall shadows in embedded_plane 2022-12-15 10:14:06 +01:00
Zeno Rogue 3b1b263c95 fixed the variants of binary tiling in embedded_plane 2022-12-15 10:03:11 +01:00
Zeno Rogue 4e3c72551a fixed random walls to appear in embedded_plane 2022-12-15 09:59:02 +01:00
Zeno Rogue 62ffefc0cc fixed the binary tiling to use correct straight lines on the vertical edges; also grid lines now work correctly 2022-12-15 09:58:47 +01:00
Zeno Rogue f9552eb74e fixed forward direction 2022-12-13 23:51:28 +01:00
Zeno Rogue d7f7f567f7 fixed mousedist with nonisotropic mouseaim_sensitivity 2022-12-13 23:28:48 +01:00
Zeno Rogue 45d2a2c4bb fixed to point2 instead of hpxy in mousedist and shmup 2022-12-13 23:27:59 +01:00
Zeno Rogue 1b8e2623ac fixup to Nil 2022-12-13 23:27:04 +01:00
Zeno Rogue 4356f41621 other noniso embeddings of Euclidean 2022-12-13 23:26:44 +01:00
Zeno Rogue e9c04e1e77 Sol/NIH geometries now have separate gc constants 2022-12-13 19:46:57 +01:00
Zeno Rogue 557d3206a8 cheatdest_list 2022-12-13 19:05:39 +01:00
Zeno Rogue 39ce564d40 load_from on float also sets the current value 2022-12-13 19:05:04 +01:00
Zeno Rogue f61adc2865 Nil embedding 2022-12-13 19:04:43 +01:00
Zeno Rogue 63b17a605c fixed a graphical glitch when drawing chasms in euc_in_hyp 2022-12-13 12:37:29 +01:00
Zeno Rogue 5477b0e863 rogueviz:: fixed some hotkey bugs in smoothcam 2022-12-11 21:14:06 +01:00
Zeno Rogue 0dd29dd7cf adjusted RogueViz to use the new 3D functions 2022-12-11 21:12:51 +01:00
Zeno Rogue aee6285505 12.1f 2022-12-09 02:49:21 +01:00
Zeno Rogue 8c601bb575 fixed spacedist and worms on sphere 2022-12-09 02:33:15 +01:00
Zeno Rogue 1bb8056e0d fixed eyes on sphere 2022-12-09 02:33:15 +01:00
Zeno Rogue 9b3324b7eb fixed rotational models on sphere 2022-12-09 02:33:15 +01:00
Zeno Rogue 0febf06462 fixed cone graphics on sphere 2022-12-09 02:33:15 +01:00
Zeno Rogue 70421ed506 2.5D: deleteSky 2022-12-09 02:33:15 +01:00
Zeno Rogue 852dc94fad draw_sky disabled now also disables Euclidean sky 2022-12-09 02:33:15 +01:00
Zeno Rogue 0570d3afee cgi_string now record geometry class 2022-12-09 02:33:15 +01:00
Zeno Rogue 07931fcf54 2.5D: improved config 2022-12-09 02:33:15 +01:00
Zeno Rogue 80ab199607 2.5D: automatically reset, delete sky, and reset GL on change embedding (not sure why reset GL is needed...) 2022-12-09 02:33:15 +01:00
Zeno Rogue acaa04dace fixed mouseover selection in embedded sphere 2022-12-09 02:33:15 +01:00
Zeno Rogue fbeac1354d fixed some more reverse levels 2022-12-09 02:33:15 +01:00
Zeno Rogue 69af3ee4e3 embedded_plane:: safer pushing 2022-12-09 02:33:15 +01:00
Zeno Rogue 0c59d626bb disabled Archimedean check in embedded_plane 2022-12-09 02:33:15 +01:00
Zeno Rogue d334062656 fixed some bugs with sphere embedded in product 2022-12-09 02:33:15 +01:00
Zeno Rogue 689f64ed98 setup for sphere embedded in product 2022-12-09 02:33:15 +01:00
Zeno Rogue 107cae8f5c fixed 2D vector art displayed on sphere 2022-12-09 02:33:15 +01:00
Zeno Rogue 2857bc95dc disabled the HYBRID flag, embedded-into-products are not really hybrids 2022-12-09 02:33:15 +01:00
Zeno Rogue 0fd929a53b fixed the computation of cgi.STUFF 2022-12-09 02:33:15 +01:00
Zeno Rogue 08b72c52b3 fixed arcm geometry setting 2022-12-09 02:33:15 +01:00
Zeno Rogue bcbd5808f9 fixed the Ivy placement in embedded_plane 2022-12-09 02:33:15 +01:00
Zeno Rogue ababcdfee8 fixed a potential bug in generate_floorshapes() -- generate the models up to FULL_EDGE, as S6 could exceed S7 2022-12-09 02:33:15 +01:00
Zeno Rogue 2f2e770d64 fixed a possible bug in gldraw -- ioffset instead of offset 2022-12-09 02:33:15 +01:00
Zeno Rogue 49c871cf19 NightStar is now smaller in Euclidean 2022-12-09 02:33:15 +01:00
Zeno Rogue 3e733ae6e9 Big change: spatial_embedding option 2022-12-09 02:33:15 +01:00
Zeno Rogue 90dd9e9866 fixed the underflow of mpdist 2022-12-09 02:33:15 +01:00
Zeno Rogue 41d28b267f fixed make_star with BADMODEL 2022-12-09 02:33:15 +01:00
Zeno Rogue 429ed81293 added finishshape before clone_shape as it could damage the previous shape 2022-12-09 02:33:15 +01:00
Zeno Rogue bf001926c2 refactored the vertical movement functions 2022-12-09 02:33:15 +01:00
Zeno Rogue adfab30c62 fixed a bug with shmup missile levels 2022-12-09 02:33:15 +01:00
Zeno Rogue 8a7b35e3ee 2.5D:: fixed sky colors 2022-12-04 16:42:08 +01:00
Zeno Rogue cfc62c5ee0 Fixed the radar transform computation in 2.5D. The bug also affected fog rendering 2022-12-04 16:30:51 +01:00
Zeno Rogue 9337240d49 inventory:: added missing outlines 2022-12-04 15:35:58 +01:00
Zeno Rogue 0f4cb95adc fixed the missing outlines in displayglyph 2022-12-04 15:35:44 +01:00
Zeno Rogue fcfadf9eaa inv:: correct dialogcolor used 2022-12-04 15:25:48 +01:00
Zeno Rogue 2524fb76d0 dialog:: added constants for all colors used in dialogs (but no settings in menu yet); refactored a bit, fixing minor inconsistencies 2022-12-04 15:24:42 +01:00
Zeno Rogue 31f7db81c7 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-12-04 14:49:23 +01:00
Zeno Rogue 2e9ee75dc3 dialog:: lists in help extensions 2022-12-04 14:49:06 +01:00
Zeno Rogue 42f96b768c improvements to sphere flipping 2022-12-04 14:48:12 +01:00
Zeno Rogue 0770a11164 dialog::first_list_fake_key constant 2022-12-04 14:46:50 +01:00
Zeno Rogue 5d13663695 improved the orb text display in OSM for icons 2022-12-04 14:45:55 +01:00
Zeno Rogue 2cb27a165b
Merge pull request #328 from jlmjlm/pof1
Give the Plane of Fire a redder floor than CR4.
2022-12-04 14:00:02 +01:00
Jacob Mandelson 2e3d0ecd7c Give the Plane of Fire a redder floor than CR4. 2022-11-28 19:10:42 -08:00
Zeno Rogue 301dad5d7b sag:: sagsmooth option 2022-11-13 16:22:55 +01:00
Zeno Rogue 9297c94028 in non-perspective modes, draw disk restriction as wireframes instead of solid walls 2022-11-13 16:22:55 +01:00
Zeno Rogue 828c185520 rogueviz:: edit weight gamma via UI 2022-11-13 16:22:55 +01:00
Zeno Rogue 84344e7d5d sag:: fixup to sag_edge 2022-11-13 16:22:55 +01:00
Zeno Rogue 6450f7c8a6 sag:: set RV_INVERSE_WEIGHT flag 2022-11-13 16:22:55 +01:00
Zeno Rogue 97fb10b6f0 sag:: vizsa_len now has a default value which does not invoke division-by-zero bugs 2022-11-13 16:22:55 +01:00
Zeno Rogue 0faf07741c rogueviz:: configure_edge_display can now edit visible_from_hi 2022-11-13 16:22:55 +01:00
Zeno Rogue 67b70ea7fd rogueviz:: an option to show edge weights as labels 2022-11-13 16:22:55 +01:00
Zeno Rogue b7aae63b90 rogueviz:: remove visible_from_help, it just displays a list 2022-11-13 16:22:55 +01:00
Zeno Rogue 06523e063e used cyclefix and raddif in more places; (c)spin90, (c)spin180 and spin180 functions; rephrased M_PI in terms of TAU and x._deg when applicable 2022-11-13 16:22:55 +01:00
Zeno Rogue 563b9c1f74 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-11-11 14:57:19 +01:00
Zeno Rogue 612356db7f added missing leastsquare 2022-11-11 14:56:59 +01:00
Zeno Rogue cf75e6f2ab
Merge pull request #323 from jlmjlm/mir-lh
Draw mimics with sword in left hand if PC's sword in left hand.
2022-11-05 16:44:59 +01:00
Zeno Rogue 13b8230238 fixed the date of update 12.1e 2022-11-04 23:59:04 +01:00
Zeno Rogue 6fff924753 version 12.1e 2022-11-04 23:57:51 +01:00
Zeno Rogue 16d142711a fixed #define T spilling 2022-11-04 23:57:51 +01:00
Zeno Rogue 1cbaf36698 added guards to dhrg.h 2022-11-04 23:53:13 +01:00
Zeno Rogue ba009a80b2 intra:: reset raycaster on changes; do not try to change scalefactor automatically 2022-11-04 23:42:48 +01:00
Zeno Rogue af851a1d70 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-11-04 23:15:44 +01:00
Zeno Rogue f2785d22a4
Merge pull request #324 from jlmjlm/weburl
Correct URL in help text.
2022-11-04 23:15:29 +01:00
Zeno Rogue 2bab227d4e Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-11-04 23:15:11 +01:00
Zeno Rogue e65723002f tactic:: fixed page buttons 2022-11-04 23:15:00 +01:00
Zeno Rogue c65d17063f yendor:: improved layout 2022-11-04 23:15:00 +01:00
Zeno Rogue 266d6fd50d shmup:: fixed Gadflies appearing forever 2022-11-04 23:15:00 +01:00
Zeno Rogue b4302ac6b4 shmup:: count_pauses is now reset to 0, and also not displayed in standard shmup 2022-11-04 23:15:00 +01:00
Zeno Rogue 035532ef26 shmup:: fixed pink tortoises 2022-11-04 23:15:00 +01:00
Zeno Rogue 774c8a9744 shmup:: Bulls now correctly destroy walls they crash into 2022-11-04 23:15:00 +01:00
Zeno Rogue 4daacb7337 shmup:: used curtime correctly instead of ticks; also fixed Flail Guards 2022-11-04 23:15:00 +01:00
Zeno Rogue 622bb9e5f7 when setting Elemental Wall as cheat destination, Elemental Wall itself is no longer picked 2022-11-04 23:15:00 +01:00
Zeno Rogue 320aac6b9a dialog:: larger file dialog, automatically set position 2022-11-04 23:15:00 +01:00
Zeno Rogue 2bc0de05a6 dialog:: search in file dialog 2022-11-04 23:15:00 +01:00
Zeno Rogue 8e1c05d3cf dialog:: refactor hasInfix 2022-11-04 23:15:00 +01:00
Zeno Rogue 0ff46ff143 dialog:: DIALOG_WIDE 2022-11-04 23:14:59 +01:00
Zeno Rogue 3ab4915ff4 dialog:: find_highlight 2022-11-04 23:14:59 +01:00
Zeno Rogue 5c4cf73937
Merge pull request #325 from jlmjlm/acc3
Have ACCONLY3 show all three alternatives.
2022-11-04 23:12:29 +01:00
Jacob Mandelson 383dd421bd Have ACCONLY3 show all three alternatives. 2022-11-04 09:12:08 -07:00
Jacob Mandelson 94d90cf5e0 Correct URL in help text. 2022-11-04 08:06:02 -07:00
Zeno Rogue 1482a7aca2 12.1d 2022-10-27 16:07:14 +02:00
Zeno Rogue 85483d62dd ineligible_starting_land disables achievements 2022-10-27 16:06:39 +02:00
Zeno Rogue cfac1cf3ab made file dialog more intuitive 2022-10-27 16:06:39 +02:00
Zeno Rogue 303d173bf6 mousewheel now works in dialog lists 2022-10-27 16:06:39 +02:00
Zeno Rogue 2d1cff6549 display F4 key name correctly, and 'fake keys' not displayed 2022-10-27 16:06:39 +02:00
Zeno Rogue 7267b3c7ce fixed overview page buttons back 2022-10-27 16:06:39 +02:00
Zeno Rogue fb6e8b72da racing:: limit on pauses 2022-10-27 16:06:39 +02:00
Zeno Rogue 32f876dc4f fixed the ogg files 2022-10-27 16:06:39 +02:00
Zeno Rogue 0639c9c027 intra:: select edge ratio 2022-10-27 16:06:39 +02:00
Zeno Rogue 64a613572a fixed through_wall 2022-10-27 16:06:39 +02:00
Zeno Rogue 18f571b683 default dialog handler now does panning 2022-10-27 16:06:39 +02:00
Zeno Rogue f606174445 fixed point_direction 2022-10-27 16:06:39 +02:00
Zeno Rogue 0c22ab2b4b intra:: allow panning, edit inside walls, and draw the portal to edit 2022-10-27 16:06:39 +02:00
Zeno Rogue 6ef282173f map editor:: building mode 2022-10-27 16:06:39 +02:00
Zeno Rogue 87921fe0f9 special welcome message for portal maps 2022-10-27 16:06:39 +02:00
Zeno Rogue 419837a375 ray::fixed_map changed from raycaster menu 2022-10-27 16:06:39 +02:00
Zeno Rogue 1ac22f4be1 ray:: use mapeditor::map_version to recreate the map 2022-10-27 16:06:39 +02:00
Zeno Rogue 3ce5597cc1 editing map/portals now changes map_version 2022-10-27 16:06:39 +02:00
Zeno Rogue f4282e1118 intra:: create/manage portal maps from the map editor 2022-10-27 16:06:39 +02:00
Zeno Rogue a83228cd15 display some help for portal maps 2022-10-27 16:06:39 +02:00
Zeno Rogue efe7eea3de intra:: an option to set recommended settings 2022-10-27 16:06:39 +02:00
Zeno Rogue 1791190493 intra:: unconnected portals form a list 2022-10-27 16:06:39 +02:00
Zeno Rogue c2acb4f271 intra:: select world for a list, or load another world from a saved map 2022-10-27 16:06:39 +02:00
Zeno Rogue e653f4eaeb shiftclick in mapeditor now deletes stuff 2022-10-27 16:06:39 +02:00
Zeno Rogue 60a3f21b9f compute_cell_color factored out 2022-10-27 16:06:39 +02:00
Zeno Rogue 7ca6eb1658 pure_keys_scroll now available in map settings 2022-10-27 16:06:39 +02:00
Zeno Rogue a71207800b rogueviz::sag::display match A/B parameters 2022-10-27 16:06:39 +02:00
Zeno Rogue 3506ccac13 rogueviz::sag:: loglik_repeat works better now 2022-10-27 16:06:39 +02:00
Zeno Rogue 5cdbca3b21 optimize_sag_loglik for match 2022-10-27 16:06:39 +02:00
Zeno Rogue e011f86671 sag:: an option to generate fake data, mainly for smMatch 2022-10-27 16:06:39 +02:00
Zeno Rogue 5a19fffd8f rogueviz::sag:: smMatch method 2022-10-27 16:06:39 +02:00
Zeno Rogue bb5fa51965 rogueviz::sag:: prepared for further methods 2022-10-27 16:06:39 +02:00
Zeno Rogue d828ff0e7e output_stats may include numiter and temperatures 2022-10-27 16:06:39 +02:00
Zeno Rogue fa7145586f fixup to long long 2022-10-27 16:06:39 +02:00
Zeno Rogue a1695a82d0 rogueviz::sag:: automatically set RT to average values 2022-10-27 16:06:39 +02:00
Zeno Rogue c8a1c8b5d7 rogueviz::sag;: geometry stats 2022-10-27 16:06:39 +02:00
Zeno Rogue 4c30e6051f rogueviz::sag:: Dijkstra edges, save/load distances from file 2022-10-27 16:06:39 +02:00
Zeno Rogue 15d97a8cd1 rogueviz::sag:: angular distances 2022-10-27 16:06:39 +02:00
Zeno Rogue d39623fdd5 rogueviz::sag:: ll fixup 2022-10-27 16:06:39 +02:00
Zeno Rogue fd9d58073a arg:: added argll 2022-10-27 16:06:39 +02:00
Zeno Rogue 7ad4668623 rogueviz::sag:: numiter is now long long 2022-10-27 16:06:39 +02:00
Zeno Rogue e7bebaa79c rogueviz::sag:: conserve memory for sagdist 2022-10-27 16:06:39 +02:00
Zeno Rogue b8b1df01e7 fixed some linewidth issues 2022-10-27 16:06:39 +02:00
Zeno Rogue 472cbe205b renamed display 'recently changed settings' to 'find a setting', also recently changed now use a list widget 2022-10-27 16:06:39 +02:00
Zeno Rogue b89204e616 expansion improved again: auto_extend can be disabled 2022-10-27 16:06:39 +02:00
Zeno Rogue fc2e10739d an option to select max distance is back 2022-10-27 16:06:39 +02:00
Zeno Rogue 8294246449 dialog:: sm::NARROW_LINES 2022-10-27 16:06:39 +02:00
Zeno Rogue caa4ac5bb4 sm::AUTO_VALUES to automatically assign option widths 2022-10-27 16:06:39 +02:00
Zeno Rogue 5c507e58fd invslider fixup 2022-10-27 16:06:39 +02:00
Zeno Rogue 9ab7bfeaae dialog:: list used in models 2022-10-27 16:06:39 +02:00
Zeno Rogue cb4955e397 dialog:: list used in inv 2022-10-27 16:06:39 +02:00
Zeno Rogue 65095edea8 lists in expansion dialog 2022-10-27 16:06:39 +02:00
Zeno Rogue bcadbdbcab rogueviz:: vertex search improvements 2022-10-27 16:06:39 +02:00
Zeno Rogue 29ba4138a4 dialog:: improvements to list dialogs 2022-10-27 16:06:39 +02:00
Zeno Rogue 06f450af22 dialog:: lists keep the mouse better 2022-10-27 16:06:39 +02:00
Zeno Rogue 3408c1119f dialog:: automatically move list_skip 2022-10-27 16:06:39 +02:00
Zeno Rogue 40ca8b8553 rogueviz:: list used in smoothcam 2022-10-27 16:06:39 +02:00
Zeno Rogue bf86077ebf rogueviz:: list used in rogueviz vertex search 2022-10-27 16:06:39 +02:00
Zeno Rogue 6b8c177c33 dialog:: list used in find_setting 2022-10-27 16:06:39 +02:00
Zeno Rogue bbbf2f9cd0 config add_edit accept int keys 2022-10-27 16:06:39 +02:00
Zeno Rogue 0fc2dc2d65 dialog:: list used in mapeditor 2022-10-27 16:06:39 +02:00
Zeno Rogue 10e9c0fabe dialog:: list used in scroes 2022-10-27 16:06:39 +02:00
Zeno Rogue 781d6f0257 dialog:: list used in Yendor 2022-10-27 16:06:39 +02:00
Zeno Rogue 3b5a5c01c5 dialog:: file dialogs now use list 2022-10-27 16:06:39 +02:00
Zeno Rogue 42a1615d0d dialog:: addBoolItem_action now accepts int argument 2022-10-27 16:06:38 +02:00
Zeno Rogue 5ca19a0d9b hotkeys for geometry filters; geometry list is now a list; unfiltered list 2022-10-27 16:06:38 +02:00
Zeno Rogue 72bdd123a2 geom-exp:: 'load from file' appears in the geometry menu 2022-10-27 16:06:38 +02:00
Zeno Rogue 601250f2de dialog:: control lists with mouse 2022-10-27 16:06:38 +02:00
Zeno Rogue 0d2f054d2b dialog:: lists; highlight should now work even if multiple items have the same name 2022-10-27 16:06:38 +02:00
Jacob Mandelson 7e2b8baf2f Draw mimics with sword in left hand if PC's sword in left hand. 2022-10-16 10:02:32 -07:00
Zeno Rogue 93892718c5 CAP_ARCM guards added 2022-10-16 10:31:17 +02:00
Zeno Rogue 49564b2e0e should no longer freeze when maxv/unit or maxv/tank is negative or too large 2022-10-16 09:48:57 +02:00
Zeno Rogue 3c867a7ff0 ads-game:: joystick control 2022-10-16 09:46:04 +02:00
Zeno Rogue 0c38c4ad68 ads-game:: improvements to dS 2022-10-16 09:37:21 +02:00
Zeno Rogue 122ea6dfb4 informed about hidden dependencies in rogueviz/ads/ 2022-10-15 22:58:46 +02:00
Zeno Rogue 875b0159e6 nonisotropic range parameters now work in all perspective modes 2022-10-15 22:58:30 +02:00
Zeno Rogue 9c603c13d4 slr:: slr::range_z parameter 2022-10-15 22:57:37 +02:00
Zeno Rogue e74f2e3c78 ads-game:: improvements to CLI switches 2022-10-15 22:56:42 +02:00
Zeno Rogue 10856a6694 ads-game:: fixes to ghosts 2022-10-15 22:56:27 +02:00
Zeno Rogue 55d4f93873 no copyright line shown if texture not shown due to wrong mode 2022-10-15 22:56:10 +02:00
Zeno Rogue 4e7b95e346 ads-game:: new view modes are now available in the menu 2022-10-15 22:55:33 +02:00
Zeno Rogue 971ce2aade ads-game:: more default settings set in set_config 2022-10-15 22:53:13 +02:00
Zeno Rogue e129ce08c6 ads-game:: print for cross_result 2022-10-15 21:38:36 +02:00
Zeno Rogue 6e1c32787a ads-game:: AdS cross0_cone now takes auto_rotate into account 2022-10-15 21:37:26 +02:00
Zeno Rogue 38fddfa43f ads-game:: past/future cone view 2022-10-15 17:56:15 +02:00
Zeno Rogue 1ace6d4fff ads-game:: switch_replay only while in pause 2022-10-15 14:26:55 +02:00
Zeno Rogue 1d41b80b2a ads-game:: no more crash when trying to restart while in spacetime 2022-10-15 14:26:42 +02:00
Zeno Rogue c6dad6ee99 ads-game:: spacetime functions renamed 2022-10-15 14:26:12 +02:00
Zeno Rogue 17e2a56320 ads-game:: better organized spacetime display 2022-10-15 14:25:31 +02:00
Zeno Rogue 5423eebc2d ads-game:: cleanup nomap 2022-10-15 14:24:56 +02:00
Zeno Rogue 0ddc6c722f ads-game:: duality modes for AdS 2022-10-15 14:23:53 +02:00
Zeno Rogue 9121eb7d72 ads-game:: refactored switch_pause 2022-10-15 14:22:09 +02:00
Zeno Rogue a5a7e8a5fa deSitter projections shown in menu 2022-10-14 01:11:29 +02:00
Zeno Rogue 1cde76c880 fixup to views : filename 2022-10-14 01:09:33 +02:00
Zeno Rogue 970c2acc96 ads-game:: no longer crashes if underlying is not-gNormal hyperbolic 2022-10-14 01:02:36 +02:00
Zeno Rogue 45141a9df0 ads-game:: underlying/spacetime views 2022-10-14 01:01:50 +02:00
Zeno Rogue a7ca4c2902 relativistic projections added 2022-10-14 00:56:48 +02:00
Zeno Rogue 7a6df6f060 fixed GF_NO_FOG 2022-10-14 00:55:34 +02:00
Zeno Rogue e6d0ff8789 perspective of any kind now has Panini 2022-10-14 00:54:51 +02:00
Zeno Rogue d218896b63 sl2:: more projections allowed 2022-10-14 00:54:31 +02:00
Zeno Rogue 7f0bf3b269 anim:: CLI animation record functions now accept 0 which means use the current value 2022-10-11 20:02:20 +02:00
Zeno Rogue 6ac17b31f1 hybrid:: new options for switching 2022-10-11 20:00:51 +02:00
Zeno Rogue f666f51bcd added an option for nonisotropic_weird_transforms 2022-10-11 20:00:33 +02:00
Zeno Rogue c10906d349 fixed 'penrose staircases' in rot spaces 2022-10-11 20:00:13 +02:00
Zeno Rogue 4cdc7db18d curvepoint_first function to loop curves automatically 2022-10-11 19:56:56 +02:00
Zeno Rogue 73c689211f shader flag to use no fog -- useful to display ultra-ideal points 2022-10-11 19:56:37 +02:00
Zeno Rogue 9184532036 ads-game:: replay mode 2022-10-09 13:15:57 +02:00
Zeno Rogue 97a4f13ff8 version 12.c 2022-10-08 02:36:13 +02:00
Zeno Rogue 757660edd0 bringris:: musicvolume editable only if music available 2022-10-08 02:02:55 +02:00
Zeno Rogue 4e0f99f60b added cvoight to credits 2022-10-08 02:02:23 +02:00
Zeno Rogue 2bafda5f18 a comment on why OINF should be divisible by 3 2022-10-08 02:02:03 +02:00
Zeno Rogue 5008609b95 tes;: refactored compute_vertex_valence, also is now able to compute valence in the 'generic' case 2022-10-08 02:01:25 +02:00
Zeno Rogue 60d0d15dab tes:: refactored find_connection 2022-10-08 01:54:30 +02:00
Zeno Rogue d8da9639d0 tes:: split get_adj into two functions, one with connection specified (inlcuding mirror), and one not 2022-10-08 01:53:02 +02:00
Zeno Rogue 29f6bbbe90 tes:: check_football_colorabilty is disabled if valence not known 2022-10-08 00:18:56 +02:00
Zeno Rogue 9284cb237a tes:: mirror without parameter is allowed if only one edge is given 2022-10-07 22:23:07 +02:00
Zeno Rogue 35fa99460b tes:: fixed the bugs with mirrors and apeirogons, and some other bugs 2022-10-07 22:21:46 +02:00
Zeno Rogue 7e28ce278e a sample with mirrors and apeirogons 2022-10-07 22:19:10 +02:00
Zeno Rogue 12316ed631 Version 12.1b 2022-10-06 21:45:11 +02:00
Zeno Rogue b76ab8ebdd rogueviz:: smoothcam:: snapping, side view 2022-10-06 19:40:22 +02:00
Zeno Rogue 2168d5ad4c orbmode in hyper.h included 2022-10-06 18:16:20 +02:00
Zeno Rogue f3427c4968 compute_vertex_valence no longer crashes with -arb-unmirror 0 -- we just ignore vertex valence in this case, we do not use it for now 2022-10-06 14:52:22 +02:00
Zeno Rogue 8b758bded9 arb:: tilings with mirrors can now be loaded with -arb-unmirror 2022-10-06 14:47:48 +02:00
Zeno Rogue 70b5da8178 arb:: debug removed 2022-10-06 14:47:17 +02:00
Zeno Rogue a1cbf8c906 minecolors and distcolors now accept less/more colors in table 2022-10-06 13:47:00 +02:00
Zeno Rogue fe937cf20a color table dialog now allows adding more / removing colors 2022-10-06 13:46:15 +02:00
Zeno Rogue 313666a240 edit unreversed colors easily 2022-10-06 13:37:21 +02:00
Zeno Rogue 03b7804817 mirrored tiles marked on or off 2022-10-06 13:35:56 +02:00
Zeno Rogue 6de6e71bd4 documented width of cell boundaries 2022-10-06 13:23:18 +02:00
Zeno Rogue ddf8ea17e3 choice of orb display style 2022-10-06 13:10:57 +02:00
Zeno Rogue 8bf80dd96c added CrashTuvai to credits (for help with racing achievement bug) 2022-10-06 12:58:21 +02:00
Zeno Rogue 2a5cdf28c8 disable Yendor on racing 2022-10-06 12:57:58 +02:00
Zeno Rogue 6a626007bb racing:: racing menu now shows whether an official track is on 2022-10-06 12:57:47 +02:00
Zeno Rogue 789770da43 racing:: switch modes correctly when loading official track 2022-10-06 12:57:19 +02:00
Zeno Rogue 07ce60c3ef ignore the land structure for the racing achievement 2022-10-06 12:56:50 +02:00
Zeno Rogue 8b6effba1b Orb of Choice now works with Orb of Safety 2022-10-06 12:32:06 +02:00
Zeno Rogue 8aaf06969c global_boundary_ratio option 2022-10-06 12:26:17 +02:00
Zeno Rogue f4cf3440ff debug_tiles is visible in experiments 2022-10-06 12:01:31 +02:00
Zeno Rogue 6c88e9b2c3 debug_tiles improvements: 2 displays more tile information, not displayed in standard except in cheat mode 2022-10-06 11:59:34 +02:00
Zeno Rogue 9004fdeee5 tes mirror tile documented 2022-10-06 11:09:03 +02:00
Zeno Rogue d44e8b6416 tes:: mirror command added 2022-10-06 10:59:57 +02:00
Zeno Rogue bef884c9dc fixed arcm colors for mirrorless 2022-10-06 10:08:21 +02:00
Zeno Rogue 5a9e7e4069 more distinct mirrored colors 2022-10-06 10:08:10 +02:00
Zeno Rogue 3369adfc98 separate color set for mirrored tiles in arb/arcm 2022-10-06 09:57:18 +02:00
Zeno Rogue 30839fdb15 Orb of Sword II now displays reversed 2022-10-06 08:49:26 +02:00
Zeno Rogue f9fdc2ee0a added Jacob Mandelson to the credits 2022-10-06 08:48:00 +02:00
Zeno Rogue 93727e433e
Merge pull request #322 from jlmjlm/hl_ani_dice
Highlight hostile dice if poly_outline is set for highlighting.
2022-10-06 08:44:02 +02:00
Zeno Rogue 06c73ad9fb
Merge pull request #321 from jlmjlm/highlight_langs
Grammar fix to Alt-to-highlight message.
2022-10-06 08:43:22 +02:00
Zeno Rogue 21cbc2d621
Merge pull request #320 from jlmjlm/whos
Flip over worm-head shape used in Orb of Domination.
2022-10-06 08:42:42 +02:00
Jacob Mandelson f2623ff6ab Highlight hostile dice if poly_outline is set for highlighting. 2022-10-05 20:40:15 -07:00
Jacob Mandelson 00c4d2c0a5 Grammar fix to Alt-to-highlight message. 2022-10-05 20:26:17 -07:00
Jacob Mandelson 6b9728b385 Flip over worm-head shape used in Orb of Domination.
Worms get drawn from tail to head, so the shape used for the head
is upside-down.  Hence it should be flipped over when used as the
icon for the Orb of Domination.
2022-10-05 08:43:16 -07:00
Zeno Rogue 1aa4242ace Orb icon updates 2022-10-04 18:14:16 +02:00
Zeno Rogue a3e6d79607
Merge pull request #319 from jlmjlm/v12.1+os
Provide orbs with shapes that hint at their function
2022-10-04 16:23:59 +02:00
Zeno Rogue 6514c8758e that was not a correct fix 2022-09-29 15:25:41 +02:00
Zeno Rogue 5a6444b45a yet another fixup for SCU 2022-09-29 15:23:25 +02:00
Zeno Rogue 0fb4033868 ads-game:: added CAP_VIDEO guard, and made SCU compile work 2022-09-29 15:13:59 +02:00
Zeno Rogue 31318862cb rogueviz:: added CAP_THREAD guard 2022-09-29 15:13:30 +02:00
Zeno Rogue ac088d1d41 laDual and laSnakeNest now appear when legal 2022-09-29 15:13:15 +02:00
Zeno Rogue 1c24daea77 added some guards 2022-09-29 15:12:56 +02:00
Zeno Rogue 628f19a0a0 ads-game:: recenter cheat 2022-09-29 15:05:57 +02:00
Zeno Rogue c4a4b21296 ads-game:: better protection from invalid in ds 2022-09-29 15:04:54 +02:00
Zeno Rogue 171b198cd8 ads-game:: debug removed 2022-09-29 14:27:40 +02:00
Zeno Rogue 9c7f23e16e ads-game:: fixed ds_max_ and ds_tank_ config variables 2022-09-29 14:27:25 +02:00
Zeno Rogue 3518c9abf3 ads-game:: -ds-recenter feature 2022-09-29 14:27:06 +02:00
Zeno Rogue 6fa7cdaf0a ads-game:: fixed the precision issues casuing weird display in dS 2022-09-29 14:26:53 +02:00
Zeno Rogue f161f9bf0a ads-game:: fixed convergent/divergent spirals 2022-09-29 14:25:18 +02:00
Zeno Rogue 80c02c7e38 ads-game:: fixed history view 2022-09-29 14:24:57 +02:00
Zeno Rogue 25997dc6c1 ads-games:: fixes to ds-record 2022-09-29 13:09:21 +02:00
Zeno Rogue 1391a0e47f ads-game:: display resources in corner for now 2022-09-29 12:12:26 +02:00
Zeno Rogue 553bd8f466 ads-game:: do not crash if list missing 2022-09-29 12:12:11 +02:00
Zeno Rogue 01c7ff5bc6 ads-game:: past fixup 2022-09-29 12:12:02 +02:00
Zeno Rogue cc1d2c1b48 ads-game:: footer/copyright shown 2022-09-29 12:11:50 +02:00
Zeno Rogue 3808d93a11 ads-game:: don't display proper time of history ships even though view_proper_times is off 2022-09-29 11:40:21 +02:00
Zeno Rogue 293c271c7f past cones are displayed too, not only future cones 2022-09-29 11:38:54 +02:00
Zeno Rogue b26ce4a067 ads-game:: missile rapidity editable, and also no longer changes when scale changes 2022-09-29 11:22:19 +02:00
Zeno Rogue b8eeec248e ads-game:: fixed some names to Relative Hell 2022-09-29 11:14:27 +02:00
Zeno Rogue 84022c1ab4 ads-game:: restart fixup 2022-09-29 11:14:14 +02:00
Zeno Rogue 6549637f8d ads-game:: fixed ads crash ship 2022-09-29 11:13:35 +02:00
Zeno Rogue b34fbba7b4 ads-game:: do not generate rocks when shooting, so that it is faster 2022-09-29 11:13:24 +02:00
Zeno Rogue 85816ca0bb ads-game:: in ds, all objects have no black boundary to make them easier to recognize 2022-09-29 11:12:49 +02:00
Zeno Rogue 864f6d7899 ads-game:: speeds and acceleration are now given in absolute units (no dep on animperiod) 2022-09-29 11:12:24 +02:00
Zeno Rogue b0ae2774a1 ads-game:: 'pick the game' screen, also dS restarts correctly 2022-09-29 11:10:16 +02:00
Zeno Rogue ef7050aed2 ads-game:: correct sphere flipping 2022-09-29 01:39:57 +02:00
Zeno Rogue 49ce0c1551 ads-game:: better ship shape handling 2022-09-29 01:39:16 +02:00
Zeno Rogue bcd6d772f6 ads-game:: fix texture glitches 2022-09-29 01:13:43 +02:00
Zeno Rogue 0c6d83b702 ads-game:: don't display ship history unless paused 2022-09-29 01:12:46 +02:00
Zeno Rogue 7f8a2f7a49 ads-game:: reduced default texture quality 2022-09-29 01:12:32 +02:00
Zeno Rogue a401a7ed67 ads-game:: sounds 2022-09-29 01:12:08 +02:00
Zeno Rogue a84a9c94dd settings for dS (also are now separate from adS) 2022-09-28 22:10:09 +02:00
Zeno Rogue a775a74bb2 fixed missiles/particles being invisible due to incorrect clockwiseness of shape 2022-09-28 21:28:47 +02:00
Zeno Rogue a3b85103b6 ads-game:: in dS, faster resources, and spin them correctly 2022-09-28 21:27:06 +02:00
Zeno Rogue 0367d9553d ads-game:: display score in dS 2022-09-28 21:26:43 +02:00
Zeno Rogue a9c416ac64 ds-game:: fixed area calculcation 2022-09-28 21:06:56 +02:00
Zeno Rogue 773e73dcc2 ads-game:: priorities (and also main rock) 2022-09-28 21:06:07 +02:00
Zeno Rogue 95b205cce0 ads-game:: resources and crashes in dS 2022-09-28 20:27:11 +02:00
Zeno Rogue ade4f9c030 ads-game:: ds-texture 2022-09-28 19:18:04 +02:00
Zeno Rogue 22a5729d35 ads-game:: dsgame patterns 2022-09-26 13:25:30 +02:00
Zeno Rogue 54e0d85ea7 ds-game:: added the main star, and fixed the precision issues (as long as close to the main star) 2022-09-26 10:53:55 +02:00
Zeno Rogue 4af232e9c1 ads:: future in AdS shown correctly (using light-like geodesics); show future for dS 2022-09-25 22:20:18 +02:00
Zeno Rogue c49b320330 rogueviz:: presentation improvements 2022-09-24 09:14:31 +02:00
Zeno Rogue 40d3c39cf1 rogueviz:: objmodel minor fix 2022-09-24 09:13:38 +02:00
Zeno Rogue 69280c7efe bringris:: adjust to gamescreen no parameter 2022-09-24 09:13:25 +02:00
Zeno Rogue df6dd67fc1 nilrider:: game_keys_scroll 2022-09-24 09:13:00 +02:00
Zeno Rogue e459723836 no rug drawn if nomap 2022-09-24 09:12:34 +02:00
Zeno Rogue 804308c03e old_center 2022-09-24 09:12:23 +02:00
Zeno Rogue 624cac0c80 game_keys_scroll not scroll if ALT is pressed 2022-09-24 09:11:06 +02:00
Zeno Rogue 2e5d9dd626 ystrafe no longer brings walking eye level below 0 2022-09-24 09:10:49 +02:00
Zeno Rogue f33d169fe1 commandline rotate commands set playermoved=false 2022-09-24 09:10:32 +02:00
Zeno Rogue 62fed6129f ads-game:: record a run 2022-09-20 12:36:16 +02:00
Zeno Rogue bdbf4e2935 ads-game:: ds-game more game-y 2022-09-20 12:29:19 +02:00
Zeno Rogue fbf0b487b1 ads-game:: added the de Sitter version 2022-09-19 23:17:27 +02:00
Zeno Rogue 720ccc649c ads-game:: removed some junk 2022-09-19 23:17:00 +02:00
Zeno Rogue 8f086f7bb5 ads-game:: display time for shipstate 2022-09-19 23:16:41 +02:00
Zeno Rogue f375d609c6 ads-game:: refactored read_movement 2022-09-19 23:16:16 +02:00
Zeno Rogue 987c0e6113 ads-game:: refactored set_default_keys 2022-09-19 23:15:27 +02:00
Zeno Rogue 2e99da82ba ads-game:: fix numerical error 2022-09-19 00:12:00 +02:00
Zeno Rogue 4b74fdf7c1 ads-game:: fix spacing 2022-09-19 00:11:48 +02:00
Zeno Rogue 277b1e1fd0 ads-game:: fixed restart 2022-09-18 23:39:04 +02:00
Zeno Rogue bbc57d9b8f ads-game:: improved celldraw priority 2022-09-18 23:36:47 +02:00
Zeno Rogue f46279843d ads-game:: restart bugfix 2022-09-18 23:36:21 +02:00
Zeno Rogue fcd54e3d62 ads-game:: const added 2022-09-18 23:36:04 +02:00
Zeno Rogue 567ef8e7e6 ads-game:: resource expiration 2022-09-18 17:29:01 +02:00
Zeno Rogue a1a65ac612 optimize center in queue 2022-09-18 17:28:48 +02:00
Zeno Rogue 43305ea1cd vctr is now the hyperbolic cell (similar for some variables); also invincibility on start 2022-09-18 17:02:15 +02:00
Zeno Rogue 03a3fd14a0 ads-game:: priority_queue-based rendering 2022-09-18 16:49:08 +02:00
Zeno Rogue 7a7ee1a13f clarified that times in settings are always specified in absolute units 2022-09-18 13:46:47 +02:00
Zeno Rogue 11a059eb60 auto-change-scale functionality 2022-09-18 13:45:45 +02:00
Zeno Rogue b7c15e0978 ads-game:: fuel particles take scale into account 2022-09-18 13:34:47 +02:00
Zeno Rogue 04c43e99e6 ads-game:: performance settings 2022-09-18 13:34:30 +02:00
Zeno Rogue 62996d0d4c missile rapidity and particle settings 2022-09-18 13:14:46 +02:00
Zeno Rogue 707247d297 ads-game:: configurable scale 2022-09-18 13:03:14 +02:00
Zeno Rogue 00b2dc522a better rock generation 2022-09-18 12:58:18 +02:00
Zeno Rogue eefb91501e ads-game:: show the (approximate) future 2022-09-18 11:24:43 +02:00
Zeno Rogue d76b2156f2 ads-game:: further improvements to the menu 2022-09-18 10:26:16 +02:00
Zeno Rogue 29ed17410b ads-game:: more settings 2022-09-18 10:22:25 +02:00
Zeno Rogue 6ea3cc4bcc time_unit and pause_speed settings 2022-09-18 10:22:13 +02:00
Zeno Rogue 11b70006aa ads-game:: easier to invoke menu 2022-09-18 10:21:29 +02:00
Zeno Rogue 8a35e6facb ads-game:: made the game easier to (re)start, also more settings 2022-09-18 10:21:13 +02:00
Zeno Rogue 11fe91fb5a debug removed 2022-09-18 10:19:02 +02:00
Jacob Mandelson 63c68831b2 Fix offsets for the shSmallHammerHead. 2022-09-17 15:21:18 -07:00
Jacob Mandelson d32772fd1e Style fixes for polygons.cpp 2022-09-17 15:08:09 -07:00
Jacob Mandelson d0564026d7 Small style cleanup. 2022-09-17 15:00:54 -07:00
Jacob Mandelson fb3c0e38b7 Restore default args to "at" lambda. 2022-09-17 14:49:10 -07:00
Jacob Mandelson 2939191fa1 Fix default lambda args & extra semicolon. 2022-09-17 14:44:50 -07:00
Jacob Mandelson c7f8cafc28 Use master's mymake.cpp 2022-09-17 14:42:46 -07:00
Jacob Mandelson 71cf4bc678 Merge branch 'orbshapes' into v12.1+os 2022-09-17 14:39:07 -07:00
Jacob Mandelson f10751a7f0 Clean up shLeafIcon. 2022-09-17 14:06:30 -07:00
Jacob Mandelson 4d766655ba More ivy-leaf tweaking. 2022-09-17 13:52:38 -07:00
Jacob Mandelson 41e8466dad Tweaking the ivy leaf. 2022-09-17 13:45:41 -07:00
Jacob Mandelson f7e8818e01 First draft of ivy leaf for Orb Of Nature. 2022-09-17 13:39:11 -07:00
Zeno Rogue fc184640d3 no ship history after game_over 2022-09-17 17:47:31 +02:00
Zeno Rogue 9799ff1ccf ads-game:: view history while paused 2022-09-17 17:34:54 +02:00
Zeno Rogue 37ab1b523d ads-game:: no more fire while paused 2022-09-17 17:34:19 +02:00
Zeno Rogue b75bb20246 missile life starts at 0 2022-09-17 17:34:11 +02:00
Zeno Rogue 21ebbc6ca4 ads-game:: more intuitive pause-scrolling 2022-09-17 16:49:09 +02:00
Zeno Rogue 75902e5fd3 ads-game:: adjust resource positioning to model 2022-09-17 16:47:35 +02:00
Zeno Rogue 22ef01964a ads-game:: model permanently switched to underlying geometry 2022-09-17 16:47:22 +02:00
Zeno Rogue de859c35aa in sl2, sl2 handling of shifts is executed even if model uses bandshift 2022-09-17 16:46:26 +02:00
Zeno Rogue 84a6d2f8f9 hooks_frame is still called when nomap == true 2022-09-17 16:45:43 +02:00
Zeno Rogue 505e9dcbbe ads-game:: better placement of resources 2022-09-17 15:17:37 +02:00
Zeno Rogue 8e23039fc0 ads-game:: better swap 2022-09-17 15:17:08 +02:00
Zeno Rogue 2f672bc4f3 more precise checking whether a rock does not hit a wall (but too expensive to use) 2022-09-17 15:17:01 +02:00
Zeno Rogue fa1f237f37 ads-game:: less expensive 2022-09-17 15:16:26 +02:00
Zeno Rogue b1baf393ba ads-game:: display other frames of reference while paused 2022-09-17 15:16:04 +02:00
Zeno Rogue 38b817187e version 12.1a 2022-09-17 12:17:35 +02:00
Zeno Rogue 3a95b5f8d5 made some item icons larger 2022-09-17 12:11:03 +02:00
Zeno Rogue cb839ed895 items/monsters in your collection have their text brightened if too dark (or the auxiliary orb color is used) 2022-09-17 12:10:44 +02:00
Zeno Rogue f0200ee32c color_diff function 2022-09-17 12:09:46 +02:00
Zeno Rogue 85f214c9a2 fixed the Onyx graphics in inventory 2022-09-17 11:37:25 +02:00
Zeno Rogue 69d0c05628 Orb of Earth no longer marked useless in Wetland 2022-09-17 11:23:13 +02:00
Zeno Rogue db353755d3 symmetric pathdist 2022-09-17 11:21:33 +02:00
Zeno Rogue f0f6ae7514 removed unused references to pathdist from kraken movement 2022-09-17 11:13:36 +02:00
Jacob Mandelson 21a7c4f365 Polish up the tree icon. 2022-09-16 22:12:27 -07:00
Jacob Mandelson 371a324085 Orb of the Woods and part of a tree icon. 2022-09-16 21:59:23 -07:00
Jacob Mandelson 1ad6b7ebe9 Orbs of Air and Empathy. 2022-09-16 19:24:01 -07:00
Zeno Rogue 5af23eab7d fixed Orb of Teleport/Illusion thinking that they are unusable 2022-09-16 22:35:37 +02:00
Jacob Mandelson 22e1799ab3 Clean up the shShield numerics. 2022-09-16 12:49:04 -07:00
Jacob Mandelson ae89d73598 shShield, mk IV. 2022-09-16 12:32:26 -07:00
Jacob Mandelson 9018d32173 Second draft of shShield. 2022-09-16 12:19:49 -07:00
Jacob Mandelson d2c4382e14 First draft of shield shape. 2022-09-16 12:13:20 -07:00
Jacob Mandelson fabf0e3eb0 Clean up the numbers for the small hook. 2022-09-15 16:24:05 -07:00
Jacob Mandelson 048ad9a030 Use a pirate hook in the Orb of Space. 2022-09-15 16:02:27 -07:00
Zeno Rogue b0577deb9a version 12.1 2022-09-15 18:46:31 +02:00
Zeno Rogue ca3cb88399
Merge pull request #318 from tranzystorek-io/desktop-file
Add desktop file
2022-09-15 14:16:19 +02:00
Zeno Rogue 5e8f3b609b
Merge pull request #316 from tranzystorek-io/readme-drop-version
docs: drop version from README
2022-09-15 14:15:48 +02:00
Zeno Rogue 30217ac23b link to format explained 2022-09-15 12:42:23 +02:00
Zeno Rogue 637ca35d62 added albatross and EncodedSpirt to credits 2022-09-15 12:39:28 +02:00
Zeno Rogue 1ec7b0ece1 fixed the compilation with CAP_SDL2 2022-09-15 12:38:56 +02:00
Zeno Rogue 308fcd90aa savefile selection / an option to use no savefile 2022-09-15 12:38:39 +02:00
Zeno Rogue a20063c119 fixed missing 'too far' messages on Frog-like orbs 2022-09-15 12:04:08 +02:00
Zeno Rogue d7e4c25c92 fixed Teleport and Illusion drain Aether etc on mousing 2022-09-15 12:03:26 +02:00
Zeno Rogue 1b4e0bfa79 license specified for the recorded sounds 2022-09-15 11:24:44 +02:00
Jacob Mandelson d0273d3ed6 Heptagon + heptagram for the Orb of Summoning. 2022-09-14 21:32:36 -07:00
Jacob Mandelson df6f9eb86a Single eccentric disk for the Orb of Discord. 2022-09-14 18:23:43 -07:00
Jacob Mandelson 2933b256e0 Use disk segments for Orbs of Vaulting & Phasing. 2022-09-14 18:11:52 -07:00
Zeno Rogue f29f908e05 fixed a crash problem with tes files in 2.5D 2022-09-15 00:19:21 +02:00
Zeno Rogue dbf9b2b325 ray:: max_well_offset anc max_celltype can be increased 2022-09-14 23:38:45 +02:00
Zeno Rogue ce5c1bc369 ray:: fixed missing samples 2022-09-14 23:38:29 +02:00
Zeno Rogue 18113f157f rulegen vs extended football 2022-09-14 22:53:39 +02:00
Zeno Rogue 53537271eb fixed a crash on rulegen for converted tessellations 2022-09-14 22:31:12 +02:00
Zeno Rogue 8715770649 prevented GPU glitches when rendering long bands 2022-09-14 21:56:02 +02:00
Zeno Rogue b6073679b2 tes:: football now works with apeirogons 2022-09-14 21:43:07 +02:00
Zeno Rogue 0084a951e6 tes:: fixed tessellations/affine/affine-square.tes 2022-09-14 21:23:54 +02:00
Zeno Rogue 3f005908c4 shape editor: shift+S also saves in the simpler format 2022-09-14 21:14:44 +02:00
Zeno Rogue 38767cf801 tes:: new options -arb-unmirror and -arb-football 2022-09-14 21:13:55 +02:00
Zeno Rogue 4c27c16931 tes:: throw exception on already connected 2022-09-14 21:13:43 +02:00
Zeno Rogue b87a936a61 tes:: football colorability detected/applied 2022-09-14 21:13:29 +02:00
Zeno Rogue 905c4e3afb rogueviz:: adjusted to patTriOther removal 2022-09-14 18:58:42 +02:00
Zeno Rogue ae7574483e slr:: formula_exp now returns 0 for vel==0 instead of nan 2022-09-14 18:30:12 +02:00
Zeno Rogue db3d710dd4 slr:: in_actual is now exported and also actually works 2022-09-14 18:29:39 +02:00
Zeno Rogue db32bae51e restriced Gray/Green Raider movepatterns to be available only if geosupport_football returns true 2022-09-14 18:10:49 +02:00
Zeno Rogue 6a39ed54c6 expansion dialog now links to line patterns dialog instead of listing some (which was bugged anyway) 2022-09-14 18:03:25 +02:00
Zeno Rogue acc90b80b7 expansion:: dfStart returns 0 if not mod allowed 2022-09-14 18:02:26 +02:00
Zeno Rogue 90669b6bb8 expansion:: mod_allowed export 2022-09-14 18:02:12 +02:00
Zeno Rogue 944f5e30af patDual now does not display edges which are displayed by patTriTree, patTree or patTriRings 2022-09-14 18:01:59 +02:00
Zeno Rogue c637dd4322 line patterns:: 'triangle grid: rings' renamed to 'lines of equal distance' and also work better now 2022-09-14 18:01:26 +02:00
Zeno Rogue f537abf71c line patterns: renamed/recolored some; TriOther removed; fixed the conditions 2022-09-14 17:59:21 +02:00
Zeno Rogue 898a2463c0 remove debug output when loading some tes 2022-09-14 17:26:22 +02:00
Zeno Rogue c3a1f8cc12 tes documentation: explained that a and b can be real 2022-09-14 16:34:14 +02:00
Zeno Rogue 16bf285f15 tes documentaiton: explained deg = pi/180 2022-09-14 16:34:05 +02:00
Zeno Rogue 02e88579f6 standard math operators 2022-09-14 16:23:09 +02:00
Zeno Rogue 142de7cdc5 typo fixed 2022-09-14 16:20:44 +02:00
Zeno Rogue b7a2e87d28 updated tessellation documentation 2022-09-14 16:19:00 +02:00
Zeno Rogue f23c10d1e6 racing:: simplifying some overcomplicated stuff, minor bugfix 2022-09-14 16:18:22 +02:00
Zeno Rogue e393929237 fixed a possible crash in IMAGESAVE when SDL_PNGFormatAlpha(s) returns s 2022-09-14 16:17:53 +02:00
Zeno Rogue d081bfb7ee tessellation doc fixed 2022-09-14 13:58:58 +02:00
Zeno Rogue d279d2098e documentation for TES files added 2022-09-14 13:51:00 +02:00
Marcin Puc 8fb143a742 add desktop file 2022-09-14 09:44:01 +02:00
Jacob Mandelson 92fc237a3e Simplify arithmetic for points in the hourglass shape. 2022-09-13 11:18:59 -07:00
Jacob Mandelson 45207e3ba7 Scale hourglass horizontally. 2022-09-13 11:02:57 -07:00
Jacob Mandelson da822fc4e9 Make into full hourglass. 2022-09-13 10:58:18 -07:00
Jacob Mandelson 360aa921aa Half an hourglass for the Orb of Time. 2022-09-13 10:49:10 -07:00
Zeno Rogue d3b4b880fc fixed a bug in ship centering 2022-09-12 15:00:00 +02:00
Zeno Rogue 818d943827 ads-game:: crash with walls 2022-09-12 14:57:47 +02:00
Zeno Rogue ae0ab132e1 ads-game:: do something about gameover, also spin the ship in handle_crashes 2022-09-12 14:57:37 +02:00
Zeno Rogue 7c87df85ac ads-game:: do not view_proper_times for particles 2022-09-12 14:57:00 +02:00
Zeno Rogue d5251664cb ads-game:: better tank display 2022-09-12 13:20:44 +02:00
Zeno Rogue d4d7842e5a ads-game:: less walls 2022-09-12 13:20:11 +02:00
Zeno Rogue 2f78601f0b ads-game:: fuel/crash particles 2022-09-12 13:20:04 +02:00
Zeno Rogue 7958c095d0 ads-game:: clear rocks near to the starting point 2022-09-12 12:58:05 +02:00
Zeno Rogue cd84dfca4f ads-game:: resources are used 2022-09-12 12:57:52 +02:00
Zeno Rogue 3578ae0631 ads-game:: resources displayed 2022-09-12 12:24:18 +02:00
Zeno Rogue dbcc88b42a ads-game:: renamed Energy to Ammo 2022-09-12 12:23:49 +02:00
Zeno Rogue b056b5c153 shapes used, unique_ptrs, resources generated 2022-09-12 11:49:28 +02:00
Zeno Rogue 9545796a1d ads-game:: new shapes, shape_ship written like other things 2022-09-12 11:48:02 +02:00
Zeno Rogue 2522b16e55 renamed flatresult to cross_result 2022-09-11 13:44:28 +02:00
Zeno Rogue a221244cab renamed rockinfo to ads_object 2022-09-11 13:43:44 +02:00
Zeno Rogue 06832c5371 ads-game:: you can now shoot rocks 2022-09-11 13:42:51 +02:00
Zeno Rogue 4eebc5858e first commit of AdS game 2022-09-11 12:16:50 +02:00
Zeno Rogue ab7ebd3bbc fix to changelog 2022-09-09 14:21:28 +02:00
Zeno Rogue ed7c5d8e69 12.0z 2022-09-09 14:21:14 +02:00
Zeno Rogue b934819ac3 bug fixed: mousing frog-like orbs could mark Aether etc as used; also jumping with Aether=1 is allowed now 2022-09-09 13:34:29 +02:00
Zeno Rogue 92291c437a bug fixed: Space mousing could mark Aether as used 2022-09-09 12:47:54 +02:00
Zeno Rogue e74d79583b fixed faster virtualRebase for sol 2022-09-09 12:30:20 +02:00
Zeno Rogue d03db1115c bug fixed: when ruleset was available only for the pure honeycomb, loading it would reset variation to pure 2022-09-09 12:26:32 +02:00
Zeno Rogue 466cc5cc0a removed redundant pre-changes orbused rollback, and made it more elegant in movegolem 2022-09-09 12:24:21 +02:00
Zeno Rogue 9110b6ac88 fixed 'orb used' flags not being rolled back in some cases 2022-09-09 12:22:49 +02:00
Zeno Rogue 852c637e4f fixed mousing over items with Energy+Time+Space combo 2022-09-09 12:21:55 +02:00
Zeno Rogue 613672b662 flush stdout on -exit 2022-09-09 12:20:33 +02:00
Jacob Mandelson 2f51cfc49e More cleanup for shLightningBolt & shHumanoid polygons. 2022-08-30 19:48:50 -07:00
Jacob Mandelson a2482b033d Clean up shLightningBolt & shHumanoid shape data further. 2022-08-30 19:14:37 -07:00
Jacob Mandelson 7441642b30 Clean up shHumanoid polygon. 2022-08-30 15:07:05 -07:00
Jacob Mandelson 4c75779692 Clean up the shLightningBolt points. 2022-08-30 15:00:31 -07:00
Jacob Mandelson 3081817872 Orb of Invisibility. 2022-08-30 14:49:37 -07:00
Jacob Mandelson 94b2a27b35 Do Orb of Aether. 2022-08-29 19:03:12 -07:00
Jacob Mandelson f8c9562a74 Do Orb of Trickery. 2022-08-29 18:50:50 -07:00
Jacob Mandelson ef28ce708e Add lightning bolt to Orb of Storms. 2022-08-29 16:14:59 -07:00
Jacob Mandelson 5239f6eadc Orbs of Lava, Matter, and Stone. 2022-08-29 10:30:37 -07:00
Jacob Mandelson 067f959ab1 Have Orb of Purity use a disk as well. 2022-08-29 10:05:40 -07:00
Jacob Mandelson c9f24344af Put disks behind the Orbs of Slaying and Undeath too. 2022-08-29 09:55:51 -07:00
Jacob Mandelson aefbd359e4 For many orb icons, put them on the disk as shadowing, instead of replacing the disk. 2022-08-29 09:44:36 -07:00
Jacob Mandelson ae284d68e8 Orb of Stunning. 2022-08-28 21:09:24 -07:00
Jacob Mandelson a6c8894166 Orb of Ferocity. 2022-08-28 20:31:25 -07:00
Jacob Mandelson 0f6754b43e Enlarge shSmallHammerHead. 2022-08-28 20:07:35 -07:00
Jacob Mandelson e1f3df2e65 Orbs of the Dragon, Domination, and the Mind. 2022-08-28 20:05:03 -07:00
Jacob Mandelson cc29338305 Use shSmallTreat for Orbs of Change, Choice, and Chaos. 2022-08-28 19:41:16 -07:00
Jacob Mandelson 5ec6783a2d Orb of Purity and Orb of Water. 2022-08-28 19:06:01 -07:00
Jacob Mandelson f1b75537f8 Clean up small bull head & horn shapes. 2022-08-28 11:31:14 -07:00
Jacob Mandelson afd57fe81d Orbs of Impact and Recall. 2022-08-28 11:10:12 -07:00
Jacob Mandelson c4a7776977 Flash shape for the Orb of Flash. 2022-08-28 10:55:09 -07:00
Jacob Mandelson 20a6876763 Orb of Winter and Orb of Luck. 2022-08-28 10:25:42 -07:00
Marcin Puc 4468061568 docs: drop version from README 2022-08-28 16:23:05 +02:00
Jacob Mandelson 0ebee6a1a3 Orb of Horns & Orb of the Bull. 2022-08-27 18:21:53 -07:00
Jacob Mandelson f5d4586d0f Orbs of Speed, Safety, and Freedom. 2022-08-27 16:37:49 -07:00
Jacob Mandelson af4a0c1da9 Orb of Choice: Two small disks. 2022-08-27 15:51:31 -07:00
Jacob Mandelson 46872919ba Orb of Energy and Orb of Intensity. 2022-08-27 12:43:22 -07:00
Jacob Mandelson cc3065f204 Bodies for Orbs of Triangle, Gravity, Warp, Matter, and Stone. 2022-08-27 11:31:58 -07:00
Jacob Mandelson 5766299c0a Adjust PickAxe, HedgehogBlade, and PSword for orbs of Earth, Thorns, and Slashing. 2022-08-27 07:14:56 -07:00
Jacob Mandelson 591acfebe4 Add hedgehog blade shape to Orb of Thorns. 2022-08-27 05:43:24 -07:00
Jacob Mandelson 1561d84f1b Sword shape for Orb of the Sword I & II. 2022-08-26 21:58:48 -07:00
Jacob Mandelson 3521ee917c Use Pickaxe shape for Orb of Earth ("Digging"). 2022-08-26 19:10:39 -07:00
Jacob Mandelson 064468b480 Added bodies to the Orb of Slaying and Orb of Undeath. 2022-08-26 18:48:21 -07:00
Jacob Mandelson 1f842704ec Add orb bodies for Orb of Slashing & Orb of the Frog. 2022-08-26 15:21:00 -07:00
Jacob Mandelson b71b34e734 Use turtle shell in the Orb of the Shell. 2022-08-26 14:00:42 -07:00
Jacob Mandelson d85ad065f6 Make Orb of Beauty use a small rose. 2022-08-26 12:34:04 -07:00
Jacob Mandelson 18e1912884 Show golem in Orb of Life. 2022-08-26 10:04:52 -07:00
Jacob Mandelson 446b23f83d Show a tame bomberbird in the Orb of Friendship. 2022-08-26 08:46:32 -07:00
Zeno Rogue ae003f7847 some fixes for older compilers 2022-08-26 14:24:58 +02:00
Zeno Rogue e70f3d1fe6 rulegen3:: fixes 2022-08-26 13:21:36 +02:00
Zeno Rogue 9f1480d21e fixup to dump 2022-08-26 13:10:29 +02:00
Zeno Rogue 3080e5d05b rogueviz::sag:: further new options 2022-08-26 12:43:59 +02:00
Zeno Rogue ec3bb7a5df rulegen-tests:: show seq-stats for 3D 2022-08-26 12:42:55 +02:00
Zeno Rogue aa539335b4 patterns:: treestarter parameter 2022-08-26 12:42:07 +02:00
Zeno Rogue eef03514ca rulegen3:: an option to dump rules in text format 2022-08-26 12:28:36 +02:00
Zeno Rogue 841108726c new system for honeycombs in action 2022-08-26 12:27:57 +02:00
Zeno Rogue 31b2bd9690 find_file to find files in HYPERPATH 2022-08-26 12:23:58 +02:00
Zeno Rogue 7be773ea03 fixed the Slaying+side attack combo 2022-08-25 10:51:56 +02:00
Zeno Rogue d66a877889 Added some land incompatibilities 2022-08-25 10:41:57 +02:00
Zeno Rogue 9f48d4f194 Pearls now use the Disk graphics 2022-08-25 10:38:22 +02:00
Zeno Rogue 5146fc00f0 using smaller field_quotients for rule_fp; also a list of field quotients is included in devmods 2022-08-25 10:31:28 +02:00
Zeno Rogue 4947b8c1b5 great success 2022-08-25 10:28:26 +02:00
Zeno Rogue 53839be194 fixup to no rels 2022-08-25 01:10:22 +02:00
Zeno Rogue 14a9961f92 reg3/field:: incorrect field computations generate errors; fixed a bug in suspending discovery; more elegant fieldpattern search not based on cgi.rels 2022-08-25 01:10:07 +02:00
Zeno Rogue 3f32112937 reg3:: do not call generate_fulls more than needed 2022-08-25 01:06:49 +02:00
Zeno Rogue a439b16602 dont generate horos in hrmap_h3 2022-08-25 01:05:58 +02:00
Zeno Rogue ae0425038b improvements to French translation 2022-08-24 12:30:45 +02:00
Zeno Rogue ffe8e9cef3 rulegen::tests:: display 3D fields 2022-08-23 21:52:36 +02:00
Zeno Rogue 7411f21b59 rogueviz:: parallelize moved from flocking to rogueviz.h 2022-08-23 21:52:36 +02:00
Zeno Rogue b6d665ff0e rogueviz:: SAG improvements 2022-08-23 21:52:36 +02:00
Zeno Rogue d4ea078f7f DHRG not exports some things 2022-08-23 21:52:36 +02:00
Zeno Rogue 5c97fbb06e another fix to Panini 2022-08-23 21:52:36 +02:00
Zeno Rogue 9ab84d9afd fixed is_master for 3D euclidean 2022-08-23 21:52:36 +02:00
Zeno Rogue ecadc352f1 minimization fixes 2022-08-23 21:52:36 +02:00
Zeno Rogue 41d14e0607 fixed reg3::in 2022-08-23 21:52:36 +02:00
Zeno Rogue b7c8e7b754 field:: hooks_solve3 2022-08-23 21:52:36 +02:00
Zeno Rogue 50087e032a faster virtualRebase in Solv 2022-08-23 21:52:36 +02:00
Zeno Rogue 0f0d0ff7a9 French translation updated 2022-08-23 21:52:36 +02:00
Zeno Rogue c07f84205b removed some music debug 2022-08-23 21:52:36 +02:00
Zeno Rogue 764afbcd11 nilrider:: save config 2022-08-23 21:52:36 +02:00
Zeno Rogue 121b3f2d58 reg3:: rule debug 2022-08-23 21:52:36 +02:00
Zeno Rogue 84d15a121b rogueviz::sag:: modernized, also made the animation possible again 2022-08-23 21:52:36 +02:00
Zeno Rogue 97c10ff878 rulegen3:: remove faster get_parent_dir as it causes problems 2022-08-23 21:52:36 +02:00
Zeno Rogue 1c4aa3e71c rulegen3:: removed the r3_neighborhood system 2022-08-23 21:52:36 +02:00
Zeno Rogue 01cb5eb9ef refactored check_road_shortcuts 2022-08-23 21:52:36 +02:00
Zeno Rogue cccab05f66 rulegen3:: fixed suspicious path analysis 2022-08-23 21:52:35 +02:00
Zeno Rogue 59b45c1be0 fixup to disable distance checks 2022-08-23 21:52:35 +02:00
Zeno Rogue 285beb4ad2 rulegen3:: remove some parts of 2D which cause bugs 2022-08-23 21:52:35 +02:00
Zeno Rogue 2d35e40dba rulegen3:: optimize the information 2022-08-23 21:52:35 +02:00
Zeno Rogue 2fe521452a yet another fixup to decision_neigh validate_neigh 2022-08-23 21:52:35 +02:00
Zeno Rogue 9c0231c455 rulegen3:: minor bugfixes 2022-08-23 21:52:35 +02:00
Zeno Rogue 7a5b2dcf25 rulegen3:: when check_det fails do not assume it succeeds 2022-08-23 21:52:35 +02:00
Zeno Rogue f866f66582 rulegen3:: w_ignore_transducer_dist flag 2022-08-23 21:52:35 +02:00
Zeno Rogue d571d2f1cb rulegen3:: validate_neighborhood 2022-08-23 21:52:35 +02:00
Zeno Rogue d6376bcaec rulegen3:: fixed bugs in build_cycle_data 2022-08-23 21:52:35 +02:00
Zeno Rogue 437dce455a fixed a bug in repeated cycle ignoring 2022-08-23 21:52:35 +02:00
Zeno Rogue 14f1da6de4 rulegen3:: renaming/refactoring 2022-08-23 21:52:35 +02:00
Zeno Rogue cc258f1f31 rulegen-tests:: set rules_known_for 2022-08-23 21:52:35 +02:00
Zeno Rogue a26234012f rulegen:: use more of rdebug_flags 2022-08-23 21:52:35 +02:00
Zeno Rogue 304c9efe54 rulegen3:: less cycles to check 2022-08-17 17:40:58 +02:00
Zeno Rogue 80c3dfcd34 rulegen3:: more improvements 2022-08-17 17:40:12 +02:00
Zeno Rogue a441ab474f include unordered_set and unordered_map 2022-08-17 17:38:28 +02:00
Zeno Rogue 2ddc35179a rulegen3:: better error reporting 2022-08-17 17:38:06 +02:00
Zeno Rogue 75c9258537 rulegen3:: w_r3_no_road_shortcuts 2022-08-17 17:34:13 +02:00
Zeno Rogue 47d2b5b27b rulegen:: clear codes on neg rule mismatch 2022-08-17 17:33:52 +02:00
Zeno Rogue ecee5b7f21 rulegen:: (some) controllable debug flags 2022-08-17 17:33:36 +02:00
Zeno Rogue ca315c2582 rulegen3:: reordered move_code 2022-08-17 17:32:15 +02:00
Zeno Rogue fe7b54d256 rulegen3:: faster get_parent_dir 2022-08-17 17:31:59 +02:00
Zeno Rogue 7f0bbcfef3 rulegen3:: faster get_roadsign 2022-08-17 17:31:32 +02:00
Zeno Rogue eb4af6c584 reg3:: in cubes_reg3, use field quotients not tori 2022-08-17 17:24:47 +02:00
Zeno Rogue d22d840f01 fpattern for Cube Tiling 2022-08-17 17:24:20 +02:00
Zeno Rogue d55a2022c0 nilrider:: audio settings 2022-08-14 19:55:25 +02:00
Zeno Rogue 9e56312dab reg3:: with extra_origins, more xpush in the Euclidean case 2022-08-14 19:26:54 +02:00
Zeno Rogue 35bd625a87 rulegen3:: improved debug 2022-08-14 19:26:36 +02:00
Zeno Rogue 16cdaa5a00 rulegen:: gen_rule 2022-08-14 19:26:13 +02:00
Zeno Rogue df5c36c2a6 music system now supports more tracks 2022-08-14 19:25:27 +02:00
Zeno Rogue 40765e8808 extra exports 2022-08-14 19:25:10 +02:00
Zeno Rogue 9108d06543 nilrider:: extra exports 2022-08-14 19:24:39 +02:00
Zeno Rogue 576e21ece9 nilrider:: fixup to new levels 2022-08-14 19:24:33 +02:00
Zeno Rogue ffcf7853cb nilrider:: compile in SDL2 2022-08-14 19:24:24 +02:00
Zeno Rogue 82e2e853bf nilrider:: synchronized music 2022-08-14 19:24:13 +02:00
Zeno Rogue dbab2254c6 nilrider:: two new levels 2022-08-14 19:23:18 +02:00
Zeno Rogue 3cffc218e6 rulegen3:: genhoneycomb throws exception if rules not known 2022-08-13 23:14:44 +02:00
Zeno Rogue dc37e1ed23 rulegen3:: w_r3_all_errors flag 2022-08-13 23:14:18 +02:00
Zeno Rogue dfce80d152 rulegen3:: call correct get_roadsign in move_code 2022-08-13 23:13:37 +02:00
Zeno Rogue 0b24804934 rulegen:: on 'reached the end', remove the relevant codes 2022-08-13 23:13:22 +02:00
Zeno Rogue 44e8f31545 changelog for 12.0x 2022-08-13 22:45:42 +02:00
Zeno Rogue 68da2e967c rogueviz:: fixed variation in create_notknot to pure 2022-08-13 22:45:10 +02:00
Zeno Rogue cfb47631ac slide text improvements 2022-08-13 22:44:44 +02:00
Zeno Rogue cafd721284 do not showMissionScreen with game_keys_scroll 2022-08-13 22:44:00 +02:00
Zeno Rogue 5e59f299c6 fixed a bug with incorrect colors_of_floors remaining 2022-08-13 22:43:45 +02:00
Zeno Rogue 48c99f296a crystal view_coordinates in tour 2022-08-13 22:43:31 +02:00
Zeno Rogue e86e6267ec the implementation in reg3 can now be used for the cube tiling 2022-08-13 22:42:59 +02:00
Zeno Rogue 0eed6a03d4 CLI -exit now uses println not printf 2022-08-13 22:40:49 +02:00
Zeno Rogue 41ccb86c8c rogueviz:: various minor fixes to presentations 2022-08-12 09:09:38 +02:00
Zeno Rogue d5467eb379 rogueviz:: links to the papers in presentations 2022-08-12 09:09:18 +02:00
Zeno Rogue dd4001601f fixed a freeze in snowballs 2022-08-12 09:08:19 +02:00
Zeno Rogue 608c283f2d rogueviz:: snow:: new options snow_random_colors and snow_just_centered 2022-08-12 09:07:59 +02:00
Zeno Rogue c7663c83be fixed a bug in stereographic projection 2022-08-12 09:07:19 +02:00
Zeno Rogue c261db8a08 rogueviz:: intra-demos:: popscreen on run 2022-08-07 15:44:49 +02:00
Zeno Rogue e686f5bc39 yet another fix to racing 2022-08-07 15:01:28 +02:00
Zeno Rogue ce8e3c8640 fixed a crash when deleting 3-sphere maps 2022-08-07 15:01:14 +02:00
Zeno Rogue 7883d569d6 debug removed 2022-08-07 15:01:00 +02:00
Zeno Rogue ad744820ae version 12.0w 2022-08-07 03:30:01 +02:00
Zeno Rogue 2a33f86f6f added missing override 2022-08-07 03:30:01 +02:00
Zeno Rogue 0265f76c69 rogueviz:: presentation:: allow pre-rendered LaTeX 2022-08-07 03:16:24 +02:00
Zeno Rogue f38da4cba9 rogueviz:: added namespace to intra demos 2022-08-07 03:16:24 +02:00
Zeno Rogue cfad696d4a rogueviz::dhrg:: fixed some confusion 2022-08-07 03:16:24 +02:00
Zeno Rogue 2354be07e5 rulegen3:: specified args to arg::args 2022-08-07 03:16:24 +02:00
Zeno Rogue 22523ccfc3 rogueviz:: in the minesweeper presentation, updated the tes filename 2022-08-07 03:16:24 +02:00
Zeno Rogue 91f0f7ff03 rogueviz::presentation:: added a comment about what package you need 2022-08-07 03:16:24 +02:00
Zeno Rogue 0dc84d8f34 racing fixed (hopefully) 2022-08-07 03:16:24 +02:00
Zeno Rogue 884a9bb2c5 fixed a bug with 'world overview' breaking ESC menu 2022-08-07 03:16:24 +02:00
Zeno Rogue 4ed44d78cc rogueviz:: added two new presentations 2022-08-07 03:16:24 +02:00
Zeno Rogue 6030dd2a47 rogueviz::presentation:: new options 2022-08-07 03:16:24 +02:00
Zeno Rogue eec0c968d9 HyperRogue help is now directly offered when displaying context help 2022-08-07 03:16:24 +02:00
Zeno Rogue c87bca5da0 help:: do not suggest to try the Guided Tour if already in the Guided Tour 2022-08-07 03:16:24 +02:00
Zeno Rogue 4497821b35 help:: do not display HyperRogue text if game_keys_scroll 2022-08-07 03:16:24 +02:00
Zeno Rogue 389acc68e3 rogeviz::inner_maps::new options 2022-08-07 03:16:24 +02:00
Zeno Rogue f138bbb5c2 rogueviz::pres::non_game_slide_scroll 2022-08-07 03:16:24 +02:00
Zeno Rogue 1f832faeba prevent stored games from having their cgi destroyed 2022-08-07 03:16:24 +02:00
Zeno Rogue 1c01cc7f94 rogueviz:: clear textures on hooks_resetGL 2022-08-07 03:16:24 +02:00
Zeno Rogue 0b3980a5a4 rogueviz:: non_game_slide 2022-08-07 03:16:24 +02:00
Zeno Rogue db8c4ee0b9 intra:: export ticks 2022-08-07 03:16:24 +02:00
Zeno Rogue 7931ced3f8 intra::switching so that you can store off an intra game 2022-08-07 03:16:24 +02:00
Zeno Rogue dd0c1e6b3d print hyperpoint now prints MDIM dimensions 2022-08-07 03:16:24 +02:00
Zeno Rogue dee519badd added make_floor_textures in raycaster 2022-08-07 03:16:24 +02:00
Zeno Rogue 7787f26bc2 added kz to some debug printouts 2022-08-07 03:16:24 +02:00
Zeno Rogue ed4c715a5e hyperpoint now uses det3 not det (faster and also avoids some bugs for unknown reason) 2022-08-07 03:16:24 +02:00
Zeno Rogue 3184aea2be game_keys_scroll option 2022-08-07 03:16:24 +02:00
Zeno Rogue 1da912a0a2 rogueviz::inner-maps:: fixed the comment (typo and order) 2022-08-07 03:16:24 +02:00
Zeno Rogue 8b68ad2fdd rulegen debug removed 2022-08-07 01:57:34 +02:00
Zeno Rogue 464f4277cc fixed a memory leak in (de)compress_string 2022-08-07 01:57:06 +02:00
Zeno Rogue fba2cc95cf rulegen3:: transducer-based check 2022-08-07 01:52:51 +02:00
Zeno Rogue c8f3dc827e rulegen3:: more careful when adding to important 2022-08-07 01:47:52 +02:00
Zeno Rogue 4b4103f667 rulegen3:: some exports added 2022-08-07 01:45:26 +02:00
Zeno Rogue 70561f1f5a rulegen3:: honeycomb_value 2022-08-07 01:44:49 +02:00
Zeno Rogue 498c9828c3 fixed loop detection in hrmap_h3_subrule 2022-08-07 01:43:14 +02:00
Zeno Rogue 647a70e27f reg3:: added the missing make_subconnections to hrmap_from_crystal 2022-08-07 01:42:43 +02:00
Zeno Rogue e6879ee806 reg3:: added the missing destructor to hrmap_closed3 2022-08-07 01:42:17 +02:00
Zeno Rogue 1529986d6a reg3:: added subshapes.clear on generate_subcells 2022-08-07 01:41:04 +02:00
Zeno Rogue e3925d6bad config:: nomap as param_b 2022-08-07 01:40:00 +02:00
Zeno Rogue c647431486 Makefile rulegen fix again 2022-07-23 16:43:02 +02:00
Zeno Rogue 7b47a301a3 Makefile rulegen fix 2022-07-23 16:41:37 +02:00
Zeno Rogue 8a58604371 factored enable_canvas_backup 2022-07-23 16:33:11 +02:00
Zeno Rogue 8e094e93a5 shmup save data not only in shmup 2022-07-23 16:33:00 +02:00
Zeno Rogue e9bb38d3b1 rogueviz::dhrg:: export some functions 2022-07-23 15:45:42 +02:00
Zeno Rogue 67267cbe6b rogueviz::dhrg::routing:: export some functions 2022-07-23 15:44:31 +02:00
Zeno Rogue cd58923454 rogueviz::dhrg:: improved cleanup 2022-07-23 15:43:26 +02:00
Zeno Rogue 57f9e3efb6 rogueviz:: easier to leave show_likelihood 2022-07-23 15:42:58 +02:00
Zeno Rogue 10f1559da0 fixup 2022-07-23 15:42:42 +02:00
Zeno Rogue 96b335e465 rogueviz::dhrg:: panning enable in show_likelihood 2022-07-23 15:42:33 +02:00
Zeno Rogue dcffdbbca5 rogueviz::som::tests:: an option to disable vertex coloring 2022-07-23 15:40:20 +02:00
Zeno Rogue 6291da56c4 rogueviz::som:: an option to make floor invisible 2022-07-23 15:39:36 +02:00
Zeno Rogue 41bfaeaf36 rogueviz:: fix legend disabling HUD if there is nothing to show 2022-07-23 15:39:13 +02:00
Zeno Rogue a8b27b2bdb rogueviz:: export more 2022-07-23 15:38:44 +02:00
Zeno Rogue 62132073de rogueviz:: highlight_target feature 2022-07-23 15:38:29 +02:00
Zeno Rogue ded7bde82c rv::presentation:: latex packages changeable 2022-07-23 15:37:56 +02:00
Zeno Rogue 42abdd223e expansion:: export distance_from 2022-07-23 15:36:38 +02:00
Zeno Rogue e8b3f0c5c9 titlecolor setting 2022-07-23 15:36:27 +02:00
Zeno Rogue b07b805b33 rogueviz:: dialog_add_latex now can have LATEX_COLOR flag to display text colored in Latex 2022-07-21 03:28:54 +02:00
Zeno Rogue 238828e300 12.0v 2022-07-17 14:52:04 +02:00
Zeno Rogue 436cc15dba Android version fixed for API 31 2022-07-17 14:48:08 +02:00
Zeno Rogue e7818829e2 improvement to rulegen3 2022-07-17 14:41:57 +02:00
Zeno Rogue b76bddb47b rulegen:: split 2022-07-17 14:41:57 +02:00
Zeno Rogue 1a245b2523 shots:: postprocessing hooks 2022-07-17 14:41:57 +02:00
Zeno Rogue f2efc6f295 in hrmap_h3_subrule, better debugging of conficts 2022-07-17 14:41:57 +02:00
Zeno Rogue 7c6fece132 reg3:: removed some debug 2022-07-17 14:41:57 +02:00
Zeno Rogue 11426c30b3 auto-land-rotation now works even if CAP_ORIENTATION is on 2022-07-17 14:41:57 +02:00
Zeno Rogue 2f7a6194a6 hprint:: print template for sets 2022-07-17 14:41:57 +02:00
Zeno Rogue 5c302a4c52 pipes: fixed bad shading because of full white overflow, more strict lengths, do not shade if not in perspective 2022-07-17 14:41:57 +02:00
Zeno Rogue 894ee3ad8e savemem:: more aggresive adj_memo clear 2022-07-17 14:41:57 +02:00
Zeno Rogue c5650e4e46 savemem:: do not crash because of flashdata not cleared 2022-07-17 14:41:57 +02:00
Zeno Rogue 6225fd38e8 savemem:: removed some more potential crashes 2022-07-17 14:41:57 +02:00
Zeno Rogue 7c1d083afa memory_saving_mode as param_b 2022-07-17 12:40:07 +02:00
Zeno Rogue 32ed3d98ee savemem:: fixed a crash caoused by not erasing adj_memo 2022-07-17 12:39:55 +02:00
Zeno Rogue b229f2c9b8 savemem:: correct delete functions used 2022-07-17 12:36:21 +02:00
Zeno Rogue 3b4571aa16 3d:: choice of end type for pipes 2022-07-14 11:28:24 +02:00
Zeno Rogue 6c4a53c001 3d:: auto-rotate pipe for nice shading 2022-07-14 11:09:47 +02:00
Zeno Rogue 43ff375435 3d:: improved pipe texture 2022-07-14 11:09:25 +02:00
Zeno Rogue f101ddb7fd utils:: read_file_as_string 2022-07-13 21:00:16 +02:00
Zeno Rogue 48702739fd reg3:: support for >= 32 move directions 2022-07-13 20:59:20 +02:00
Zeno Rogue f25379ca7d reg3:: removed/improved some debug 2022-07-13 20:59:11 +02:00
Zeno Rogue 58c78220df reg3:: subrule:: remove non-branching NLES 2022-07-13 20:58:42 +02:00
Zeno Rogue 0e14d06e40 reg3:: made extra_origins more distant to prevent accidental crash 2022-07-13 20:56:49 +02:00
Zeno Rogue 4c4120e4f0 fixes to hrmap_subrule 2022-07-13 19:56:32 +02:00
Zeno Rogue 906ad4ab90 less-states 2022-07-13 19:33:00 +02:00
Zeno Rogue 0b4df47964 rulegen3:: new features 2022-07-13 19:31:24 +02:00
Zeno Rogue 6bc3dc9d6f subrule 3D maps implemented 2022-07-13 19:30:36 +02:00
Zeno Rogue 7252b04626 fixup move 2022-07-13 19:02:35 +02:00
Zeno Rogue 94a243a825 moved genhoneycomb to rulegen3 2022-07-13 18:59:04 +02:00
Zeno Rogue 5ef8092af2 further ruleset refactoring 2022-07-13 18:51:31 +02:00
Zeno Rogue 91e405e421 reg3:: factored off ruleset, and disabled the special handling of Space535 2022-07-13 17:34:29 +02:00
Zeno Rogue ffdc74a0b5 rulegen:: fixed a bug which caused problems on MYSTERY-th state 2022-07-13 17:25:04 +02:00
Zeno Rogue 0bcf2ca0ab Android update 2022-07-13 00:02:03 +02:00
Zeno Rogue 68507a555f 12.0u 2022-07-12 14:48:28 +02:00
Zeno Rogue dfe0d7ccf9 rulegen:: removed debug 2022-07-12 14:46:32 +02:00
Zeno Rogue 591d370ea4 centering menus is now configurable 2022-07-12 14:46:31 +02:00
Zeno Rogue 4a4e48400a settings to view less stuff on the screen; fixed items/kills going over buttons in the portrait mode 2022-07-12 14:46:31 +02:00
Zeno Rogue 8256b398b1 added missing override 2022-07-12 14:46:31 +02:00
Zeno Rogue c9c066ccec updated mobile for menu changes 2022-07-12 14:46:31 +02:00
Zeno Rogue ff16f35e0b added some missing guards for CAP_RACING and CAP_COMMANDLINE 2022-07-12 14:46:31 +02:00
Zeno Rogue de5e0505a3 honeycomb rules for 345 and 355 2022-07-12 14:46:31 +02:00
Zeno Rogue 45d1675d8f rulegen:: improved troubleshooting 2022-07-12 14:46:31 +02:00
Zeno Rogue 4bbf4a1a88 rulegen:: fixed get_aid 2022-07-12 14:46:31 +02:00
Zeno Rogue 8fdbe7714a rulegen3:: fixed for ultra 2022-07-12 14:46:31 +02:00
Zeno Rogue 81248f0558 rogueviz:: anygraph removed since it is in dhrg now 2022-07-12 14:46:31 +02:00
Zeno Rogue 9a916f1ef3 rogueviz:: added DHRG 2022-07-12 14:46:31 +02:00
Zeno Rogue e04a6bc49a rogueviz:: reads hidden dependencies 2022-07-12 14:46:31 +02:00
Zeno Rogue b3728b109f devmods/tests updated 2022-07-12 14:46:31 +02:00
Zeno Rogue 85b4785447 devmods/solv-table updated 2022-07-12 14:46:31 +02:00
Zeno Rogue 0b29dc3964 devmods/musictable updated 2022-07-12 14:46:31 +02:00
Zeno Rogue b8ad184d70 devmods/honeycomb-rule-generator updated 2022-07-12 14:46:31 +02:00
Zeno Rogue c914dfbeb4 devmods/edit-shaders updated 2022-07-12 14:46:31 +02:00
Zeno Rogue a0abdb6f6f devmods/manual-animations:: updated 2022-07-12 14:46:31 +02:00
Zeno Rogue 9c9726249a update devmods/knuth-bendix.cpp 2022-07-12 14:46:31 +02:00
Zeno Rogue b3c3cc331e rogueviz:: readLabel 2022-07-12 14:46:31 +02:00
Zeno Rogue 9002ef2681 rogueviz:: max_line_splits parameter 2022-07-12 14:46:31 +02:00
Zeno Rogue 1cdf638128 rogueviz;: nilcompass:: fixup 2022-07-12 14:46:31 +02:00
Zeno Rogue 37f8479629 rulegen-tests:: -urq now has a parameter detailing what you want to do 2022-07-12 14:46:31 +02:00
Zeno Rogue 98d95a520c rulegen-tests:: -gen-honeycomb minimizes 2022-07-12 14:46:30 +02:00
Zeno Rogue dbb02d6bc9 rulegen:: a fixup for substates becoming a map 2022-07-12 14:46:30 +02:00
Zeno Rogue ae170378f5 mobile:: fixed an incorrect button shown in the game menu 2022-07-12 14:46:30 +02:00
Zeno Rogue dabc227cbe hprint:: some extra functions 2022-07-12 14:46:30 +02:00
Zeno Rogue ea66cb9706 rulegen-tests:: generate honeycombs 2022-07-12 14:46:30 +02:00
Zeno Rogue cdb2a001ca rulegen3 2022-07-12 14:46:30 +02:00
Zeno Rogue 3318c1e4b4 reg3:: fixed origins 2022-07-12 14:46:30 +02:00
Zeno Rogue a5c67624fd reg3:: fixed hrmap_h3 pure 2022-07-12 14:46:30 +02:00
Zeno Rogue 6113e0fd56 reg3:: improved strafe test 2022-07-12 14:46:30 +02:00
Zeno Rogue ef712a3b4f rulegen:: also number_of_types 2022-07-12 14:46:30 +02:00
Zeno Rogue c3ba88cb6c hrmap_h3 supports extra_origins 2022-07-12 14:46:30 +02:00
Zeno Rogue a920b837e1 reg3:: hrmap_h3 now works with subcells 2022-07-12 14:46:30 +02:00
Zeno Rogue a6116d678e reg3:: factored gen_quotient_map 2022-07-12 14:46:30 +02:00
Zeno Rogue 3f56f158ee rulegen:: tests:: animation of the algorithm 2022-07-12 14:46:30 +02:00
Zeno Rogue 1cd8abd011 rulegen:: tests:: view_actual_seq 2022-07-12 14:46:30 +02:00
Zeno Rogue 46cf751200 rulegen-tests:: fix gamescreen 2022-07-12 14:46:30 +02:00
Zeno Rogue c775936970 rulegen:: generalize to work with other maps than arbi 2022-07-12 14:46:30 +02:00
Zeno Rogue fb9bf4263a rulegen:: call hooks to animate the algorithm 2022-07-12 14:46:30 +02:00
Zeno Rogue 220a4b1a88 12.0t1 2022-07-12 14:46:30 +02:00
Zeno Rogue 710ae06e03
Merge pull request #310 from Technochips/master
FRENCH: more gender fixes (-e...)
2022-07-07 20:51:50 +02:00
Technochips efa8567a2b FRENCH: added "de" / "d'" 2022-07-05 23:16:56 +02:00
Technochips d69f4e868d FRENCH: more gender fixes (-e...) 2022-07-05 23:00:10 +02:00
Zeno Rogue c652b6bd00 made flags in hyper.h consistent with langen.cpp 2022-07-05 21:20:21 +02:00
Zeno Rogue 7fda3c08c4
Merge pull request #309 from Technochips/master
WIP: French improvements
2022-07-05 21:12:59 +02:00
Technochips 3881da340c FRENCH: fixed strings in language.cpp 2022-07-05 21:04:28 +02:00
Zeno Rogue 78b2482bbb
Merge pull request #308 from Quuxplusone/fixups
Various small compiler-warning fixes
2022-07-05 20:43:33 +02:00
Arthur O'Dwyer 1b8296a1f8 Fix Clang error where lambdas can't capture structured bindings until C++20
./rogueviz/nil-compass.cpp:98:10: error: reference to local binding 'i'
    declared in enclosing function 'rogueviz::nilcompass::draw_compass'
          if(i == _i && is == _is) return col;
             ^
2022-07-05 14:14:53 -04:00
Technochips 3dc7c3b086 FRENCH: gender flags, fixed a bunch of small stuff 2022-07-05 19:57:02 +02:00
Arthur O'Dwyer 2ec10ff7f2 Fix -Wsuggest-override on Clang 2022-07-05 13:28:00 -04:00
Arthur O'Dwyer ad47db4240 Suppress -Wchar-subscripts on Clang
For example:

    ./rogueviz/platformer.cpp:388:14: error: array subscript is
    of type 'char' [-Werror,-Wchar-subscripts]
      if(keystate['3'])
                 ^~~~
2022-07-05 13:28:00 -04:00
Arthur O'Dwyer 559301e69f Fix -Wmisleading-indentation warning on Clang 2022-07-05 13:28:00 -04:00
Arthur O'Dwyer 3c3f2b2b21 Silence overzealous -Wunused-result warnings on GCC 2022-07-05 13:28:00 -04:00
Arthur O'Dwyer dd55129ed3 Fix "extra ;" warnings on GCC 2022-07-05 13:28:00 -04:00
Arthur O'Dwyer 0ae74aad62 Fix more instances of Clang's -Wunqualified-std-cast-call 2022-07-05 13:28:00 -04:00
Arthur O'Dwyer 85753d240f Fix instances of Clang's -Wunqualified-std-cast-call 2022-07-05 12:19:04 -04:00
Technochips d315c74261 FRENCH: fixed a few typos 2022-07-05 16:30:04 +02:00
Technochips 3cdfd6e953 FRENCH: fixed extra apostrophes 2022-07-05 16:23:21 +02:00
Zeno Rogue 2d619d2f7c fixed the version number in changelog 2022-07-05 16:13:06 +02:00
Zeno Rogue 80eaaf93e7 rv::kohonen:: heatmap drawing 2022-07-05 16:04:19 +02:00
Zeno Rogue b2fb02f863 gamescreen updated in rogueviz 2022-07-05 16:03:12 +02:00
Zeno Rogue 80cc89f6eb 12.0t 2022-07-05 15:52:02 +02:00
Zeno Rogue 59ea72d506 side for sightrange edit 2022-07-05 14:02:51 +02:00
Zeno Rogue a0d3c402d7 fixup: addalpha 2022-07-05 14:02:45 +02:00
Zeno Rogue a2113d4142 darken the menu side of the screen 2022-07-05 14:00:51 +02:00
Zeno Rogue bbc495b2fb darken the menu side of the screen 2022-07-05 13:57:34 +02:00
Zeno Rogue 6e1743ac86 prettier color items 2022-07-05 12:54:59 +02:00
Zeno Rogue 5763120dae color dialog has the new sliders 2022-07-05 12:34:31 +02:00
Zeno Rogue 3ae7d8b2d7 graphical sliders 2022-07-05 12:26:20 +02:00
Zeno Rogue 52186377a0 fixed French 2022-07-05 11:52:05 +02:00
Zeno Rogue a19adccf82 startanims now can be disabled 2022-07-05 11:51:49 +02:00
Zeno Rogue 09d67c24f0 fixed the help button in the pause menu 2022-07-05 11:51:32 +02:00
Zeno Rogue 75f58766a2 made background screen darkening consistent and optional 2022-07-05 11:51:06 +02:00
Zeno Rogue b3a394c266 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-07-05 02:59:33 +02:00
Zeno Rogue db2139e4ab documented new options in Readme 2022-07-05 02:56:15 +02:00
Zeno Rogue 1987eff6cd remove -Werror and -march=native from mymake 2022-07-05 02:54:07 +02:00
Zeno Rogue 510d3785a7
Merge pull request #305 from AMDmi3/flags
Don't set -march=native and -Werror by default
2022-07-05 02:49:08 +02:00
Zeno Rogue 8eaeff85eb fixes in the French translation 2022-07-05 02:45:04 +02:00
Zeno Rogue 1bc7cd04cb implemented French translation 2022-07-05 02:44:19 +02:00
Zeno Rogue fe68186e5a refactored basicrep and parrep: genderrep to avoid repeated lines in both %y0 and %yINDEX, no more need for special case when noun not found 2022-07-05 01:57:33 +02:00
Zeno Rogue f69fce0050 fixed the Polish translation of the description of False Princess 2022-07-05 01:32:26 +02:00
Zeno Rogue e50c22134c
Merge pull request #307 from Quuxplusone/language-fr
Add @3raven's language-fr.cpp
2022-07-04 12:02:15 +02:00
Arthur O'Dwyer 8a1ee4622b French language translation by @3raven 2022-07-01 14:11:14 -04:00
Arthur O'Dwyer 77e2c64538 [Makefile] langen depends on language-ptbr.cpp 2022-07-01 14:08:05 -04:00
Arthur O'Dwyer 48800f58f8 Fix some compiler errors and a mistake in config.cpp. 2022-07-01 14:07:58 -04:00
Dmitry Marakasov b7975f20ce Enable -Werror for CI 2022-06-29 21:58:11 +03:00
Dmitry Marakasov 6f812233d2 Don't set -march=native and -Werror by default
See https://amdmi3.ru/posts/packaging-friendliness-compiler-flags-to-avoid/
2022-06-24 13:59:05 +03:00
Zeno Rogue 2486937720 10.2s 2022-06-24 00:23:04 +02:00
Zeno Rogue 5fe6aee84f show treasure bubbles in Dice Reserve 2022-06-23 13:46:34 +02:00
Zeno Rogue 217c6287fe all cheat keys are now displayed in the cheat menu -- also removed some outdated ones 2022-06-23 13:46:14 +02:00
Zeno Rogue 3ef10f1996 removed the extra 'racing menu' option from the pause menu 2022-06-23 13:05:25 +02:00
Zeno Rogue 5e27a2cc88 shift+A now exits the map editor 2022-06-23 13:02:37 +02:00
Zeno Rogue 9497eb31b9 fixup -- stars also do not have_valence 2022-06-23 10:49:27 +02:00
Zeno Rogue 1b832b4a54 arb:: tes files with tree data provided work again 2022-06-23 10:36:37 +02:00
Zeno Rogue c544ce5ed0 clearer comment on minimize_on_convert 2022-06-23 10:35:49 +02:00
Zeno Rogue 18549100f1 tes:: convert:: an option to produce minimal representation 2022-06-23 10:29:49 +02:00
Zeno Rogue d20b6a2e0f rogueviz:: added dpgen and antidesitter to rogueviz-all 2022-06-23 09:44:43 +02:00
Zeno Rogue 224376e234 rogueviz:: reset compass 2022-06-23 09:44:15 +02:00
Zeno Rogue 38099bd7cb hybrid:: new value of 'next' for get_corner 2022-06-23 09:35:16 +02:00
Zeno Rogue 11c4b7974f fixed Ctrl+keys on some systems 2022-06-23 09:34:21 +02:00
Zeno Rogue e691c63abe CLI option -cview 2022-06-23 09:33:58 +02:00
Zeno Rogue 61fcf62727 arb:: fixed cycle_length and repeat_value for conversion 2022-06-23 09:33:41 +02:00
Zeno Rogue 7480d1e0ea rogueviz:: updated to hr changes 2022-06-23 09:32:58 +02:00
Zeno Rogue ebeb22c448 rogueviz:: antidesitter comment added 2022-06-23 09:32:10 +02:00
Zeno Rogue e07f3eb5ff rogueviz:: antidesitter updated 2022-06-23 09:31:39 +02:00
Zeno Rogue de4b436d48 rogueviz:: VR in ascending/descending 2022-06-23 08:59:14 +02:00
Zeno Rogue 3b816f46fc fixed race reset 2022-06-21 10:34:43 +02:00
Zeno Rogue 952b99856d fixed Minesweeper in the highlights menu 2022-06-21 10:28:24 +02:00
Zeno Rogue ddf11f4b42 12.0r 2022-06-17 12:17:29 +02:00
Zeno Rogue 9fbe770db9 ghosts prioritize attacking players over attacking allies 2022-06-17 10:56:31 +02:00
Zeno Rogue fe42b5e2ef fixed Orbs not affecting slime 2022-06-17 10:46:13 +02:00
Zeno Rogue c6369ac832 Orb of the Sword can now kill yourself through mirror or topology 2022-06-17 10:40:26 +02:00
Zeno Rogue 7a7a982b33 sword attacks reflect in mirrors 2022-06-17 10:27:02 +02:00
Zeno Rogue 9ae7bb3d7b swords in mirrors are now displayed correctly 2022-06-17 09:43:37 +02:00
Zeno Rogue 227270283f mimics are now affected by Empathy, and no longer can reverse slime colors by going through mirror 2022-06-17 09:22:25 +02:00
Zeno Rogue a87ef1b02c Woods+Time: do not waste charge on attacking monsters in trees 2022-06-17 09:13:46 +02:00
Zeno Rogue 80e5a9d50e fixed help for life Orbs in the shmup mode 2022-06-17 09:09:53 +02:00
Zeno Rogue 56b0912ef0 Halloween:: fixed the jack-o-lantern 2022-06-17 01:26:44 +02:00
Zeno Rogue 9bb9fd572d moved dual geometry puzzle to RogueViz 2022-06-17 01:20:34 +02:00
Zeno Rogue f3f502e65e special modes cleanup, highlights cleanup 2022-06-17 01:03:31 +02:00
Zeno Rogue c9dae8e753 peace:: cleanup 2022-06-17 01:03:05 +02:00
Zeno Rogue fd36f65fc4 moved creative to game menu 2022-06-17 00:27:56 +02:00
Zeno Rogue 0c445ef365 switching shmup no longer invokes keyboard configuration 2022-06-16 23:58:28 +02:00
Zeno Rogue e6d0c0c803 unified the Quest screen and Main menu. 2022-06-16 23:54:47 +02:00
Zeno Rogue f196d706a6 racing:: don't block cells on load 2022-06-16 23:23:29 +02:00
Zeno Rogue 54971828da racing:: fixup 2022-06-16 23:14:19 +02:00
Zeno Rogue e5b561c804 optimize_shift function for shiftpoint 2022-06-16 23:14:10 +02:00
Zeno Rogue 784dc0d13a tour:: don't display help on NOTITLE 2022-06-16 23:13:54 +02:00
Zeno Rogue 5e2ba55e46 CLI command -rotate-up 2022-06-16 23:13:38 +02:00
Zeno Rogue ba99e537a3 revert uploadScore 2022-06-16 23:13:21 +02:00
Zeno Rogue d2333c15c3 racing:: restore_goals on save 2022-06-16 23:13:06 +02:00
Zeno Rogue 83eb725448 racing:: just reset the race on restart 2022-06-16 23:11:34 +02:00
Zeno Rogue b888205a17 racing:: save records 2022-06-16 23:11:22 +02:00
Zeno Rogue d2bd8933dd racing:: new system 2022-06-16 23:10:44 +02:00
Zeno Rogue 9331309af9 map:: lost memory not saved 2022-06-16 23:07:36 +02:00
Zeno Rogue f0e07eca66 map:: save halls of mirrors correctly 2022-06-16 23:07:20 +02:00
Zeno Rogue 86d1f109bc mapstreams:: now work with sstream too 2022-06-16 23:06:49 +02:00
Zeno Rogue 45e80ca5b5 mymake:: SDL2 with mingw-cross 2022-06-10 18:45:50 +02:00
Zeno Rogue 066b683bde walking:: switch_walking function 2022-06-10 18:45:28 +02:00
Zeno Rogue 91b6628922 fixed SDL2 (with GLEW) on Windows 2022-06-10 18:45:15 +02:00
Zeno Rogue 3fa23afdce rv::presentation:: added -slide-textoff 2022-06-08 18:05:18 +02:00
Zeno Rogue 73ceb6400d rv::presentation:: split empty_screen and white_screen 2022-06-08 18:05:05 +02:00
Zeno Rogue f02b385138 nilrider:: reverted duration check 2022-06-08 18:04:27 +02:00
Zeno Rogue 4d3a9081a9 dynamic-wfc: animation 2022-06-08 18:03:32 +02:00
Zeno Rogue fd5458eaed in history::progress, progress_each is now configurable 2022-06-08 18:01:23 +02:00
Zeno Rogue 88fcca886c fixed write_in_space to use poly_outline 2022-06-08 18:00:43 +02:00
Zeno Rogue d0a5c52889 fixed numerical_minefield display to darken numbers correctly 2022-06-08 18:00:28 +02:00
Zeno Rogue 6039c40bc2 fixed adj_minefield_cells_full 2022-06-08 18:00:00 +02:00
Zeno Rogue 356bce6842 fixup 2022-05-28 19:30:29 +02:00
Zeno Rogue 8660baf3e1 rogueviz:: added dynamic-wfc 2022-05-28 19:30:01 +02:00
Zeno Rogue a28e9e4df5 rogueviz::som:: fixup to last 2022-05-28 19:02:20 +02:00
Zeno Rogue 3b6dac7471 rogueviz::som:: fixup bounded -> closed_manifold 2022-05-28 19:00:53 +02:00
Zeno Rogue 743d9bd7f0 replaced std::sort in pattern2 with manual sort to avoid spurious warning in gcc 12.1.0 2022-05-28 18:58:37 +02:00
Zeno Rogue 5e2a1b6424 fixed a 'pointer used after free' warning 2022-05-28 18:52:10 +02:00
Zeno Rogue cd4cc52768 nilrider:: special music handling 2022-05-28 18:49:29 +02:00
Zeno Rogue a7dac1b28e NilRider version number set to 1.0 2022-05-28 18:48:38 +02:00
Zeno Rogue 1ac9df7c3c partial implementation of antidesitter 2022-05-28 18:48:10 +02:00
Zeno Rogue 5e22163d38 rogueviz:: fixed nil-compass order 2022-05-28 18:47:30 +02:00
Zeno Rogue b0e136dc85 rogueviz:: changed texture twidth to 4096 2022-05-28 18:47:08 +02:00
Zeno Rogue 3d05c9ae84 rogueviz::heatx:: added heat mode as parameter, and added '3' for fake Euclidean heat 2022-05-28 18:46:27 +02:00
Zeno Rogue b6b32d2c2b fixed sl2 rendering 2022-05-28 18:44:42 +02:00
Zeno Rogue a4d8e8314b hooks_sync_music 2022-05-28 18:44:22 +02:00
Zeno Rogue 4892541287 added comments for sl:: parameters, set them as param_, renamed steps to shader_iterations 2022-05-28 18:43:43 +02:00
Zeno Rogue 9c1dd1088b 12.0q 2022-05-21 17:25:39 +02:00
Zeno Rogue 57fd87e1d4 minesweeper now disables minefield range 2022-05-21 17:12:02 +02:00
Zeno Rogue ff2aa90321 numerical_minefield is now editable 2022-05-21 17:12:02 +02:00
Zeno Rogue 1cf26b5380 disk shape configurable 2022-05-21 17:12:02 +02:00
Zeno Rogue 296726a887 mark_always internal option 2022-05-21 17:12:02 +02:00
Zeno Rogue e32f1a4670 marked mines are now displayed at full intensity when ispeed==0 2022-05-21 17:12:02 +02:00
Zeno Rogue c9d90c1c64 now can change the shape of the disk 2022-05-21 17:12:02 +02:00
Zeno Rogue c9d1f8dfeb adj_memo now can keep separate memos for different rules 2022-05-21 17:12:01 +02:00
Zeno Rogue c80d6134e3 adj_minefields_cells_with_orientation upgraded to adj_minefield_cells_full 2022-05-21 16:38:39 +02:00
Zeno Rogue 37f4e400bd made all_disk_cells and all_disk_cells_sorted different, for consistency 2022-05-21 13:09:46 +02:00
Zeno Rogue 793148729b An option to play on a disk (and use bounded space rules). Also renamed 'bounded' flag to 'closed' or similar, and improved Halloween 2022-05-21 13:08:42 +02:00
Zeno Rogue 9bc0623022 disable_orb_range cheat for presentations 2022-05-17 09:45:09 +02:00
Zeno Rogue a703e1af2d dont_display_minecount flag 2022-05-17 09:45:09 +02:00
Zeno Rogue 238422fe89 ray:: renamed deparabolic13 and enparabolic13 adding 'i' to signify that they reorder the coordinates 2022-05-17 09:45:09 +02:00
Zeno Rogue 6285e39b06 export some linepatterns and expansion stuff 2022-05-17 09:45:09 +02:00
Zeno Rogue a6dc4b9314 new projections mostly for Solv: Lie perspective and Lie orthogonal 2022-05-17 09:45:09 +02:00
Zeno Rogue 69a82a8ce1 fixed lie_exp to use correct rules in solnih, and also avoid division by h[2] == 0 2022-05-17 09:37:32 +02:00
Zeno Rogue b9fd64e1d9 numerical_minefield option -- not yet changed in menu 2022-05-17 09:34:58 +02:00
Zeno Rogue 228c3e9866 v12.0p 2022-05-10 09:02:37 +02:00
Zeno Rogue 94c7cf6b03 more guard fixes 2022-05-10 08:53:58 +02:00
Zeno Rogue 319e316b55 nilrider:: fixed panning 2022-05-09 15:58:36 +02:00
Zeno Rogue 001be27c87 nilrider:: do not init textures and shapes before they are needed 2022-05-09 15:15:58 +02:00
Zeno Rogue 20ebc8b488 nilrider:: CAP_SAVE guards 2022-05-09 15:09:28 +02:00
Zeno Rogue 3ac690434d nilrider:: we need CAP_TEXTURE, and CAP_CONFIG guard added 2022-05-09 15:09:28 +02:00
Zeno Rogue b0c34c4f2c added CAP_RAY guard to intra stuff 2022-05-09 15:09:23 +02:00
Zeno Rogue 3c491fb7ac nilrider:: unilrun removed 2022-05-09 14:47:06 +02:00
Zeno Rogue 0f1f4ce99b nilrider:: recording if CAP_VIDEO is available 2022-05-09 14:47:06 +02:00
Zeno Rogue da5a17f8df nilrider:: new track (obstacle track) 2022-05-09 14:47:06 +02:00
Zeno Rogue 7ff9177484 nilrider:: no levellines by default 2022-05-09 14:47:06 +02:00
Zeno Rogue da21b1cb00 rogueviz:: Impossibility presentation updated 2022-05-09 14:47:06 +02:00
Zeno Rogue bd10f06a4c intra:: fix the VR settings 2022-05-09 14:47:06 +02:00
Zeno Rogue e51747dd42 draw sidewalls for shallow 2022-05-09 10:30:50 +02:00
Zeno Rogue 17a18d7579 nilrider:: levellines 2022-05-09 10:02:21 +02:00
Zeno Rogue d4957fd56b nilrider: CAP_VR guards 2022-05-09 09:40:35 +02:00
Zeno Rogue a300cb6ca0 nilrider:: fixed save comment 2022-05-09 09:39:29 +02:00
Zeno Rogue c8e5c3e763 precision in binsearch 2022-05-07 15:18:20 +02:00
Zeno Rogue 9c29f39f7e vr:: fixed buttons 2022-05-07 15:17:30 +02:00
Zeno Rogue acfc18b6a8 nilrider:: reduce quality feature 2022-05-06 21:08:15 +02:00
Zeno Rogue 6d8ce6db68 made some things faster 2022-05-06 21:07:57 +02:00
Zeno Rogue 381523515e nilrider:: vr improvements 2022-05-06 20:28:08 +02:00
Zeno Rogue 279fe685ec nilrider:: VR support 2022-05-06 19:55:09 +02:00
Zeno Rogue 00d606de47 nilrider:: fixed the seat model 2022-05-06 19:55:09 +02:00
Zeno Rogue 3f0dc27140 vr:: refactored vr_enable_button 2022-05-06 19:55:09 +02:00
Zeno Rogue da3584a89d nilrider:: fixed castle texture and minitriangle regen 2022-05-06 19:55:09 +02:00
Zeno Rogue 54fa76ecf8 nilrider:: smooth scrolling enabled 2022-05-06 19:55:09 +02:00
Zeno Rogue 775213345f nilrider:: expanded the level descriptions 2022-05-06 19:55:09 +02:00
Zeno Rogue 4846ffcb53 rogueviz:: fixed smooth movement in smoothcam 2022-05-06 19:55:09 +02:00
Zeno Rogue 6fe07c389c fixed smooth movement in modes other than sm::NORMAL 2022-05-06 19:55:09 +02:00
Zeno Rogue 0c2c32c126 nilrider:: debug removed 2022-05-06 19:55:09 +02:00
Zeno Rogue f6000cbf7a nilrider:: set black outline in menu 2022-05-06 19:55:09 +02:00
Zeno Rogue 54fde5348d nilrider:: don't pause if we have not even started 2022-05-06 19:55:09 +02:00
Zeno Rogue 34d8cb6f27 nilrider:: redesigned the track menu, and starting in it 2022-05-06 19:55:09 +02:00
Zeno Rogue b67b37f8f4 clear ext in prepare_shapes 2022-05-06 19:55:09 +02:00
Zeno Rogue 738d12ddf0 nilrider:: fixed loading records 2022-05-06 19:55:05 +02:00
Zeno Rogue 0f07b7866f nilrider:: fixed incorrect vertexlists in cgi 2022-05-06 19:55:05 +02:00
Zeno Rogue bc8811530f nilrider:: saving/viewing goals 2022-05-06 19:55:05 +02:00
Zeno Rogue 09266b3059 nilrider:: records and currentscores 2022-05-06 19:55:05 +02:00
Zeno Rogue aec4f78ac6 nilrider:: remove timer from checkerparam 2022-05-06 19:55:05 +02:00
Zeno Rogue 4d1c3b0956 nilrider:: fixed slowdown in planning 2022-05-06 19:55:03 +02:00
Zeno Rogue d95bbe2574 nilrider:: fixed missing textures in planning 2022-05-06 19:54:58 +02:00
Zeno Rogue 19a83d2ea8 nilrider:: timer is now recorded with timestamp 2022-05-06 19:54:58 +02:00
Zeno Rogue 4ab376caa7 nilrider:: fixed a bug in pfloor 2022-05-06 19:54:55 +02:00
Zeno Rogue 13e6fa057c nilrider:: sound effects 2022-05-06 19:54:55 +02:00
Zeno Rogue 426361ad96 nilrider:: standalone version 2022-05-06 19:54:55 +02:00
Zeno Rogue a0058eed72 nilrider:: textures invalidating should be fixed 2022-05-06 19:54:55 +02:00
Zeno Rogue dc375ade49 nilrider:: fixed recording surfaces to wrong cgi 2022-05-06 19:54:55 +02:00
Zeno Rogue 9502fc97fc nilrider:: the road starts closer so we know where to go 2022-05-06 19:54:55 +02:00
Zeno Rogue 0dace6f3c2 nilrider:: loaded_or_planned flag 2022-05-06 19:54:55 +02:00
Zeno Rogue b0587572ae fixed some CAP_TOUR guards in rogueviz 2022-05-06 19:54:55 +02:00
Zeno Rogue 78b0324a91 fixed some CAP guards 2022-05-06 19:54:55 +02:00
Zeno Rogue 075630e753 nilrider:: fixed wrong-sized instruments (and maybe something else) 2022-05-06 19:54:55 +02:00
Zeno Rogue e3c8a4c5bf nilrider:: fixed texturing in stepped 2022-05-06 19:54:55 +02:00
Zeno Rogue c057e10051 nilrider:: -nilrider CLI option (and function initialize_all) 2022-05-06 19:54:55 +02:00
Zeno Rogue 80ba9b4835 nilrider:: two projection styles 2022-05-06 19:54:55 +02:00
Zeno Rogue 418eb072dc lie_exp approximation for other geometries 2022-05-06 19:54:55 +02:00
Zeno Rogue 1c907be9da shift_view with geodesic-movement disabled is now based on Lie exponentials (NYI: SL2, Berger) 2022-05-06 19:54:55 +02:00
Zeno Rogue 97c7aef1a9 nilrider:: fix poly_outline changing 2022-05-06 19:54:55 +02:00
Zeno Rogue 28b7800d68 nilrider:: immediate reaction to camera distance 2022-05-06 19:54:55 +02:00
Zeno Rogue 2a9a219e61 nilrider:: stepped display 2022-05-06 19:54:55 +02:00
Zeno Rogue 166ae943ea nilrider:: to instruments, add display triangles, goals, and reversals 2022-05-06 19:54:55 +02:00
Zeno Rogue 117e2cb6f4 nilrider:: goal checking and goal solving and goals for all levels 2022-05-06 19:54:55 +02:00
Zeno Rogue b3e29d9e03 nilrider:: nlrOrder flag to order the triangles correctly 2022-05-06 19:54:55 +02:00
Zeno Rogue 0e3e3b9042 nilrider:: do not put the camera inside a wall 2022-05-06 19:54:55 +02:00
Zeno Rogue 2a5e83d760 nilrider:: remove the outdated initial plan 2022-05-06 19:54:55 +02:00
Zeno Rogue 775fc9b523 nilrider:: start on no-slope 2022-05-06 19:54:55 +02:00
Zeno Rogue 3772f45366 nilrider:: added triangles to remaining levels 2022-05-06 19:54:47 +02:00
Zeno Rogue fe947e0369 hilrider:: goal added in geodesical4 2022-05-06 19:54:47 +02:00
Zeno Rogue 9d2acb89c6 nilrider:: implemented xy_ functions for polar 2022-05-06 19:54:47 +02:00
Zeno Rogue e227119edb nilrider:: fixed pfloor 2022-05-06 19:54:47 +02:00
Zeno Rogue 9fc078e9c7 nilrider:: added a speeding area in the longtrack level 2022-05-06 19:54:47 +02:00
Zeno Rogue dcf0d8af9c nilrider:: refactored mapchar and get_xy 2022-05-06 19:54:47 +02:00
Zeno Rogue 2bd079003a nilrider:: loading saved plans and replays 2022-05-02 03:38:20 +02:00
Zeno Rogue ae503cf322 rv:: missing nil-compass 2022-05-01 21:09:06 +02:00
Zeno Rogue 7ac06e00a1 other settings are now changeable 2022-05-01 16:53:50 +02:00
Zeno Rogue 62331b43f1 nilrider:: basic save functionality (no load though) 2022-05-01 16:45:18 +02:00
Zeno Rogue 3072a998ba nilrider:: consistent replays 2022-05-01 16:44:35 +02:00
Zeno Rogue f82043e87e nilrider:: now using multi::get_actions() 2022-05-01 16:43:55 +02:00
Zeno Rogue 5a13f629d1 split off get_actions from handleInput 2022-05-01 16:43:30 +02:00
Zeno Rogue c4d4bfa517 nilrider:: replays available in manual mode 2022-05-01 16:42:38 +02:00
Zeno Rogue 1e176bb3b0 nilrider:: removed speedlimit -- will do it other way 2022-05-01 12:51:58 +02:00
Zeno Rogue 8ba5c58ac2 nilrider:: configurable keys, smooth reversal 2022-05-01 12:51:17 +02:00
Zeno Rogue 80acbc788f aimspeed settings 2022-05-01 12:12:04 +02:00
Zeno Rogue f3a597dd97 rv:: balloonsim added 2022-05-01 11:27:41 +02:00
Zeno Rogue 15e09eb6ec fixed buggy resizing 2022-05-01 11:25:49 +02:00
Zeno Rogue d3864a2e2c arb:: simplified display of apeirogons 2022-05-01 11:18:39 +02:00
Zeno Rogue 292bb72794 arb:: refactored set_defaults 2022-05-01 11:14:30 +02:00
Zeno Rogue edee92d877 arb:: fixed warning 2022-05-01 11:14:12 +02:00
Zeno Rogue 561a986b3d nilrider:: a simple solver 2022-04-30 12:04:50 +02:00
Zeno Rogue 523e000664 nilrider:: planning:: insert command now lets to drag to set vel 2022-04-30 12:03:54 +02:00
Zeno Rogue a5313d24c4 nilrider::planning:: derivative points now have priority when moving, otherwise they were immovable if vel == 0 2022-04-30 12:03:30 +02:00
Zeno Rogue e21a0180af nilrider:: show cursor in planning 2022-04-30 12:02:30 +02:00
Zeno Rogue 02d195ca0b new screen option sm::SHOWCURSOR 2022-04-30 12:02:05 +02:00
Zeno Rogue 59b11a74ad nilrider:: collecting triangles 2022-04-30 12:01:18 +02:00
Zeno Rogue a234a76d20 fixed the bug with partial symmetry apeirogons 2022-04-28 08:39:47 +02:00
Zeno Rogue 84d48789c7 apeirogonal color fixup 2022-04-28 08:24:13 +02:00
Zeno Rogue 51ea62977f debug_tiles feature 2022-04-28 08:23:33 +02:00
Zeno Rogue 63e855562c fixed the problem where apeirogons got outside boundary 2022-04-28 08:23:07 +02:00
Zeno Rogue f1ccf0450c 12.0o 2022-04-28 00:03:41 +02:00
Zeno Rogue 53289b3ba6 tes:: fix to apeirogons 2022-04-27 23:56:48 +02:00
Zeno Rogue 41d1ac743c fixed spherical geometry 2022-04-27 23:55:16 +02:00
Zeno Rogue 8e8de810fe v12.0n 2022-04-26 23:15:59 +02:00
Zeno Rogue 711fdf6c0d comments added to the new tes samples 2022-04-26 16:29:32 +02:00
Zeno Rogue b9c76d8162 options to disable apeirogon_consistent_coloring and apeirogon_hide_grid_edges 2022-04-26 16:19:02 +02:00
Zeno Rogue 61c3e41e8a gridlines now draw correctly for (ultra)ideal vertices 2022-04-26 16:19:02 +02:00
Zeno Rogue bff04eaf34 ultratriangle sample added 2022-04-26 16:19:02 +02:00
Zeno Rogue 27c9f59caa fixed the dice layering issue 2022-04-26 16:19:02 +02:00
Zeno Rogue 20e44ef18c fixed slime movement on nonorientable 2022-04-26 16:19:02 +02:00
Zeno Rogue 920fc454f0 slime spill is now predictable when multiple colors hit the same cell at once 2022-04-26 16:19:02 +02:00
Zeno Rogue 7adb3dac5a mirrors now flip Alchemist Lab colors (may be a bit unpredictable in minimal quotient) 2022-04-26 16:19:02 +02:00
Zeno Rogue 49d7ab3ed3 floating bubbles now should work correctly for Mirror Shards, Elemental Gems and Ancient Jewelry 2022-04-26 16:19:02 +02:00
Zeno Rogue 12b6ff7208 fixed Prairie in field quotient 2022-04-26 16:19:02 +02:00
Zeno Rogue 38564c3daf marked Hell as no-the 2022-04-26 16:19:02 +02:00
Zeno Rogue 5269c357d4 run away from the lava 2022-04-26 16:19:02 +02:00
Zeno Rogue a788b9e540 CLI command -keys 2022-04-26 16:19:02 +02:00
Zeno Rogue 64ece33a97 fixed Zebra-patterned lands in Zebra quotient space 2022-04-26 16:19:02 +02:00
Zeno Rogue 4707347f3b netgen:: should no longer switch to OpenGL-less and crash 2022-04-26 16:19:02 +02:00
Zeno Rogue 2c2b1ce127 in OpenGL need to reopen on resolution change 2022-04-26 16:19:02 +02:00
Zeno Rogue 4f2b64febe fixup to spiral 2022-04-26 16:19:02 +02:00
Zeno Rogue e0856c420f render spiral no longer tries to disable OpenGL 2022-04-26 16:19:02 +02:00
Zeno Rogue 90a123dcb6 fixed renderbuffer from SDL 2022-04-26 16:19:02 +02:00
Zeno Rogue ccdc858f65 fixed some floors scaled incorrectly when 'creature scale' is changed 2022-04-26 16:19:02 +02:00
Zeno Rogue 234041d39b arb:: used closest_to_zero in get_midedge 2022-04-26 16:19:02 +02:00
Zeno Rogue 31a554f077 ultra-ideal vertices should work now 2022-04-26 16:19:02 +02:00
Zeno Rogue 403f38521e samples for pseudogons and fake inf polygon 2022-04-26 16:19:02 +02:00
Zeno Rogue ad6430a97f arb:: finish_apeirogon now works with material vertices too 2022-04-26 16:19:02 +02:00
Zeno Rogue 8e3c5d367c finish_apeirogon now works with ultra-ideal center 2022-04-25 00:08:27 +02:00
Zeno Rogue 575fd136d7 fixed towards_inf to actually accept dist parameter 2022-04-25 00:07:37 +02:00
Zeno Rogue 65ab10ff18 added samples for the new tessellations 2022-04-24 22:57:35 +02:00
Zeno Rogue 0acebce55a parser:: MAX_EDGE and MAX_VALENCE constants are now available 2022-04-24 22:57:35 +02:00
Zeno Rogue 0301ae44db also increased OINF to be above FULLEDGE 2022-04-24 22:57:35 +02:00
Zeno Rogue ee475ac5b7 tes:: fixed -arb-slider option 2022-04-24 22:57:35 +02:00
Zeno Rogue a8412ac5f0 increased the value of special-move constants to >100 so that the limit on sides is indeed 120 2022-04-24 22:57:35 +02:00
Zeno Rogue 0c7a429985 parser:: ifz function 2022-04-24 22:57:34 +02:00
Zeno Rogue d82ac26ef0 parser:: removed exceptions in arcmedge since they might not work correctly with conditionals 2022-04-24 22:57:34 +02:00
Zeno Rogue 89efe24c2d arb:: int sliders 2022-04-24 22:57:34 +02:00
Zeno Rogue 5a748e113a arb:: added an argument for some functions 2022-04-24 22:57:34 +02:00
Zeno Rogue 87f1c9f972 arb:: added a comment explaining the meaning of slided 2022-04-24 22:57:34 +02:00
Zeno Rogue b09646f01c arb:: c2 auto-curvature option 2022-04-24 22:57:34 +02:00
Zeno Rogue f845523bcd parser:: arcmcurv function 2022-04-24 22:57:34 +02:00
Zeno Rogue 920bf96088 nilrider:: first commit 2022-04-24 22:57:34 +02:00
Zeno Rogue e25b8b94c2 CLI option -canvasfloor 2022-04-24 22:57:34 +02:00
Zeno Rogue a2f0f89c18 patterns now use the same color for the whole apeirogon 2022-04-24 22:57:34 +02:00
Zeno Rogue 59078497dd arb:: support for apeirogons using '*inf' 2022-04-24 22:57:34 +02:00
Zeno Rogue c6cca03248 do_klenize now activates on IDEAL flag 2022-04-24 22:57:34 +02:00
Zeno Rogue 24eccca370 renamed towards_ideal to towards_inf 2022-04-24 22:57:34 +02:00
Zeno Rogue cb654ca990 tes:: fixed get_adj with infinite points 2022-04-24 22:57:34 +02:00
Zeno Rogue 47da0d9f09 barriers:: do not freeze on OINF 2022-04-24 22:57:34 +02:00
Zeno Rogue 1acf4fa477 get_valence now can use the information from arb 2022-04-24 22:57:34 +02:00
Zeno Rogue 3f8e9dde2b parser:: regangle now works with inf edges 2022-04-24 22:57:34 +02:00
Zeno Rogue 32ff898cd1 compute_edgelength accepts inf-faces 2022-04-24 22:57:34 +02:00
Zeno Rogue 506a8b8f1b parser accepts inf 2022-04-24 22:57:34 +02:00
Zeno Rogue 592605c6e2 Arcmedge now accepts a^:b which means that a is repeated b times. Also the computations now work for real a, b 2022-04-24 22:57:34 +02:00
Zeno Rogue fb2431cc31 animperiod as param 2022-04-24 22:57:34 +02:00
Zeno Rogue f95e3e3f0f when parsing time_formula failed, show the error 2022-04-24 22:57:34 +02:00
Zeno Rogue 42cc598dd0 rv::som:: changed the type of analyze_each to ld, so that it can be animated 2022-04-24 22:57:34 +02:00
Zeno Rogue 065666a5a1 rv::som:: even better animations 2022-04-24 22:57:34 +02:00
Zeno Rogue 7624dadb71 parser:: min and max functions 2022-04-24 22:57:33 +02:00
Zeno Rogue 9f0b21cd8a rv:: playing-with-impossibility:: added extra screens 2022-04-21 12:39:49 +02:00
Zeno Rogue bc78a005d1 rv::notknot:: option -nk-solv for convenience 2022-04-21 12:36:03 +02:00
Zeno Rogue e37cc8216a rv::notknot:: fixed the fog colors 2022-04-21 12:35:18 +02:00
Zeno Rogue 858ea26b66 rv:: added nil-compass to rogueviz-all 2022-04-21 12:34:23 +02:00
Zeno Rogue 192cd50e5c rv::som:: fixed paths in rogueviz-all 2022-04-21 12:34:11 +02:00
Zeno Rogue 6e0960bb58 replaced loop_multiplier and loop_shift with more general -animformula 2022-04-21 12:33:37 +02:00
Zeno Rogue 7e8ae4262f rv::som:: need -kst-keys to use keys in som tests 2022-04-21 12:22:06 +02:00
Zeno Rogue 0c71c3724f rv::som:: improved animation 2022-04-21 12:21:23 +02:00
Zeno Rogue f67d16b0f8 rv::som:: junk removed 2022-04-21 12:18:32 +02:00
Zeno Rogue e4ddfa8250 hyperboloid fixup 2022-04-21 11:59:50 +02:00
Zeno Rogue 6d1ded7fd4 Viziers were immune to some attacks in illogical circumstances -- this is no longer the case 2022-04-21 11:59:15 +02:00
Zeno Rogue 91faa3faf3 rv::som:: added our tests 2022-04-21 11:56:01 +02:00
Zeno Rogue e57f69b936 rv::som:: spaces 2022-04-21 11:55:34 +02:00
Zeno Rogue 733d5e5e0e rv::som:: moved SOM to a subdirectory 2022-04-21 11:53:33 +02:00
Zeno Rogue 5e0bd689ef shot:: fixed default loop_multipolier to 1, also added loop_shift 2022-04-16 14:00:10 +02:00
Zeno Rogue 197157838d fixed in_smart_range to use nisot::in_table_range 2022-04-16 13:59:38 +02:00
Zeno Rogue f86670ec19 fixed freezes on VirtualRebase in Nil portal spaces 2022-04-16 13:59:03 +02:00
Zeno Rogue d3fa8a6c2a custom dialog items 2022-04-16 13:58:26 +02:00
Zeno Rogue 1a55a5cfb2 frustum_culling as parameter 2022-04-16 13:58:01 +02:00
Zeno Rogue 8a6f96cba9 rv::presentation:: -presangle to set the angle via CLI 2022-04-12 13:13:08 +02:00
Zeno Rogue f7f0a0ea02 rv::playing-with-impossibility:: loop_multiplier taken into account 2022-04-12 13:03:24 +02:00
Zeno Rogue 461025ca8f rv::simple-impossible:: loop_multiplier taken into account 2022-04-12 13:02:41 +02:00
Zeno Rogue 9bcd0be3f3 rv::presentation:: latex support, add rv_latex=1 to CLI to enable 2022-04-12 13:02:08 +02:00
Zeno Rogue 232736e465 shot:: loop_multiplier parameter 2022-04-12 12:55:23 +02:00
Zeno Rogue b9532031e4 shot:: AA now affects vid.fsize 2022-04-12 12:55:11 +02:00
Zeno Rogue e2cf3c0752 added a repeat command to tile/unittile 2022-04-11 19:58:23 +02:00
Zeno Rogue 7c0a2ba447 tes:: fixed some warnings and a bug 2022-04-11 19:58:23 +02:00
Zeno Rogue be7e4ce70d tes:: preliminary implementation of (ultra)ideal vertices 2022-04-11 19:58:23 +02:00
Zeno Rogue 4122c1336c tes:: repeat can now be stated before conway/c 2022-04-11 19:58:23 +02:00
Zeno Rogue ec033786e1 arb:: removed legacy 2022-04-11 19:58:23 +02:00
Zeno Rogue e318410bff improved handling of missing models/images 2022-04-11 19:58:23 +02:00
Zeno Rogue d075987fa4 rogueviz:: gen_dual 2022-04-07 20:58:53 +02:00
Zeno Rogue 0f49333644 rogueviz:: alt poincare (disabled) 2022-04-07 20:58:42 +02:00
Zeno Rogue e159eb7b47 rogueviz:: export show_animation 2022-04-07 20:57:18 +02:00
Zeno Rogue 816007c268 rogueviz:: an option to launch a slideshow or a specific slide by name 2022-04-07 20:57:02 +02:00
Zeno Rogue 091d747ae8 fixed objmodel reading 2022-04-07 20:56:17 +02:00
Zeno Rogue 306a5b6c0f scanline_noblank function 2022-04-07 20:54:33 +02:00
Zeno Rogue 82d9124d3f fixed hadoken missiles not displaying correctly in shmup 3D 2022-04-07 20:52:33 +02:00
Zeno Rogue ca0fc95a52 read_model now prioritizes the names from the current geometry 2022-04-07 20:51:29 +02:00
Zeno Rogue 2aeb74511d fixup to radar_transform in VR 2022-04-07 20:51:15 +02:00
Zeno Rogue 8c0600d8fe logarithmic fog parameter (logfog) 2022-04-07 20:50:59 +02:00
Zeno Rogue 589d2dd72c hemisphere in spherical now produces the hyperboloid model 2022-04-07 20:50:16 +02:00
Zeno Rogue 65b4b88ce4 uint -> color_t 2022-04-07 20:46:59 +02:00
Zeno Rogue 06023efddc fixup to achievements 2022-04-07 20:46:37 +02:00
Zeno Rogue d319173110 12.0m 2022-03-27 22:47:51 +02:00
Zeno Rogue 8ecb1ce593 rv:: intra-demos:: set playermoved to false 2022-03-27 22:47:51 +02:00
Zeno Rogue 36c71eb583 prevent a crash when entering '(0,0)' in Archimedean 2022-03-27 22:47:51 +02:00
Zeno Rogue 8489550aed multi:: radar works correctly in split_screen 2022-03-27 22:47:51 +02:00
Zeno Rogue 53d5813267 fixed cool fog in split screen 2022-03-27 22:47:51 +02:00
Zeno Rogue 31f70bbbfa ray:: fixed hyperbolic fragdepth (but this should not work, some bug in GLSL?) 2022-03-27 22:47:51 +02:00
Zeno Rogue 049eb33105 ray:: fixed levellines in hyperbolic 2022-03-27 22:47:51 +02:00
Zeno Rogue b79280e423 in non-fake 2.5D the raycaster is disabled by default 2022-03-27 22:47:51 +02:00
Zeno Rogue 14ed4b7603 display a hint when player hidden 2022-03-27 22:47:51 +02:00
Zeno Rogue 00d640fa22 fixed the Orb of Safety not disappearing in shmup+OSM 2022-03-27 22:47:51 +02:00
Zeno Rogue 0843b3c600 multi:: don't count pkills/selfhits if still protected byfragoff; increased the bullet_time 2022-03-27 22:47:51 +02:00
Zeno Rogue 17fcd83f6a multi:: fixed stats 2022-03-27 22:47:51 +02:00
Zeno Rogue 84446a6b9f disable X'es in set_multi 2022-03-27 22:47:51 +02:00
Zeno Rogue 719aab3fb5 fixed the orientation of two-point azimuthal and two-point hybrid 2022-03-27 22:47:51 +02:00
Zeno Rogue a6338d3c49 multi:: disable achievements in split-screen 2022-03-27 22:47:51 +02:00
Zeno Rogue 6d554d6b2e multi:: two-focus projections 2022-03-27 22:47:51 +02:00
Zeno Rogue a6cbedc944 multi:: PvP, friendly-fire, and self-hits options 2022-03-27 22:47:51 +02:00
Zeno Rogue 248c48613e shmup:: in split screen, monsters/missiles are now handled with the closest player 2022-03-27 22:47:51 +02:00
Zeno Rogue 68b2960dd5 shmup:: improved docs for monster struct 2022-03-27 22:47:51 +02:00
Zeno Rogue 37575bcdaf hr::span exported 2022-03-27 22:47:51 +02:00
Zeno Rogue 78ddda1b4f changed constant 3 to caflWarp 2022-03-27 22:47:51 +02:00
Zeno Rogue fbb75309d0 multi:: split_screen for standard shmup, not racing 2022-03-27 22:47:51 +02:00
Zeno Rogue 9a25da1989 multi:: more modern centering 2022-03-27 22:47:50 +02:00
Zeno Rogue 72865478aa splitscreen off now works correctly in racing 2022-03-27 22:47:50 +02:00
Zeno Rogue 23639b1e46 racing:: addsaver -> param 2022-03-27 22:47:50 +02:00
Zeno Rogue 7af95b950a racing:: disabling splitscreen works (except second player movement) 2022-03-27 22:47:50 +02:00
Zeno Rogue d294128ac8 fixed the displayed unlock rule for Crossroads III in Casual 2022-03-27 22:47:50 +02:00
Zeno Rogue 9eff4e597f rogueviz:: sunflower:: don't change whichShape to 9 2022-03-27 22:47:50 +02:00
Zeno Rogue fc29739741 rogueviz:: sunflower:: change sunflower-angle (partial) 2022-03-27 22:47:50 +02:00
Zeno Rogue d92f7f6765 rv:: sunflower:: new options for colors, overlay, and yshift 2022-03-27 22:47:50 +02:00
Zeno Rogue 998af473ca rogueviz:: add extra-projections 2022-03-27 22:47:50 +02:00
Zeno Rogue 5a73eccd4c an option to add more projections via plugins 2022-03-27 22:47:50 +02:00
Zeno Rogue 166f076f2d models:: makeband as a function 2022-03-27 22:47:50 +02:00
Zeno Rogue 8e710784df fixed scale_at for cylindrical projections 2022-03-27 22:47:50 +02:00
Zeno Rogue 930e0c6830 named technical projections 2022-03-27 22:47:50 +02:00
Zeno Rogue a6aa91dfab export qs flags 2022-03-27 22:47:50 +02:00
Zeno Rogue b840082c19 arb:: operators for connection_t 2022-03-27 22:47:50 +02:00
Zeno Rogue 08cfed6658 multi:: split-screen mode is now an option 2022-03-27 22:47:50 +02:00
Zeno Rogue bcc7c9c646
Merge pull request #303 from lottieratworld/main
Extra canvas-specific options + extra animation options
2022-03-26 15:59:31 +01:00
Zeno Rogue 7f2d579251 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-03-20 09:52:37 +01:00
Zeno Rogue 5084764275 rogueviz:: missing variables from objmodels 2022-03-20 09:52:32 +01:00
Zeno Rogue 6b0b198446 shape editor: fixed distances shown, also more precision when snapping 2022-03-20 00:51:43 +01:00
Zeno Rogue bbfdcea370 shape editor: mouse snapping feature 2022-03-20 00:51:43 +01:00
Charlotte Peppers 11fa88022f Merge branch 'main' of github.com:lottieratworld/hyperrogue 2022-03-07 19:00:36 -07:00
Charlotte Peppers ff67930be3
Added game version check for loading maps with canvas floor and darkening 2022-03-07 18:59:49 -07:00
Charlotte Peppers 6663a33df4
Merge branch 'zenorogue:master' into main 2022-03-07 17:44:10 -07:00
Charlotte Peppers 904faabd96
Added tower to canvas floor options, added new Flashing Effects option which currently effects storms and some curses 2022-03-07 17:37:35 -07:00
Zeno Rogue 3fe834e726 README now explains what RogueViz is 2022-03-07 13:25:19 +01:00
Charlotte Peppers ab08a69cc6
Added Canvas Floor and Canvas Darkness options 2022-03-06 20:01:59 -07:00
Charlotte Peppers 6117d626d8
Merge branch 'zenorogue:master' into main 2022-03-06 17:10:14 -07:00
Zeno Rogue 1ef969b0e2 version 12.0l 2022-03-01 09:53:30 +01:00
Zeno Rogue 490abd176f added aismallard to credits 2022-03-01 09:37:52 +01:00
Zeno Rogue 694c75efbc rv:: kohonen:: some missing } 2022-03-01 09:32:56 +01:00
Zeno Rogue bde3efbc35 rv:: some fixes to the demos 2022-03-01 09:32:39 +01:00
Zeno Rogue 0429c8353a fixed a crash when drawing aura in some projections 2022-03-01 09:23:51 +01:00
Zeno Rogue aaeab82425 rv:: objmodels:: fixed loading the city model 2022-03-01 08:57:08 +01:00
Zeno Rogue e2b6b6b2eb picking a pres from the list when another one is running no longer just turns the presentation off 2022-03-01 08:52:25 +01:00
Zeno Rogue 2f7bec5634 rv:: embeddings:: removed unused variable 2022-03-01 08:48:13 +01:00
Zeno Rogue 2a32a423d4 rv:: changed the hotkey for RogueViz demos to 'd' 2022-03-01 08:47:40 +01:00
Zeno Rogue 98cf022a44 rv:: snow:: fixes 2022-03-01 08:46:48 +01:00
Zeno Rogue 19019c907a rv:: objmodels fixes 2022-03-01 08:46:06 +01:00
Zeno Rogue 4d234a96f8 rv:: notknot:: faster and no player 2022-03-01 08:45:21 +01:00
Zeno Rogue 1e07875d05 rv:: kohonen:: removed debug 2022-03-01 08:44:59 +01:00
Zeno Rogue beb47aeb26 rv:: kohonen:: bugfix 2022-03-01 08:43:42 +01:00
Zeno Rogue 85d0173d36 rv:: kohonen 2022-03-01 08:42:20 +01:00
Zeno Rogue bd46fbd0ae rv:: embeddings 2022-03-01 08:40:18 +01:00
Zeno Rogue ebe0433168 rv:: hide player in intra-demos 2022-03-01 08:38:42 +01:00
Zeno Rogue 7a1d3822b3 rv:: fifteen:: changed the hotkey, added new puzzles and descriptions 2022-03-01 08:38:22 +01:00
Zeno Rogue 3f0bde3515 rv:: changed the hotkey to Playing with Impossibility 2022-03-01 08:37:47 +01:00
Zeno Rogue f5eae99531 rv:: impossibility:: fixed destroying other slides 2022-03-01 08:37:30 +01:00
Zeno Rogue f3d6f831dd Curse of Repulsion now correctly marked as used 2022-02-28 20:15:51 +01:00
Zeno Rogue f50f3c89dc Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2022-02-28 17:38:19 +01:00
Zeno Rogue 21bd4d7fe0 ray:: uProjection is now always taken as a 4x4 matrix 2022-02-28 17:34:00 +01:00
Zeno Rogue ad6a466837 gamedata:: store vid data more carefully 2022-02-28 17:32:56 +01:00
Zeno Rogue a8f8ca8536 mapeditor:: don't erase maps when loading intra maps 2022-02-28 17:32:19 +01:00
Zeno Rogue 0e39a8a485 intra:: CLI command -walk-on 2022-02-28 17:31:46 +01:00
Zeno Rogue 73738226dd intra:: walking works with vr correctly now 2022-02-28 17:31:27 +01:00
Zeno Rogue bee5a92443 vr:: render should now work even if apply_movement transcends a portal 2022-02-28 17:29:31 +01:00
Zeno Rogue 4891c735b7 vr:: compute iproj correctly 2022-02-28 17:28:50 +01:00
Zeno Rogue b022c3c84e intra:: change floor status of wallcolors 2022-02-27 15:21:58 +01:00
Zeno Rogue 1efd0b4441 rv:: platformer:: now possible to change settings, better explanation in the slide 2022-02-27 15:12:23 +01:00
Zeno Rogue 13cbece9df
Merge pull request #302 from ammongit/crossroads-wiki
Add exception for handling of "Crossroads" in wiki links
2022-02-27 14:59:45 +01:00
Zeno Rogue 3d5cc67f63 <ctime> is included in hyper.h 2022-02-27 14:58:37 +01:00
Zeno Rogue 78049518a5
Merge pull request #301 from ammongit/valentines
Valentine's Easter Egg: Add +1 extra charge to Orb of Love
2022-02-27 14:56:49 +01:00
Zeno Rogue 50e1497405 rv:: portal demos now organized into a separate presentation 2022-02-27 14:53:22 +01:00
Zeno Rogue e827d2a69f tour:: slide_action function 2022-02-27 14:51:02 +01:00
Zeno Rogue ded172b0d3 intra:: fixed a crash on reloading 2022-02-27 14:50:46 +01:00
Zeno Rogue 45fb8fcb44 intra:: shift_view_portal now calls itself recursively so multiple portal passes at once work 2022-02-27 14:50:33 +01:00
Zeno Rogue eed81a3630 fixed extra semicolon 2022-02-27 01:16:42 +01:00
Zeno Rogue 41bd09d4ba rv:: loading intra demos 2022-02-27 01:15:45 +01:00
Zeno Rogue 443ecf0331 intra:: correct cleanup of intra maps 2022-02-27 01:15:45 +01:00
Zeno Rogue 0aa338e9eb rv::platformer:: slide 2022-02-27 01:15:45 +01:00
Zeno Rogue d8d5e2512d rv::platformer::added missing create_sprite_texture 2022-02-27 01:15:45 +01:00
Zeno Rogue 4df17161d7 walking:: save colors_of_floors 2022-02-27 01:15:45 +01:00
Zeno Rogue 48260b781e tour:: next_slide function 2022-02-27 01:15:45 +01:00
Zeno Rogue 3410a20275 rv:: do not destroy change water into chasms (except demos that do that) 2022-02-27 01:15:45 +01:00
Zeno Rogue 162edb85a8 when having Orb of Freedom + Orb of Time, other orbs are no longer drained by Freedom checks 2022-02-27 01:15:45 +01:00
Zeno Rogue 253bec46cb fixed some settings incorrectly showing a warning on editing (this also brings back the 'play music when out of focus' option) 2022-02-27 01:15:45 +01:00
Zeno Rogue 22fc90a30e walking:: walking in solv-h3 2022-02-27 01:15:45 +01:00
Zeno Rogue 94d660cc43 intra:: walking mode 2022-02-27 01:15:45 +01:00
Zeno Rogue cfaa52cf42 intra:: extra debug 2022-02-27 01:15:45 +01:00
Zeno Rogue 822c77b302 smaller eps in apply_other_model 2022-02-27 01:15:45 +01:00
Zeno Rogue 729566d147 smaller eps in zlev 2022-02-27 01:15:45 +01:00
Zeno Rogue 961b09033f config:: reaction called on edit for list settings 2022-02-27 01:15:45 +01:00
Zeno Rogue 5a67e7c040 reduced epsilons in hyperpoint 2022-02-27 01:15:45 +01:00
Zeno Rogue 015006546e ray:: fixed dark lines in H2xR which happened when we got a=0 in quadratic equation 2022-02-27 01:15:45 +01:00
Zeno Rogue 80b9d9533c intra:: fixed portals to/from S3 and H3 2022-02-27 01:15:45 +01:00
Zeno Rogue 6b17cd6412 intra:: fixed Euclidean portals from/to product spaces 2022-02-26 09:48:49 +01:00
Zeno Rogue 8569242082 material works for s2xe and h2xe 2022-02-26 09:46:40 +01:00
Zeno Rogue 1bdb187735 made Yendor/Haunted sight radius consistent when the tiling is changed 2022-02-21 22:47:22 +01:00
Zeno Rogue 9c39688b49 infinite generation for single-land Camelot now only happens in hyperbolic geometry (also fixes the missing Grail in Crystal) 2022-02-21 20:02:58 +01:00
Zeno Rogue 67a19d93bb added missing MAXMDIM guards 2022-02-17 21:00:10 +01:00
Ammon Smith 7bd50b5068 Add missing "ed". 2022-02-15 18:22:56 -05:00
Ammon Smith 83372e7dea Add explanatory comment.
The 0-indexed month value may be confusing.
2022-02-14 18:11:49 -05:00
Ammon Smith 465ec66760 Add +1 charge for Orb of Love on Valentine's day.
Minor date-based easter egg, small enough to not impact gameplay
notably.
2022-02-14 18:06:19 -05:00
Ammon Smith aacea315f2 Add exception for handling of "Crossroads" in wiki links. 2022-02-12 17:57:34 -05:00
Zeno Rogue 4394502e3e 12.0k 2022-02-12 00:13:05 +01:00
Zeno Rogue 3337786c04 Orb of Slaying now works on big trees 2022-02-12 00:11:10 +01:00
Dennis Payne 3023b12e93 Add optional fontconfig support. 2022-02-08 12:44:51 -05:00
Charlotte Peppers a9820ef385
Merge branch 'zenorogue:master' into main 2022-02-05 21:50:16 -07:00
Zeno Rogue b46221bad8 Lazurite Figurines no longer appear immediately after using an Orb of Safety 2022-02-03 01:07:30 +01:00
Zeno Rogue c9ee75cdea Orb of Chaos is now forbidden in the Dungeon 2022-02-03 01:05:41 +01:00
Zeno Rogue 0c20fdeccb Stunning from the Orb of Chaos now destroys birds/shadows just like the other sources of stunning 2022-02-03 01:05:25 +01:00
Zeno Rogue ee246d4a93 Stunning the Shadow now temporarily destroys it 2022-02-03 01:04:19 +01:00
Zeno Rogue 2f2ff3184b Beauty now stuns the Shadows 2022-02-03 01:03:52 +01:00
Zeno Rogue af46e515fe fixup to GRAILH 2022-02-03 01:02:39 +01:00
Zeno Rogue f855106613 fixed Crystal 2022-02-02 11:54:53 +01:00
Zeno Rogue 064ac7de63 fixed racing official track generation 2022-02-02 03:07:12 +01:00
Zeno Rogue fd634e6de8 fixed land_structure for princess/racing/heptagonal achievements 2022-02-02 03:01:31 +01:00
Zeno Rogue fae4ceb672 the orb power gaining order is now: Purity extras -> Choice loss -> standard gain 2022-02-01 17:27:29 +01:00
Charlotte Peppers 0a9d671bd3
Merge branch 'zenorogue:master' into main 2022-02-01 09:23:13 -07:00
Zeno Rogue 231b510f16 patterns:: more distinct colors in 'eight domains' 2022-02-01 17:09:36 +01:00
Zeno Rogue bdc2697f98 fixed pmodel to md in some places in apply_other_model 2022-02-01 17:09:20 +01:00
Zeno Rogue b634d930cb gp:: fixed the comment about GOLDBERG_BITS 2022-02-01 17:08:54 +01:00
Zeno Rogue f61247afe2 arb:: partial option for combinatiorial tessellations 2022-02-01 17:06:56 +01:00
Zeno Rogue 45d684d813 fixed drawPlayerEffects arguments changed in shmup 2022-02-01 17:02:00 +01:00
Zeno Rogue 9f9b757735 rulegen:: tests improvements 2022-02-01 17:00:39 +01:00
Zeno Rogue 37ebe6af5d rulegen:: debug improvements 2022-02-01 16:57:47 +01:00
Zeno Rogue bff37f0274 rulegen:: fixed some bugs with sidecache 2022-02-01 16:57:34 +01:00
Zeno Rogue afb3a2be59 rulegen:: first_restart_on parameter 2022-02-01 16:57:13 +01:00
Zeno Rogue 7d49d7ee81 rulegen:: max_shortcut_length parameter 2022-02-01 16:56:44 +01:00
Charlotte Peppers 9a731572f6
Added idle animation option, fixed palace hypersian rugs using "ticks" instead of "pticks" 2022-01-31 14:39:41 -07:00
Zeno Rogue f366e4fbad mymake error: == not = 2022-01-17 22:34:27 +01:00
Zeno Rogue 549e57b3d1 Goldberg dialog now warns if outside of the supported limits 2022-01-08 19:30:46 +01:00
Zeno Rogue 450aa28d67 gp:: added -gph (better -gp) 2022-01-08 19:20:53 +01:00
Zeno Rogue 7ea8c765d9 gp:: fixed GP(1,3) for 4-valent 2022-01-08 19:20:35 +01:00
Zeno Rogue e9609df06b gp:: fixed some cases 2022-01-08 18:55:06 +01:00
Zeno Rogue 6ea3ad8493 perfect_linewidth as param_i 2022-01-08 18:54:24 +01:00
Zeno Rogue d6bf35201c flush method on hstream 2022-01-08 18:54:08 +01:00
Zeno Rogue b99e0f448f draw fishtails on friends with empathy 2022-01-08 18:53:57 +01:00
Zeno Rogue 1a7d55fd52 changed disable_flooshapes to floorshapes_level 2022-01-08 18:52:17 +01:00
Zeno Rogue b87a47eaaa fixed relative_matrix in crystal 2022-01-08 18:52:02 +01:00
Zeno Rogue 894da8c55a doubling distance_warning, getside and examine_branch to detect loops early 2021-12-29 04:27:17 +01:00
Zeno Rogue 014e995ef1 changed slow_side to the default as it turns out to be incompatible with branch skipping 2021-12-29 04:20:58 +01:00
Zeno Rogue e190fc63a7 rulegen:: branch skipping now made optional, also reset in case of serious errors 2021-12-29 04:20:19 +01:00
Zeno Rogue d40ea1d6ba rulegen:: smarter get_side by caching data inside tcell and by noting down known information on the way 2021-12-29 03:35:31 +01:00
Zeno Rogue d7d3d21d2a fixed a bug causing skipped branches to interact badly with single live branches 2021-12-29 03:34:31 +01:00
Zeno Rogue 61c5ad9344 fixed overzealous cache clearing 2021-12-29 03:33:35 +01:00
Zeno Rogue 2e17df921d rulegen:: fixed deleting tmap 2021-12-29 03:33:25 +01:00
Zeno Rogue 9787b3e52d rulegen:: fixed cleanups 2021-12-28 11:38:45 +01:00
Zeno Rogue 410d5c3015 rulegen:: clear branch checks on clean_data 2021-12-28 11:36:44 +01:00
Zeno Rogue 316b8d4f7c rulegen:: also set sidecache for the reverse twalker 2021-12-28 11:35:59 +01:00
Zeno Rogue 872ce9d389 rulegen:: distance warnings 2021-12-28 11:35:37 +01:00
Zeno Rogue 775a087624 larger values allowed for codes 2021-12-28 11:34:50 +01:00
Zeno Rogue 468873da29 rulegen:: skipping branches which seem good 2021-12-27 23:09:37 +01:00
Zeno Rogue a5d24e0ff7 rulegen:: tests:: auto disable floorshapes 2021-12-27 20:23:13 +01:00
Zeno Rogue a3a5b7c17e rulegen:: improved stats 2021-12-27 20:23:02 +01:00
Zeno Rogue 6ee2f4d3d1 fixup to last :: tests forking 2021-12-27 20:22:18 +01:00
Zeno Rogue 09ec5b0ee0 rulegen:: tests:: forking 2021-12-27 20:22:09 +01:00
Zeno Rogue e425bf9bf9 rulegen:: tests:: remove sprawl 2021-12-27 20:21:23 +01:00
Zeno Rogue eb8ea9c735 retry not failure on neg rule mismatch 2021-12-27 20:20:10 +01:00
Zeno Rogue 77bfa5c9a7 use vectors not maps for shortcuts and analyzers 2021-12-27 20:19:18 +01:00
Zeno Rogue f9b23b6c39 handle_queued_extensions fixup, should be in earlier commit 2021-12-27 13:30:36 +01:00
Zeno Rogue 38f3414828 rulegen:: retry not failure on reaching the end 2021-12-27 13:30:14 +01:00
Zeno Rogue 94e06b3bbf new analyzers, based on decision trees 2021-12-27 13:03:15 +01:00
Zeno Rogue f43f80b0ad rulegen:: better debug 2021-12-26 22:34:15 +01:00
Zeno Rogue 9eb7b2e337 fixup to some std 2021-12-26 22:34:07 +01:00
Zeno Rogue ac259bcc95 rulegen:: queue extensions 2021-12-26 22:33:33 +01:00
Zeno Rogue e466ed8e22 Revert "rulegen:: trace_rootpath changed to beats_exhaustive"
This reverts commit 81e8a1f113.
2021-12-26 17:31:42 +01:00
Zeno Rogue 81e8a1f113 rulegen:: trace_rootpath changed to beats_exhaustive 2021-12-26 16:28:47 +01:00
Zeno Rogue 045a439d64 fixup to parent_updates 2021-12-26 10:09:13 +01:00
Zeno Rogue a3a1845d49 clean_parent() on restart 2021-12-25 21:32:45 +01:00
Zeno Rogue 22ffb60ec3 rulegen:: improved overzealous xsidefreeze detection 2021-12-25 21:32:34 +01:00
Zeno Rogue 71fd8eccf5 rulegen:: optimized smart shortcuts 2021-12-25 21:32:08 +01:00
Zeno Rogue d74edf07db rulegen:: build shortcuts on parent change 2021-12-25 21:31:36 +01:00
Zeno Rogue d1ed0ab779 fixed >= to > in smart shortcut 2021-12-25 01:36:44 +01:00
Zeno Rogue 99486bfc3c disabled debug of smart shortcuts 2021-12-25 01:36:25 +01:00
Zeno Rogue d1043152dc in fix_distances, also fix parent_dir 2021-12-25 01:35:48 +01:00
Zeno Rogue 5115a379ee fixup to smart shortcuts 2021-12-24 23:13:57 +01:00
Zeno Rogue f861126171 rulegen:: smarter shortcuts 2021-12-24 23:13:05 +01:00
Zeno Rogue 127b64dc66 fixup to twalker I think 2021-12-24 23:11:50 +01:00
Zeno Rogue 2af34b84f2 rulegen:: better debugging on solid 2021-12-24 23:11:33 +01:00
Zeno Rogue 31272587b5 arb:: extra stats about the tiling available 2021-12-24 23:10:47 +01:00
Zeno Rogue c160a506e6 rulegen:: tests:: do not crash on failure 2021-12-24 23:10:18 +01:00
Zeno Rogue 67dcda0f25 rulegen:: tests:: more stats available 2021-12-24 23:10:06 +01:00
Zeno Rogue 0fb6ddb3bc rulegen:: tests:: list coordination sequences 2021-12-24 23:09:47 +01:00
Zeno Rogue 1343eacc1c rulegen:: tests:: disable timeout on iterate and irradiate 2021-12-24 23:08:47 +01:00
Zeno Rogue a065fc4d86 rulegen:: base the functions on twalkers to avoid unification errors 2021-12-24 23:08:14 +01:00
Zeno Rogue a373bad6c7 hyper-main:: convenience functions for the shared library 2021-12-19 13:08:12 +01:00
Zeno Rogue cf0d9ac501 mymake:: an option -shared to create a less intrusive shared object library 2021-12-19 13:07:50 +01:00
Zeno Rogue 92745fe1bb mymake:: an option -o to change the executable name 2021-12-19 13:07:18 +01:00
Zeno Rogue 87c902c4b8 fixed fat edges in some H3 honeycombs 2021-12-14 11:19:15 +01:00
Zeno Rogue fa79d67016 12.0j 2021-12-13 22:34:35 +01:00
Zeno Rogue 217d4a770d fixed selecting gravity/ocean as the starting land 2021-12-13 22:30:26 +01:00
Zeno Rogue abec39422c fixed a problem with victory achievements 2021-12-13 22:15:08 +01:00
Zeno Rogue 1eb762fde2 12.0i 2021-12-13 22:15:08 +01:00
Zeno Rogue d3fb683a95 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-12-12 22:39:54 +01:00
Zeno Rogue 973fc68b66 rogueviz:: added new modules to rogueviz-all.cpp 2021-12-12 22:39:16 +01:00
Zeno Rogue 58630373e7 rogueviz:: horo63 added 2021-12-12 22:38:49 +01:00
Zeno Rogue bbe6843390 rogueviz:: GoBot added 2021-12-12 22:38:15 +01:00
Zeno Rogue 8658d2abde rogueviz:: platformer added 2021-12-12 21:42:07 +01:00
Zeno Rogue c4a55669c8 Hyperbugs now ignore the player in peace mode. 2021-12-12 21:21:27 +01:00
Zeno Rogue 7350af18f2 fixed the Nature + movement orb combo, without Empathy 2021-12-12 21:14:41 +01:00
Zeno Rogue e238a7ddf9 fixed the Nature + Slaying + Empathy combo 2021-12-12 21:06:47 +01:00
Zeno Rogue 5d476fff1c fixed 'Orb of the Love' 2021-12-12 20:41:11 +01:00
Zeno Rogue 32bfdf42c3 Krakens no longer destroy player boats in peaceful mode 2021-12-12 20:35:18 +01:00
Zeno Rogue 3dde8d805a ray:: rmap_get_by_id and rmap_get_id_of 2021-12-12 00:30:44 +01:00
Zeno Rogue 00c71c5212 export curvedata 2021-12-12 00:30:07 +01:00
Zeno Rogue d3f397fe27 fieldpattern:: call analyze immediately 2021-12-12 00:29:03 +01:00
Zeno Rogue df2180cf67 fieldpattern:: removed currfp. in analyze which could cause a loop 2021-12-12 00:28:48 +01:00
Zeno Rogue 5d81260f0b expansion_analyzer is now in cgi 2021-12-11 23:28:05 +01:00
Zeno Rogue cfcd8a5e57 fixed a bug in parsing unary - 2021-12-09 20:53:52 +01:00
Zeno Rogue 8220611718 third_person_rotation 2021-11-30 20:56:36 +01:00
Zeno Rogue a4ec0cabf0 knuth-bendix implementation 2021-11-23 10:25:28 +01:00
Zeno Rogue 914f2b9a57 rulegen-tests improved 2021-11-23 10:25:16 +01:00
Zeno Rogue a98d9cb699 disable_floorshapes 2021-11-23 10:24:51 +01:00
Zeno Rogue 237a521e80
Merge pull request #299 from dulsi/master
Add HYPERFONTPATH to make it easier to package on Fedora.
2021-11-18 17:26:02 +01:00
Dennis Payne d31c330d8b Add HYPERFONTPATH to make it easier to package on Fedora. 2021-11-17 10:11:13 -05:00
Zeno Rogue 770949978a reduced the other land range for currentLocalTreasure in 3D geometries 2021-11-07 10:53:04 +01:00
Zeno Rogue 9ca670af20 do not remove faraway treasures in 3D geometries (they are not that far away...) 2021-11-07 10:52:25 +01:00
Zeno Rogue a8d2e589f1 that fixup was added? 2021-11-07 10:41:27 +01:00
Zeno Rogue 98969e4b6b fixed openplains in nowalls mode 2021-11-07 10:34:53 +01:00
Zeno Rogue d07ae075bc ray:: fixed raycaster in 2dim geometries crashing 2021-11-07 10:19:21 +01:00
Zeno Rogue 456adb32c0 fixup to 'which_copy includes rotation' 2021-11-07 10:14:08 +01:00
Zeno Rogue a5d5cba14d fixed allies affecting Terracotta Warriors without actually moving next to them 2021-11-07 10:11:16 +01:00
Zeno Rogue ea079ba0d1 which_copy now consistenly includes rotation -- seems to fix cat moving problem 2021-11-07 10:03:16 +01:00
Zeno Rogue 18f2ccf1d4 rulegen:: fix_distances on tmove 2021-11-07 09:59:44 +01:00
Zeno Rogue 12dcd348b0 sol:: stop crashing if coordinates are NAN 2021-11-07 09:59:22 +01:00
Zeno Rogue 6078f53dbc fixed colors in coxeter 2021-11-07 09:07:51 +01:00
Zeno Rogue 215f203d40 removed the Gardener flag as it is handled by achievement_gain_once 2021-11-07 08:43:41 +01:00
Zeno Rogue 0d08dceddf fixed a subtle issue causing max_examine_branch error 2021-11-03 10:20:29 +01:00
Zeno Rogue ea9936c544 rulegen:: fix memory leak in add_other_origins 2021-11-03 09:42:40 +01:00
Zeno Rogue f3d7601c88 rulegen:: fix_distances in numerical_fix 2021-11-03 09:42:21 +01:00
Zeno Rogue 54b37284eb devmods:: rulegen-tests:: -tesgen option 2021-11-01 17:27:28 +01:00
Zeno Rogue 65355469ff devmods:: rulegen-tests:: a comment 2021-11-01 17:27:06 +01:00
Zeno Rogue 9c2d0dec05 devmods/rulegen-tests:: some extra stats 2021-11-01 17:26:28 +01:00
Zeno Rogue 391d1a646b rulegen:: simplified get_parent_dir 2021-11-01 17:25:50 +01:00
Zeno Rogue cca9afaba9 rulegen:: fixed a bug with sidecache not clearing on single_live_branch_close_to_root 2021-11-01 17:25:39 +01:00
Zeno Rogue 233934630f rulegen:: find_new_shortcut also called in the other direction 2021-11-01 17:25:24 +01:00
Zeno Rogue 78298432da rulegen:: numerical-fix, known-structure and known-distances 2021-11-01 17:24:54 +01:00
Zeno Rogue e36a8970f4 rulegen:: some extra debug 2021-11-01 17:22:50 +01:00
Zeno Rogue ed156e9efb rulegen:: reinforced trace_root_path 2021-11-01 17:21:50 +01:00
Zeno Rogue 523f640fa5 rulegen:: fixed hashing in case of incompatible distances 2021-11-01 17:20:08 +01:00
Zeno Rogue a7149f7054 rulegen:: fix_distances on connect_and_check 2021-11-01 17:18:16 +01:00
Zeno Rogue 78d33ec573 rulegen:: used EX 2021-11-01 17:18:06 +01:00
Zeno Rogue 045dc90378 another fixup to last 2021-11-01 17:17:16 +01:00
Zeno Rogue 159ed86045 fixup to last 2021-11-01 17:15:23 +01:00
Zeno Rogue 1a74241cd9 devmods:: rulegen-tests:: time measuring improvements (movecount and attempts) 2021-11-01 17:14:01 +01:00
Zeno Rogue 1e2ffd611c devmods:: rulegen-tests:: disdable bigstuff 2021-11-01 17:13:07 +01:00
Zeno Rogue 4040f56262 rogueviz:: added the missing function on_cleanup_or_next 2021-10-17 17:02:34 +02:00
Zeno Rogue 1e504d98ae arb:: loading tes options is now optional 2021-10-17 09:40:28 +02:00
Zeno Rogue 839ca440ea refer to color by HTML name in commandline arguments 2021-10-17 09:18:31 +02:00
Zeno Rogue 9d26e98fcd colors:: allocate more colors 2021-10-17 09:05:51 +02:00
Zeno Rogue 25b77617cd star samples 2021-10-17 08:31:57 +02:00
Zeno Rogue eac543fe07 fixup to last 2021-10-15 22:39:45 +02:00
Zeno Rogue ce4be1bc6b fixed pseudogonal to pseudohedral 2021-10-15 22:38:24 +02:00
Zeno Rogue cb75ba44dc pseudogonal mode 2021-10-15 22:36:43 +02:00
Zeno Rogue e3c80b70bf arb:: a feature to add commandline options 2021-10-15 22:15:47 +02:00
Zeno Rogue 6821caa509 arb:: star option 2021-10-15 22:15:15 +02:00
Zeno Rogue a6022178b3 arg:: run_arguments function 2021-10-15 22:14:30 +02:00
Zeno Rogue 432499f903 eatchar in parser 2021-10-15 22:13:52 +02:00
Zeno Rogue 9f9a95059a intra:: perf/edit setting 2021-10-10 00:49:59 +02:00
Zeno Rogue 2d3ed4a79d 12.0h 2021-10-10 00:40:22 +02:00
Zeno Rogue 56af053d4b ray:: requested in intra, no cgi_string used 2021-10-10 00:40:22 +02:00
Zeno Rogue 6db94b134d intra:: optimize saved maps 2021-10-10 00:40:22 +02:00
Zeno Rogue 5d5f93e1bc rogueviz:: added intra-demos 2021-10-10 00:40:22 +02:00
Zeno Rogue 6e9245a6ce ray:: param_i for ray_max_cells 2021-10-10 00:40:22 +02:00
Zeno Rogue ea2899d7e0 ray:: iteration in intra fix 2021-10-10 00:40:22 +02:00
Zeno Rogue 7d60c2d73e multigame:: save hybrid::csteps and patterns::rwalls 2021-10-10 00:40:22 +02:00
Zeno Rogue ef67ed4a75 mapstream:: save sol correctly 2021-10-10 00:40:22 +02:00
Zeno Rogue 868b75f64e intra:: set T=Id to prevent possible rendering errors 2021-10-10 00:40:22 +02:00
Zeno Rogue 09f8aefba7 ray:: reordered just in case 2021-10-10 00:40:22 +02:00
Zeno Rogue 912aab9d27 ray:: use the same shader for all starting points in intra 2021-10-10 00:40:22 +02:00
Zeno Rogue a97fa8a95d ray:: special maxstep and max_iter for intra 2021-10-10 00:40:22 +02:00
Zeno Rogue 32684298a0 intra:: option -intra-kill 2021-10-10 00:40:22 +02:00
Zeno Rogue 12fe1e1d54 intra:: improved debug 2021-10-10 00:40:22 +02:00
Zeno Rogue a79d28fafe more portal fixes 2021-10-10 00:40:22 +02:00
Zeno Rogue 7d5d2e44e8 function idv 2021-10-10 00:40:22 +02:00
Zeno Rogue b6986879ec fixed a crash when generating daily 2021-10-10 00:40:22 +02:00
Zeno Rogue 84f5d2b454 allowed Dice and Curse and walls in Daily 2021-10-10 00:40:22 +02:00
Zeno Rogue 8f59ff7016 do not switch variation to pure when switching to Archimedean product 2021-10-10 00:40:22 +02:00
Zeno Rogue 4aa0dcf2fa mapstream:: correctly save coxeter and subcube-based variations 2021-10-10 00:40:22 +02:00
Zeno Rogue 09655ebf9f intra:: improved be-square 2021-10-10 00:40:22 +02:00
Zeno Rogue af18ee7ae1 intra:: become() now adds more spaces if called inside intra 2021-10-10 00:40:22 +02:00
Zeno Rogue 11aa9d0ddd intra:: improved debug 2021-10-10 00:40:22 +02:00
Zeno Rogue 57e58b3302 intra:: non-regular-shaped portals e.g. right-angled triangles 2021-10-10 00:40:22 +02:00
Zeno Rogue be1df0a68d fixed gen_sample_list (more walkaround than fix) 2021-10-10 00:40:22 +02:00
Zeno Rogue 41308e8e98 fixed product in dual archimedean 2021-10-10 00:40:22 +02:00
Zeno Rogue f97282099c intra:: binary x Z now connects to Solv/H3, fixes to product vertical 2021-10-10 00:40:22 +02:00
Zeno Rogue a04635111c fixed 20/21 resolution in multi-cell spaces 2021-10-10 00:40:22 +02:00
Zeno Rogue 2b8c19a6f7 ray:: works with Ternary and BinaryTiling product 2021-10-10 00:40:22 +02:00
Zeno Rogue 569c968a41 ray:: now works with Binary4 product 2021-10-10 00:40:22 +02:00
Zeno Rogue 83da34d6ac ray:: no portal_connections if not needed 2021-10-10 00:40:22 +02:00
Zeno Rogue 43cefcaca1 ray:: fixed the names of len functions 2021-10-10 00:40:22 +02:00
Zeno Rogue 77feff1c30 ray:: renamed bt/minkowski function to deparabolic and enparabolic for cinsistency 2021-10-10 00:40:22 +02:00
Zeno Rogue fe1e1d1f16 binary product now uses curved shapes 2021-10-10 00:40:22 +02:00
Zeno Rogue 62c4ddef45 made bt wider by default to match Binary3 and Solv 2021-10-10 00:40:22 +02:00
Zeno Rogue b4ffffe6ba shot:: hack to work in intra 2021-10-10 00:40:22 +02:00
Zeno Rogue 6605092515 ray:: fixup to solv portals 2021-10-10 00:40:22 +02:00
Zeno Rogue 2e5b46ff45 mapeditor:: save plevel_factor 2021-10-10 00:40:22 +02:00
Zeno Rogue b866647622 fixes to parabolic 2021-10-10 00:40:22 +02:00
Zeno Rogue 8217fb474e intra:: reduced eps to 1e-5 2021-10-10 00:40:22 +02:00
Zeno Rogue b1774a0763 intra:: using .at instead of [] 2021-10-10 00:40:22 +02:00
Zeno Rogue cb6226b5ab intra:: better H3/Solv portals 2021-10-10 00:40:22 +02:00
Zeno Rogue e4ea3b9de2 intra:: portal debugging 2021-10-10 00:40:22 +02:00
Zeno Rogue 0966d5e36c more accurate portal movement 2021-10-07 12:43:45 +02:00
Zeno Rogue 8d0059a760 refactored bt coordinate functions 2021-10-07 12:41:44 +02:00
Zeno Rogue 4ff08f3f3e deparabolic13 in hyperpoint 2021-10-07 12:41:29 +02:00
Zeno Rogue ac54fe909d inverse_exp more precise for very small vectors 2021-10-07 12:40:52 +02:00
Zeno Rogue 8bdf5aa404 param_f for levellines 2021-10-07 12:39:49 +02:00
Zeno Rogue 4a904b73c5 intra:: fix -be-square 2021-10-03 18:07:46 +02:00
Zeno Rogue f52b02b638 intra:: be more careful in infinite spaces 2021-10-03 18:07:32 +02:00
Zeno Rogue 36f3a0cf7b ray:: do not switch if no sample 2021-10-03 18:06:39 +02:00
Zeno Rogue 8385cad774 ray:: fixed levellines 2021-10-03 18:06:27 +02:00
Zeno Rogue 74906727c6 intra:: Solv portalsP 2021-10-03 18:06:15 +02:00
Zeno Rogue 6920382634 intra:: fixed wrongly rotating portals 2021-10-03 18:04:52 +02:00
Zeno Rogue 30a99f762f ray:: step-based works with intra 2021-10-03 18:03:14 +02:00
Zeno Rogue 4f3988602c ray:: nicer bt_to_minkowski 2021-10-03 11:16:15 +02:00
Zeno Rogue d2c8527213 ray:: fixed intra in bt 2021-10-03 11:15:33 +02:00
Zeno Rogue 80ce840b3d add_function in raygen 2021-10-03 10:55:07 +02:00
Zeno Rogue 6fea0c31e4 intra:: H3-bt portals (preliminary) 2021-10-03 10:19:45 +02:00
Zeno Rogue 1458929a5d clearer functions bt::bt_to_minkowski and bt::minkowski_to_bt 2021-10-02 19:49:29 +02:00
Zeno Rogue e70e2fc404 intra:: fixed the mirroring on product ceiling portals 2021-10-02 14:01:22 +02:00
Zeno Rogue 49fcd23397 12.0g 2021-10-01 08:18:49 +02:00
Zeno Rogue 53a4a472aa made rulegen compile in older compiler 2021-10-01 08:18:49 +02:00
Zeno Rogue 77063c135d back_and_front was not added in hyper.h 2021-10-01 08:03:16 +02:00
Zeno Rogue 5d4df5d9d6 fixed message about 9 types 2021-10-01 08:00:42 +02:00
Zeno Rogue 486803aca6 intra:: CLI option -be-square 2021-10-01 07:56:57 +02:00
Zeno Rogue 8f0d6585cd options to create intra map 2021-09-30 19:05:15 +02:00
Zeno Rogue 011611d575 re-enabled Caribbean 2021-09-30 16:17:37 +02:00
Zeno Rogue 8b6a745a8f intra:: more portal combinations are working (product upwards, portal to self) 2021-09-30 16:13:47 +02:00
Zeno Rogue b3fc40a8fc intra:: fixed mirroring 2021-09-30 15:02:16 +02:00
Zeno Rogue ed88c6dfbb fixed asin_auto_clamp in product 2021-09-30 14:13:19 +02:00
Zeno Rogue 631469490f parallel linepattern is now configurable 2021-09-30 13:23:35 +02:00
Zeno Rogue 642f0899b5 fixed box display which sometimes removed parts of the picture 2021-09-30 13:22:48 +02:00
Zeno Rogue 99f85aecfd option disable_bigstuff for some experiments 2021-09-30 13:22:12 +02:00
Zeno Rogue aeb93f7e3f arb::convert:: added more tests as the current sometimes did not work 2021-09-30 13:18:34 +02:00
Zeno Rogue b88ec8550e mimics destroyed correctly in the map editor 2021-09-30 13:16:22 +02:00
Zeno Rogue 7e57852788 gp:: pBring works with GP(2,2) and larger 2021-09-30 13:11:55 +02:00
Zeno Rogue 9ffdf3aa67 gp:: improved debug 2021-09-30 13:10:52 +02:00
Zeno Rogue aeb889119d gp(1,1) now works with non-orientable S3==4 2021-09-30 12:05:16 +02:00
Zeno Rogue 70c0fb1c7a UNRECTIFIED now works with non-orientable 2021-09-30 12:04:58 +02:00
Zeno Rogue 3967aee968 new geometry gHalfBring 2021-09-30 12:04:26 +02:00
Zeno Rogue 6929b2f1b4 rogueviz:: edgewidth parameter 2021-09-30 11:42:23 +02:00
Zeno Rogue af00aaac2d rogueviz:: improved line quality 2021-09-30 11:42:02 +02:00
Zeno Rogue 89696a8e2c rogueviz:: weirdmaze:: option atleast == -1 2021-09-30 11:40:30 +02:00
Zeno Rogue 73c16f9586 rogueviz::smoothcam:: disable sm::SIDE 2021-09-30 11:39:48 +02:00
Zeno Rogue 66f0e22dae rogueviz:: objmodels:: removed debug 2021-09-30 11:38:57 +02:00
Zeno Rogue e1fa7345ff rogueviz:: objmodels:: ignore_mtlname option 2021-09-30 11:38:45 +02:00
Zeno Rogue 36ee3b7ebe rogueviz::objmodels:: root option 2021-09-30 11:37:53 +02:00
Zeno Rogue d29cf4bda5 rogueviz:: snow:: -use-model option 2021-09-30 11:36:04 +02:00
Zeno Rogue 2b2eabd63a rogueviz:: added sokoban to highdim-demo 2021-09-30 11:35:09 +02:00
Zeno Rogue d2d9483065 rogueviz:: fundamental:: add clearmemory 2021-09-30 11:33:44 +02:00
Zeno Rogue 9564f0fdc6 rogueviz:: fixed crystal-sokoban 2021-09-30 11:33:13 +02:00
Zeno Rogue 9a32a462cc crystal:: fixed a crash bug 2021-09-30 11:14:31 +02:00
Zeno Rogue 402fabeefb rogueviz:: use enable_canvas 2021-09-30 10:49:12 +02:00
Zeno Rogue 2377ccb434 fixed -r option and made it more powerful: -f1 -r 0, -f1 -r XxYxF, -f0 -r .9x.9, -f0 -r 1000x1000 2021-09-18 01:55:55 +02:00
Zeno Rogue 3ece943c9f fixup to intra editing (point_direction was missing) 2021-09-18 01:39:30 +02:00
Zeno Rogue 96c143da8e backandfront projection option 2021-09-18 01:39:09 +02:00
Zeno Rogue a7ddaae7d4 intra:: improved keeping cgi's 2021-09-17 13:50:43 +02:00
Zeno Rogue 9076056fc4 geometry_information:: edgelen available 2021-09-17 13:50:24 +02:00
Zeno Rogue c16686404d fineline as param_b 2021-09-17 13:49:43 +02:00
Zeno Rogue aa6c0cb1cd fixup to save field 3d fix 2021-09-17 13:49:31 +02:00
Zeno Rogue a5228b06a5 mapeditor:: loading maps now sets the default settings like pmodel for 3D 2021-09-17 12:20:15 +02:00
Zeno Rogue 23a860d405 intra:: intra maps are now saved correctly 2021-09-17 12:00:53 +02:00
Zeno Rogue 7a7198c45a mapeditor:: 3D field quotients are now saved correctly 2021-09-17 11:56:18 +02:00
Zeno Rogue 716f7684e0 intra:: portals now can be edited 2021-09-17 10:26:51 +02:00
Zeno Rogue e8e6d0aa25 two-sided display of hyperbolic disk with -1<pconf.alpha<0 2021-09-16 22:26:23 +02:00
Zeno Rogue eb58d78555 ray:: fixed mirrors in intra::in 2021-09-16 22:14:30 +02:00
Zeno Rogue 09b4191758 ray:: used variable m intead of calling getM("woi") 2021-09-16 22:11:09 +02:00
Zeno Rogue f7bcadab50 intra:: fix 2021-09-16 22:04:24 +02:00
Zeno Rogue 5f4e03b1da intra:: fixes 2021-09-16 21:58:35 +02:00
Zeno Rogue 64268f7990 fixed PAGEDOWN rotating in the same direction as PAGEUP 2021-09-16 21:31:36 +02:00
Zeno Rogue 663e334e38 intra:: first version 2021-09-16 21:30:26 +02:00
Zeno Rogue 30f964e6e3 ray:: protect_prod applied 2021-09-16 20:53:05 +02:00
Zeno Rogue 35fda985f1 ray:: refactoring in raycaster 2021-09-16 20:50:39 +02:00
Zeno Rogue c7ccb0b64f improved citation metadata 2021-09-15 17:21:56 +02:00
Zeno Rogue a086dc568e improved metadata 2021-09-15 17:17:50 +02:00
Zeno Rogue 5561351769 more metadata 2021-09-15 17:16:01 +02:00
Zeno Rogue 78bf27f514 CITATION.cff updated 2021-09-15 16:51:28 +02:00
Zeno Rogue 93f98c3036 added CITATION.cff 2021-09-15 16:42:55 +02:00
Zeno Rogue 8a007fc1d6 rogueviz:: one more CAP_TEXTURE guard 2021-09-04 22:01:35 +02:00
Zeno Rogue 01ebce9496 added missing CAP_TEXTURE guard in rogueviz 2021-09-04 22:00:41 +02:00
Zeno Rogue 46f2fa4f9a moved draw_sky out of #if 2021-09-04 21:58:45 +02:00
Zeno Rogue f87e3b3dce mymake:: added option -sdl0 for SDL-less builds 2021-09-04 21:57:17 +02:00
Zeno Rogue d97c4bbde3 mymake:: added -march=native 2021-09-04 21:57:01 +02:00
Zeno Rogue 97ec940744 added CAP_GL guards 2021-09-04 21:54:42 +02:00
Zeno Rogue e2ba882b55 refactored compute_geometry_data 2021-08-27 12:06:10 +02:00
Zeno Rogue e432991abe rulegen:: minor fixes 2021-08-25 12:58:02 +02:00
Zeno Rogue 73d5862d04 refactored check_timeout 2021-08-25 12:57:50 +02:00
Zeno Rogue 9df74125bd fix_distances: do not fix while fixing uni 2021-08-25 12:57:33 +02:00
Zeno Rogue 0e3acfe91b check_timeout in find_new_shortcuts 2021-08-25 12:57:14 +02:00
Zeno Rogue 83e69a4872 rulegen:: addstep used in one more place 2021-08-25 12:56:56 +02:00
Zeno Rogue 25dba5a13c do not crash on memory clean in case of precision errors 2021-08-25 12:55:51 +02:00
Zeno Rogue 42d87d39ac in be_solid check that c1 is not null (not sure how it could happen) 2021-08-24 12:55:56 +02:00
Zeno Rogue 510c28227b Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-08-24 12:20:52 +02:00
Zeno Rogue 0b7b1845bf rogueviz:: recursive-house added 2021-08-24 12:20:13 +02:00
Zeno Rogue 3e269fe053 rulegen:: w_near_solid 2021-08-24 12:06:17 +02:00
Zeno Rogue 74bf728b84 rulegen:: some weird stuff 2021-08-24 03:37:09 +02:00
Zeno Rogue 25c636c54a rulegen:: improved shortcut generation 2021-08-24 03:36:50 +02:00
Zeno Rogue 4d127e824a rulegen:: tests:: use clock() 2021-08-24 00:34:35 +02:00
Zeno Rogue 9174a8210b rulegen:: tests:: new features 2021-08-24 00:34:25 +02:00
Zeno Rogue cda7d2337a rulegen:: origin_id can be changed now 2021-08-24 00:33:52 +02:00
Zeno Rogue 61c400c459 rulegen:: debuglist for solid errors 2021-08-24 00:33:38 +02:00
Zeno Rogue 0c6b6e4b8e rulegen:: improved handling of distance errors 2021-08-24 00:33:24 +02:00
Zeno Rogue 6215039f9d rulegen:: export ufind 2021-08-24 00:32:53 +02:00
Zeno Rogue ea44116beb rulegen:: tests:: fixed set_dir 2021-08-23 15:57:22 +02:00
Zeno Rogue cd1f421c70 rulegen:: tests:: changing colors and some other new features for making screenshots 2021-08-23 15:57:12 +02:00
Zeno Rogue e5aa10df83 move_to function 2021-08-23 15:56:45 +02:00
Zeno Rogue 711ae44605 rulegen:: handle dead roots 2021-08-23 15:50:08 +02:00
Zeno Rogue 308ed5cbb1 rulegen:: fixed branch conflicts handled incorrectly 2021-08-23 15:49:48 +02:00
Zeno Rogue 9e04e053df rulegen:: do not include conversion time 2021-08-23 12:07:18 +02:00
Zeno Rogue c36116f125 rulegen:: tests:: precision testing, report solid_err 2021-08-23 12:06:52 +02:00
Zeno Rogue b41785d671 mymake:: quiet option -q 2021-08-22 23:42:12 +02:00
Zeno Rogue 6c9f7e71e1 better handling of precision errors in arcm and arb 2021-08-22 23:41:38 +02:00
Zeno Rogue c6aa583a3d
Merge pull request #296 from jruderman/rose_crash
Erase rosemap entries for deleted cells
2021-08-22 23:35:18 +02:00
Zeno Rogue 5e87f08f54 walker::peek() is now const 2021-08-22 23:34:19 +02:00
Zeno Rogue 536c1c21ea sidecache was not cleared -- added 2021-08-22 19:42:25 +02:00
Zeno Rogue 59aed89f96 rulegen:: w_bfs option 2021-08-22 19:42:07 +02:00
Zeno Rogue 320ff44ef3 fixup to export flag names 2021-08-22 19:41:44 +02:00
Zeno Rogue 565d43665e rulegen:: fixup to numerical 2021-08-22 14:31:30 +02:00
Zeno Rogue c5c8d4a928 rulegen:: fixup to time computation 2021-08-22 14:31:23 +02:00
Zeno Rogue 359227c84a rulegen:: fix weird errors 2021-08-22 14:31:13 +02:00
Zeno Rogue d361d2bf61 rulegen:: report all_solid_errors 2021-08-22 14:30:52 +02:00
Zeno Rogue 1c08b5500f rulegen:: implemented w_numerical 2021-08-22 14:30:24 +02:00
Zeno Rogue 75e637be30 rulegen:: epxort flag names 2021-08-22 14:28:54 +02:00
Jesse Ruderman 34537282f8 Erase rosemap entries for deleted cells 2021-08-22 02:00:04 -07:00
Zeno Rogue 489c930ced rulegen:: new test value 2021-08-22 00:28:52 +02:00
Zeno Rogue 3616221118 rulegen:: updated tests to use new features 2021-08-22 00:23:51 +02:00
Zeno Rogue 29f2570662 rulegen:: timeout feature 2021-08-22 00:12:22 +02:00
Zeno Rogue db28ca7c4a stats fixup 2021-08-22 00:10:14 +02:00
Zeno Rogue 6db8f857e1 rulegen:: flags to test variants of the algorithm 2021-08-22 00:10:02 +02:00
Zeno Rogue 3654ca58aa rulegen:: more fixes in reporting 2021-08-21 23:40:50 +02:00
Zeno Rogue 7f33024321 fixup to dlbonus removal 2021-08-21 23:38:42 +02:00
Zeno Rogue 60a8992b29 rulegen:: extra stats, extra cleanup 2021-08-21 23:38:36 +02:00
Zeno Rogue a272bb399d rulegen:: removed dlbonus as it is unused 2021-08-21 23:35:04 +02:00
Zeno Rogue 5f1f10c79f Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-08-20 11:40:09 +02:00
Zeno Rogue c999d4c314 rulegen:: tests:: now can test regular and Archimedean tessellations and their variations 2021-08-20 11:37:38 +02:00
Zeno Rogue 566f05a6d0 arb::convert:: had debug lines which caused conversion to end up even if it worked correctly 2021-08-20 11:35:09 +02:00
Zeno Rogue 647f7132dd improved find_single_live_branch 2021-08-20 01:36:14 +02:00
Zeno Rogue 78ee00ddea fixed problems in resolve_confusion 2021-08-20 01:35:19 +02:00
Zeno Rogue 1135aaab7e set try_to_resolve_confusion to true 2021-08-20 01:34:00 +02:00
Zeno Rogue 71d416f78d max_getside configurable 2021-08-20 00:48:09 +02:00
Zeno Rogue 25aa5d62e1 rulegen:: do not repeat importants 2021-08-20 00:46:22 +02:00
Zeno Rogue 153a639337 rulegen:: removed junk 2021-08-20 00:45:46 +02:00
Zeno Rogue 40792a3aa1 faster get_side hard case 2021-08-20 00:44:24 +02:00
Zeno Rogue 0d60ff6bdc find_new_shortcuts fix hid original shortcuts 2021-08-20 00:44:12 +02:00
Zeno Rogue e80782be87 converted wrongcode from rulegen_failure to rulegen_retry 2021-08-19 13:22:31 +02:00
Zeno Rogue 0ed4b8f367 rulegen-tests:: improvements 2021-08-19 13:19:32 +02:00
Zeno Rogue 2f11f9babb refactored clean_data and clean_parents 2021-08-19 13:19:11 +02:00
Zeno Rogue 881b262174 removed mismatch_error to multiple error causes 2021-08-19 13:19:01 +02:00
Zeno Rogue 19f65644e7 rulegen:: check all live branches, not until the first error 2021-08-19 13:18:38 +02:00
Zeno Rogue c58f12cfc6 rulegen:: just call rules_iteration_for for unknown states, no need to restart 2021-08-19 13:17:56 +02:00
Zeno Rogue d7f40b8cdb more handle_distance_errors 2021-08-19 13:14:57 +02:00
Zeno Rogue 5e249ba4f4 rulegen:: in find_new_shortcuts don't find subshortcuts 2021-08-19 13:14:15 +02:00
Zeno Rogue cd52fe35b2 rulegen:: renamed check_solid to find_new_shortcuts 2021-08-19 13:13:59 +02:00
Zeno Rogue 31d359d908 multiple shortcuts per sample, check_solid on unification 2021-08-19 13:12:26 +02:00
Zeno Rogue 1b1d38bda6 fixup to tests improved 2021-08-19 01:40:15 +02:00
Zeno Rogue 80d5ee7c37 rulegen:: tests improved 2021-08-19 01:39:49 +02:00
Zeno Rogue 9b741ebb47 fixup to MYSTERY_DIST removal 2021-08-19 01:33:07 +02:00
Zeno Rogue 755e1df101 rulegen:: minor fixes 2021-08-19 01:27:56 +02:00
Zeno Rogue 49e92f4288 addstep, protected cw+wstep 2021-08-19 01:27:26 +02:00
Zeno Rogue 8b5c0bbe70 rulegen:: better export/error reporting 2021-08-19 01:25:18 +02:00
Zeno Rogue 8d764fd8ef removed MYSTERY_DIST 2021-08-19 01:24:35 +02:00
Zeno Rogue d321e4b5ec sidecache 2021-08-19 01:24:01 +02:00
Zeno Rogue 1798bc4612 rulegen::clear analyzers on doubling 2021-08-19 01:21:44 +02:00
Zeno Rogue 137763dae9 rulegen:: fix unification errors 2021-08-17 23:05:56 +02:00
Zeno Rogue 627963c634 rulegen:: improved memory usage 2021-08-17 20:08:06 +02:00
Zeno Rogue 858fd61794 rulegen:: perform get_code if code is given but no parent_dir 2021-08-17 20:07:17 +02:00
Zeno Rogue 57dffb8af9 rulegen:: cleaner push_unify and improved assertions 2021-08-17 20:06:48 +02:00
Zeno Rogue 73edbfee90 longer shortcuts allowed 2021-08-17 19:27:02 +02:00
Zeno Rogue f5d0d928cb throw mismatch errors quickly 2021-08-17 18:58:23 +02:00
Zeno Rogue afc92c586c rulegen:: added single_live_branch_close_to_root to cleanup 2021-08-17 17:43:24 +02:00
Zeno Rogue c97290890e fixed push_deadstack in the root 2021-08-17 17:24:11 +02:00
Zeno Rogue 4c3800f2b4 removed sub_status -- unused in the current branchtester 2021-08-17 17:15:11 +02:00
Zeno Rogue 5c95359763 rulegen:: debug removed in find_sub_status 2021-08-17 17:04:29 +02:00
Zeno Rogue 47c6495652 rulegen:: simpler branch testing 2021-08-17 17:04:17 +02:00
Zeno Rogue bc511cf37b rulegen:: tests:: can print rules 2021-08-17 14:35:53 +02:00
Zeno Rogue 2fed33ae43 rulegen:: tests:: able to set -resolve 2021-08-17 14:35:46 +02:00
Zeno Rogue 943682f1d5 rulegen:: tests:: comments now available in .lst files 2021-08-17 14:35:31 +02:00
Zeno Rogue 9fafad3ee0 rulegen:: tests:: options to specify what statistics to report 2021-08-17 14:35:13 +02:00
Zeno Rogue d9b8c338d3 rulegen:: tests:: display root states 2021-08-17 14:34:34 +02:00
Zeno Rogue 89958ea3c8 rulegen:: tests:: an option to debug parent_dir 2021-08-17 14:34:27 +02:00
Zeno Rogue 72f0f9b28b rulegen:: tests:: nicer MYSTERY_DIST display 2021-08-17 14:34:14 +02:00
Zeno Rogue 096364bb06 rulegen:: tests:: set canvas land just in case 2021-08-17 14:33:50 +02:00
Zeno Rogue 41978a6a03 rulegen:: tests:: YA fixup for multi 2021-08-17 14:33:37 +02:00
Zeno Rogue f17f8cacf1 second part of last -- fixup 2021-08-17 14:30:36 +02:00
Zeno Rogue 631827c657 simpler multi-connection system 2021-08-17 14:28:27 +02:00
Zeno Rogue 031d6a2c50 rulegen:: ufind in extend_analyzer just in case 2021-08-17 14:25:20 +02:00
Zeno Rogue e0db5d8f6a rulegen:: set C_CHILD for id==0 2021-08-17 14:24:58 +02:00
Zeno Rogue 85acd05ee7 rulegen:: improved get_side 2021-08-17 14:24:32 +02:00
Zeno Rogue b307ab2762 rulegen:: rulegen_retry on no extension 2021-08-17 14:24:06 +02:00
Zeno Rogue 43aec99cd8 rulegen:: debug get_parent_dir 2021-08-17 14:20:54 +02:00
Zeno Rogue dd79a01f02 rulegen:: attempt to resolve confusion (for testing other parts mainly) 2021-08-17 14:18:54 +02:00
Zeno Rogue 5e534dbe28 rulegen:: get_parent_dir now finds a conflict in symmetric case 2021-08-17 14:18:05 +02:00
Zeno Rogue 6080443fde dealing with single live branches correctly 2021-08-17 02:32:03 +02:00
Zeno Rogue 02a6ca7441
Merge pull request #292 from blargdag/ru2
More Russian translations
2021-08-17 00:36:02 +02:00
Zeno Rogue e4fdac9d65
Merge pull request #291 from blargdag/typo
Fix typo in Russian translation.
2021-08-17 00:35:49 +02:00
Zeno Rogue a96b3daf69 rulegen: unused var removed 2021-08-17 00:25:07 +02:00
Zeno Rogue 48b91ddafb rulegen:: some fixes in get_parent_dir 2021-08-17 00:24:38 +02:00
Zeno Rogue f19ba00324 rulegen:: fixed for the case of a single live branch at root. TBH more hack than a proper fix 2021-08-15 21:01:47 +02:00
Zeno Rogue fc0763362e improved get_parent_dir 2021-08-15 18:06:23 +02:00
Zeno Rogue 749b8aead6 rulegen:: simplified since we know LEFT/RIGHT directions 2021-08-15 17:43:13 +02:00
Zeno Rogue 0f0aef8dd9 rulegen:: faster shortcuts 2021-08-15 17:26:38 +02:00
blargdag 1565691bb5 Advance marked line. :-D 2021-08-12 16:56:58 -07:00
blargdag 12f9f48577 Translate description of Free Fall. 2021-08-12 16:56:58 -07:00
blargdag b7f29095bc Translate Brown Island description. 2021-08-12 15:11:05 -07:00
blargdag 0b667f5d42 Fix typo. 2021-08-11 16:55:56 -07:00
Zeno Rogue 68949a4ea4 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-08-09 14:42:12 +02:00
Zeno Rogue 53010a259e removed reachedfrom from system 2021-08-09 14:42:07 +02:00
Zeno Rogue 30a6a55ba0
Merge pull request #288 from jruderman/aenum
Update autoplay for #221
2021-08-09 13:50:02 +02:00
Zeno Rogue 838b9d0b10
Merge pull request #289 from jruderman/illusion_item
Orb of Trickery messages no longer reveal underwater items
2021-08-09 13:49:28 +02:00
Zeno Rogue f1e495be4f
Merge pull request #290 from jruderman/vault_phase_msgs
Add Orb error messages for Phasing and Vaulting
2021-08-09 13:47:54 +02:00
Jesse Ruderman dbb6488557 Add Orb error messages for Phasing and Vaulting 2021-08-09 04:26:56 -07:00
Jesse Ruderman 8d98193e70 check_vault: ensure error codes don't depend on angle 2021-08-09 04:26:28 -07:00
Jesse Ruderman aad8441d83 Orb of Trickery messages no longer reveal underwater items 2021-08-09 02:24:18 -07:00
Jesse Ruderman 85a4dd2683 Update autoplay for #221 2021-08-09 02:22:12 -07:00
Zeno Rogue 77f6d2db14 improved ranged Orb error messages 2021-08-09 02:07:32 +02:00
Zeno Rogue f8c13ea531 better checking of pathlock 2021-08-09 00:50:39 +02:00
Zeno Rogue 5dbda4c896 split reachedfrom to path_reachedfrom and bfs_reachedfrom; also fix bfs_reachedfrom for other geoms 2021-08-09 00:49:22 +02:00
Zeno Rogue 897ba90628 added missing pathdata structure creation 2021-08-09 00:48:11 +02:00
Zeno Rogue bb77f035b0 pathdata:: no longer inline 2021-08-09 00:48:11 +02:00
Zeno Rogue fbc32c6bc4 don't set landparam for hunting dogs outside of laHunting 2021-08-08 22:12:32 +02:00
Zeno Rogue d33fc20c6b movei constructor now calls cmove, not move 2021-08-08 19:43:58 +02:00
Zeno Rogue 68ba57142a warning protection no longer evokes Flash/Lightning 2021-08-08 19:33:26 +02:00
Zeno Rogue a6151f185f refactored whirlline loop detection 2021-08-08 19:13:09 +02:00
Zeno Rogue 025893e946 cleaned up where summoned creature appears for Orb of Life and Orb of Friendship 2021-08-08 19:04:58 +02:00
Zeno Rogue 683ab67ad9 prevent freezes in West Wall with wrong data 2021-08-08 18:32:10 +02:00
Zeno Rogue 4902d2db8d fake_edgelength constant in parser 2021-08-08 18:29:49 +02:00
Zeno Rogue a8eef4b717 fixed set_view for 2.5D 2021-08-08 18:29:35 +02:00
Zeno Rogue ba7b9d6097 an option to disable sky drawing 2021-08-08 18:29:21 +02:00
Zeno Rogue 7b0b41967f wall shadows no longer drawn with noshadow 2021-08-08 18:28:24 +02:00
Zeno Rogue ae03bd5272 some Euclidean lands are now available only in single land mode 2021-08-08 18:23:38 +02:00
Zeno Rogue 2f11237171 no more fatigue_cost checking when the Curse is gone 2021-08-08 17:24:09 +02:00
Zeno Rogue e55fe37803 gravityLevelDiff is now clamped to [-1,1] 2021-08-08 17:23:17 +02:00
Zeno Rogue 6a3e12836f added CAP_COMMANDLINE guards in rulegen 2021-08-08 17:14:19 +02:00
Zeno Rogue bdeee41e98 fixed rot spaces 2021-08-08 17:11:05 +02:00
Zeno Rogue 1756a634a5 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-08-08 13:31:19 +02:00
Zeno Rogue 0105808adf added RogueViz sample 2021-08-08 13:31:11 +02:00
Zeno Rogue fad27e34c1
Merge pull request #287 from jruderman/event_targets
emscripten: specify event targets to fix a JS error
2021-08-07 11:50:57 +02:00
Zeno Rogue 501f5c59bc fixed the interesting dodecahedral quotient spaces (535c, 535s, 533s) 2021-08-07 11:32:54 +02:00
Zeno Rogue de83eeeef2 weirdmaze add fixup 2021-08-07 11:25:36 +02:00
Zeno Rogue 8b43724b6c rogueviz/weirdmaze added 2021-08-07 11:24:50 +02:00
Jesse Ruderman 75d67fb7d9 emscripten: specify event targets to fix a JS error 2021-08-06 11:30:30 -07:00
Zeno Rogue 610d5cc399 raycaster fix continued 2021-08-06 15:38:54 +02:00
Zeno Rogue dfa682ea8a fixed a possible bug while raycasting the first frame 2021-08-06 15:03:06 +02:00
Zeno Rogue cba7ed1db9 added -Wno-invalid-offset in Makefile 2021-08-05 20:34:08 +02:00
Zeno Rogue c4c862ad01 fake:: added missing override 2021-08-05 20:33:40 +02:00
Zeno Rogue dda9f29403 12.0f 2021-08-05 13:49:41 +02:00
Zeno Rogue 317e9d5549 mentioned one more fix in changelog 2021-08-05 13:47:24 +02:00
Zeno Rogue 3f155298b4 updated to 12.0f 2021-08-05 13:30:32 +02:00
Zeno Rogue 8545c7d66f shot:: more 16:9 formats 2021-08-05 13:22:29 +02:00
Zeno Rogue 14afd51049 when switching dimension in arb/fake, the correct geometry is used for fixmatrix 2021-08-05 13:17:40 +02:00
Zeno Rogue 51ad054012 arcm:: debug output uses index_pointer 2021-08-05 12:48:48 +02:00
Zeno Rogue f21a36a7aa arcm:: correct cgip is used for the altmap 2021-08-05 12:48:14 +02:00
Zeno Rogue fcf55f1852 arcm:: arcm_euclid_length parameter 2021-08-05 12:21:39 +02:00
Zeno Rogue 2c074a7088 rulegen:: analyzer improvements 2021-08-05 11:56:49 +02:00
Zeno Rogue 9e9b331b3a sky debug removed 2021-08-05 11:56:20 +02:00
Zeno Rogue cb6a28f7c1 fixed some problems with 2D fake 2021-08-05 11:56:12 +02:00
Zeno Rogue 8d2dcb462e rulegen:: fractal debug removed 2021-08-04 20:48:24 +02:00
Zeno Rogue eae1b67013 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-08-04 20:22:52 +02:00
Zeno Rogue cb2972f207 changelog was not pushed with 12.0e 2021-08-04 20:22:18 +02:00
Zeno Rogue 932cb7c997 rulegen:: fractal landscapes 2021-08-04 20:21:03 +02:00
Zeno Rogue 9896f8d311 fixed BabyTortoise generation for ls::single() 2021-08-04 20:18:54 +02:00
Zeno Rogue 9ce7a243ed fixed switching messages 2021-08-04 20:15:46 +02:00
Zeno Rogue 8ca6d3407a
Merge pull request #271 from jruderman/nestcolors
Adjust Snake Nest colors so drawMonster can add them without overflowing to black
2021-08-04 19:14:43 +02:00
Zeno Rogue 2ac3b6f949
Merge pull request #275 from jruderman/fall_alch_msg
Show correct message when trying to move from a high Brown Island cell to a Red Slime cell
2021-08-04 19:13:10 +02:00
Zeno Rogue 4710110421
Merge pull request #274 from jruderman/recall_tense
Fix typo in Orb of Recall description
2021-08-04 19:12:36 +02:00
Zeno Rogue 3af71a1388
Merge pull request #272 from jruderman/snake_high
Fix highlight colors for snakes
2021-08-04 19:12:02 +02:00
Zeno Rogue e61a69207a
Merge pull request #273 from jruderman/vsnekcolor
Fix RRV snakes sometimes being colored like SN snakes
2021-08-04 19:11:26 +02:00
Zeno Rogue 4f33b4297b
Merge pull request #277 from jruderman/chaos_trap
Orb of Chaos now destroys arrow traps
2021-08-04 19:11:10 +02:00
Zeno Rogue 69e5356e8a
Merge pull request #276 from jruderman/slime_color_in_brown
Fix color of slime on Brown Island
2021-08-04 19:10:46 +02:00
Zeno Rogue 965b40cf11
Merge pull request #279 from jruderman/ndfe
Fix discontinuity in notDippingForExtra
2021-08-04 19:09:58 +02:00
Zeno Rogue f5264e49c7
Merge pull request #278 from jruderman/detrap_particles
Animate destruction of arrow traps
2021-08-04 19:09:41 +02:00
Zeno Rogue 0f746b5009
Merge pull request #281 from jruderman/gen_no_stun
Clear stuntime when generating new monsters
2021-08-04 19:09:18 +02:00
Zeno Rogue ba3c117d97
Merge pull request #282 from jruderman/terra_wparam
Fix terra statue interactions with Chaos+Icy, BSoC swap, Alch dup
2021-08-04 19:07:42 +02:00
Zeno Rogue d98c8a025f fixup to memory perf 2021-08-04 18:36:38 +02:00
Zeno Rogue a5bb0b7ffc rulegen:: rule_status is now logged 2021-08-04 18:35:48 +02:00
Zeno Rogue 6935aa1cf7 rulegen:: branches starting at other roots were not examined 2021-08-04 18:35:37 +02:00
Zeno Rogue b60618d28a rulegen:: improved the memory performance 2021-08-04 18:35:04 +02:00
Zeno Rogue 7c9c599e4c index_pointer now produces better sequences of chars 2021-08-04 18:25:52 +02:00
Zeno Rogue b544461dc7 flat_model_enabler now sets the default variation, fixes issue #254 2021-08-04 18:23:26 +02:00
Zeno Rogue 6999277715 arb:: fixed a bug with 'ended at wrong edge determining vertex_valence' 2021-08-04 18:00:34 +02:00
Zeno Rogue e175f522dc arcm:: cleared spam in DF_GEOM 2021-08-04 18:00:09 +02:00
Zeno Rogue e2077620c8 general_barrier: removed useless at_corner = true 2021-08-04 17:59:09 +02:00
Zeno Rogue d8e13ed88d general_barrier:: fixed holes 2021-08-04 17:58:52 +02:00
Zeno Rogue 917e42e4a5 CR4/Elemental Planes now supported generally 2021-08-04 17:46:47 +02:00
Zeno Rogue 9d8cde1508 renamed checkBarriersNowall to general_barrier_check 2021-08-04 17:45:24 +02:00
Zeno Rogue 3c4e3f0e3e fixed general_barrier not working correctly at all with CEPOSNEG 2021-08-04 17:43:51 +02:00
Zeno Rogue fdf2162b36 function wsname for debugging 2021-08-04 17:41:54 +02:00
Zeno Rogue 0b5a32d1c1 fixed the raycaster in elliptic S3 2021-08-04 15:28:17 +02:00
Zeno Rogue 8c2dfad20f fix elliptic S3 2021-08-04 15:18:22 +02:00
Jesse Ruderman d8509a0528 Fix terra statue interactions with Chaos+Icy, BSoC swap, Alch dup 2021-08-03 17:15:53 -07:00
Jesse Ruderman 85cfd1d01f Clear stuntime when generating new monsters 2021-08-03 16:32:04 -07:00
Jesse Ruderman ddd4f81b97 Fix discontinuity in notDippingForExtra 2021-08-02 22:37:23 -07:00
Jesse Ruderman b8aab5e50d Animate destruction of arrow traps 2021-08-02 22:18:23 -07:00
Jesse Ruderman e90999e5b6 Orb of Chaos now destroys arrow traps 2021-08-02 22:13:40 -07:00
Jesse Ruderman 07035f3c09 Fix raised colors in Snake Nest 2021-08-02 19:40:05 -07:00
Jesse Ruderman 7f73dc88ab Fix color of slime on Brown Island 2021-08-02 19:11:58 -07:00
Jesse Ruderman 46ca5f81a0 Show correct message when trying to move from a high Brown Island cell to a Red Slime cell 2021-08-02 19:09:45 -07:00
Jesse Ruderman 00fe4eaf16 Fix typo in Orb of Recall description 2021-08-02 13:31:57 -07:00
Jesse Ruderman 5d4584c66a Fix RRV snakes sometimes being colored like SN snakes 2021-08-02 12:45:46 -07:00
Jesse Ruderman 34b4ffffae Fix highlight colors for snakes 2021-08-02 12:14:21 -07:00
Jesse Ruderman 74ae7a72c5 Adjust Snake Nest colors so drawMonster can add them without overflowing to black 2021-08-02 12:06:10 -07:00
Zeno Rogue b67b946126 upgraded Android version number 2021-08-01 11:43:57 +02:00
Zeno Rogue ce1d48c415 added missing override 2021-08-01 11:28:45 +02:00
Zeno Rogue b0dd4ebf94 rulegen:: added MLEFT and MRIGHT to treestates in files 2021-08-01 03:02:39 +02:00
Zeno Rogue 5dd6789762 treestate reading now actually supports placing PARENT in other places 2021-08-01 03:00:24 +02:00
Zeno Rogue d04416dae8 fived bugs with moving the key with boats 2021-08-01 02:39:42 +02:00
Zeno Rogue 8da22c4ba9 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-07-31 20:38:26 +02:00
Zeno Rogue ed1a1dc37c
Merge pull request #270 from jruderman/drc2
Dice hover map now indicates hardness with color
2021-07-31 20:36:13 +02:00
Zeno Rogue 96f03dee31
Merge pull request #266 from jruderman/teleport_euclid
Teleport cheat (from overview) now works in Euclidean
2021-07-31 20:35:08 +02:00
Zeno Rogue d0c231b057
Merge pull request #267 from jruderman/a3
Autoplay improvements 3
2021-07-31 20:34:47 +02:00
Zeno Rogue a15d3e5811 don't return no_great_walls any longer 2021-07-31 20:30:41 +02:00
Zeno Rogue 923420fd0d altmap:: protect from crashing barriers 2021-07-31 20:30:12 +02:00
Zeno Rogue 8498e0ce14 fixup to bin fix 2021-07-31 20:29:44 +02:00
Zeno Rogue c89b97b244 generate_random_path fixed in 3D 2021-07-31 20:29:11 +02:00
Zeno Rogue c588837375 rulegen:: fixed a crash in generate_random_path when exploring a dead branch 2021-07-31 20:28:51 +02:00
Zeno Rogue 8e88ceb3bc removed disabling barriers in gBinary4 2021-07-31 20:18:32 +02:00
Zeno Rogue 36d3314eae currentmap for generating floorshapes is now of correct class in bt 2021-07-31 20:12:43 +02:00
Zeno Rogue 8079b0ffa4 paragraphs in strict tree maps help 2021-07-31 16:10:37 +02:00
Zeno Rogue ad454f2c67 more features explained in the sample 2021-07-31 16:10:23 +02:00
Zeno Rogue a065e73013 an option to change rule_root in the tes file 2021-07-31 16:10:08 +02:00
Zeno Rogue 769411554f an option to enable strict tree maps from the expansion menu 2021-07-31 16:02:30 +02:00
Zeno Rogue 0f05bb5e59 rulegen:: dialog now shows the statistics on success 2021-07-31 15:58:13 +02:00
Zeno Rogue 1fc3961a6f rulegen:: added the dialog enabling these 2021-07-31 15:50:20 +02:00
Zeno Rogue c843af9131 reduced the default max_tcellcount 2021-07-31 15:48:12 +02:00
Zeno Rogue 8d5d311555 arb::convert:: fixed a bug when trying to run multiple times 2021-07-31 15:47:58 +02:00
Zeno Rogue 0a141e0606 shvid-pattern ('A') is now universally available 2021-07-31 15:14:31 +02:00
Zeno Rogue dae0aacbb7 shvid now calls require_shapes() 2021-07-31 15:14:31 +02:00
Zeno Rogue c661290930 rulegen:: fixed a bug with generating Camelot root 2021-07-31 15:14:31 +02:00
Zeno Rogue 7fcc4de28b alt error reported differently 2021-07-31 15:14:31 +02:00
Zeno Rogue e8a8a75620 rulegen:: fixed UB in get_corner while doing floorshapes 2021-07-31 15:14:31 +02:00
Zeno Rogue c8b4d6b159 basic generate_random_path in strict_tree_rules 2021-07-31 15:14:31 +02:00
Zeno Rogue 3972e5a6bb altmap:: generate_random_path used 2021-07-31 15:14:31 +02:00
Zeno Rogue 0f2f435534 randomdir option for generate_random_path 2021-07-31 15:14:31 +02:00
Zeno Rogue ebfe0b6f48 exp_parser:: crash on unknown values starting with capital letters and _ 2021-07-31 15:14:31 +02:00
Zeno Rogue da4429e327 disabled surround problemfix in arb 2021-07-31 15:14:31 +02:00
Zeno Rogue d7a7447699 factored generate_random_path from yendor out 2021-07-31 15:14:31 +02:00
Zeno Rogue f567f0012b renamed 'nowall' functions to clearer general_barrier_* 2021-07-31 15:14:31 +02:00
Zeno Rogue 834457a24f added a new tessellation sample using the new features 2021-07-31 15:14:31 +02:00
Zeno Rogue fa03033c99 arb/rulegen:: trees can now be defined in tes files 2021-07-31 15:14:31 +02:00
Zeno Rogue 0559fce5fb barrier:: the barrier _WALL algorithm now moves step by step 2021-07-31 15:14:31 +02:00
Zeno Rogue b29e27e1c8 stars now are placed lower in FPP to prevent glitches 2021-07-31 15:14:31 +02:00
Zeno Rogue c9a1e52aaf sky now interacts better with stars and other high objects 2021-07-31 15:14:31 +02:00
Zeno Rogue 3cabddeb65 added is_boundary for &out_of_bounds just in case 2021-07-31 15:14:31 +02:00
Zeno Rogue 70702a8cd9 barrier:: fixed getNewLand to know the old land with new barriers 2021-07-31 15:14:31 +02:00
Zeno Rogue 8d913f525d altmap height now uses an outside parameter 2021-07-31 15:14:31 +02:00
Zeno Rogue 83ffa89fbf arb:: valence known 2021-07-31 15:14:31 +02:00
Zeno Rogue 06c8f48aa0 arb:: style improvement in compute_vertex_valence 2021-07-31 15:14:31 +02:00
Zeno Rogue 21942ff7b9 arb:: fixed shape id info in unmirror 2021-07-31 15:14:31 +02:00
Zeno Rogue c70dc65846 adapted rulegen-tests to change in rulegen 2021-07-31 15:14:31 +02:00
Zeno Rogue 8871efcc0c rulegen:: generate roots of all sid's 2021-07-31 15:14:31 +02:00
Zeno Rogue 0dfa361453 arb:: converted and rulegen status is now saved in save_geometry 2021-07-31 15:14:31 +02:00
Zeno Rogue 253c5ee531 arb:: two new parameters, boundary_ratio and floor_scale 2021-07-31 15:14:31 +02:00
Zeno Rogue d0e7541b45 nicer auto sight range computation, and range(...) directive in the tes language 2021-07-31 15:14:31 +02:00
Zeno Rogue c8cbe55e1f fixed minimize_rules() not updating id's 2021-07-31 15:14:31 +02:00
Zeno Rogue 872587d156 barrier:: great-wall-like barriers now correctly create sea buoys etc. 2021-07-31 15:14:31 +02:00
Zeno Rogue 184d32a89d rulegen:: added relative_matrixh 2021-07-31 15:14:31 +02:00
Zeno Rogue 6f9a784775 an expansion mode to display pointer indices 2021-07-31 15:14:31 +02:00
Zeno Rogue ebfbc3d1c9 do not try to make horos needlessly in Euclidean 2021-07-31 15:14:31 +02:00
Zeno Rogue a2211590b3 implemented great-wall-like walls for all H2 tessellations 2021-07-31 15:14:31 +02:00
Zeno Rogue a55111c226 improved NOWALLs in other geometries 2021-07-31 15:14:31 +02:00
Zeno Rogue 6e1e4a7db4 rulegen:: added some tests to devmods 2021-07-31 15:14:31 +02:00
Zeno Rogue 4a0f688673 rulegen:: apply arb::convert, and imrpoved generation 2021-07-31 15:14:31 +02:00
Zeno Rogue c996805533 rulegen:: adj for floorshapes 2021-07-31 15:13:44 +02:00
Zeno Rogue 1ca7175e56 rulegen:: removed useless current_geometry_name 2021-07-31 15:13:44 +02:00
Zeno Rogue ef0116b3b6 arb:: all are pseudohept if have_ph not specified 2021-07-31 15:13:44 +02:00
Zeno Rogue 0d62a7878f arb:: convert compatible tessellations to arb internal format 2021-07-31 15:13:44 +02:00
Zeno Rogue 24fcc1a642 expansion:: show correct types in strict_tree_rules 2021-07-31 15:13:44 +02:00
Zeno Rogue ebf9a299b5 altmap:: fixed Camelot for strict_tree_rules 2021-07-31 15:13:44 +02:00
Zeno Rogue bc79fd05df changed names generateAlts to extend_altmap and createAlternateMap to create_altmap 2021-07-31 15:13:44 +02:00
Zeno Rogue 0e71e67ba6 reg3:: more happy to create initial altmap 2021-07-31 15:13:44 +02:00
Zeno Rogue c0f91c0ea9 fixed a typo in comment 2021-07-31 15:13:44 +02:00
Zeno Rogue ced16a2f4e sword:: fixed a possible crash on incomplete maps 2021-07-31 15:13:44 +02:00
Zeno Rogue f92e26dc00 rulegen:: set state correctly 2021-07-31 15:13:44 +02:00
Zeno Rogue c797d376e5 fixed and improved rendering of tree patterns 2021-07-31 15:13:44 +02:00
Zeno Rogue c579db717f improved updir and updir_alt 2021-07-31 15:13:44 +02:00
Zeno Rogue c53270ca16 introduced rulegen.cpp which generates strict_tree_rules for arb 2021-07-31 15:13:44 +02:00
Zeno Rogue bb3fbc5256 removed debug from generateAlt 2021-07-31 15:13:44 +02:00
Zeno Rogue 9c07ea7d3d expansion:: curr_dist in dfWorld mode is now more helpful 2021-07-31 15:13:44 +02:00
Zeno Rogue 05d4fcc280 altmap parameters are now accessible via altmap:: functions 2021-07-31 15:13:44 +02:00
Zeno Rogue bac88ea9fd altmap relspin is now remembered in altmap::relspin 2021-07-31 15:12:06 +02:00
Zeno Rogue 2e47da5d2c moved the virtual functions in hrmap and its basic subclasses outside of the classes 2021-07-31 15:12:06 +02:00
Zeno Rogue d10181e363 gp:: replaced draw_li with current_li which is computed when needed 2021-07-31 15:12:06 +02:00
Zeno Rogue f996104074 improved timestamps 2021-07-31 15:12:06 +02:00
Zeno Rogue 5bff87f5e1 added oob (out_of_bounds heptagon) 2021-07-31 15:12:06 +02:00
Zeno Rogue 64947fe456 reg3:: fixed a bug in link_alt 2021-07-31 15:12:06 +02:00
Zeno Rogue bdfe78eaf5 arb:: fixed compute_vertex_valence 2021-07-31 15:12:06 +02:00
Zeno Rogue ae33c14337 arb:: fixed cycle_length computation 2021-07-31 15:12:06 +02:00
Zeno Rogue 1c31a987a8 refactored link_alt 2021-07-31 15:12:06 +02:00
Zeno Rogue 6540c9968c arb:: commented arb::shape 2021-07-29 12:58:54 +02:00
Zeno Rogue d2fdfc02ea arb:: compute_vertex_valence function 2021-07-29 12:58:54 +02:00
Zeno Rogue 46a3cf220f arb:: replaced tuple with connection_t 2021-07-29 12:58:54 +02:00
Jesse Ruderman b941d46733 Dice hover map now indicates hardness with color 2021-07-28 03:24:30 -07:00
Jesse Ruderman afa97376eb Autoplay: fix types for prairie::enter check 2021-07-25 23:17:08 -07:00
Jesse Ruderman 042b95a8bb Autoplay: skip 'missing princess info' check in euclid 2021-07-25 23:15:14 -07:00
Jesse Ruderman ab7d6c407e Autoplay: split into several functions 2021-07-25 23:13:24 -07:00
Jesse Ruderman b086946163 Teleport cheat (from overview) now works in Euclidean 2021-07-25 18:01:07 -07:00
Zeno Rogue 4dfb77d727
Merge pull request #264 from blargdag/pl-typo
Russian translation for Wetland strings.
2021-07-23 15:27:16 +02:00
blargdag d910743685 Translate Wetland strings. 2021-07-22 09:14:08 -07:00
blargdag 90650831e1 Add missing Polish translation for "Pike". 2021-07-22 09:14:08 -07:00
blargdag db9e9f879c Fix typo in Polish translation.
Wrong key was used for deep water.
2021-07-22 08:06:03 -07:00
Zeno Rogue 936ddb838d
Merge pull request #261 from ammongit/goblin-text
Change goblin text to account for its presence in other lands
2021-07-21 22:39:35 +02:00
Zeno Rogue 4c0d0e2a6f
Merge pull request #262 from jruderman/pc_peril
Princess Quest no longer shows fail screen merely due to the princess being in peril
2021-07-21 22:38:53 +02:00
Jesse Ruderman 4e44dab836 Princess Quest no longer shows fail screen merely due to the princess being in peril 2021-07-21 13:24:44 -07:00
Ammon Smith 79894038d4 Join lines, add TODO for translators. 2021-07-21 13:59:58 -04:00
Ammon Smith 2afaf26e9a Change goblin flavortext to use "caves" generically. 2021-07-21 12:27:24 -04:00
Zeno Rogue 1769ec6b69 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-07-21 10:51:40 +02:00
Zeno Rogue cc18251160 rogueviz::embeddings:: mark_signposts_subg 2021-07-21 10:51:06 +02:00
Zeno Rogue 8b3ea9031a nil:: fixed a possible crash due to missing compute_hept() 2021-07-21 10:49:48 +02:00
Zeno Rogue 4425556ebc gp:: conj() function for gp::loc 2021-07-21 10:49:09 +02:00
Zeno Rogue 9941d602f6
Merge pull request #246 from Quuxplusone/adc
Adc
2021-07-21 10:20:41 +02:00
Zeno Rogue 79bc004b2b
Merge pull request #256 from jruderman/dc_far
Prevent dice overlap after an animated die rolls away
2021-07-21 10:16:15 +02:00
Zeno Rogue cbb98436a1
Merge pull request #257 from jruderman/dc_geom
Fix Dice Reserve crash in geometries that support d6/d12
2021-07-21 10:15:53 +02:00
Zeno Rogue eedca281ef
Merge pull request #250 from jruderman/mirror_p
Palace no longer generates monsters on mirrors
2021-07-21 10:15:31 +02:00
Zeno Rogue 994b3b9122
Merge pull request #253 from jruderman/regroup_at_8
Hunting Dogs now notify stragglers of failed ambushes
2021-07-21 10:15:11 +02:00
Zeno Rogue 748d8bcf3a
Merge pull request #258 from jruderman/describe_dice_2
Show dice type/value on mouseover
2021-07-21 10:13:58 +02:00
Zeno Rogue 037528a50c
Merge pull request #259 from blargdag/ru_adj
Fix wrong Russian adjective ending.
2021-07-21 10:13:26 +02:00
blargdag b24d82307b Fix wrong Russian adjective ending. 2021-07-20 15:36:58 -07:00
Jesse Ruderman 362c6f673f Show dice type/value on mouseover 2021-07-20 07:00:48 -07:00
Jesse Ruderman 9ac1f2577a Fix Dice Reserve crash in geometries that support d6/d12 2021-07-20 05:50:02 -07:00
Jesse Ruderman ecfbe7de49 Prevent dice overlap after an animated die rolls away 2021-07-20 05:39:52 -07:00
Jesse Ruderman 7a7f2476b6 Hunting Dogs now notify stragglers of failed ambushes 2021-07-20 00:45:16 -07:00
Zeno Rogue cb2d24aca9
Merge pull request #251 from blargdag/freefall2
Translate more strings from Free Fall.
2021-07-20 09:29:38 +02:00
blargdag 9624ff1ee7 Translate more strings from Free Fall. 2021-07-19 15:54:23 -07:00
Zeno Rogue d765104f7f
Merge pull request #249 from jruderman/ruin_treas
Ruined City treasure now increases with the correct kill types
2021-07-19 20:54:50 +02:00
Zeno Rogue c1fd437a11
Merge pull request #248 from jruderman/turretb
Cursed Canyon no longer generates monsters in walls
2021-07-19 20:54:16 +02:00
Jesse Ruderman c894e8dd61 Palace no longer generates monsters on mirrors 2021-07-19 03:33:50 -07:00
Jesse Ruderman 01509406a3 Ruined City treasure now increases with the correct kill types 2021-07-19 02:28:29 -07:00
Jesse Ruderman 6b781bc0d8 Cursed Canyon no longer generates monsters in walls 2021-07-19 02:14:01 -07:00
Arthur O'Dwyer 67a54d3aa1 Finish replacing macro ADC with plain old code. 2021-07-18 17:43:03 -04:00
Arthur O'Dwyer d606c3183b Replace hr::find_or_null with hr::at_or_null. 2021-07-18 17:43:03 -04:00
Arthur O'Dwyer 3c8a9e5274 Replace macro ADC with a plain old function hr::span_at. 2021-07-18 17:30:07 -04:00
Arthur O'Dwyer 74052ef2bf Replace IF_KEY_EXISTS with a plain old function, not a macro. 2021-07-18 17:21:38 -04:00
Zeno Rogue 8c6aba5f6f
Merge pull request #242 from jruderman/slaying_cursed
Allow Orb of Slaying to appear in Cursed Canyon as a prize orb
2021-07-18 18:35:21 +02:00
Zeno Rogue 65065c7e69 Merge branch 'master' of https://github.com/zenorogue/hyperrogue 2021-07-18 18:33:02 +02:00
Zeno Rogue 81e066d0c3 gp:: replaced the magic constants 15, 16, 31, 32 with named constants derived from GOLDBERG_BITS 2021-07-18 18:32:50 +02:00
Zeno Rogue 5a8e31c626
Merge pull request #237 from jruderman/wcheat
Starting in a non-basic land with -W now enables cheat mode
2021-07-18 12:25:51 +02:00
Zeno Rogue 3ae26f5888
Merge pull request #238 from jruderman/a2
Autoplay improvements 2
2021-07-18 12:25:04 +02:00
Zeno Rogue 4dfedc421d
Merge pull request #240 from jruderman/ally_rose
Rose scent can now force the player's allies to walk into rosebushes
2021-07-18 12:23:53 +02:00
Zeno Rogue 7f3382c08f
Merge pull request #241 from jruderman/mutivy_stun
ASCII monsters: don't draw stun stars for Mutant Ivy
2021-07-18 12:23:30 +02:00
Zeno Rogue 933e789d9a
Merge pull request #236 from blargdag/frogpark
Translation of Frog Park strings.
2021-07-18 12:23:16 +02:00
Zeno Rogue d0e6ac7d48
Merge pull request #243 from jruderman/woods_bull
Allow Orb of the Woods to appear in Bull Dash as a prize orb
2021-07-18 12:22:37 +02:00
Zeno Rogue 196510d788
Merge pull request #245 from jruderman/weak_hp
Weak attacks no longer affect enemy HP
2021-07-18 12:22:17 +02:00
Zeno Rogue e567fa2033 IF_KEY_EXISTS used in util.cpp 2021-07-18 12:19:49 +02:00
Zeno Rogue cd60b0ffb3 renamed IF_MAP_CONTAINS_KEY to IF_KEY_EXISTS, and used a better implementation 2021-07-18 12:19:49 +02:00
Zeno Rogue 18c6aa7823 ADC now checks IF_MAP_CONTAINS_KEY 2021-07-18 11:53:35 +02:00
Zeno Rogue ef8b24ff2a added IF_MAP_CONTAINS_KEY macro 2021-07-18 11:53:18 +02:00
Zeno Rogue cebb0180a5 kohonen:: triangulate in 3D manifolds 2021-07-18 11:40:03 +02:00
Zeno Rogue 04c9bd193a rogueviz:: added a header for kohonen.cpp and (newly added) embeddings.cpp 2021-07-18 11:38:45 +02:00
Zeno Rogue 0fc8dfde15 fixed generate_brm in 3D 2021-07-18 11:15:31 +02:00
Zeno Rogue 6cf00a1c3c stop_game on 3dim variations 2021-07-18 11:15:13 +02:00
Zeno Rogue c53b60adf5 reg3:: exit -> exception 2021-07-18 11:14:29 +02:00
Zeno Rogue 0701a5e194 reg3:: removed debug that called exit while all was OK 2021-07-18 11:14:22 +02:00
Jesse Ruderman 7d2f2aad7b Weak attacks no longer affect enemy HP 2021-07-17 23:50:57 -07:00
Jesse Ruderman 877ce3771a Allow Orb of the Woods to appear in Bull Dash as a prize orb 2021-07-17 08:20:20 -07:00
Jesse Ruderman 6098b0f488 Allow Orb of Slaying to appear in Cursed Canyon as a prize orb 2021-07-17 08:13:18 -07:00
Jesse Ruderman c24e32de7c ASCII monsters: don't draw stun stars for Mutant Ivy 2021-07-17 02:24:38 -07:00
Jesse Ruderman 1f88b87154 Rose scent can now force the player's allies to walk into rosebushes 2021-07-16 09:28:47 -07:00
Jesse Ruderman 36af5f186f Autoplay improvements 2 2021-07-14 20:56:46 -07:00
Jesse Ruderman 7bf23df2dd Starting in a non-basic land with -W now enables cheat mode 2021-07-14 17:47:32 -07:00
blargdag 285605c0f2 Translation of Frog Park strings. 2021-07-14 05:44:03 -07:00
Zeno Rogue bfe81feb2c rogueviz::kohonen:: reverted unintentional revert 2021-07-14 09:22:33 +02:00
349 changed files with 637159 additions and 13256 deletions

View File

@ -17,6 +17,7 @@ fi
export CC=$GH_COMPILER
export CXX=${CC%cc}++
export CXXFLAGS_EARLY=-Werror
if [[ "$GH_BUILDSYS" == "makefile" ]]; then
make

View File

@ -1,68 +0,0 @@
name: Github CI on Android
on:
workflow_dispatch:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
android_build:
name: Test build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Validate gradle-wrapper.jar
uses: gradle/wrapper-validation-action@v1
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get -y install gcc libsdl1.2-dev libsdl-ttf2.0-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libglew-dev libpng-dev
- name: Build
run: |
cd hyperroid
./copy.sh
./gradlew assembleDebug
- name: Upload APK
uses: actions/upload-artifact@v2
with:
name: hyperroid_debug
path: hyperroid/app/build/outputs/apk/debug/app-debug.apk
android_test:
needs: android_build
name: Test-run in emulator
runs-on: macos-latest
steps:
- name: Download APK
uses: actions/download-artifact@v2
with:
name: hyperroid_debug
- name: Create a helper wait script
run: |
cat > wait-for-load.sh << ENDOFSCRIPT
#!/bin/sh
while ! adb logcat -d "HyperRogue:V" "*:S" | grep "Game initialized"
do
sleep 2
done
ENDOFSCRIPT
chmod u+x wait-for-load.sh
- name: Run in emulator
uses: ReactiveCircus/android-emulator-runner@v2.11.1
with:
api-level: 28
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -no-snapstorage -noaudio -no-boot-anim -skin 1440x2560
script: |
adb wait-for-device
adb install -t app-debug.apk
adb shell am start -W -n com.roguetemple.hyperroid/com.roguetemple.hyperroid.HyperRogue
./wait-for-load.sh
adb shell input keyevent 41 # send "M" keypress to display main menu
adb shell screencap /sdcard/hyperroid.png
adb pull /sdcard/hyperroid.png
- name: Upload screenshot
uses: actions/upload-artifact@v2
with:
name: screenshot
path: hyperroid.png

View File

@ -13,7 +13,9 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
# os: [ubuntu-latest, macos-latest]
# macos is broken for now
os: [ubuntu-latest]
compiler: [gcc, clang]
build_system: [makefile, mymake]
hyper_use_rviz: [rviz_1, rviz_0]
@ -71,13 +73,15 @@ jobs:
- name: Do a simple test
run: .github/workflows/test_simple.sh
emscripten:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: |
docker run --rm -v $(pwd):/src trzeci/emscripten make emscripten
- name: Do a simple test
run: |
ls -lAF hyper.html hyper.js hyper.wasm
# broken for now
# emscripten:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - name: Build
# run: |
# docker run --rm -v $(pwd):/src trzeci/emscripten make emscripten
# - name: Do a simple test
# run: |
# ls -lAF hyper.html hyper.js hyper.wasm

View File

@ -9,7 +9,9 @@ cat << ENDOFCMDS > .github/workflows/gdb_cmds.txt
exit 1
ENDOFCMDS
gdb --batch -x .github/workflows/gdb_cmds.txt ./hyperrogue
echo not running gdb -- not working currently
echo gdb --batch -x .github/workflows/gdb_cmds.txt ./hyperrogue
else
./hyperrogue --version
fi

View File

@ -1,192 +0,0 @@
language: cpp
dist: bionic
services:
- docker
matrix:
include:
- os: linux # Linux GCC, make
compiler: gcc
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=gcc
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
- os: linux # Linux GCC, make, no libpng
compiler: gcc
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=gcc
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=0
- os: linux # Linux GCC, make, Rogueviz
compiler: gcc
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=gcc
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
HYPERROGUE_USE_ROGUEVIZ=1
- os: linux # Linux Clang, make
compiler: clang
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
- os: linux # Linux Clang, make, Rogueviz
compiler: clang
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
HYPERROGUE_USE_ROGUEVIZ=1
- os: osx # OSX, make
osx_image: xcode12u
compiler: clang
env: >-
TRAVIS_OS_NAME=osx
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
- os: osx # OSX, make, no libpng
osx_image: xcode11.6
compiler: clang
env: >-
TRAVIS_OS_NAME=osx
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=0
- os: osx # OSX, make, Rogueviz
osx_image: xcode11.5
compiler: clang
env: >-
TRAVIS_OS_NAME=osx
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=Makefile
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
HYPERROGUE_USE_ROGUEVIZ=1
- os: linux # Linux GCC, mymake
compiler: gcc
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=gcc
TRAVIS_BUILD_SYSTEM=mymake
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
- os: linux # Linux GCC, mymake, Rogueviz
compiler: gcc
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=gcc
TRAVIS_BUILD_SYSTEM=mymake
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
HYPERROGUE_USE_ROGUEVIZ=1
- os: osx # OSX, mymake
osx_image: xcode11.4
compiler: clang
env: >-
TRAVIS_OS_NAME=osx
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=mymake
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
- os: osx # OSX, mymake, Rogueviz
osx_image: xcode11.3
compiler: clang
env: >-
TRAVIS_OS_NAME=osx
TRAVIS_COMPILER_NAME=clang
TRAVIS_BUILD_SYSTEM=mymake
HYPERROGUE_USE_GLEW=1
HYPERROGUE_USE_PNG=1
HYPERROGUE_USE_ROGUEVIZ=1
- os: linux # Emscripten
env: >-
TRAVIS_OS_NAME=linux
TRAVIS_COMPILER_NAME=emscripten
TRAVIS_BUILD_SYSTEM=emscripten
before_install:
- |-
# Install SDL
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo apt-get update -qq
sudo apt-get install -qq libsdl1.2-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew update
brew install sdl sdl_gfx sdl_mixer sdl_ttf
# work around https://stackoverflow.com/questions/51034399/ for now
(cd /usr/local/include && ln -sf SDL/SDL.h)
else
exit 'Unsupported OS'
fi
- |-
# Install GLEW if asked for
if [[ "$HYPERROGUE_USE_GLEW" == "1" ]]; then
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo apt-get install -qq libglew-dev
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew install glew
else
exit 'Unsupported OS'
fi
fi
- |-
# Install libpng if asked for
if [[ "$HYPERROGUE_USE_PNG" == "1" ]]; then
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
echo 'libpng is installed by default'
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew install libpng
else
exit 'Unsupported OS'
fi
fi
script:
- |-
make clean
if [[ "$(git status --porcelain)" ]]; then
git status
exit 'A build artifact was committed; git rm it and try again'
fi
- |-
# Build hyperrogue.
if [[ "$TRAVIS_BUILD_SYSTEM" == "Makefile" ]]; then
make
elif [[ "$TRAVIS_BUILD_SYSTEM" == "mymake" ]]; then
make mymake
if [[ "$HYPERROGUE_USE_ROGUEVIZ" == "1" ]]; then
./mymake -rv
else
./mymake
fi
mv hyper hyperrogue
elif [[ "$TRAVIS_BUILD_SYSTEM" == "emscripten" ]]; then
docker run --rm -v $(pwd):/src trzeci/emscripten make emscripten
else
exit 'Unsupported build system'
fi
- |-
# Test hyperrogue.
if [[ "$TRAVIS_BUILD_SYSTEM" == "emscripten" ]]; then
ls -lAF hyper.html hyper.js hyper.wasm
else
./hyperrogue --help
fi
- |-
make clean
if [[ "$(git status --porcelain)" ]]; then
git status
exit 'make clean did not return the repository to its pre-build state'
fi

View File

@ -15,9 +15,9 @@ ld eyepos;
#if MAXMDIM >= 4
#define S (cgi.scalefactor / 0.805578)
#define SH (cgi.scalefactor / 0.805578 * vid.height_width / 1.5)
#define SH (embedded_plane ? cgi.human_height : (cgi.scalefactor / 0.805578 * (vid.height_width / 1.5)))
#define revZ ((WDIM == 2 || prod) ? -1 : 1)
#define revZ ((WDIM == 2 || gproduct) ? -1 : 1)
hyperpoint shcenter;
@ -34,7 +34,8 @@ vector<hyperpoint> geometry_information::get_shape(hpcshape sh) {
hyperpoint get_center(const vector<hyperpoint>& vh) {
hyperpoint h = Hypc;
for(auto h1: vh) h = h + h1;
return normalize_flat(h);
h /= isize(vh);
return cgi.emb->normalize_flat(h);
}
EX ld zc(ld z) {
@ -46,9 +47,9 @@ EX ld zc(ld z) {
void geometry_information::add_cone(ld z0, const vector<hyperpoint>& vh, ld z1) {
last->flags |= POLY_TRIANGLES;
for(int i=0; i<isize(vh); i++) {
hpcpush(zpush(z0) * vh[i]);
hpcpush(zpush(z0) * vh[(i+1) % isize(vh)]);
hpcpush(zpush(z1) * shcenter);
hpcpush(lzpush(z0) * vh[i]);
hpcpush(lzpush(z0) * vh[(i+1) % isize(vh)]);
hpcpush(lzpush(z1) * shcenter);
}
}
@ -56,12 +57,12 @@ void geometry_information::add_prism_sync(ld z0, vector<hyperpoint> vh0, ld z1,
last->flags |= POLY_TRIANGLES;
for(int i=0; i<isize(vh0); i++) {
int i1 = (i+1) % isize(vh0);
hpcpush(zpush(z0) * vh0[i]);
hpcpush(zpush(z1) * vh1[i]);
hpcpush(zpush(z0) * vh0[i1]);
hpcpush(zpush(z1) * vh1[i]);
hpcpush(zpush(z0) * vh0[i1]);
hpcpush(zpush(z1) * vh1[i1]);
hpcpush(lzpush(z0) * vh0[i]);
hpcpush(lzpush(z1) * vh1[i]);
hpcpush(lzpush(z0) * vh0[i1]);
hpcpush(lzpush(z1) * vh1[i]);
hpcpush(lzpush(z0) * vh0[i1]);
hpcpush(lzpush(z1) * vh1[i1]);
}
}
@ -88,19 +89,19 @@ void geometry_information::add_prism(ld z0, vector<hyperpoint> vh0, ld z1, vecto
for(auto pp: pairs) {
int id = pp.owner;
hpcpush(zpush(z0) * lasts[0]);
hpcpush(zpush(z1) * lasts[1]);
hpcpush(zpush(id == 0 ? z0 : z1) * pp.h);
hpcpush(lzpush(z0) * lasts[0]);
hpcpush(lzpush(z1) * lasts[1]);
hpcpush(lzpush(id == 0 ? z0 : z1) * pp.h);
lasts[id] = pp.h;
}
}
void geometry_information::shift_last(ld z) {
for(int i=last->s; i<isize(hpc); i++) hpc[i] = zshift(hpc[i], z);
for(int i=last->s; i<isize(hpc); i++) hpc[i] = lzpush(z) * hpc[i];
}
void geometry_information::shift_shape(hpcshape& sh, ld z) {
for(int i=sh.s; i<sh.e; i++) hpc[i] = zshift(hpc[i], z);
for(int i=sh.s; i<sh.e; i++) hpc[i] = lzpush(z) * hpc[i];
}
void geometry_information::shift_shape_orthogonally(hpcshape& sh, ld z) {
@ -115,9 +116,19 @@ void geometry_information::add_texture(hpcshape& sh) {
auto& utt = models_texture;
sh.tinf = &utt;
sh.texture_offset = isize(utt.tvertices);
auto f = [] (hyperpoint h) {
if(!embedded_plane && gproduct) return product::inverse_exp(h);
return cgi.emb->actual_to_logical(h);
};
hyperpoint ct = Hypc;
int n = 0;
for(int i=sh.s; i<isize(hpc); i++) ct += f(hpc[i]), n++;
ct /= n;
for(int i=sh.s; i<isize(hpc); i++) {
hyperpoint h = hpc[i];
if(prod) h = product::inverse_exp(h);
hyperpoint h = f(hpc[i]) - ct;
ld rad = hypot_d(3, h);
ld factor = 0.50 + (0.17 * h[2] + 0.13 * h[1] + 0.15 * h[0]) / rad;
utt.tvertices.push_back(glhr::makevertex(0, factor, 0));
@ -127,18 +138,18 @@ void geometry_information::add_texture(hpcshape& sh) {
vector<hyperpoint> scaleshape(const vector<hyperpoint>& vh, ld s) {
vector<hyperpoint> res;
for(hyperpoint h: vh) res.push_back(normalize_flat(h * s + shcenter * (1-s)));
for(hyperpoint h: vh) res.push_back(cgi.emb->normalize_flat(h * s + shcenter * (1-s)));
return res;
}
ld get_zlevel(hyperpoint h) {
if(prod) return zlevel(h);
if(gproduct) return zlevel(h);
if(sl2) return atan2(h[2], h[3]);
return asin_auto(h[2]);
}
void geometry_information::make_ha_3d(hpcshape& sh, bool isarmor, ld scale) {
shcenter = C0;
shcenter = tile_center();
auto groin = get_shape(shHumanGroin);
auto body = get_shape(shPBodyOnly);
@ -154,13 +165,15 @@ void geometry_information::make_ha_3d(hpcshape& sh, bool isarmor, ld scale) {
auto body26 = body[26];
body.clear();
auto& T = cgi.emb->intermediate_to_logical;
bool foundplus = false, foundminus = false;
for(hyperpoint h: fullbody) {
if(h[1] > 0.14 * S) {
if((T*h)[1] > 0.14 * S) {
if(foundplus) ;
else foundplus = true, body.push_back(body7);
}
else if(h[1] < -0.14 * S) {
else if((T*h)[1] < -0.14 * S) {
if(foundminus) ;
else foundminus = true, body.push_back(body26);
}
@ -171,19 +184,20 @@ void geometry_information::make_ha_3d(hpcshape& sh, bool isarmor, ld scale) {
bool armused = false;
arm.clear();
for(hyperpoint h: fullbody) {
if(h[1] < 0.08 * S) ;
else if(h[0] > -0.03 * S) {
if((T*h)[1] < 0.08 * S) ;
else if((T*h)[0] > -0.03 * S) {
if(armused) ;
else armused = true, arm.push_back(arm8);
}
else arm.push_back(h);
}
auto hand0 = hand[0];
hand.clear();
hand.push_back(hand0);
for(hyperpoint h: fullbody) {
if(h[1] + h[0] > 0.13 * S) hand.push_back(h);
auto h1 = T*h;
if(h1[1] + h1[0] > 0.13 * S) hand.push_back(h);
}
bshape(sh, PPR::MONSTER_BODY);
@ -207,12 +221,12 @@ void geometry_information::make_ha_3d(hpcshape& sh, bool isarmor, ld scale) {
for(int i=arm0; i<arm1; i++) {
hyperpoint h = hpc[i];
ld zl = get_zlevel(h);
h = zpush(-zl) * h;
h = lzpush(-zl) * h;
ld rad = hdist0(h);
rad = (rad - 0.1124*S) / (0.2804*S - 0.1124*S);
rad = 1 - rad;
rad *= zc(0.7) - BODY;
hpc[i] = zpush(rad) * hpc[i];
hpc[i] = lzpush(rad) * hpc[i];
}
}
// 0.2804 - keep
@ -259,7 +273,7 @@ void geometry_information::addtri(array<hyperpoint, 3> hs, int kind) {
bool ok = true;
ld zzes[3];
for(int s=0; s<3; s++) {
hs[s] = normalize_flat(hs[s]);
hs[s] = cgi.emb->normalize_flat(hs[s]);
hyperpoint h = hs[s];
ld zz = zc(0.78);
hsh[s] = abs(h[1]);
@ -267,8 +281,8 @@ void geometry_information::addtri(array<hyperpoint, 3> hs, int kind) {
zz -= h[0] * h[0] / 0.10 / 0.10 * 0.01 / S / S * SH;
if(abs(h[1]) > 0.14*S) ok = false, zz -= revZ * (abs(h[1])/S - 0.14) * SH;
if(abs(h[0]) > 0.08*S) ok = false, zz -= revZ * (abs(h[0])/S - 0.08) * (abs(h[0])/S - 0.08) * 25 * SH;
h = normalize_flat(h);
if(!prod || kind != 1) ht[s] = zpush(zz) * h;
h = cgi.emb->normalize_flat(h);
if(!gproduct || kind != 1) ht[s] = lzpush(zz) * h;
else ht[s] = h;
if(hsh[s] < 0.1*S) shi[s] = 0.5;
else if(hsh[s] < 0.12*S) shi[s] = 0.1 + 0.4 * (hsh[s]/S - 0.1) / (0.12 - 0.1);
@ -285,14 +299,14 @@ void geometry_information::addtri(array<hyperpoint, 3> hs, int kind) {
htx[2][i][1] *= 1.7;
htx[4][i][0] = htx[4][i][0] * 0.4 + scalefactor * 0.1;
htx[5][i][0] = htx[5][i][0] * 0.3 + scalefactor * 0.1;
if(!prod)
if(!gproduct)
for(int a=0; a<6; a++) htx[a][i] = hpxy3(htx[a][i][0], htx[a][i][1], htx[a][i][2]);
else
for(int a=0; a<6; a++) htx[a][i] = zpush(zzes[i]) * hpxy(htx[a][i][0], htx[a][i][1]);
for(int a=0; a<6; a++) htx[a][i] = lzpush(zzes[i]) * hpxy(htx[a][i][0], htx[a][i][1]);
}
ld levels[6] = {0, 0.125, 0.125, 0.250, 0.375, 0.5};
for(int a=0; a<6; a++) for(int i=0; i<3; i++)
htx[a][i] = zpush(-min(shi[i], levels[a]) * human_height * revZ) * htx[a][i];
htx[a][i] = lzpush(-min(shi[i], levels[a]) * human_height * revZ) * htx[a][i];
hpcpush(htx[0][0]);
hpcpush(htx[0][1]);
@ -320,7 +334,7 @@ void geometry_information::addtri(array<hyperpoint, 3> hs, int kind) {
if(hdist0(h) <= 0.0501*S) {
zz += revZ * sqrt(0.0026 - pow(hdist0(h)/S, 2)) * SH;
}
hpcpush(zpush(zz) * h);
hpcpush(lzpush(zz) * h);
}
}
}
@ -376,13 +390,13 @@ void geometry_information::make_foot_3d(hpcshape& sh) {
add_cone(zc(0.4), leg5, zc(0.45));
add_texture(sh);
// shift_last(-LEG0);
for(int i=last->s; i<isize(hpc); i++) hpc[i] = cpush(0, -0.0125*S) * hpc[i];
for(int i=last->s; i<isize(hpc); i++) hpc[i] = lxpush(-0.0125*S) * hpc[i];
}
void geometry_information::make_head_only() {
auto addpt = [this] (int d, int u) {
hpcpush(zpush(zc(eyepos) + 0.06 * SH * sin(u * degree)) * xspinpush0(d * degree, 0.05 * S * cos(u * degree)));
hpcpush(lzpush(zc(eyepos) + 0.06 * SH * sin(u * degree)) * xspinpush0(d * degree, 0.05 * S * cos(u * degree)));
};
bshape(shPHeadOnly, shPHeadOnly.prio);
@ -415,7 +429,7 @@ void geometry_information::make_head_3d(hpcshape& sh) {
array<ld, 2> zero = make_array<ld>(0,0);
pts[1].emplace_back(zero);
head.push_back(C0);
head.push_back(tile_center());
bshape(sh, sh.prio);
@ -491,8 +505,15 @@ void geometry_information::make_skeletal(hpcshape& sh, ld push) {
}
hyperpoint yzspin(ld alpha, hyperpoint h) {
if(prod) return product::direct_exp(cspin(1, 2, alpha) * product::inverse_exp(h));
else return cspin(1, 2, alpha) * h;
if(embedded_plane) {
h = cgi.emb->actual_to_logical(h);
h = cspin(1, 2, alpha) * h;
h[2] *= cgi.human_height;
h = cgi.emb->logical_to_actual(h);
return h;
}
if(gproduct) return product::direct_exp(cspin(1, 2, alpha) * product::inverse_exp(h));
return cspin(1, 2, alpha) * h;
}
void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) {
@ -519,8 +540,8 @@ void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) {
void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push, ld width) {
auto body = get_shape(sh);
body.resize(isize(body) / 2);
ld fx = body[0][0];
ld lx = body.back()[0];
ld fx = cgi.emb->actual_to_logical(body[0])[0];
ld lx = cgi.emb->actual_to_logical(body.back())[0];
body.insert(body.begin(), hpxy(fx + (fx-lx) * 1e-3, 0));
body.push_back(hpxy(lx + (lx-fx) * 1e-3, 0));
int n = isize(body);
@ -541,9 +562,12 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
int cand = -1;
ld cv = 0;
for(int i=1; i<n-1; i++) if(stillin[i]) {
if((gbody[i][0] < gbody[lastid[i]][0] && gbody[i][0] < gbody[nextid[i]][0]) || (gbody[i][0] > gbody[lastid[i]][0] && gbody[i][0] > gbody[nextid[i]][0]) || abs(gbody[i][1]) > width)
if(abs(gbody[i][1]) > cv)
cand = i, cv = abs(gbody[i][1]);
auto gi = cgi.emb->actual_to_logical(gbody[i]);
auto gl = cgi.emb->actual_to_logical(gbody[lastid[i]]);
auto gn = cgi.emb->actual_to_logical(gbody[nextid[i]]);
if((gi[0] < gl[0] && gi[0] < gn[0]) || (gi[0] > gl[0] && gi[0] > gn[0]) || abs(gi[1]) > width)
if(abs(gi[1]) > cv)
cand = i, cv = abs(gi[1]);
}
if(cand == -1) break;
int i = cand;
@ -556,7 +580,11 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
for(int i=0; i<n; i++) if(!stillin[i] && !stillin[lastid[i]]) lastid[i] = lastid[lastid[i]];
for(int i=0; i<n; i++) {
if(!stillin[i]) gbody[i] = normalize_flat(gbody[lastid[i]] * (i - lastid[i]) + gbody[nextid[i]] * (nextid[i] - i));
if(!stillin[i]) {
auto gl = cgi.emb->actual_to_logical(gbody[lastid[i]]);
auto gn = cgi.emb->actual_to_logical(gbody[nextid[i]]);
gbody[i] = cgi.emb->logical_to_actual((gl * (i - lastid[i]) + gn * (nextid[i] - i)) / (nextid[i] - lastid[i]));
}
}
bshape(sh, PPR::MONSTER_BODY);
@ -596,6 +624,7 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
}
void geometry_information::clone_shape(hpcshape& sh, hpcshape& target) {
finishshape();
target = sh;
target.s = isize(hpc);
for(int i=sh.s; i<sh.e; i++) hpc.push_back(hpc[i]);
@ -606,13 +635,18 @@ void geometry_information::animate_bird(hpcshape& orig, hpcshape_animated& anima
for(int i=0; i<=WINGS; i++) {
auto& tgt = animated[i];
clone_shape(orig, tgt);
ld alpha = cos(180. * degree * i / WINGS) * 30 * degree;
ld alpha = cos(M_PI * i / WINGS) * 30 * degree;
for(int i=tgt.s; i<tgt.e; i++) {
if(abs(hpc[i][1]) > body) {
ld off = hpc[i][1] > 0 ? body : -body;
hpc[i][2] += abs(hpc[i][1] - off) * sin(alpha);
hpc[i][1] = off + (hpc[i][1] - off) * cos(alpha);
hpc[i] = normalize(hpc[i]);
hyperpoint h = hpc[i];
h = cgi.emb->actual_to_logical(hpc[i]);
if(abs(h[1]) > body) {
ld off = h[1] > 0 ? body : -body;
h[2] += abs(h[1] - off) * sin(alpha);
if(embedded_plane) h[2] *= cgi.human_height;
h[1] = off + (h[1] - off) * cos(alpha);
h = cgi.emb->logical_to_actual(h);
h = normalize(h);
hpc[i] = h;
}
}
}
@ -622,9 +656,12 @@ void geometry_information::animate_bird(hpcshape& orig, hpcshape_animated& anima
void geometry_information::slimetriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) {
dynamicval<int> d(vid.texture_step, 8);
ld sca = 1;
if(mhybrid) sca = .5;
if(cgi.emb->is_euc_in_noniso()) sca *= .3 * geom3::euclid_embed_scale;
texture_order([&] (ld x, ld y) {
ld z = 1-x-y;
ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * (hybri ? .5 : 1);
ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * sca;
hyperpoint h = direct_exp(tangent_length(a*x+b*y+c*z, r));
hpcpush(h);
});
@ -691,9 +728,10 @@ void geometry_information::make_star(hpcshape& sh, ld rad) {
ld r1 = sqrt(1 - z1*z1) * rad;
z0 *= rad;
z1 *= rad;
for(int b=0; b<360; b+=(BADMODEL?60:15)) {
int step = BADMODEL ? 60 : 15;
for(int b=0; b<360; b+=step) {
ld b0 = b * degree;
ld b1 = (b+15) * degree;
ld b1 = (b+step) * degree;
hpcsquare(
hpxy3(r0 * cos(b0), r0 * sin(b0), z0), hpxy3(r0 * cos(b1), r0 * sin(b1), z0),
hpxy3(r1 * cos(b0), r1 * sin(b0), z1), hpxy3(r1 * cos(b1), r1 * sin(b1), z1)
@ -705,18 +743,23 @@ void geometry_information::make_star(hpcshape& sh, ld rad) {
void geometry_information::make_euclidean_sky() {
bshape(cgi.shEuclideanSky, PPR::EUCLIDEAN_SKY);
for(int x=-20; x<20; x++)
for(int y=-20; y<20; y++)
for(int y=-20; y<20; y++) {
auto x0 = x * cgi.LOWSKY;
auto x1 = (x+1) * cgi.LOWSKY;
auto y0 = y * cgi.LOWSKY;
auto y1 = (y+1) * cgi.LOWSKY;
hpcsquare(
zpush(cgi.WALL) * hpxy(x, y),
zpush(cgi.WALL) * hpxy(x, y+1),
zpush(cgi.WALL) * hpxy(x+1, y),
zpush(cgi.WALL) * hpxy(x+1, y+1)
lzpush(cgi.LOWSKY) * hpxy(x0, y0),
lzpush(cgi.LOWSKY) * hpxy(x0, y1),
lzpush(cgi.LOWSKY) * hpxy(x1, y0),
lzpush(cgi.LOWSKY) * hpxy(x1, y1)
);
}
}
/** res[0] and res[1] place H on the plane, while res[2] is the altitude */
hyperpoint psmin(hyperpoint H) {
if(prod) {
if(gproduct) {
auto d = product_decompose(H);
d.second[2] = d.first;
return d.second;
@ -732,8 +775,10 @@ hyperpoint psmin(hyperpoint H) {
void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye, ld shift_head, int q, ld zoom) {
hyperpoint center = Hypc;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) center += hpc[i];
center = normalize_flat(center);
int c = 0;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) center += hpc[i], c++;
center /= c;
center = cgi.emb->normalize_flat(center);
// center /= (eye.e - eye.s);
ld rad = 0;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) rad += hdist(center, hpc[i]);
@ -746,14 +791,14 @@ void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye
vector<hyperpoint> pss;
for(int i=head.s; i<head.e; i++) pss.push_back(psmin(zpush(shift_head) * hpc[i]));
for(int i=head.s; i<head.e; i++) pss.push_back(psmin(lzpush(shift_head - cgi.emb->center_z()) * hpc[i]));
ld zmid = 0;
for(hyperpoint& h: pss) zmid += h[2];
zmid /= isize(pss);
ld mindist = 1e9;
for(int i=0; i<isize(pss); i+=3) if(pss[i][2] < zmid || (WDIM == 3 && !prod)) {
for(int i=0; i<isize(pss); i+=3) if(pss[i][2] < zmid || (WDIM == 3 && !gproduct)) {
ld d = sqhypot_d(2, pss[i]-pscenter) + sqhypot_d(2, pss[i+1]-pscenter) + sqhypot_d(2, pss[i+2]-pscenter);
if(d < mindist) mindist = d, pos = min(min(pss[i][2], pss[i+1][2]), pss[i+2][2]), qty++;
qtyall++;
@ -764,11 +809,11 @@ void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye
if(&eye == &shFamiliarEye) cgi.eyelevel_familiar = pos;
make_ball(eye, rad, 0);
transmatrix T = zpush(-shift_eye) * rgpushxto0(center) * zpush(pos);
transmatrix T = lzpush(-shift_eye) * rgpushxto0(center) * lzpush(pos);
for(int i=eye.s; i<isize(hpc); i++) hpc[i] = T * hpc[i];
int s = isize(hpc);
if(&eye == &shSkullEyes)
for(int i=eye.s; i<s; i++) hpc[i] = xpush(0.07 * scalefactor) * hpc[i];
for(int i=eye.s; i<s; i++) hpc[i] = lxpush(0.07 * scalefactor) * hpc[i];
if(q == 2)
for(int i=eye.s; i<s; i++) {
hpcpush(MirrorY * hpc[i]);
@ -782,22 +827,22 @@ void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye
}
void geometry_information::shift_last_straight(ld z) {
for(int i=last->s; i<isize(hpc); i++) hpc[i] = zpush(z) * hpc[i];
for(int i=last->s; i<isize(hpc); i++) hpc[i] = lzpush(z) * hpc[i];
}
EX void queueball(const shiftmatrix& V, ld rad, color_t col, eItem what) {
if(what == itOrbSpeed) {
shiftmatrix V1 = V * cspin(1, 2, M_PI/2);
shiftmatrix V1 = V * cspin90(1, 2);
ld tt = ptick(100);
for(int t=0; t<5; t++) {
for(int a=-50; a<50; a++)
curvepoint(cspin(0, 2, a * M_PI/100.) * cspin(0, 1, t * 72 * degree + tt + a*2*M_PI/50.) * xpush0(rad));
curvepoint(cspin(0, 2, a * M_PI/100.) * cspin(0, 1, t * 72._deg + tt + a*TAU/50.) * xpush0(rad));
queuecurve(V1, col, 0, PPR::LINE);
}
return;
}
ld z = 63.43 * degree;
shiftmatrix V1 = V * cspin(0, 2, M_PI/2);
shiftmatrix V1 = V * cspin90(0, 2);
if(what == itOrbShield) V1 = V * cspin(0, 1, ptick(500));
if(what == itOrbFlash) V1 = V * cspin(0, 1, ptick(1500));
if(what == itOrbShield) V1 = V * cspin(1, 2, ptick(1000));
@ -821,7 +866,7 @@ EX void queueball(const shiftmatrix& V, ld rad, color_t col, eItem what) {
line(a, c);
line(a, d);
line(d, c);
line(c, spin(M_PI));
line(c, spin180());
}
}
@ -835,7 +880,7 @@ void geometry_information::make_3d_models() {
if(GDIM == 2 || noGUI) return;
eyepos = WDIM == 2 ? 0.875 : 0.925;
DEBBI(DF_POLY, ("make_3d_models"));
shcenter = C0;
shcenter = tile_center();
#if CAP_GL
if(floor_textures) {
@ -851,12 +896,13 @@ void geometry_information::make_3d_models() {
&shEagle, &shFemaleBody, &shFlailMissile, &shGadflyWing, &shGargoyleWings, &shHawk, &shJiangShi, &shKnife,
&shPBody, &shPHead, &shRaiderBody, &shReptileBody, &shSkeletonBody, &shTongue, &shTrapArrow, &shTrylobite,
&shWaterElemental, &shWolfBody, &shYeti, &shWormHead, &shWormHead, &shDragonHead, &shDragonSegment, &shDragonTail,
&shTentacleX, &shTentHead, &shILeaf[0], &shILeaf[1], &shWormSegment, &shSmallWormSegment, &shFrogBody })
&shTentacleX, &shTentHead, &shILeaf[0], &shILeaf[1], &shWormSegment, &shSmallWormSegment,
&shWormTail, &shSmallWormTail, &shFrogBody })
make_shadow(*sh);
for(int i=0; i<8; i++) make_shadow(shAsteroid[i]);
}
DEBB(DF_POLY, ("humanoids"));
make_humanoid_3d(shPBody);
make_humanoid_3d(shYeti);
@ -926,9 +972,9 @@ void geometry_information::make_3d_models() {
for(int i=shDogRearPaw.s; i<shDogRearPaw.e; i++) rear_leg += hpc[i];
front_leg = normalize(front_leg);
rear_leg = normalize(rear_leg);
front_leg_move = zpush(zc(0.4)) * rgpushxto0(front_leg);
front_leg_move = lzpush(zc(0.4)) * rgpushxto0(front_leg);
front_leg_move_inverse = inverse(front_leg_move);
rear_leg_move = zpush(zc(0.4)) * rgpushxto0(rear_leg);
rear_leg_move = lzpush(zc(0.4)) * rgpushxto0(rear_leg);
rear_leg_move_inverse = inverse(rear_leg_move);
leg_length = zc(0.4) - zc(0);
@ -1075,13 +1121,10 @@ void geometry_information::make_3d_models() {
make_ball(shDisk, orbsize*.2, 2);
make_ball(shHeptaMarker, zhexf*.2, 1);
make_ball(shSnowball, zhexf*.1, 1);
if(euclid) {
make_ball(shSun, 0.5, 2);
make_euclidean_sky();
}
else
make_star(shSun, 3);
make_star(shNightStar, 0.75);
make_ball(shSkyboxSun, 8 * zhexf, 2);
if(euclid) make_euclidean_sky();
make_star(shSun, vid.sun_size * zhexf);
make_star(shNightStar, vid.star_size * zhexf);
if(WDIM == 2) {
for(int i=0; i<3; i++) {
@ -1130,10 +1173,10 @@ void geometry_information::make_3d_models() {
hyperpoint atip = xtangent(-1);
ld z = 63.43 * degree;
for(int i=0; i<5; i++) {
auto a = cspin(1, 2, (72 * i ) * degree) * spin(z) * xtangent(1);
auto b = cspin(1, 2, (72 * i-72) * degree) * spin(z) * xtangent(1);
auto c = cspin(1, 2, (72 * i+36) * degree) * spin(M_PI-z) * xtangent(1);
auto d = cspin(1, 2, (72 * i-36) * degree) * spin(M_PI-z) * xtangent(1);
auto a = cspin(1, 2, (72 * i ) * degree) * cspin(0, 1, z) * xtangent(1);
auto b = cspin(1, 2, (72 * i-72) * degree) * cspin(0, 1, z) * xtangent(1);
auto c = cspin(1, 2, (72 * i+36) * degree) * cspin(0, 1, M_PI-z) * xtangent(1);
auto d = cspin(1, 2, (72 * i-36) * degree) * cspin(0, 1, M_PI-z) * xtangent(1);
slimetriangle(tip, a, b, 1, 0);
slimetriangle(a, b, c, 1, 0);
slimetriangle(b, c, d, 1, 0);
@ -1141,7 +1184,7 @@ void geometry_information::make_3d_models() {
}
last->flags |= POLY_TRIANGLES;
add_texture(*last);
if(WDIM == 2) shift_last_straight(FLOOR);
if(WDIM == 2) shift_last_straight(FLOOR + cgi.emb->center_z());
finishshape();
shJelly = shSlime;
@ -1219,9 +1262,9 @@ void geometry_information::make_3d_models() {
texture_order([&] (ld x, ld y) {
ld z = 1-x-y;
ld rad = 2.1 - i * 0.2;
hyperpoint hx = ddi(t*12, -zhexf*rad) * C0;
hyperpoint hy = ddi(t*12+12, -zhexf*rad) * C0;
hyperpoint hz = C0;
hyperpoint hx = ddi(t*12, -zhexf*rad) * tile_center();
hyperpoint hy = ddi(t*12+12, -zhexf*rad) * tile_center();
hyperpoint hz = tile_center();
hyperpoint h = hx * x + hy * y + hz * z;
h = mid(h, h);
h = orthogonal_move(h, FLOOR - human_height * (i+2.5) / 100 * (x+y+1)/2);
@ -1235,45 +1278,101 @@ void geometry_information::make_3d_models() {
finishshape();
}
hpcshape& geometry_information::generate_pipe(ld length, ld width) {
int id = int(length * 17 + .5) + int(157003 * log(width+.001));
if(shPipe.count(id)) return shPipe[id];
hpcshape& pipe = shPipe[id];
println(hlog, "generating pipe of length ", length, " and width ", width);
bshape(pipe, PPR::WALL);
hpcshape& geometry_information::gen_pipe(hpcshape& pipe, ePipeEnd endtype, ld ratio, const hr::function<hyperpoint(ld,ld,ld)>& f) {
cgi.bshape(pipe, PPR::WALL);
const int MAX_X = 8;
#if CAP_GL
auto& utt = cgi.models_texture;
if(floor_textures) {
pipe.tinf = &utt;
pipe.texture_offset = isize(utt.tvertices);
}
#endif
const int MAX_X = 32;
const int MAX_R = 20;
auto at = [length, width] (int i, int a) {
return xpush(i * length / MAX_X) * cspin(1, 2, 360 * degree * a / MAX_R) * ypush0(width);
auto at = [&] (ld i, ld a, ld z = 1, ld s = 1) {
a += 0.5;
ld alpha = TAU * a / MAX_R;
cgi.hpcpush(f(i / MAX_X, alpha, z));
#if CAP_GL
if(floor_textures) utt.tvertices.push_back(glhr::makevertex(0, true ? 0.549 - s * 0.45 * sin(alpha) : 0.999, 0));
#endif
};
for(int i=0; i<MAX_X; i++) {
for(int a=0; a<MAX_R; a++) {
hpcpush(at(i, a));
hpcpush(at(i, a+1));
hpcpush(at(i+1, a));
hpcpush(at(i+1, a+1));
hpcpush(at(i+1, a));
hpcpush(at(i, a+1));
at(i, a, 1);
at(i, a+1, 1);
at(i+1, a, 1);
at(i+1, a+1, 1);
at(i+1, a, 1);
at(i, a+1, 1);
}
}
for(int a=0; a<MAX_R; a++) {
hpcpush(at(MAX_X, a));
hpcpush(at(MAX_X, a+1));
hpcpush(xpush0(length));
hpcpush(at(MAX_X, a+1));
hpcpush(at(MAX_X, a));
hpcpush(C0);
if(endtype == ePipeEnd::sharp) for(int a=0; a<MAX_R; a++) for(int x: {0, MAX_X}) {
at(x, a, 1, 0);
at(x, a+1, 1, 0);
at(x, 0, 0, 0);
}
if(endtype == ePipeEnd::ball) for(int a=0; a<MAX_R; a++) for(int x=-MAX_R; x<MAX_R; x++) {
ld xb = x < 0 ? 0 : MAX_X;
ld mul = MAX_X * ratio * .9; // .9 to prevent Z-fighting
ld x0 = xb + mul * sin(x * 90._deg / MAX_R);
ld x1 = xb + mul * sin((x+1) * 90._deg / MAX_R);
ld z0 = cos(x * 90._deg / MAX_R);
ld z1 = cos((x+1) * 90._deg / MAX_R);
at(x0, a, z0, z0);
at(x0, a+1, z0, z0);
at(x1, a, z1, z1);
at(x1, a+1, z1, z1);
at(x1, a, z1, z1);
at(x0, a+1, z0, z0);
}
last->flags |= POLY_TRIANGLES | POLY_PRINTABLE;
add_texture(*last);
finishshape();
extra_vertices();
return pipe;
}
hpcshape& geometry_information::get_pipe_noniso(hyperpoint target, ld width, ePipeEnd endtype) {
int id = bucketer(target) + int(157003 * log(width+.001));
if(cgi.shPipe.count(id)) return cgi.shPipe[id];
hpcshape& pipe = cgi.shPipe[id];
hyperpoint lmax = sol ? inverse_exp_newton(target, 10) : inverse_exp(shiftless(target));
transmatrix lT;
ld length;
if(1) {
dynamicval<eGeometry> g(geometry, gCubeTiling);
length = hdist0(lmax);
lT = rspintox(lmax);
}
return gen_pipe(pipe, endtype, width/length, [&] (ld i, ld alpha, ld z) {
hyperpoint p;
if(1) {
dynamicval<eGeometry> g(geometry, gCubeTiling);
p = xpush(i * length) * cspin(1, 2, alpha) * ypush0(width*z);
p = lT * p;
}
return direct_exp(p);
});
}
hpcshape& geometry_information::get_pipe_iso(ld length, ld width, ePipeEnd endtype) {
int id = int(length * 172 + .5) + int(157003 * log(width+.001));
bool pers = in_perspective();
if(!pers) id ^= 0x4126891;
if(shPipe.count(id)) return shPipe[id];
hpcshape& pipe = shPipe[id];
println(hlog, "generating pipe of length ", length, " and width ", width);
return gen_pipe(pipe, endtype, width/length, [&] (ld i, ld alpha, ld z) { return xpush(i * length) * cspin(1, 2, alpha) * ypush0(width*z); });
}
#undef S
#undef SH
#undef revZ

33
CITATION.cff Normal file
View File

@ -0,0 +1,33 @@
cff-version: 1.2.0
message: "If you use RogueViz in your research, please cite it as below. Please also cite the 2017 paper about HyperRogue (see https://archive.bridgesmathart.org/2017/bridges2017-9.html for BibTeX)."
authors:
- family-names: "Kopczyński"
given-names: "Eryk"
orcid: "https://orcid.org/0000-0001-5588-1181"
- family-names: "Celińska-Kopczyńska"
given-names: "Dorota"
orcid: "https://orcid.org/0000-0001-5910-0039"
title: "RogueViz: non-Euclidean geometry engine for visualizations, games, math art, and research"
type: software
version: 12.0f
date-released: 2021-08-05
url: "https://github.com/zenorogue/hyperrogue/"
references:
- authors:
- family-names: Kopczyński
given-names: Eryk
- family-names: Celińska
given-names: Dorota
- family-names: Čtrnáct
given-names: Marek
title: "HyperRogue: Playing with Hyperbolic Geometry"
pages: "9--16"
collection-title: "Proceedings of Bridges 2017: Mathematics, Art, Music, Architecture, Education, Culture"
year: 2017
editor: "Swart, David and S\\'equin, Carlo H. and Fenyvesi, Krist\\'of"
isbn: "978-1-938664-22-9"
issn: "1099-6702"
publisher: "Tessellations Publishing, Phoenix, Arizona"
note: "Available online at \\url{http://archive.bridgesmathart.org/2017/bridges2017-9.pdf}"
type: article

View File

@ -1,16 +1,24 @@
# This Makefile works for Mac OS X (El Capitan), MinGW, and Linux.
#
# Environmental vairables:
# If you want to build with Glew, set
# HYPERROGUE_USE_GLEW=1
# If you want to use libpng, set
# HYPERROGUE_USE_PNG=1
#
# For Mac OS X:
# Run "brew install sdl" to install SDL in /usr/local.
# Run "brew install sdl_gfx".
# Run "brew install sdl_mixer".
# Run "brew install sdl_ttf".
# Run "make" to build HyperRogue as ./hyperrogue.
# Run `brew install sdl12-compat sdl_gfx sdl_mixer sdl_ttf`
# Run `brew install glew libpng` to install the optional dependencies
# Run `make` to build HyperRogue as `./hyperrogue`.
#
# For MSYS2 and MinGW-w64:
# You might need to run commands such as "pacman -S mingw-w64-x86_64-SDL"
# to install SDL and other required libraries.
# Run "make" to build HyperRogue as ./hyperrogue.exe.
# To install SDL and other required libraries, run these commands
# from the MSYS2 shell:
# pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-glew
# pacman -S mingw-w64-ucrt-x86_64-SDL mingw-w64-ucrt-x86_64-SDL_mixer
# pacman -S mingw-w64-ucrt-x86_64-SDL_ttf mingw-w64-ucrt-x86_64-SDL_gfx
# pacman -S make
# Then run "make" to build HyperRogue as ./hyperrogue.exe.
#
# For Ubuntu Linux:
# Run "sudo apt-get install libsdl-dev" to install SDL in /usr/local.
@ -54,7 +62,7 @@ ifeq (${OS},linux)
endif
ifeq (${OS},mingw)
CXXFLAGS_EARLY += -DWINDOWS -mwindows -D_A_VOLID=8
CXXFLAGS_EARLY += -DWINDOWS -mwindows -D_A_VOLID=8 -I/ucrt64/include/SDL
EXE_EXTENSION := .exe
LDFLAGS_GL := -lopengl32
LDFLAGS_GLEW := -lglew32
@ -68,9 +76,10 @@ ifeq (${OS},mingw)
endif
ifeq (${OS},osx)
CXXFLAGS_EARLY += -DMAC -I/usr/local/include
HOMEBREW_PREFIX := $(shell brew --prefix)
CXXFLAGS_EARLY += -DMAC -I$(HOMEBREW_PREFIX)/include -I$(HOMEBREW_PREFIX)/include/SDL
EXE_EXTENSION :=
LDFLAGS_EARLY += -L/usr/local/lib
LDFLAGS_EARLY += -L$(HOMEBREW_PREFIX)/lib
LDFLAGS_GL := -framework AppKit -framework OpenGL
LDFLAGS_GLEW := -lGLEW
LDFLAGS_PNG := -lpng
@ -80,27 +89,32 @@ ifeq (${OS},osx)
endif
ifeq (${TOOLCHAIN},clang)
CXXFLAGS_STD = -std=c++11
CXXFLAGS_EARLY += -march=native -fPIC
CXXFLAGS_EARLY += -W -Wall -Wextra -Wsuggest-override -Werror -pedantic
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized -Wno-unknown-warning-option
CXXFLAGS_STD = -std=c++14
CXXFLAGS_EARLY += -fPIC
CXXFLAGS_EARLY += -W -Wall -Wextra -Wsuggest-override -pedantic
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized -Wno-char-subscripts -Wno-unknown-warning-option
CXXFLAGS_EARLY += -Wno-invalid-offsetof
endif
ifeq (${TOOLCHAIN},gcc)
CXXFLAGS_STD = -std=c++11
CXXFLAGS_EARLY += -march=native -fPIC
CXXFLAGS_EARLY += -W -Wall -Wextra -Werror -pedantic
CXXFLAGS_STD = -std=c++14
CXXFLAGS_EARLY += -fPIC
CXXFLAGS_EARLY += -W -Wall -Wextra -pedantic
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized
CXXFLAGS_EARLY += -Wno-invalid-offsetof
endif
ifeq (${TOOLCHAIN},mingw)
CXXFLAGS_STD = -std=c++11
CXXFLAGS_EARLY += -march=native
CXXFLAGS_EARLY += -W -Wall -Wextra -Werror
CXXFLAGS_STD = -std=c++14
CXXFLAGS_EARLY += -W -Wall -Wextra
CXXFLAGS_EARLY += -Wno-unused-parameter -Wno-implicit-fallthrough -Wno-maybe-uninitialized
CXXFLAGS_EARLY += -Wno-invalid-offsetof
endif
ifeq (${FONTCONFIG},1)
CXXFLAGS_EARLY += -DFONTCONFIG `pkg-config --cflags fontconfig`
LDFLAGS_EARLY += `pkg-config --libs fontconfig`
endif
## We have now finished OS-specific and TOOLCHAIN-specific computations.
## Begin customization points for user-specifiable HYPERROGUE_USE_XXX macros.
@ -154,7 +168,7 @@ makeh$(EXE_EXTENSION): makeh.cpp
$(CXX) -O2 makeh.cpp -o $@
autohdr.h: makeh$(EXE_EXTENSION) language-data.cpp *.cpp
./makeh classes.cpp locations.cpp colors.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp util.cpp complex.cpp *.cpp > autohdr.h
./makeh classes.cpp locations.cpp colors.cpp hyperpoint.cpp geometry.cpp embeddings.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp util.cpp complex.cpp multigame.cpp arbitrile.cpp rulegen.cpp *.cpp > autohdr.h
language-data.cpp: langen$(EXE_EXTENSION)
./langen > language-data.cpp
@ -168,7 +182,7 @@ mymake$(EXE_EXTENSION): mymake.cpp
emscripten: hyper.html
%.html %.js %.wasm: %.emscripten-sources
emcc -std=c++11 -O3 -s USE_ZLIB=1 -s LEGACY_GL_EMULATION=1 -s TOTAL_MEMORY=128MB hyperweb.cpp -o hyper.html
emcc -std=c++14 -O3 -s USE_ZLIB=1 -s LEGACY_GL_EMULATION=1 -s TOTAL_MEMORY=128MB hyperweb.cpp -o hyper.html
hyper.emscripten-sources: *.cpp autohdr.h

View File

@ -63,7 +63,7 @@ savepng-loc.o: savepng.cpp
hyper-rogueviz.o: hyper.cpp graph.cpp hyperpoint.cpp geometry.cpp cell.cpp heptagon.cpp game.cpp classes.cpp polygons.cpp language.cpp language-data.cpp achievement.cpp shmup.cpp patterns.cpp mapeditor.cpp netgen.cpp yendor.cpp hyper.h rug.cpp flags.cpp system.cpp landgen.cpp orbs.cpp complex.cpp conformal.cpp menus.cpp init.cpp dialogs.cpp sound.cpp util.cpp ${drogueviz} fieldpattern.cpp ${MAIN} control.cpp commandline.cpp
${CXX} ${PROF} ${MAIN} -c -o hyper-rogueviz.o ${MYFLAGS}
langen: langen.cpp language-cz.cpp language-pl.cpp language-tr.cpp language-ru.cpp language-de.cpp
langen: langen.cpp language-cz.cpp language-pl.cpp language-tr.cpp language-ru.cpp language-de.cpp language-ptbr.cpp language-fr.cpp
${CXX} langen.cpp -o langen -g
language-data.cpp: langen

View File

@ -1,14 +1,4 @@
# HyperRogue
<p align="right">
<a href="https://travis-ci.org/zenorogue/hyperrogue/builds">
<img align="right" src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=Makefile&label=make" alt="TravisCI badge">
<img align="right" src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=mymake&label=mymake" alt="TravisCI badge">
<img align="right" src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=emscripten&label=web" alt="TravisCI badge">
</a>
</p>
<p align="left">
<b>Current version: 11.3f</b>
</p>
A puzzle roguelike in the hyperbolic plane. See the [HyperRogue website](http://roguetemple.com/z/hyper.php) for detailed and most up-to-date information.
Compiled executables can be downloaded from [itch.io](https://zenorogue.itch.io/hyperrogue) and from the [HyperRogue website](http://www.roguetemple.com/z/hyper/download.php).
@ -48,8 +38,12 @@ You can aim for the Orb of Yendor, or you can simply aim for as high score as po
## Modifications
OK, now lots of the above can be changed. You can change the geometry and topology (to Euclidean, spherical, or even to nonisotropic 3D geometries). You can play challenges based on
various in-game quests, and even try some other game genres in non-Euclidean spaces (roguelite aka shmup, racing, peaceful puzzles). Or use the engine for non-Euclidean computations
and visualizations (see [RogueViz](http://roguetemple.com/z/hyper/rogueviz.php)). Have fun!
various in-game quests, and even try some other game genres in non-Euclidean spaces (roguelite aka shmup, racing, peaceful puzzles).
## RogueViz
HyperRogue uses [RogueViz](http://roguetemple.com/z/hyper/rogueviz.php), which is our engine for non-Euclidean games, computations and visualizations. This repo includes the source code of RogueViz demos in subdirectory `rogueviz`, but
not the data, which is available on [itch.io](https://zenorogue.itch.io/rogueviz). RogueViz is funded by the National Science Centre, Poland, grant UMO-2019/35/B/ST6/04456.
## Development ##
@ -61,22 +55,25 @@ On Linux with apt-get:
On macOS with Homebrew:
```brew install sdl sdl_ttf sdl_gfx sdl_mixer glew```
macOS users might also have to edit /usr/local/include/SDL/SDL_gfxPrimitives.h at line 38 to use quote include.
```brew install sdl sdl_ttf sdl_gfx sdl_mixer glew libpng```
### Building HyperRogue from source ###
```
git clone https://github.com/zenorogue/hyperrogue.git hyperrogue
cd hyperrogue
make
HYPERROGUE_USE_GLEW=1 HYPERROGUE_USE_PNG=1 make
```
The `mymake` program builds HyperRogue in parts. It takes longer than the method shown above, but it uses significantly less memory during compilation, and when you change something, `mymake` will only recompile the changed file.
Additionally, it can be easily configured, e.g., to produce an optimized build, or to include addons (see `mymake.cpp` for some example invocations, and `devmods` for some example addons).
Most useful parameters include `-O3` (optimized build), `-rv` (include the RogueViz demos), `-vr` (build the VR version). Compiler flags like `-Werror` (treat warnings as errors) and `-march=native` work too.
```
make mymake && ./mymake
```
The source code is not documented very well. You can see the current state of the documentation, as generated by Doxygen, [here](https://zenorogue.github.io/hyperrogue-doc/).
## Discussion ##
The best place to discuss HyperRogue is our [Discord server|https://discord.com/invite/8G44XkR].

View File

@ -10,7 +10,9 @@
#include "hyper.h"
namespace hr {
#define NUMLEADER 87
#if HDR
#define NUMLEADER 90
#endif
EX bool test_achievements = false;
@ -80,12 +82,33 @@ EX const char* leadernames[NUMLEADER] = {
"Lazurite Figurines", // 83
"Water Lilies", // 84
"Capon Stones", // 85
"Crystal Dice" // 86
"Crystal Dice", // 86
"Crossbow (bull)", // 87
"Crossbow (geodesic)", // 88
"Crossbow (geometric)", // 89
};
#if HDR
#define LB_PRINCESS 36
#define LB_STATISTICS 62
#define LB_HALLOWEEN 63
#define LB_HALLOWEEN 63
#define LB_YENDOR_CHALLENGE 40
#define LB_PURE_TACTICS 41
#define LB_PURE_TACTICS_SHMUP 49
#define LB_PURE_TACTICS_COOP 50
#define LB_RACING 81
#endif
EX void achievement_init();
EX string myname();
EX void achievement_close();
EX void achievement_pump();
/** gain the given achievement.
* @param s name of the achievement, e.g., DIAMOND1
* @param flags one of the constants from namespace rg. The achievement is only awarded if special modes are matched exactly.
*/
EX void achievement_gain(const char* s, char flags IS(0));
EX bool haveLeaderboard(int id);
EX int get_currentscore(int id);
@ -93,11 +116,11 @@ EX void set_priority_board(int id);
EX int get_sync_status();
EX bool score_loaded(int id);
EX int score_default(int id);
EX void improveItemScores();
EX void upload_score(int id, int v);
string achievementMessage[3];
int achievementTimer;
EX string achievementMessage[3];
EX int achievementTimer;
/** achievements received this game */
EX vector<string> achievementsReceived;
@ -108,11 +131,15 @@ EX bool wrongMode(char flags) {
if(cheater) return true;
if(casual) return true;
if(flags == rg::global) return false;
if(flags == rg::fail) return true;
if(flags != rg::special_geometry) {
if(flags != rg::special_geometry && flags != rg::special_geometry_nicewalls) {
if(!BITRUNCATED) return true;
if(geometry != gNormal) return true;
if(disksize) return true;
}
if(ineligible_starting_land && !flags) return true;
if(use_custom_land_list) return true;
if(shmup::on != (flags == rg::shmup || flags == rg::racing)) return true;
if(racing::on != (flags == rg::racing)) return true;
@ -124,16 +151,24 @@ EX bool wrongMode(char flags) {
if(yendor::on) return true;
if(peace::on) return true;
if(tactic::on) return true;
if(dpgen::in) return true;
#if CAP_TOUR
if(tour::on) return true;
#endif
if(flags == rg::special_geometry && !ls::single())
return true;
if(flags != rg::special_geometry && ineligible_starting_land)
return true;
if(flags == rg::chaos && !ls::std_chaos()) return true;
if(flags != rg::chaos && flags != rg::special_geometry && !ls::nice_walls()) return true;
eLandStructure dls = lsNiceWalls;
if(flags == rg::princess && !princess::challenge) return true;
if(flags == rg::special_geometry || flags == rg::princess)
dls = lsSingle;
if(flags == rg::chaos)
dls = lsChaos;
/* in the official racing achievements, the tracks are saved maps anyway */
if(flags == rg::racing)
dls = land_structure;
if(land_structure != dls) return true;
if(shmup::on && vid.creature_scale != 1) return true;
if(numplayers() > 1 && !multi::friendly_fire) return true;
if(numplayers() > 1 && multi::pvp_mode) return true;
if(numplayers() > 1 && multi::split_screen) return true;
if((numplayers() > 1) != (flags == rg::multi)) return true;
return false;
}
@ -151,6 +186,25 @@ EX void achievement_gain_once(const string& s, char flags IS(0)) {
achievement_gain(s.c_str(), flags);
}
namespace rg {
char check(bool b, char val = special_geometry) { return b ? val : fail; }
}
EX char specgeom_zebra() { return rg::check(geometry == gZebraQuotient && !disksize && BITRUNCATED && firstland == laDesert); }
EX char specgeom_lovasz() { return rg::check(geometry == gKleinQuartic && variation == eVariation::untruncated && gp::param == gp::loc(1,1) && !disksize && in_lovasz()); }
EX char specgeom_halloween() { return rg::check((geometry == gSphere || geometry == gElliptic) && BITRUNCATED && !disksize && firstland == laHalloween); }
EX char specgeom_heptagonal() { return rg::check(PURE && geometry == gNormal && !disksize, rg::special_geometry_nicewalls); }
EX char specgeom_euclid_gen() { return rg::check(geometry == gEuclid && !disksize && firstland == laMirrorOld); }
EX char specgeom_crystal1() { return rg::check(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside && !disksize && firstland == laCamelot); }
EX char specgeom_crystal2() { return rg::check(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside && !disksize && firstland == laCamelot); }
EX vector<std::function<char()>> all_specgeom_checks = { specgeom_zebra, specgeom_lovasz, specgeom_halloween, specgeom_heptagonal, specgeom_crystal1, specgeom_crystal2, specgeom_euclid_gen };
EX char any_specgeom() {
for(auto chk: all_specgeom_checks) if(chk() != rg::fail) return chk();
return rg::fail;
}
EX void achievement_log(const char* s, char flags) {
if(wrongMode(flags)) {
@ -170,7 +224,7 @@ EX void achievement_log(const char* s, char flags) {
#if CAP_SAVE
remove_emergency_save();
FILE *f = fopen(scorefile, "at");
FILE *f = fopen(scorefile.c_str(), "at");
if(!f) return;
int t = (int) (time(NULL) - timerstart);
@ -185,29 +239,24 @@ EX void achievement_log(const char* s, char flags) {
#endif
}
EX void achievement_init();
EX string myname();
EX void achievement_close();
#ifndef LEADER
#define LEADER "Unknown"
#define LEADERFULL "Unknown"
#endif
/** gain the given achievement.
* @param s name of the achievement, e.g., DIAMOND1
* @param flags one of the constants from namespace rg. The achievement is only awarded if special modes are matched exactly.
*/
EX void achievement_gain(const char* s, char flags IS(0));
#if ISSTEAM
void improveItemScores();
#include "private/hypersteam.cpp"
#elif !ISANDROID && !ISIOS
#if !CAP_ACHIEVE
void achievement_init() {}
string myname() { return "Rogue"; }
void achievement_close() {}
// gain the achievement with the given name.
// flags: 'e' - for Euclidean, 's' - for Shmup, '7' - for heptagonal
// Only awarded if special modes are matched exactly.
void achievement_gain(const char* s, char flags IS(0)) {
void achievement_gain(const char* s, char flags) {
achievement_log(s, flags);
}
void achievement_pump() {}
EX int get_sync_status() { return 0; }
EX void set_priority_board(int) { }
#endif
// gain the achievement for collecting a number of 'it'.
@ -221,11 +270,11 @@ EX void achievement_collection2(eItem it, int q) {
if(randomPatternsMode) return;
LATE( achievement_collection2(it, q); )
if(it == itTreat && q == 50 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED)
achievement_gain("HALLOWEEN1", rg::special_geometry);
if(it == itTreat && q == 50)
achievement_gain("HALLOWEEN1", specgeom_halloween());
if(it == itTreat && q == 100 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED)
achievement_gain("HALLOWEEN2", rg::special_geometry);
if(it == itTreat && q == 100)
achievement_gain("HALLOWEEN2", specgeom_halloween());
if(q == 1) {
if(it == itDiamond) achievement_gain("DIAMOND1");
@ -305,13 +354,10 @@ EX void achievement_collection2(eItem it, int q) {
// 32
if(it == itHolyGrail) {
if(q == 1) achievement_gain("GRAIL2");
if(PURE && geometry == gNormal)
achievement_gain("GRAILH", rg::special_geometry);
achievement_gain("GRAILH", specgeom_heptagonal());
#if CAP_CRYSTAL
if(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside)
achievement_gain("GRAIL4D", rg::special_geometry);
if(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside)
achievement_gain("GRAIL4D2", rg::special_geometry);
achievement_gain("GRAIL4D", specgeom_crystal1());
achievement_gain("GRAIL4D2", specgeom_crystal2());
#endif
if(q == 3) achievement_gain("GRAIL3");
if(q == 8) achievement_gain("GRAIL4");
@ -595,14 +641,18 @@ EX void achievement_count(const string& s, int current, int prev) {
achievement_gain("LIGHTNING2");
if(s == "LIGHTNING" && current-prev >= 10)
achievement_gain("LIGHTNING3");
if(s == "MIRAGE" && current >= 35 && geometry == gEuclid)
achievement_gain("MIRAGE", rg::special_geometry);
if(s == "MIRAGE" && current >= 35)
achievement_gain("MIRAGE", specgeom_euclid_gen());
if(s == "ORB" && current >= 10)
achievement_gain("ORB3");
if(s == "BUG" && current >= 1000)
achievement_gain("BUG3");
if(s == "ELEC" && current >= 10)
achievement_gain("ELEC3");
if(s == "BOWVARIETY" && current >= 2)
achievement_gain("BOWVARIETY1");
if(s == "BOWVARIETY" && current >= 6)
achievement_gain("BOWVARIETY2");
}
int specific_improved = 0;
@ -611,7 +661,7 @@ int specific_what = 0;
EX void improve_score(int i, eItem what) {
if(offlineMode) return;
LATE( improve_score(i, what); )
#ifdef HAVE_ACHIEVEMENTS
#if CAP_ACHIEVE
if(haveLeaderboard(i)) updateHi(what, get_currentscore(i));
if(items[what] && haveLeaderboard(i)) {
if(items[what] > get_currentscore(i) && score_loaded(i)) {
@ -625,10 +675,11 @@ EX void improve_score(int i, eItem what) {
// scores for special challenges
EX void achievement_score(int cat, int number) {
if(offlineMode) return;
#ifdef HAVE_ACHIEVEMENTS
#if CAP_ACHIEVE
if(cheater) return;
if(casual) return;
LATE( achievement_score(cat, number); )
if(disksize) return;
if(cat == LB_HALLOWEEN) {
if(geometry != gSphere && geometry != gElliptic)
return;
@ -645,6 +696,8 @@ EX void achievement_score(int cat, int number) {
if(tactic::on && cat != LB_PURE_TACTICS && cat != LB_PURE_TACTICS_SHMUP && cat != LB_PURE_TACTICS_COOP)
return;
if(racing::on && cat != LB_RACING) return;
if(bow::weapon) return;
if(use_custom_land_list) return;
upload_score(cat, number);
#endif
}
@ -728,7 +781,7 @@ EX void achievement_final(bool really_final) {
LATE( achievement_final(really_final); )
#ifdef HAVE_ACHIEVEMENTS
#if CAP_ACHIEVE
if(ticks > next_stat_tick) {
upload_score(LB_STATISTICS, time(NULL));
next_stat_tick = ticks + 600000;
@ -766,6 +819,10 @@ EX void achievement_final(bool really_final) {
if(PURE) specialcode+=4;
if(numplayers() > 1) specialcode+=8;
if(inv::on) specialcode+=16;
if(bow::crossbow_mode() && bow::style == bow::cbBull) specialcode += 32;
if(bow::crossbow_mode() && bow::style == bow::cbGeodesic) specialcode += 64;
if(bow::crossbow_mode() && bow::style == bow::cbGeometric) specialcode += 96;
if(shmup::on && vid.creature_scale != 1) return;
if(sphere && specialland == laHalloween) {
if(specialcode) return;
@ -776,6 +833,11 @@ EX void achievement_final(bool really_final) {
if(ineligible_starting_land) return;
if(geometry) return;
if(NONSTDVAR) return;
if(use_custom_land_list) return;
if(numplayers() > 1 && !multi::friendly_fire) return;
if(numplayers() > 1 && multi::pvp_mode) return;
if(numplayers() > 1 && multi::split_screen) return;
// determine the correct leaderboard ID for 'total score'
// or return if no leaderboard for the current mode
@ -788,6 +850,9 @@ EX void achievement_final(bool really_final) {
case 8: sid = 61; break;
case 9: sid = 44; break;
case 16: sid = 69; break;
case 32: sid = 87; break;
case 64: sid = 88; break;
case 96: sid = 89; break;
default: return;
}
@ -851,9 +916,10 @@ EX void check_total_victory() {
EX void achievement_victory(bool hyper) {
DEBBI(DF_STEAM, ("achievement_victory"))
if(offlineMode) return;
#ifdef HAVE_ACHIEVEMENTS
#if CAP_ACHIEVE
if(cheater) return;
if(casual) return;
if(bow::weapon) return;
if(geometry) return;
if(CHANGED_VARIATION) return;
if(randomPatternsMode) return;
@ -862,7 +928,8 @@ EX void achievement_victory(bool hyper) {
if(peace::on) return;
if(tactic::on) return;
if(!ls::nice_walls()) return;
if(!ineligible_starting_land) return;
if(ineligible_starting_land) return;
if(use_custom_land_list) return;
LATE( achievement_victory(hyper); )
DEBB(DF_STEAM, ("after checks"))
@ -935,7 +1002,7 @@ EX string get_rich_presence_text() {
return "Guided Tour";
string res;
if(geometry != gNormal || !BITRUNCATED)
if(geometry != gNormal || !BITRUNCATED || disksize)
res = res + full_geometry_name() + " ";
if(land_structure != default_land_structure()) res += land_structure_name(false) + " ";
@ -945,6 +1012,7 @@ EX string get_rich_presence_text() {
if(inv::on) res += "OSM ";
if(multi::players > 1) res += "multi ";
if(casual) res += "casual ";
if(bow::weapon) res += bow::style == bow::cbBull ? "bow/bull " : "bow/geo ";
if(cheater || among(cwt.at->land, laCanvas, laCA))
return res + "(?)";
@ -982,13 +1050,9 @@ EX string get_rich_presence_text() {
return res;
}
#ifndef HAVE_ACHIEVEMENTS
void achievement_pump() {}
#endif
/** display the last achievement gained. */
EX void achievement_display() {
#ifdef HAVE_ACHIEVEMENTS
#if CAP_ACHIEVE
if(achievementTimer) {
int col = (ticks - achievementTimer);
if(col > 5000) { achievementTimer = 0; return; }
@ -1018,9 +1082,4 @@ EX int score_default(int i) {
else return 0;
}
#ifndef HAVE_ACHIEVEMENTS
EX int get_sync_status() { return 0; }
EX void set_priority_board(int) { }
#endif
}

1233
aperiodic-hat.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,8 @@ EX namespace arcm {
EX bool in() { return cgflags & qARCHI; }
EX ld euclidean_edge_length = .5;
#if HDR
struct hr_archimedean_error : hr_exception {
hr_archimedean_error(string _s) : hr_exception(_s) {}
@ -94,11 +96,11 @@ struct archimedean_tiling {
#endif
#if HDR
static const int sfPH = 1;
static const int sfLINE = 2;
static const int sfCHESS = 4;
static const int sfTHREE = 8;
static const int sfSEMILINE = 16;
static constexpr int sfPH = 1;
static constexpr int sfLINE = 2;
static constexpr int sfCHESS = 4;
static constexpr int sfTHREE = 8;
static constexpr int sfSEMILINE = 16;
#endif
#if CAP_ARCM
@ -150,6 +152,36 @@ void archimedean_tiling::make_match(int a, int i, int b, int j) {
/** mostly to protect the user from entering too large numbers */
const int MAX_EDGE_ARCM = FULL_EDGE;
/** compute the edge length of an Archimedean tiling. Each element of facemul is (face sides, multiplicity) */
EX ld compute_edgelength(vector<pair<ld, ld>> facemul, ld halftotal IS(M_PI)) {
ld elmin = 0, elmax = hyperbolic ? 10 : sphere ? M_PI : 2 * euclidean_edge_length;
ld edgelength;
for(int p=0; p<100; p++) {
edgelength = (elmin + elmax) / 2;
ld alpha_total = 0;
for(auto fm: facemul) {
if(isinf(fm.first)) {
ld u = sqrt(cosh(edgelength) * 2 - 2);
ld a = atan2(1, u/2);
alpha_total += a * fm.second;
}
else {
ld gamma = M_PI / fm.first;
auto c = asin_auto(sin_auto(edgelength/2) / sin(gamma));
hyperpoint h = lxpush(c) * spin(M_PI - 2*gamma) * lxpush0(c);
ld a = atan2(h);
cyclefix(a, 0);
if(a < 0) a = -a;
alpha_total += a * fm.second;
}
}
if(isnan(alpha_total)) elmax = edgelength;
else if(sphere ^ (alpha_total > halftotal)) elmin = edgelength;
else elmax = edgelength;
}
return edgelength;
}
void archimedean_tiling::compute_sum() {
N = isize(faces);
euclidean_angle_sum = 0;
@ -259,7 +291,7 @@ void archimedean_tiling::prepare() {
int inv = oi;
DEBB0(DF_GEOM, ("vertex "));
for(int z=0; z<faces[i]; z++) {
DEBB0(DF_GEOM, (format("[%d %d] " , at, inv)));
DEBB0(DF_GEOM, (hr::format("[%d %d] " , at, inv)));
adjacent[2*i+oi].emplace_back(2*N+int(inv), inv ? (2*at+2*N-2) % (2*N) : 2*at);
if(invert[at]) inv ^= 1;
at = adj[at];
@ -267,7 +299,7 @@ void archimedean_tiling::prepare() {
else at = (at+N-1) % N;
}
if(!inv) make_match(2*i, 0, inv ? (2*at+2*N-1) % 2*N : 2*at, 0);
DEBB(DF_GEOM, (format("-> [%d %d]\n", at, inv)));
DEBB(DF_GEOM, (hr::format("-> [%d %d]\n", at, inv)));
}
}
for(int i=0; i<N; i++) {
@ -316,11 +348,11 @@ void archimedean_tiling::prepare() {
int ai = i, aj = j;
DEBB0(DF_GEOM, ("triangle "));
for(int s=0; s<3; s++) {
DEBB0(DF_GEOM, (format("[%d %d] ", ai, aj)));
DEBB0(DF_GEOM, (hr::format("[%d %d] ", ai, aj)));
tie(ai, aj) = adjacent[ai][aj];
aj++; if(aj >= isize(adjacent[ai])) aj = 0;
}
DEBB(DF_GEOM, (format("-> [%d %d]\n", ai, aj)));
DEBB(DF_GEOM, (hr::format("-> [%d %d]\n", ai, aj)));
make_match(i, j, ai, aj);
}
}
@ -374,23 +406,35 @@ void archimedean_tiling::regroup() {
if(debugflags & DF_GEOM) {
for(int i=0; i<M; i+=(have_symmetry?1:2)) {
DEBB(DF_GEOM, (format("tiling group of %2d: [%2d]%2d+Z%2d\n", i, tilegroup[i], groupoffset[i], periods[i])));
DEBB(DF_GEOM, (hr::format("tiling group of %2d: [%2d]%2d+Z%2d\n", i, tilegroup[i], groupoffset[i], periods[i])));
}
}
}
geometryinfo1& archimedean_tiling::get_geometry(ld mul) {
if(euclidean_angle_sum * mul < 1.999999) return ginf[gSphere].g;
else if(euclidean_angle_sum * mul > 2.000001) return ginf[gNormal].g;
else return ginf[gEuclid].g;
if(euclidean_angle_sum * mul < 1.999999) return giSphere2;
else if(euclidean_angle_sum * mul > 2.000001) return giHyperb2;
else return giEuclid2;
}
void archimedean_tiling::compute_geometry() {
ginf[gArchimedean].g = get_geometry();
set_flag(ginf[gArchimedean].flags, qBOUNDED, get_class() == gcSphere);
DEBB(DF_GEOM, (format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum))));
if(embedded_plane && geometry != gArchimedean) return;
if(embedded_plane) return IPF(compute_geometry());
auto gg = get_geometry();
for(int a=0; a<2; a++) {
auto& arr = a ? geom3::ginf_backup : ginf;
if(arr.empty()) continue;
if(gg.kind == gcSphere) arr[gArchimedean].g = arr[gSphere].g;
if(gg.kind == gcEuclid) arr[gArchimedean].g = arr[gEuclid].g;
if(gg.kind == gcHyperbolic) arr[gArchimedean].g = arr[gNormal].g;
set_flag(arr[gArchimedean].flags, qCLOSED, gg.kind == gcSphere);
}
DEBB(DF_GEOM, (hr::format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum))));
bool infake = fake::in();
dynamicval<eGeometry> dv(geometry, gArchimedean);
@ -399,7 +443,6 @@ void archimedean_tiling::compute_geometry() {
inradius.resize(N+1); inradius[N] = 0;
circumradius.resize(N+1); circumradius[N] = 0;
alphas.resize(N);
ld elmin = 0, elmax = hyperbolic ? 10 : sphere ? M_PI : 1;
ld total = M_PI;
@ -410,29 +453,35 @@ void archimedean_tiling::compute_geometry() {
ginf[geometry].g = get_geometry(fake::around / N);
}
ld elmin = 0, elmax = hyperbolic ? 10 : sphere ? M_PI : 2 * euclidean_edge_length;
/* inradius[N] is used in farcorner and nearcorner. Probably a bug */
bool need_flip = embedded_plane;
if(need_flip) geom3::light_flip(true);
if(real_faces == 2) {
/* standard methods fail for dihedra, but the answer is easy */
edgelength = 2 * M_PI / faces[0];
edgelength = TAU / faces[0];
for(int i=0; i<N; i++)
if(faces[i] == 2)
alphas[i] = 0,
circumradius[i] = M_PI / real_face_type,
inradius[i] = 0;
else
alphas[i] = M_PI/2,
circumradius[i] = inradius[i] = M_PI/2;
alphas[i] = 90._deg,
circumradius[i] = inradius[i] = 90._deg;
}
else if(real_faces == 0) {
// these are called hosohedra
edgelength = M_PI;
for(int i=0; i<N; i++)
alphas[i] = M_PI / N,
circumradius[i] = M_PI/2,
circumradius[i] = 90._deg,
inradius[i] = 0;
}
else for(int p=0; p<100; p++) {
/* unfortunately we cannot just use compute_edgelength because we need to set other values */
edgelength = (elmin + elmax) / 2;
ld alpha_total = 0;
@ -444,9 +493,9 @@ void archimedean_tiling::compute_geometry() {
auto& c = circumradius[i];
c = asin_auto(sin_auto(edgelength/2) / sin(gamma));
inradius[i] = hdist0(mid(xpush0(circumradius[i]), xspinpush0(2*gamma, circumradius[i])));
inradius[i] = hdist0(mid(xpush0(circumradius[i]), cspin(0, 1, 2*gamma) * xpush0(circumradius[i])));
hyperpoint h = xpush(c) * spin(M_PI - 2*gamma) * xpush0(c);
hyperpoint h = xpush(c) * cspin(0, 1, M_PI - 2*gamma) * xpush0(c);
ld a = atan2(h);
cyclefix(a, 0);
if(a < 0) a = -a;
@ -455,6 +504,7 @@ void archimedean_tiling::compute_geometry() {
}
if(debugflags & DF_GEOM)
if(p < 10 || p == 99)
println(hlog, "edgelength = ", edgelength, " angles = ", alphas, " inradius = ", inradius, " circumradius = ", circumradius);
if(isnan(alpha_total)) elmax = edgelength;
@ -462,14 +512,16 @@ void archimedean_tiling::compute_geometry() {
else elmax = edgelength;
if(euclid) break;
}
if(need_flip) geom3::light_flip(false);
DEBB(DF_GEOM, (format("computed edgelength = %f\n", float(edgelength))));
DEBB(DF_GEOM, (hr::format("computed edgelength = %f\n", float(edgelength))));
triangles.clear();
triangles.resize(2*N+2);
for(int i=0; i<N; i++) for(int j=0; j<2; j++)
for(int k=0; k<faces[i]; k++)
triangles[2*i+j].emplace_back(2*M_PI/faces[i], circumradius[i]);
triangles[2*i+j].emplace_back(TAU/faces[i], circumradius[i]);
for(int k=0; k<N; k++) {
triangles[2*N].emplace_back(alphas[k], circumradius[k]);
@ -485,7 +537,7 @@ void archimedean_tiling::compute_geometry() {
if(debugflags & DF_GEOM) for(auto& ts: triangles) {
DEBB0(DF_GEOM, ("T"));
for(auto& t: ts) DEBB0(DF_GEOM, (format(" %f@%f", float(t.first), float(t.second))));
for(auto& t: ts) DEBB0(DF_GEOM, (hr::format(" %f@%f", float(t.first), float(t.second))));
DEBB(DF_GEOM, ());
}
@ -494,9 +546,9 @@ void archimedean_tiling::compute_geometry() {
}
ld archimedean_tiling::scale() {
if(real_faces == 0 && N == 2) return M_PI / 2;
if(real_faces == 2) return M_PI / 2;
if(real_faces == 0) return 2 * M_PI / N;
if(real_faces == 0 && N == 2) return 90._deg;
if(real_faces == 2) return 90._deg;
if(real_faces == 0) return TAU / N;
return edgelength;
}
@ -520,6 +572,16 @@ EX bool use_gmatrix = true;
* not used by arcm itself, but used in fake arcm
*/
EX geometry_information *alt_cgip[2];
EX geometry_information *find_alt_cgip() {
auto& galt_cgip = alt_cgip[embedded_plane];
if(galt_cgip) return galt_cgip;
check_cgi();
cgi.require_basics();
return galt_cgip = cgip;
}
struct hrmap_archimedean : hrmap {
map<gp::loc, struct cdata> eucdata;
heptagon *origin;
@ -539,14 +601,24 @@ struct hrmap_archimedean : hrmap {
heptagon *alt = NULL;
if(hyperbolic) {
dynamicval<eGeometry> g(geometry, gNormal);
alt = init_heptagon(S7);
alt->s = hsOrigin;
alt->alt = alt;
current_altmap = newAltMap(alt);
bool f = geom3::flipped;
if(f) geom3::light_flip(false);
if(1) {
dynamicval<eGeometry> g(geometry, gNormal);
dynamicval<eVariation> gv(variation, eVariation::pure);
dynamicval<geometry_information*> gi(cgip, find_alt_cgip());
alt = init_heptagon(S7);
alt->s = hsOrigin;
alt->alt = alt;
current_altmap = newAltMap(alt);
}
if(f) geom3::light_flip(true);
}
transmatrix T = xpush(.01241) * spin(1.4117) * xpush(0.1241) * Id;
bool f = geom3::flipped;
if(f) geom3::light_flip(false);
transmatrix T = lxpush(.01241) * spin(1.4117) * lxpush(0.1241) * Id;
if(f) geom3::light_flip(true);
archimedean_gmatrix[origin] = make_pair(alt, T);
altmap[alt].emplace_back(origin, T);
@ -578,10 +650,7 @@ struct hrmap_archimedean : hrmap {
origin->move(1)->c.connect(1, origin->move(0), 2*current.N-1, false);
}
cgi.base_distlimit = 0;
celllister cl(origin->c7, 1000, 200, NULL);
ginf[geometry].distlimit[!BITRUNCATED] = cgi.base_distlimit = cl.dists.back();
if(sphere) cgi.base_distlimit = SEE_ALL;
auto_compute_range(origin->c7);
}
~hrmap_archimedean() {
@ -590,6 +659,8 @@ struct hrmap_archimedean : hrmap {
archimedean_gmatrix.clear();
if(current_altmap) {
dynamicval<eGeometry> g(geometry, gNormal);
dynamicval<eVariation> gv(variation, eVariation::pure);
dynamicval<geometry_information*> gi(cgip, find_alt_cgip());
delete current_altmap;
current_altmap = NULL;
}
@ -598,7 +669,20 @@ struct hrmap_archimedean : hrmap {
heptagon *create_step(heptagon *h, int d) override {
DEBB(DF_GEOM, (format("%p.%d ~ ?\n", hr::voidp(h), d)));
bool f = geom3::flipped;
if(f) {
dynamicval<int> uc(cgip->use_count, cgip->use_count+1);
auto bcgip = cgip;
geom3::light_flip(false);
check_cgi();
cgi.require_basics();
auto h1 = create_step(h, d);
geom3::light_flip(true);
cgip = bcgip;
return h1;
}
DEBB(DF_GEOM, (heptspin(h,d), " ~ ?"));
dynamicval<geometryinfo1> gi(ginf[geometry].g, ginf[gArchimedean].g);
@ -608,17 +692,20 @@ struct hrmap_archimedean : hrmap {
auto& t1 = current.get_triangle(hi);
// * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first)
// * spin(-tri[id][pi+i].first) * lxpush(t.second) * pispin * spin(tri[id'][p'+d'].first)
auto& p1 = archimedean_gmatrix[h];
heptagon *alt = p1.first;
transmatrix T = p1.second * spin(-t1.first) * xpush(t1.second);
transmatrix T = p1.second * spin(-t1.first) * lxpush(t1.second);
transmatrix U = Id;
if(hyperbolic) {
dynamicval<eGeometry> g(geometry, gNormal);
dynamicval<int> uc(cgip->use_count, cgip->use_count+1);
dynamicval<eGeometry> g(geometry, gNormal);
dynamicval<eVariation> gv(variation, eVariation::pure);
dynamicval<geometry_information*> gi(cgip, find_alt_cgip());
dynamicval<hrmap*> cm(currentmap, current_altmap);
U = T;
current_altmap->virtualRebase(alt, T);
@ -631,24 +718,24 @@ struct hrmap_archimedean : hrmap {
alt = (heptagon*) s;
}
DEBB(DF_GEOM, ("look for: ", alt, " / ", T * C0));
DEBB(DF_GEOM, ("look for: ", alt, " / ", kz(T * C0)));
for(auto& p2: altmap[alt]) if(intval(p2.second * C0, T * C0) < 1e-4) {
for(auto& p2: altmap[alt]) if(same_point_may_warn(p2.second * tile_center(), T * tile_center())) {
DEBB(DF_GEOM, ("cell found: ", p2.first));
for(int d2=0; d2<p2.first->degree(); d2++) {
heptspin hs(p2.first, d2);
auto& t2 = current.get_triangle(p2.first, d2);
transmatrix T1 = T * spin(M_PI + t2.first);
DEBB(DF_GEOM, ("compare: ", T1 * xpush0(1), ":: ", p2.second * xpush0(1)));
if(intval(T1 * xpush0(1), p2.second * xpush0(1)) < 1e-4) {
DEBB(DF_GEOM, ("compare: ", kz(T1 * lxpush0(1)), ":: ", kz(p2.second * lxpush0(1))));
if(same_point_may_warn(T1 * lxpush0(1), p2.second * lxpush0(1))) {
// T1 = p2.second
// T * spin(pi+t2.first) == p2.second
// p1.second * spinm(-t1.first) * xpush(t1.second) * spin(pi+t2.first) == p2.second
// p1.second * spinm(-t1.first) * lxpush(t1.second) * spin(pi+t2.first) == p2.second
// bring p1 and p2 closer, to prevent floating point errors
if(hyperbolic) {
fixup_matrix(p1.second, U * p2.second * spin(-M_PI - t2.first) * xpush(-t1.second) * spin(t1.first), 0.25);
fixup_matrix(p1.second, U * p2.second * spin(-M_PI - t2.first) * lxpush(-t1.second) * spin(t1.first), 0.25);
fixup_matrix(p2.second, T1, 0.25);
}
@ -790,7 +877,7 @@ struct hrmap_archimedean : hrmap {
auto& t1 = ac.get_triangle(c->master, cid);
hyperpoint h0 = xspinpush0(-t0.first, t0.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1));
hyperpoint h1 = xspinpush0(-t1.first, t1.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1));
return mid3(C0, h0, h1);
return mid3(tile_center(), h0, h1);
}
if(DUAL) {
auto& t0 = ac.get_triangle(c->master, 2*cid-1);
@ -806,7 +893,7 @@ EX hrmap *new_map() { return new hrmap_archimedean; }
heptagon *build_child(heptspin p, pair<int, int> adj) {
indenter ind;
auto h = buildHeptagon1(tailored_alloc<heptagon> (isize(current.adjacent[adj.first])), p.at, p.spin, hstate(1), 0);
DEBB(DF_GEOM, (format("NEW %p.%d ~ %p.0\n", hr::voidp(p.at), p.spin, hr::voidp(h))));
DEBB(DF_GEOM, ("NEW ", p, " ~ ", heptspin(h, 0)));
id_of(h) = adj.first;
parent_index_of(h) = adj.second;
int nei = neighbors_of(h);
@ -850,23 +937,23 @@ void connect_digons_too(heptspin h1, heptspin h2) {
// no need to specify archimedean_gmatrix and altmap
hnew->c.connect(1, h2);
h1--, h2++;
DEBB(DF_GEOM, (format("OL2 %p.%d ~ %p.%d\n", hr::voidp(h1.at), h1.spin, hr::voidp(h2.at), h2.spin)));
DEBB(DF_GEOM, (hr::format("OL2 %p.%d ~ %p.%d\n", hr::voidp(h1.at), h1.spin, hr::voidp(h2.at), h2.spin)));
h1.at->c.connect(h1.spin, h2);
}
}
void connectHeptagons(heptspin hi, heptspin hs) {
DEBB(DF_GEOM, (format("OLD %p.%d ~ %p.%d\n", hr::voidp(hi.at), hi.spin, hr::voidp(hs.at), hs.spin)));
DEBB(DF_GEOM, ("OLD ", hi, " ~ ", hs));
if(hi.at->move(hi.spin) == hs.at && hi.at->c.spin(hi.spin) == hs.spin) {
DEBB(DF_GEOM, (format("WARNING: already connected\n")));
DEBB(DF_GEOM, (hr::format("WARNING: already connected\n")));
return;
}
if(hi.peek()) {
DEBB(DF_GEOM, (format("ERROR: already connected left\n")));
DEBB(DF_GEOM, (hr::format("ERROR: already connected left\n")));
throw hr_archimedean_error("Archimedean error: already connected left");
}
if(hs.peek()) {
DEBB(DF_GEOM, (format("ERROR: already connected right\n")));
DEBB(DF_GEOM, (hr::format("ERROR: already connected right\n")));
throw hr_archimedean_error("Archimedean error: already connected right");
}
hi.at->c.connect(hi.spin, hs);
@ -918,7 +1005,7 @@ transmatrix archimedean_tiling::adjcell_matrix(heptagon *h, int d) {
int d2 = h->c.spin(d);
auto& t2 = get_triangle(h2, d2);
return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first);
return spin(-t1.first) * lxpush(t1.second) * spin(M_PI + t2.first);
}
EX int fix(heptagon *h, int spin) {
@ -991,6 +1078,20 @@ void archimedean_tiling::parse() {
prepare();
}
EX bool load_symbol(const string& s, bool switch_geom) {
archimedean_tiling at; at.parse(s);
if(at.errors) {
DEBB(DF_ERROR | DF_GEOM, ("error: ", at.errormsg));
return false;
}
if(!switch_geom && geometry != gArchimedean) return true;
stop_game();
set_geometry(gArchimedean);
current = at;
if(!delayed_start) start_game();
return true;
}
#if CAP_COMMANDLINE
int readArgs() {
using namespace arg;
@ -998,16 +1099,8 @@ int readArgs() {
if(0) ;
else if(argis("-symbol")) {
PHASEFROM(2);
archimedean_tiling at;
shift(); at.parse(args());
if(at.errors) {
DEBB(DF_ERROR | DF_GEOM, ("error: ", at.errormsg));
}
else {
set_geometry(gArchimedean);
current = at;
showstartmenu = false;
}
shift(); load_symbol(args(), true);
showstartmenu = false;
}
else if(argis("-dual")) { PHASEFROM(2); set_variation(eVariation::dual); }
else if(argis("-d:arcm"))
@ -1026,8 +1119,22 @@ auto hook =
#if MAXMDIM >= 4
auto hooksw = addHook(hooks_swapdim, 100, [] {
if(!arcm::in()) return;
dynamicval<eGeometry> g(geometry, gNormal);
dynamicval<eVariation> gv(variation, eVariation::pure);
alt_cgip[0] = nullptr;
alt_cgip[1] = nullptr;
dynamicval<geometry_information*> gi(cgip, find_alt_cgip());
for(auto& p: altmap) for(auto& pp: p.second) swapmatrix(pp.second);
for(auto& p: archimedean_gmatrix) swapmatrix(p.second.second);
alt_cgip[0] = nullptr;
alt_cgip[1] = nullptr;
});
#endif
@ -1239,15 +1346,25 @@ EX void enable(archimedean_tiling& arct) {
start_game();
}
function<void()> setcanvas(char c) {
return [c] () {
function<void()> setcanvas(ccolor::data& c) {
auto pc = &c;
return [pc] () {
stop_game();
enable_canvas();
patterns::whichCanvas = c;
ccolor::which = pc;
start_game();
};
}
dialog::string_dialog se;
EX void init_symbol_edit() {
symbol_editing = true;
edited = current;
se.start_editing(edited.symbol);
edited.parse();
}
EX void show() {
if(lastsample < isize(samples)) {
string s = samples[lastsample].first;
@ -1260,7 +1377,7 @@ EX void show() {
}
else {
tested.coloring = col;
tilings.push_back(move(tested));
tilings.push_back(std::move(tested));
/* sort(tilings.begin(), tilings.end(), [] (archimedean_tiling& s1, archimedean_tiling& s2) {
if(s1.euclidean_angle_sum < s2.euclidean_angle_sum - 1e-6) return true;
if(s2.euclidean_angle_sum < s1.euclidean_angle_sum - 1e-6) return false;
@ -1269,11 +1386,11 @@ EX void show() {
}
}
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
dialog::init(XLAT("Archimedean tilings"));
if(symbol_editing) {
dialog::addSelItem("edit", dialog::view_edited_string(), '/');
dialog::addSelItem("edit", se.view_edited_string(), '/');
dialog::add_action([] () {
symbol_editing = false;
if(!edited.errors) enable(edited);
@ -1301,12 +1418,7 @@ EX void show() {
else {
string cs = in() ? current.symbol : XLAT("OFF");
dialog::addSelItem("edit", cs, '/');
dialog::add_action([] () {
symbol_editing = true;
edited = current;
dialog::start_editing(edited.symbol);
edited.parse();
});
dialog::add_action(init_symbol_edit);
dialog::addBreak(100);
int nextpos = spos;
int shown = 0;
@ -1360,11 +1472,15 @@ EX void show() {
});
if(in()) {
dialog::addSelItem(XLAT("size of the world"), current.world_size(), 0);
dialog::addSelItem(XLAT("size of the world"), current.world_size(), 'S');
add_size_action();
dialog::addSelItem(XLAT("edge length"), current.get_class() == gcEuclid ? (fts(current.edgelength) + XLAT(" (arbitrary)")) : fts(current.edgelength), 0);
dialog::addItem(XLAT("color by symmetries"), 't');
dialog::add_action(setcanvas('A'));
dialog::add_action(setcanvas(ccolor::shape));
dialog::addItem(XLAT("color by symmetries (reversed tiles marked)"), 'r');
dialog::add_action(setcanvas(ccolor::shape_mirror));
}
else {
dialog::addBreak(100);
@ -1374,20 +1490,20 @@ EX void show() {
if(true) {
dialog::addItem(XLAT("color by sides"), 'u');
dialog::add_action(setcanvas('B'));
dialog::add_action(setcanvas(ccolor::sides));
}
if(geosupport_threecolor() == 2) {
dialog::addItem(XLAT("three colors"), 'w');
dialog::add_action(setcanvas('T'));
dialog::add_action(setcanvas(ccolor::threecolor));
}
else if(geosupport_football() == 2) {
dialog::addItem(XLAT("football"), 'w');
dialog::add_action(setcanvas('F'));
dialog::add_action(setcanvas(ccolor::football));
}
else if(geosupport_chessboard()) {
dialog::addItem(XLAT("chessboard"), 'w');
dialog::add_action(setcanvas('c'));
dialog::add_action(setcanvas(ccolor::chessboard));
}
else dialog::addBreak(100);
@ -1405,7 +1521,7 @@ EX void show() {
keyhandler = [] (int sym, int uni) {
if(symbol_editing && sym == SDLK_RETURN) sym = uni = '/';
dialog::handleNavigation(sym, uni);
if(symbol_editing && dialog::handle_edit_string(sym, uni)) {
if(symbol_editing && se.handle_edit_string(sym, uni)) {
edited.parse(edited.symbol);
return;
}
@ -1416,6 +1532,10 @@ EX void show() {
void archimedean_tiling::get_nom_denom(int& anom, int& adenom) {
int nom = 2 - N, denom = 2;
for(int f: faces) {
if(f == 0) {
/* prevent a crash */
anom = 1; adenom = 1; return;
}
int g = gcd(denom, f);
nom = (nom * f + denom) / g;
denom = denom / g * f;
@ -1460,6 +1580,14 @@ EX bool is_vertex(heptagon *h) {
return id_of(h) >= 2 * current.N;
}
EX int get_graphical_id(cell *c) {
int id = arcm::id_of(c->master);
int tid = arcm::current.tilegroup[id];
int tid2 = arcm::current.tilegroup[id^1];
if(tid2 >= 0) tid = min(tid, tid2);
return tid;
}
bool archimedean_tiling::get_step_values(int& steps, int& single_step) {
int nom = -2;

View File

@ -214,7 +214,7 @@ EX int period_xy_edit, period_z_edit;
EX void set_flags() {
auto& flag = ginf[gArnoldCat].flags;
set_flag(flag, qANYQ, period_xy || period_z);
set_flag(flag, qBOUNDED, period_xy && period_z);
set_flag(flag, qCLOSED, period_xy && period_z);
set_flag(flag, qSMALL, period_xy && period_z && (period_xy * period_xy * period_z <= 4096));
set_flag(flag, qHUGE_BOUNDED, period_xy * period_xy * period_z > 16384);
}
@ -226,7 +226,7 @@ EX void prepare_config() {
EX void show_config() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(1);
gamescreen();
dialog::init(XLAT("Solv quotient spaces"));
dialog::addSelItem(XLAT("%1 period", "X/Y"), its(period_xy_edit), 'x');

View File

@ -126,8 +126,10 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
if(!(flags & AF_NOSHIELD) && ((flags & AF_NEXTTURN) ? checkOrb2 : checkOrb)(m2, itOrbShield)) return false;
if((flags & AF_STAB) && m2 != moHedge)
if((flags & AF_STAB) && m2 != moHedge) {
if(!checkOrb(m1, itOrbThorns)) return false;
else flags |= AF_IGNORE_UNARMED;
}
if(flags & AF_BACK) {
if(m2 == moFlailer && !c2->stuntime) flags |= AF_IGNORE_UNARMED;
@ -135,9 +137,9 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
else return false;
}
if(flags & AF_APPROACH) {
if(m2 == moLancer) ;
else if((flags & AF_HORNS) && checkOrb(m1, itOrbHorns)) ;
if(flags & (AF_APPROACH | AF_HORNS)) {
if(m2 == moLancer && (flags & AF_APPROACH)) ;
else if((flags & AF_HORNS) && checkOrb(m1, itOrbHorns)) { flags |= AF_IGNORE_UNARMED; }
else return false;
}
@ -149,7 +151,7 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
if(!(flags & (AF_GUN | AF_SWORD | AF_SWORD_INTO | AF_MAGIC | AF_PLAGUE)))
if(c1 != c2 && !logical_adjacent(c1, m1, c2)) return false;
if(!(flags & (AF_LANCE | AF_STAB | AF_BACK | AF_APPROACH | AF_GUN | AF_MAGIC | AF_PLAGUE | AF_SIDE)))
if(!(flags & (AF_LANCE | AF_STAB | AF_BACK | AF_APPROACH | AF_GUN | AF_MAGIC | AF_PLAGUE | AF_SIDE | AF_BOW)))
if(c1 && c2 && againstRose(c1, c2) && !ignoresSmell(m1))
return false;
@ -157,7 +159,8 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
if(isWorm(m2) && m2 != moTentacleGhost && !isDragon(m2)) return false;
// dragon can't attack itself, or player who mounted it
if(c1 && c2 && isWorm(c1->monst) && isWorm(c2->monst) && wormhead(c1) == wormhead(c2)
cell *cp = (flags & AF_BOW) ? cwt.at : c1;
if(cp && c2 && isWorm(cp->monst) && isWorm(c2->monst) && wormhead(cp) == wormhead(c2)
&& m1 != moTentacleGhost && m2 != moTentacleGhost)
return false;
@ -173,9 +176,6 @@ EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags)
if(m2 == moFlailer && !c2->stuntime)
if(!(flags & (AF_MAGIC | AF_TOUGH | AF_EAT | AF_HORNS | AF_LANCE | AF_BACK | AF_SWORD_INTO | AF_BULL | AF_CRUSH))) return false;
if(m2 == moVizier && c2->hitpoints > 1 && !c2->stuntime)
if(!(flags & (AF_MAGIC | AF_TOUGH | AF_EAT | AF_HORNS | AF_LANCE | AF_BACK | AF_FAST | AF_BULL | AF_CRUSH))) return false;
return true;
}
@ -229,6 +229,27 @@ EX void killIvy(cell *c, eMonster who) {
killIvy(c->move(i), who), kills[moIvyDead]++;
}
struct spillinfo {
eWall orig;
int spill_a, spill_b;
spillinfo() { spill_a = spill_b = 0; }
};
map<cell*, spillinfo> spillinfos;
EX void reset_spill() {
spillinfos.clear();
}
EX void record_spillinfo(cell *c, eWall t) {
if(!isAlchAny(t)) return;
auto& si = spillinfos[c];
if(si.spill_a == 0 && si.spill_b == 0) si.orig = c->wall;
if(si.spill_a == 0 && si.spill_b == 0) si.orig = c->wall;
if(t == waFloorA) si.spill_a++;
if(t == waFloorB) si.spill_b++;
}
EX void prespill(cell* c, eWall t, int rad, cell *from) {
if(againstWind(c, from)) return;
changes.ccell(c);
@ -283,8 +304,10 @@ EX void prespill(cell* c, eWall t, int rad, cell *from) {
c->wall == waCamelotMoat || c->wall == waSea || c->wall == waCTree ||
c->wall == waRubble || c->wall == waGargoyleFloor || c->wall == waGargoyle ||
c->wall == waRose || c->wall == waPetrified || c->wall == waPetrifiedBridge || c->wall == waRuinWall ||
among(c->wall, waDeepWater, waShallow))
among(c->wall, waDeepWater, waShallow)) {
record_spillinfo(c, t);
t = waTemporary;
}
if(c->wall == waSulphur) {
// remove the center as it would not look good
@ -299,14 +322,26 @@ EX void prespill(cell* c, eWall t, int rad, cell *from) {
destroyHalfvine(c);
if(c->wall == waTerraWarrior) kills[waTerraWarrior]++;
record_spillinfo(c, t);
c->wall = t;
// destroy items...
c->item = itNone;
// block spill
if(t == waTemporary) return;
// cwt.at->item = itNone;
if(rad) for(cell *c2: adj_minefield_cells(c))
prespill(c2, t, rad-1, c);
if(rad) for(auto p: adj_minefield_cells_full(c)) {
prespill(p.c, conditional_flip_slime(p.mirrored, t), rad-1, c);
}
}
EX eWall conditional_flip_slime(bool flip, eWall t) {
if(flip && t == waFloorA) return waFloorB;
if(flip && t == waFloorB) return waFloorA;
return t;
}
EX void chainspill(cell *c) {
if(c->wall == waMagma && c->monst == moSlimeNextTurn) killMonster(c, moNone, 0);
}
EX void spillfix(cell* c, eWall t, int rad) {
@ -314,12 +349,26 @@ EX void spillfix(cell* c, eWall t, int rad) {
changes.ccell(c);
c->wall = t;
}
if(rad) for(cell *c2: adj_minefield_cells(c))
spillfix(c2, t, rad-1);
if(rad) for(auto p: adj_minefield_cells_full(c)) {
spillfix(p.c, conditional_flip_slime(p.mirrored, t), rad-1);
}
chainspill(c);
}
EX void spill(cell* c, eWall t, int rad) {
prespill(c,t,rad, c); spillfix(c,t,rad);
if(isAlchAny(c) && (spillinfos[c].spill_a || spillinfos[c].spill_b) && isAlchAny(spillinfos[c].orig))
t = spillinfos[c].orig;
prespill(c,t,rad, c);
spillfix(c,t,rad);
for(auto si: spillinfos) {
if(si.second.spill_a && si.second.spill_b)
si.first->wall =
si.second.spill_a > si.second.spill_b ? waFloorA :
si.second.spill_b > si.second.spill_a ? waFloorB :
isAlchAny(si.second.orig) ? si.second.orig :
waNone;
chainspill(c);
}
}
EX void degradeDemons() {
@ -361,7 +410,7 @@ EX void stunMonster(cell *c2, eMonster killer, flagtype flags) {
((flags & AF_WEAK) && !attackJustStuns(c2, flags &~ AF_WEAK, killer)) ? min(5+c2->stuntime, 15) :
3);
if(killer == moArrowTrap) newtime = min(newtime + 3, 7);
if(!isMetalBeast(c2->monst) && !among(c2->monst, moSkeleton, moReptile, moSalamander, moTortoise, moWorldTurtle, moBrownBug)) {
if(!(flags & AF_WEAK) && !isMetalBeast(c2->monst) && !among(c2->monst, moSkeleton, moReptile, moSalamander, moTortoise, moWorldTurtle, moBrownBug)) {
c2->hitpoints--;
if(c2->monst == moPrincess)
playSound(c2, princessgender() ? "hit-princess" : "hit-prince");
@ -414,7 +463,7 @@ EX void killMutantIvy(cell *c, eMonster who) {
changes.ccell(c);
removeIvy(c);
for(int i=0; i<c->type; i++)
if(c->move(i)->mondir == c->c.spin(i) && (isMutantIvy(c->move(i)) || c->move(i)->monst == moFriendlyIvy))
if(c->move(i) && c->move(i)->mondir == c->c.spin(i) && (isMutantIvy(c->move(i)) || c->move(i)->monst == moFriendlyIvy))
kills[c->move(i)->monst]++, killMutantIvy(c->move(i), who);
if(c->land == laClearing) clearing::imput(c);
}
@ -466,6 +515,8 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
}
#endif
if(m == moHunterGuard) ambush::guard_attack();
if(m == moGolemMoved) m = moGolem;
if(m == moKnightMoved) m = moKnight;
if(m == moSlimeNextTurn) m = moSlime;
@ -527,7 +578,7 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
princess::reviveAt = gold(NO_LOVE) + 20;
}
}
if(princess::challenge) showMissionScreen();
if(princess::challenge) changes.at_commit([] { showMissionScreen(); });
}
}
@ -712,13 +763,18 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
// a reward for killing him before he shoots!
c->item = itOrbDragon;
}
if(m == moAsteroid && !shmup::on && c->item == itNone && c->wall != waChasm && c->land == laAsteroids) {
c->item = itAsteroid;
changes.value_add(splitrocks, 2);
}
if(m == moOutlaw && (c->item == itNone || c->item == itRevolver) && c->wall != waChasm)
c->item = itBounty;
// note: an Orb appears underwater!
if(m == moWaterElemental && c->item == itNone)
c->item = itOrbWater;
if(m == moPirate && isOnCIsland(c) && c->item == itNone && (
if(m == moPirate && (isOnCIsland(c) || ls::hv_structure()) && c->item == itNone && (
eubinary ||
(c->master->alt && celldistAlt(c) <= 2-getDistLimit()) ||
isHaunted(c->land)) && !cryst) {
@ -894,6 +950,14 @@ EX void fightmessage(eMonster victim, eMonster attacker, bool stun, flagtype fla
else
addMessage(XLAT("You pierce %the1.", victim)); // normal
}
else if(items[itOrbSlaying]) {
playSound(NULL, "hit-crush"+pick123());
addMessage(XLAT("You crush %the1!", victim)); // normal
}
else if(stun && items[itCurseWeakness]) {
playSound(NULL, "click");
addMessage(XLAT("You punch %the1.", victim)); // normal
}
else if(!peace::on) {
playSound(NULL, "hit-sword"+pick123());
addMessage(XLAT("You kill %the1.", victim)); // normal
@ -1059,14 +1123,18 @@ EX bool should_switchplace(cell *c1, cell *c2) {
if(isPrincess(c2->monst) || among(c2->monst, moGolem, moIllusion, moMouse, moFriendlyGhost))
return true;
if(peace::on) return c2->monst && !isMultitile(c2->monst);
if(peace::on) return c2->monst;
return false;
}
EX bool switchplace_prevent(cell *c1, cell *c2, bool checkonly) {
EX bool switchplace_prevent(cell *c1, cell *c2, struct pcmove& m) {
if(!should_switchplace(c1, c2)) return false;
if(peace::on && (isMultitile(c2->monst) || saved_tortoise_on(c2) || isDie(c2->monst))) {
if(m.vmsg(miRESTRICTED, siMONSTER, c2, c2->monst)) addMessage(XLAT("Cannot switch places with %the1!", c2->monst));
return true;
}
if(c1->monst && c1->monst != moFriendlyIvy) {
if(!checkonly) addMessage(XLAT("There is no room for %the1!", c2->monst));
if(m.vmsg(miRESTRICTED, siMONSTER, c1, c1->monst)) addMessage(XLAT("There is no room for %the1!", c2->monst));
return true;
}
if(passable(c1, c2, P_ISFRIEND | (c2->monst == moTameBomberbird ? P_FLYING : 0))) return false;
@ -1158,6 +1226,8 @@ EX void killHardcorePlayer(int id, flagtype flags) {
}
}
EX bool suicidal;
EX void killThePlayer(eMonster m, int id, flagtype flags) {
if(markOrb(itOrbShield)) return;
if(shmup::on) {
@ -1176,17 +1246,20 @@ EX void killThePlayer(eMonster m, int id, flagtype flags) {
}
else if(hardcore) {
addMessage(XLAT("You are killed by %the1!", m));
yasc_message = XLAT("killed by %the1", m);
killHardcorePlayer(id, flags);
}
else if(m == moLightningBolt && lastmovetype == lmAttack && isAlchAny(playerpos(id))) {
addMessage(XLAT("You are killed by %the1!", m));
addMessage(XLAT("Don't play with slime and electricity next time, okay?"));
yasc_message = XLAT("killed by %the1", m);
kills[moPlayer]++;
items[itOrbSafety] = 0;
}
else {
// printf("confused!\n");
addMessage(XLAT("%The1 is confused!", m));
changes.value_set(suicidal, true);
}
}
@ -1232,6 +1305,7 @@ EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
for(int bb=0; bb<2; bb++) achievement_count("SLASH", numbb[bb], 0);
if(peace::on) return;
bool out = who == moPlayer && bow::crossbow_mode();
for(int t=0; t<mf->type; t++) {
cell *c = mf->move(t);
@ -1239,13 +1313,14 @@ EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
bool stabthere = false, away = true;
if(logical_adjacent(mt, who, c)) stabthere = true, away = false;
if(inmirror(c)) c = mirror::reflect(c).at;
if(stabthere && c->wall == waExplosiveBarrel && markOrb(itOrbThorns))
explodeBarrel(c);
if(stabthere && canAttack(mt,who,c,c->monst,AF_STAB)) {
if(stabthere && (items[itOrbThorns] || !out) && canAttack(mt,who,c,c->monst,AF_STAB)) {
changes.ccell(c);
if(c->monst != moHedge) {
if(c->monst != moHedge || out) {
markOrb(itOrbThorns); if(who != moPlayer) markOrb(itOrbEmpathy);
}
eMonster m = c->monst;
@ -1289,11 +1364,13 @@ EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
}
}
if(!isUnarmed(who)) forCellIdEx(c, t, mt) {
forCellIdEx(c, t, mt) {
if(!logical_adjacent(mt, who, c)) continue;
eMonster mm = c->monst;
int flag = AF_APPROACH;
int flag = 0;
if(!isUnarmed(who) && !out) flag |= AF_APPROACH;
if(proper(mt, backdir) && anglestraight(mt, backdir, t)) flag |= AF_HORNS;
if(!flag) continue;
if(canAttack(mt,who,c,c->monst, flag)) {
changes.ccell(c);
if(attackMonster(c, flag | AF_MSG, who)) numlance++;
@ -1302,7 +1379,7 @@ EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
}
}
if(who == moPlayer) {
if(who == moPlayer && !bow::crossbow_mode()) {
if(numsh) achievement_count("STAB", numsh, 0);
if(numlance && numflail && numsh) achievement_gain_once("MELEE3");

View File

@ -34,11 +34,11 @@ EX bool checkBarriersFront(cellwalker bb, int q IS(5), bool cross IS(false)) {
/** return true if the cell c is not allowed to generate barriers because of other large things already existing nearby. */
EX bool hasbardir(cell *c) {
return c->bardir != NODIR && c->bardir != NOBARRIERS;
return c->bardir != NODIR && c->bardir != NOBARRIERS && c->bardir != NOBARRIERS2;
}
EX void preventbarriers(cell *c) {
if(hybri) c = hybrid::get_where(c).first;
if(mhybrid) c = hybrid::get_where(c).first;
if(c && c->bardir == NODIR) c->bardir = NOBARRIERS;
}
@ -68,48 +68,219 @@ EX bool checkBarriersBack(cellwalker bb, int q IS(5), bool cross IS(false)) {
/** warp coasts use a different algorithm for nowall barriers when has_nice_dual() is on. Check whether we should use this different algorithm when the lands are l1 and l2 */
EX bool warped_version(eLand l1, eLand l2) {
return (has_nice_dual() && (l1 == laWarpCoast || l1 == laWarpSea || l2 == laWarpSea || l2 == laWarpCoast)) || (valence() == 3);
return (has_nice_dual() && (l1 == laWarpCoast || l1 == laWarpSea || l2 == laWarpSea || l2 == laWarpCoast));
}
EX bool checkBarriersNowall(cellwalker bb, int q, int dir, eLand l1 IS(laNone), eLand l2 IS(laNone)) {
if(bb.at->mpdist < BARLEV && l1 == l2) return false;
if(bb.cpeek()->bardir != NODIR && l1 == l2) return false;
if(bb.at->bardir != NODIR && l1 == l2) return false;
// if(bb.at->move(dir) && bb.at->move(dir)->bardir != NODIR && l1 == laNone) return false;
// if(bb.at->move(dir) && bb.at->move(dir)->mpdist < BARLEV && l1 == laNone) return false;
if(l1 != l2) {
bb.at->bardir = bb.spin; bb.at->barright = l2; bb.at->barleft = NOWALLSEP;
setland(bb.at, l1);
EX int get_valence(cellwalker bb, int dir, bool& ok) {
if(arb::in() && arb::current_or_slided().have_valence) {
auto& sh = arb::current_or_slided().shapes[arb::id_of(bb.at->master)];
if(bb.mirrored) dir = -dir;
if(dir == 1)
return sh.vertex_valence[bb.spin];
else
return sh.vertex_valence[gmod(bb.spin - 1, bb.at->type)];
}
if(q > 20) return true;
if(l1 == laNone) for(int i=0; i<bb.at->type; i++) {
cell *c1 = bb.at->move(i);
if(!c1) continue;
for(int j=0; j<c1->type; j++) {
cell *c2 = c1->move(j);
if(!c2) continue;
if(c2 && c2->bardir == NOBARRIERS)
return false;
if(c2 && c2->bardir != NODIR && c2->barleft != NOWALLSEP)
return false;
// note: "far crashes" between NOWALL lines are allowed
int steps = 0;
cellwalker bb1 = bb;
while(bb1 != bb || !steps) {
bb1 += dir;
bb1 += wstep;
steps++;
}
return steps;
}
EX void set_and_wall(cell *c, eLand l) {
setland(c, l);
if(c->bardir == NODIR) {
c->barleft = NOWALLSEP_USED;
c->bardir = NOBARRIERS;
}
}
EX void surround_by(bool setit, cellwalker bb, int dir, int a, int b, eLand which, bool swapped, bool& ok) {
for(int i=0; i<a; i++) {
bb += dir;
bb += wstep;
}
for(int i=a; i<b; i++) {
if(setit) set_and_wall(bb.at, which);
else {
if(bb.at->bardir != NODIR) ok = false;
if(swapped && bb.at->mpdist < BARLEV) ok = false;
}
bb += dir;
bb += wstep;
}
}
EX void spin_around_by(cellwalker& bb, int dir, int q) {
for(int i=0; i<q; i++) {
bb += dir;
bb += wstep;
}
}
EX bool on_wall(eLand ws) {
return among(ws, NOWALLSEP_WALL_CPOS, NOWALLSEP_WALL_CNEG, NOWALLSEP_WALL_EPOS, NOWALLSEP_WALL_ENEG);
}
string wsname(eLand ws) {
if(ws == NOWALLSEP) return "NO";
if(ws == NOWALLSEP_SWAP) return "SWAP";
if(ws == NOWALLSEP_USED) return "USED";
if(ws == NOWALLSEP_WALL) return "WALL";
if(ws == NOWALLSEP_WALL_CPOS) return "CPOS";
if(ws == NOWALLSEP_WALL_CNEG) return "CNEG";
if(ws == NOWALLSEP_WALL_EPOS) return "EPOS";
if(ws == NOWALLSEP_WALL_ENEG) return "ENEG";
return dnameof(ws);
}
EX bool general_barrier_advance(cellwalker& bb, int& dir, eLand& l1, eLand& l2, eLand& ws, bool setit) {
bool ok = true;
if(ws == NOWALLSEP_WALL) {
if(warped_version(l1, l2)) {
bb = bb + wstep + (2*dir) + wstep + dir;
/*
if(setit) bb.at->monst = moBug0;
if(setit) bb.cpeek()->monst = moBug2;
*/
int steps = get_valence(bb, dir, ok);
if(steps % 2 == 0) goto again;
if(steps >= OINF) return ok;
int s = (steps - 1) / 2;
surround_by(setit, bb, dir, 1, s, l1, false, ok);
surround_by(setit, bb, dir, s+1, steps-1, l2, true, ok);
spin_around_by(bb, dir, s);
ws = dir > 0 ? NOWALLSEP_WALL_CPOS : NOWALLSEP_WALL_CNEG;
// goto tile;
return ok;
}
else if(valence() > 3) {
bb = bb + dir + wstep + dir;
if(on_wall(ws)) {
bool at_corner = among(ws, NOWALLSEP_WALL_CPOS, NOWALLSEP_WALL_CNEG);
cell *current = bb.at;
// if at_corner: bb is facing the tile 1 before the first inside
int t = bb.at->type;
int q = at_corner ? t/2 : (t-1) / 2;
if(1) {
auto bb1 = bb;
if(at_corner) bb1 += dir;
bb1 -= dir;
for(int i=1; i<q; i++) {
int d = get_valence(bb1, -dir, ok);
if(d >= OINF) return ok;
surround_by(setit, bb1, -dir, 1, d, l1, false, ok);
bb1-=dir;
}
}
bb += dir;
for(int i=1; i<q; i++) {
int d = get_valence(bb, dir, ok);
if(d >= OINF) return ok;
surround_by(setit, bb, dir, 1, d, l2, true, ok);
bb+=dir;
}
// bb is now facing the last neighbor inside
if(t % 2 == (at_corner ? 1 : 0)) {
if(setit) setbarrier(current, l1, l2, at_corner);
int d = get_valence(bb, dir, ok);
if(d >= OINF) return ok;
surround_by(setit, bb, dir, 2, d, l2, true, ok);
bb += dir;
bb += wstep;
d = get_valence(bb, -dir, ok);
if(d >= OINF) return ok;
surround_by(setit, bb, -dir, 2, d-1, l1, false, ok);
ws = dir > 0 ? NOWALLSEP_WALL_EPOS : NOWALLSEP_WALL_ENEG;
return ok;
}
int steps1 = get_valence(bb, dir, ok);
if(steps1 >= OINF) return ok;
if(setit) setbarrier(current, l1, l2, true);
if(steps1 % 2 == 0) {
int s1 = steps1 / 2;
surround_by(setit, bb, dir, 1, s1, l1, false, ok);
surround_by(setit, bb, dir, s1+1, steps1-1, l2, true, ok);
spin_around_by(bb, dir, s1);
ws = dir > 0 ? NOWALLSEP_WALL_CPOS : NOWALLSEP_WALL_CNEG;
return ok;
}
int s1 = (steps1 - 1) / 2;
surround_by(setit, bb, dir, 1, s1, l1, false, ok);
surround_by(setit, bb, dir, s1+2, steps1-1, l2, true, ok);
spin_around_by(bb, dir, s1);
bb += dir;
ws = NOWALLSEP_WALL;
}
else if(warped_version(l1, l2)) {
bb = bb + wstep + (2*dir) + wstep + dir;
dir = -dir;
swap(l1, l2);
}
else {
bb = bb + (dir>0?3:4) + wstep - (dir>0?3:4);
else {
again:
cellwalker bb1 = bb;
int steps = get_valence(bb, dir, ok);
if(steps >= OINF) return ok;
int s = 2;
if(ws == NOWALLSEP_SWAP) s = 5 - s;
if(dir == -1) s = 5 - s;
s = (1 + steps - s) / 2;
surround_by(setit, bb, dir, 1, s, l1, false, ok);
surround_by(setit, bb, dir, s+2, steps-1, l2, true, ok);
spin_around_by(bb, dir, s);
bb += dir;
if(steps & 1) ws = (ws == NOWALLSEP ? NOWALLSEP_SWAP : NOWALLSEP);
if(bb.at == bb1.at) goto again;
}
return checkBarriersNowall(bb, q+1, -dir, l2, l1);
return ok;
}
EX bool general_barrier_check(cellwalker bb, int q, int dir, eLand ws, eLand l1 IS(laNone), eLand l2 IS(laNone)) {
if(l1 == l2) {
if(bb.at->mpdist < BARLEV || bb.cpeek()->mpdist < BARLEV || bb.cpeek()->bardir != NODIR || bb.at->bardir != NODIR)
return false;
for(int i=0; i<bb.at->type; i++) {
cell *c1 = bb.at->move(i);
if(!c1) continue;
if(c1->bardir != NODIR) return false;
}
}
if(l1 != l2 && bb.at->barleft != NOWALLSEP_USED) {
bb.at->bardir = bb.spin; bb.at->barright = l2; bb.at->barleft = ws;
setland(bb.at, l1);
}
if(q <= 0) return true;
bool b = general_barrier_advance(bb, dir, l1, l2, ws, l1 != l2);
if(l1 == l2 && !b) return false;
return general_barrier_check(bb, q-1, dir, ws, l1, l2);
}
EX bool general_barrier_check_after(cellwalker bb, int steps, int q, int dir, eLand ws, eLand l1 IS(laNone), eLand l2 IS(laNone)) {
for(int i=0; i<steps; i++) general_barrier_advance(bb, dir, l1, l2, ws, l1 != l2);
return general_barrier_check(bb, q, dir, ws, l1, l2);
}
EX eWall getElementalWall(eLand l) {
@ -120,27 +291,26 @@ EX eWall getElementalWall(eLand l) {
return waNone;
}
EX void setbarrier(cell *c) {
if(isSealand(c->barleft) && isSealand(c->barright)) {
bool setbar = ctof(c);
if(c->barleft == laKraken || c->barright == laKraken)
if(c->barleft != laWarpSea && c->barright != laWarpSea)
EX void setbarrier(cell *c, eLand l1, eLand l2, bool setbar) {
if(isSealand(l1) && isSealand(l2)) {
if(l1 == laKraken || l2 == laKraken)
if(l1 != laWarpSea && l2 != laWarpSea)
setbar = !setbar;
c->wall = setbar ? waBarrier : waSea;
c->land = laOceanWall;
}
else if(isElemental(c->barleft) && isElemental(c->barright)) {
else if(isElemental(l1) && isElemental(l2)) {
c->land = laElementalWall;
c->wall = getElementalWall(c->barleft);
c->wall = getElementalWall(l1);
}
else if(c->barleft == laHaunted || c->barright == laHaunted) {
else if(l1 == laHaunted || l2 == laHaunted) {
c->land = laHauntedWall;
}
else if(c->barleft == laMirrored2 || c->barright == laMirrored2)
else if(l1 == laMirrored2 || l2 == laMirrored2)
c->land = laMirrorWall2;
else if(c->barleft == laMirrored || c->barright == laMirrored)
else if(l1 == laMirrored || l2 == laMirrored)
c->land = laMirrorWall;
else if(c->barleft == laTerracotta && c->barright == laTerracotta) {
else if(l1 == laTerracotta && l2 == laTerracotta) {
c->land = laMercuryRiver;
c->wall = waMercury;
}
@ -150,12 +320,19 @@ EX void setbarrier(cell *c) {
}
}
EX void setbarrier(cell *c) {
setbarrier(c, c->barleft, c->barright, ctof(c));
}
EX int setland_max = 5;
EX void setland(cell *c, eLand l) {
if(c->land != l) {
c->landparam = 0;
}
if(l == laNone) {
printf("setland\n"); // NONEDEBUG
if(l == laNone && setland_max > 0) {
setland_max--;
printf("error: set land to laNone\n"); // NONEDEBUG
}
c->land = l;
}
@ -253,55 +430,92 @@ EX void extendBarrierBack(cell *c) {
extendBarrier(bb.at);
}
EX void extendNowall(cell *c) {
EX void general_barrier_extend(cell *c) {
eLand ws = c->barleft;
cellwalker cw(c, c->bardir);
c->barleft = NOWALLSEP_USED;
cellwalker cw(c, c->bardir);
bool warpv = warped_version(c->land, c->barright);
if(warpv) {
cw += wstep;
setland(cw.at, c->barright);
eLand l1 = c->land;
eLand l2 = c->barright;
if(!on_wall(ws)) {
if(c->bardir == NODIR) {
println(hlog, "error: NODIR barrier at ", c);
return;
}
setland(cw.cpeek(), l2);
cw.cpeek()->barleft = NOWALLSEP_USED;
}
else if(valence() > 3) {
auto cw2 = cw + wstep;
setland(cw2.at, c->barright);
cw2.at->barleft = NOWALLSEP_USED;
cw2.at->barright = c->land;
cw2.at->bardir = cw2.spin;
}
for(int i=-1; i<2; i+=2) {
cellwalker cw0;
if(warpv) {
cw0 = cw + (2*i) + wstep;
if(ws == NOWALLSEP_WALL && barrier_cross(l1, l2)) {
cellwalker p_cw = cw;
eLand p_l1 = l1, p_l2 = l2;
eLand p_ws = ws;
int i = 1;
general_barrier_advance(p_cw, i, p_l1, p_l2, p_ws, false);
cellwalker n_cw = cw;
eLand n_l1 = l1, n_l2 = l2;
eLand n_ws = ws;
i = -1;
general_barrier_advance(n_cw, i, n_l1, n_l2, n_ws, false);
int dir = 0;
println(hlog, "left ", n_cw, " = ", n_cw.at->barleft, " right ", p_cw, " = ", p_cw.at->barleft, " USED = ", NOWALLSEP_USED);
if(n_cw.at->barleft == NOWALLSEP_USED && p_cw.at->barleft != NOWALLSEP_USED) dir = 1;
if(p_cw.at->barleft == NOWALLSEP_USED && n_cw.at->barleft != NOWALLSEP_USED) dir = -1;
if(dir) {
if(!general_barrier_check_after(cw, 2, 10, 1, NOWALLSEP_WALL_EPOS, l1, l1)) {
println(hlog, "failed to check 1");
dir = 0;
}
if(!general_barrier_check_after(cw+wstep, 2, 10, 1, NOWALLSEP_WALL_EPOS, l1, l1)) {
println(hlog, "failed to check 2");
dir = 0;
}
}
else if(valence() > 3) {
cw0 = cw + i + wstep + i;
}
else {
cw0 = cw + (i>0?3:4) + wstep - (i>0?3:4);
//cw0 = cw + (3*i) + wstep - (3*i);
}
if(cw0.at->barleft != NOWALLSEP_USED) {
cw0.at->barleft = NOWALLSEP;
if(valence() > 3) {
cw0.at->barright = c->barright;
cw0.at->bardir = cw0.spin;
setland(cw0.at, c->land);
if(dir) {
eLand xl1 = oppositeElement(l1, l2);
eLand xl2 = oppositeElement(l2, l1);
if(dir == 1) {
general_barrier_check_after(cw, 0, 10, 1, NOWALLSEP_WALL_EPOS, l1, xl2);
general_barrier_check_after(cw+wstep, 0, 10, 1, NOWALLSEP_WALL_EPOS, xl1, l2);
}
else {
setland(cw0.at, c->barright);
cw0.at->barright = c->land;
if(c->barright == laNone) {
printf("barright\n");
}// NONEDEBUG
setland(cw0.at, c->barright);
if(warpv) cw0 += i;
cw0.at->bardir = cw0.spin;
if(warpv) cw0 -= i;
general_barrier_check_after(cw, 0, 10, 1, NOWALLSEP_WALL_EPOS, xl2, l1);
general_barrier_check_after(cw+wstep, 0, 10, 1, NOWALLSEP_WALL_EPOS, l2, xl1);
}
general_barrier_check(cw, 10, dir, ws, xl2, xl1);
return;
}
}
for(int i: {-1, 1}) {
if(i == -1 && among(ws, NOWALLSEP_WALL_CPOS, NOWALLSEP_WALL_EPOS)) continue;
if(i == +1 && among(ws, NOWALLSEP_WALL_CNEG, NOWALLSEP_WALL_ENEG)) continue;
// general_barrier_check((cw, 10, i, ws, l1, l2);
cellwalker cw0 = cw;
eLand xl1 = l1, xl2 = l2;
eLand ws1 = ws;
int i1 = i;
general_barrier_advance(cw0, i1, xl1, xl2, ws1, true);
if(cw0.at->barleft != NOWALLSEP_USED) {
setland(cw0.at, xl1);
cw0.at->barleft = ws1;
cw0.at->barright = xl2;
cw0.at->bardir = cw0.spin;
extendcheck(cw0.at);
extendBarrier(cw0.at);
}
@ -344,6 +558,14 @@ EX bool isbar4(cell *c) {
c->land == laMercuryRiver;
}
EX bool barrier_cross(eLand l, eLand r) {
if(land_structure == lsVineWalls) return false;
if(l == laCrossroads3 || r == laCrossroads3) return hrand(100) < 66;
if(land_structure == lsCrossWalls && !among(laCrossroads2, l, r)) return hrand(100) < 90;
if(isElemental(l) && isElemental(r)) return hrand(100) < 75;
return false;
}
EX void extendBarrier(cell *c) {
limitgen("extend barrier %p\n", hr::voidp(c));
if(buggyGeneration) return;
@ -364,12 +586,12 @@ EX void extendBarrier(cell *c) {
return; // == INFD) return;
}
if(c->barleft == NOWALLSEP) {
if(c->barleft == NOWALLSEP || c->barleft == NOWALLSEP_SWAP || c->barleft == NOWALLSEP_WALL || on_wall(c->barleft)) {
#if MAXMDIM >= 4
if(WDIM == 3) extend3D(c);
else
#endif
extendNowall(c);
general_barrier_extend(c);
return;
}
@ -395,10 +617,13 @@ EX void extendBarrier(cell *c) {
if(buildBarrier6(cw, 2)) return;
}
if(((c->barleft == laCrossroads3 || c->barright == laCrossroads3) && hrand(100) < 66) ||
(isElemental(c->barleft) && isElemental(c->barright) && hrand(100) < 75)
|| (firstmirror && hrand(100) < 60)
) {
if(land_structure == lsCursedWalls && c->barleft != laMirror && c->barright != laMirror && hrand(100) < 80 && !among(laCrossroads2, c->barleft, c->barright)) {
cellwalker cw(c, c->bardir);
cw = cw + wstep + 3 + wstep - 1;
if(buildBarrier6(cw, c->barright, c->barleft)) return;
}
if(barrier_cross(c->barleft, c->barright) || (firstmirror && hrand(100) < 60)) {
cellwalker cw(c, c->bardir);
if(PURE) {
@ -450,6 +675,12 @@ EX void buildBarrierForce(cell *c, int d, eLand l) {
}
EX void buildBarrier(cell *c, int d, eLand l IS(laNone)) {
if(!old_nice_walls()) {
general_barrier_build(NOWALLSEP_WALL, c, l ? l : getNewLand(c->land), NODIR);
return;
}
d %= 7;
cellwalker bb(c, d);
@ -457,6 +688,7 @@ EX void buildBarrier(cell *c, int d, eLand l IS(laNone)) {
buildBarrierForce(c, d, l);
}
/** mirror variant of 6-fold walls */
EX bool buildBarrier6(cellwalker cw, int type) {
limitgen("build6 %p/%d (%d)\n", hr::voidp(cw.at), cw.spin, type);
@ -501,21 +733,28 @@ EX bool buildBarrier6(cellwalker cw, int type) {
if(!(PURE?checkBarriersFront:checkBarriersBack)(b[0], 6, true)) return false;
if(!(PURE?checkBarriersFront:checkBarriersBack)(b[3], 6, true)) return false;
}
eLand m0 = laMirror;
eLand m1 = laMirrored;
eLand m2 = laMirrored2;
eLand mw1 = laMirrorWall;
eLand mw2 = laMirrorWall2;
eWall w = waMirrorWall;
for(int d=0; d<4; d++) {
b[d].at->bardir = b[d].spin;
if(PURE) {
b[0].at->barleft = laMirrored, b[0].at->barright = laMirrored2;
b[1].at->barleft = laMirror, b[1].at->barright = laMirrored;
b[2].at->barleft = laMirrored2, b[2].at->barright = laMirrored;
b[3].at->barleft = laMirrored, b[3].at->barright = laMirror;
b[0].at->barleft = m1, b[0].at->barright = m2;
b[1].at->barleft = m0, b[1].at->barright = m1;
b[2].at->barleft = m2, b[2].at->barright = m1;
b[3].at->barleft = m1, b[3].at->barright = m0;
}
else {
b[0].at->barleft = laMirror, b[0].at->barright = laMirrored;
b[1].at->barleft = laMirrored, b[1].at->barright = laMirror;
b[2].at->barleft = laMirrored, b[2].at->barright = laMirrored2;
b[3].at->barleft = laMirrored2, b[3].at->barright = laMirrored;
b[0].at->barleft = m0, b[0].at->barright = m1;
b[1].at->barleft = m1, b[1].at->barright = m0;
b[2].at->barleft = m1, b[2].at->barright = m2;
b[3].at->barleft = m2, b[3].at->barright = m1;
}
(PURE?extendBarrierFront:extendBarrierBack)(b[d].at);
@ -529,45 +768,87 @@ EX bool buildBarrier6(cellwalker cw, int type) {
}
if(BITRUNCATED) {
setland((cw+1).cpeek(), laMirrorWall);
setland((cw+2).cpeek(), laMirrored);
setland((cw+3).cpeek(), laMirrorWall2);
setland((cw+4).cpeek(), laMirrorWall2);
setland((cw+5).cpeek(), laMirrored);
setland((cw+0).cpeek(), laMirrorWall);
setland((b[0]+2).cpeek(), laMirrored);
setland((b[3]+6).cpeek(), laMirrored2);
setland((b[3]+5).cpeek(), laMirrored2);
setland((b[1]-1).cpeek(), laMirrored);
setland((b[2]-2).cpeek(), laMirrored);
setland((b[1]-2).cpeek(), laMirrored);
setland((b[0]-2).cpeek(), laMirror);
cw.at->land = laMirrorWall;
cw.at->wall = waMirrorWall;
setland((cw+1).cpeek(), mw1);
setland((cw+2).cpeek(), m1);
setland((cw+3).cpeek(), mw2);
setland((cw+4).cpeek(), mw2);
setland((cw+5).cpeek(), m1);
setland((cw+0).cpeek(), mw1);
setland((b[0]+2).cpeek(), m1);
setland((b[3]+6).cpeek(), m2);
setland((b[3]+5).cpeek(), m2);
setland((b[1]-1).cpeek(), m1);
setland((b[2]-2).cpeek(), m1);
setland((b[1]-2).cpeek(), m1);
setland((b[0]-2).cpeek(), m0);
cw.at->land = mw1;
cw.at->wall = w;
cw.at->landparam = 1;
}
else {
setland(cw.at, laMirrorWall2);
setland((cw+0).cpeek(), laMirrorWall2);
setland((cw+1).cpeek(), laMirrored);
setland((cw+2).cpeek(), laMirrored);
setland((cw+3).cpeek(), laMirrorWall);
setland((cw+4).cpeek(), laMirrored);
setland((cw+5).cpeek(), laMirrorWall2);
setland((cw+6).cpeek(), laMirrored2);
setland(cw.at, mw2);
setland((cw+0).cpeek(), mw2);
setland((cw+1).cpeek(), m1);
setland((cw+2).cpeek(), m1);
setland((cw+3).cpeek(), mw1);
setland((cw+4).cpeek(), m1);
setland((cw+5).cpeek(), mw2);
setland((cw+6).cpeek(), m2);
setland((b[1]).cpeek(), laMirrorWall);
setland((b[1]+1).cpeek(), laMirror);
setland((b[1]+2).cpeek(), laMirrorWall);
setland((b[1]+6).cpeek(), laMirrored);
setland((b[1]).cpeek(), mw1);
setland((b[1]+1).cpeek(), m0);
setland((b[1]+2).cpeek(), mw1);
setland((b[1]+6).cpeek(), m1);
setland((b[0] + wstep - 2).cpeek(), laMirrored);
setland((b[3] + wstep - 2).cpeek(), laMirrored);
setland((b[0] + wstep - 2).cpeek(), m1);
setland((b[3] + wstep - 2).cpeek(), m1);
}
return true;
}
EX int curse_percentage = 10;
/** cursed variant of 6-fold walls */
EX bool buildBarrier6(cellwalker cw, eLand m0, eLand m1) {
cellwalker b[6];
if(buggyGeneration) return true;
for(int i=0; i<6; i+=2)
b[i] = cw + i + wstep;
for(int i=1; i<6; i+=2)
b[i] = cw + i + wstep + 3 + wstep;
for(int i=0; i<6; i++) if(i != 1) {
if(!(PURE?checkBarriersFront:checkBarriersBack)(b[i], 6, true)) return false;
}
for(int d=0; d<6; d++) {
b[d].at->bardir = b[d].spin;
b[d].at->barleft = (d&1) ? m1 : m0;
b[d].at->barright = (d&1) ? m0 : m1;
(PURE?extendBarrierFront:extendBarrierBack)(b[d].at);
}
cw.at->land = laBarrier;
cw.at->wall = waBarrier;
forCellCM(c, cw.at) { c->land = laBarrier; c->wall = waBarrier; }
for(int d=0; d<6; d+=2) {
setland((b[d]-2).cpeek(), m0);
setland((b[d]+2).cpeek(), m1);
setland((b[d+1]-2).cpeek(), m1);
setland((b[d+1]+2).cpeek(), m0);
}
if(hrand(100) < curse_percentage) {
setland(cw.at, laCursed);
cw.at->wall = waRubble;
cw.at->monst = moHexer;
cw.at->item = random_curse();
}
return true;
}
EX bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) {
limitgen("build4 %p\n", hr::voidp(c));
if(buggyGeneration) return true;
@ -651,6 +932,7 @@ EX void buildCrossroads2(cell *c) {
if(buggyGeneration) return;
if(!c) return;
if(ls::hv_structure()) return;
for(int i=0; i<c->type; i++)
if(c->move(i) && !c->move(i)->landparam && c->move(i)->mpdist < c->mpdist)
@ -875,10 +1157,14 @@ EX bool buildBarrier3D(cell *c, eLand l2, int forced_dir) {
#endif
EX bool buildBarrierNowall(cell *c, eLand l2, int forced_dir IS(NODIR)) {
if(among(l2, laCrossroads2, laCrossroads5)) return false;
return general_barrier_build(NOWALLSEP, c, l2, forced_dir);
}
EX bool general_barrier_build(eLand ws, cell *c, eLand l2, int forced_dir IS(NODIR)) {
if(S3 >= OINF) { c->land = l2; return true; }
if(geometry == gBinary4) return false;
#if MAXMDIM >= 4
// 3D binary tilings create walls using their own methods
if(WDIM == 3 && bt::in()) return false;
@ -896,24 +1182,24 @@ EX bool buildBarrierNowall(cell *c, eLand l2, int forced_dir IS(NODIR)) {
if(warpv && !arcm::in() && !pseudohept(c)) return false;
vector<int> ds = hrandom_permutation(c->type);
eLand wsx = warpv ? laWarpCoast : laNone;
eLand l1 = c->land;
if(forced_dir != NODIR) {
cellwalker cw(c, forced_dir);
general_barrier_check(cw, 20, -1, ws, l1, l2);
general_barrier_check(cw, 20, 1, ws, l1, l2);
extendBarrier(c);
return true;
}
for(int i=0; i<c->type; i++) {
int d = forced_dir != NODIR ? forced_dir : (valence()>3 && c->type > 3 && !INVERSE) ? (2+(i&1)) : ds[i];
/* if(warpv && GOLDBERG) {
d = hrand(c->type); */
if(warpv && c->move(d) && c->move(d)->mpdist < c->mpdist) continue;
if(GOLDBERG && a4 && c->move(d) && c->move(d)->mpdist <= c->mpdist) continue;
/* }
else
d = (S3>3 && !warpv) ? (2+(i&1)) : dtab[i]; */
cellwalker cw(c, d);
eLand ws = warpv ? laWarpCoast : laNone;
if(forced_dir != NODIR || (checkBarriersNowall(cw, 0, -1, ws, ws) && checkBarriersNowall(cw, 0, 1, ws, ws))) {
eLand l1 = c->land;
checkBarriersNowall(cw, 0, -1, l1, l2);
checkBarriersNowall(cw, 0, 1, l1, l2);
for(int d: ds) {
if(c->move(d) && c->move(d)->mpdist <= c->mpdist) continue;
cellwalker cw(c, d);
if(general_barrier_check(cw, 20, -1, ws, wsx, wsx) && general_barrier_check(cw, 20, 1, ws, wsx, wsx)) {
general_barrier_check(cw, 20, -1, ws, l1, l2);
general_barrier_check(cw, 20, 1, ws, l1, l2);
extendBarrier(c);
return true;
}

View File

@ -6,9 +6,25 @@
*/
#include "hyper.h"
#ifdef FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
namespace hr {
#if HDR
struct radarpoint {
hyperpoint h;
char glyph;
color_t color;
color_t line;
};
struct radarline {
hyperpoint h1, h2;
color_t line;
};
/** configuration of the current view */
struct display_data {
/** The cell which is currently in the center. */
@ -36,8 +52,13 @@ struct display_data {
ld tanfov;
flagtype next_shader_flags;
vector<radarpoint> radarpoints;
vector<radarline> radarlines;
transmatrix radar_transform;
transmatrix radar_transform_post;
ld eyewidth();
bool stereo_active();
bool separate_eyes();
bool in_anaglyph();
void set_viewport(int ed);
@ -87,7 +108,7 @@ EX int get_sightrange_ambush() {
}
bool display_data::in_anaglyph() { return vid.stereo_mode == sAnaglyph; }
bool display_data::stereo_active() { return vid.stereo_mode != sOFF; }
bool display_data::separate_eyes() { return among(vid.stereo_mode, sAnaglyph, sLR); }
ld display_data::eyewidth() {
switch(vid.stereo_mode) {
@ -156,6 +177,8 @@ EX SDL_Renderer *s_renderer, *s_software_renderer;
#endif
EX SDL_Texture *s_texture;
EX SDL_Window *s_window;
EX SDL_GLContext s_context;
EX bool s_have_context;
#endif
EX color_t qpixel_pixel_outside;
@ -197,12 +220,49 @@ EX void present_screen() {
#if CAP_SDLTTF
EX string fontpath = ISWEB ? "sans-serif" : HYPERPATH "DejaVuSans-Bold.ttf";
#define DEFAULT_FONT "DejaVuSans-Bold.ttf"
#ifdef FONTCONFIG
/** if this is non-empty, find the font using fontconfig */
EX string font_to_find = DEFAULT_FONT;
#endif
/** actual font path */
EX string fontpath = ISWEB ? "sans-serif" : string(HYPERFONTPATH) + DEFAULT_FONT;
const string& findfont() {
#ifdef FONTCONFIG
if(font_to_find == "") return fontpath;
FcPattern *pat;
FcResult result;
if (!FcInit()) {
return fontpath;
}
pat = FcNameParse((FcChar8 *)font_to_find.c_str());
FcConfigSubstitute(0, pat, FcMatchPattern);
FcDefaultSubstitute(pat);
FcPattern *match;
match = FcFontMatch(0, pat, &result);
if (match) {
FcChar8 *file;
if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch) {
fontpath = (const char *)file;
}
FcPatternDestroy(match);
}
FcPatternDestroy(pat);
FcFini();
font_to_find = "";
if(debugflags & DF_INIT) println(hlog, "fontpath is: ", fontpath);
#endif
return fontpath;
}
void loadfont(int siz) {
fix_font_size(siz);
if(!font[siz]) {
font[siz] = TTF_OpenFont(fontpath.c_str(), siz);
font[siz] = TTF_OpenFont(findfont().c_str(), siz);
// Destination set by ./configure (in the GitHub repository)
#ifdef FONTDESTDIR
if (font[siz] == NULL) {
@ -897,12 +957,19 @@ EX color_t colormix(color_t a, color_t b, color_t c) {
return a;
}
/* color difference for 24-bit colors, from 0 to 255*3 */
EX int color_diff(color_t a, color_t b) {
int res = 0;
for(int i=0; i<3; i++) res += abs(part(a, i) - part(b, i));
return res;
}
EX int rhypot(int a, int b) { return (int) sqrt(a*a - b*b); }
EX ld realradius() {
ld vradius = current_display->radius;
if(sphere) {
if(sphereflipped())
if(flip_sphere())
vradius /= sqrt(pconf.alpha*pconf.alpha - 1);
else
vradius = 1e12; // use the following
@ -999,7 +1066,7 @@ EX void drawCircle(int x, int y, int size, color_t color, color_t fillcolor IS(0
if(pts > 1500) pts = 1500;
if(ISMOBILE && pts > 72) pts = 72;
for(int r=0; r<pts; r++) {
float rr = (M_PI * 2 * r) / pts;
float rr = (TAU * r) / pts;
glcoords.push_back(glhr::makevertex(x + size * sin(rr), y + size * pconf.stretch * cos(rr), 0));
}
current_display->set_all(0, lband_shift);
@ -1088,6 +1155,10 @@ EX void compute_fsize() {
EX bool graphics_on;
EX bool request_resolution_change;
EX void do_request_resolution_change() { request_resolution_change = true; }
EX bool want_vsync() {
if(vrhr::active())
return false;
@ -1101,6 +1172,8 @@ EX bool need_to_reopen_window() {
return true;
if(want_vsync() != vid.current_vsync)
return true;
if(request_resolution_change)
return true;
return false;
}
@ -1126,6 +1199,9 @@ EX void close_renderer() {
EX void close_window() {
#if CAP_SDL2
close_renderer();
if(s_have_context) {
SDL_GL_DeleteContext(s_context), s_have_context = false;
}
if(s_window) SDL_DestroyWindow(s_window), s_window = nullptr;
#endif
}
@ -1255,8 +1331,13 @@ EX void setvideomode() {
auto create_win = [&] {
#if CAP_SDL2
if(s_window && current_window_flags != (flags | sizeflag))
if(s_window && current_window_flags != (flags | sizeflag)) {
if(s_have_context) {
SDL_GL_DeleteContext(s_context), s_have_context = false;
glhr::glew = false;
}
SDL_DestroyWindow(s_window), s_window = nullptr;
}
if(s_window)
SDL_SetWindowSize(s_window, vid.xres, vid.yres);
else
@ -1293,6 +1374,7 @@ EX void setvideomode() {
}
#if CAP_SDL2
if(s_renderer) SDL_DestroyRenderer(s_renderer), s_renderer = nullptr;
s_renderer = SDL_CreateRenderer(s_window, -1, vid.current_vsync ? SDL_RENDERER_PRESENTVSYNC : 0);
SDL_GetRendererOutputSize(s_renderer, &vid.xres, &vid.yres);
@ -1319,6 +1401,12 @@ EX void setvideomode() {
glDisable(GL_MULTISAMPLE_ARB);
}
#if CAP_SDL2
if(s_have_context) SDL_GL_DeleteContext(s_context), s_have_context = false;
if(!s_have_context) s_context = SDL_GL_CreateContext(s_window);
s_have_context = true; glhr::glew = false;
#endif
glViewport(0, 0, vid.xres, vid.yres);
glhr::init();
resetGL();
@ -1428,12 +1516,14 @@ EX void initialize_all() {
DEBBI(DF_INIT | DF_GRAPH, ("initgraph"));
DEBB(DF_INIT, ("initconfig"));
initConfig();
#if CAP_SDLJOY
joyx = joyy = 0; joydir.d = -1;
#endif
DEBB(DF_INIT, ("restartGraph"));
restartGraph();
if(noGUI) {
@ -1443,32 +1533,42 @@ EX void initialize_all() {
return;
}
DEBB(DF_INIT, ("preparesort"));
preparesort();
#if CAP_CONFIG
DEBB(DF_INIT, ("loadConfig"));
loadConfig();
#endif
#if CAP_ARCM
DEBB(DF_INIT, ("parse symbol"));
arcm::current.parse();
#endif
if(hybri) geometry = hybrid::underlying;
if(mhybrid) geometry = hybrid::underlying;
#if CAP_COMMANDLINE
arg::read(2);
#endif
DEBB(DF_INIT | DF_GRAPH, ("init graph"));
init_graph();
DEBB(DF_INIT | DF_POLY, ("check CGI"));
check_cgi();
DEBB(DF_INIT | DF_POLY, ("require basic"));
cgi.require_basics();
DEBB(DF_INIT | DF_GRAPH, ("init font"));
init_font();
#if CAP_SDLJOY
initJoysticks();
initJoysticks_async();
#endif
#if CAP_SDLAUDIO
DEBB(DF_INIT, ("init audio"));
initAudio();
#endif
DEBB(DF_INIT, ("initialize_all done"));
}
EX void quit_all() {
@ -1497,6 +1597,7 @@ EX int calcfps() {
EX namespace subscreens {
EX vector<display_data> player_displays;
/** 'in' is on if we are currently working on a single display */
EX bool in;
EX int current_player;
@ -1528,7 +1629,7 @@ EX namespace subscreens {
EX bool split(reaction_t what) {
using namespace racing;
if(in) return false;
if(!racing::on && !(shmup::on && GDIM == 3)) return false;
if(!multi::split_screen) return false;
if(!player_displays.empty()) {
in = true;
int& p = current_player;

File diff suppressed because it is too large Load Diff

View File

@ -136,7 +136,7 @@ EX namespace bt {
h->emeraldval = gmod((parent->emeraldval - d1) * 7508, 15015);
break;
case gTernary:
if(d < 2)
if(d <= 2)
h->emeraldval = gmod(parent->emeraldval * 3 + d, 10010);
else
h->emeraldval = gmod((parent->emeraldval - d1) * 3337, 10010);
@ -478,24 +478,24 @@ EX namespace bt {
}
if(d == NODIR) return 0;
if(d == c->type-1) d++;
return -(d+2)*M_PI/4;
return -(d+2) * 45._deg;
}
transmatrix adj(heptagon *h, int dir) override {
if(geometry == gBinaryTiling) switch(dir) {
case bd_up: return xpush(-log(2));
case bd_left: return parabolic(-1);
case bd_right: return parabolic(+1);
case bd_up: return lxpush(-log(2));
case bd_left: return parabolic(-2);
case bd_right: return parabolic(+2);
case bd_down:
if(h->type == 6) return xpush(log(2));
if(h->type == 6) return lxpush(log(2));
/* case bd_down_left: */
return parabolic(-1) * xpush(log(2));
return parabolic(-2) * lxpush(log(2));
case bd_down_right:
return parabolic(+1) * xpush(log(2));
return parabolic(+2) * lxpush(log(2));
case bd_up_left:
return xpush(-log(2)) * parabolic(-1);
return lxpush(-log(2)) * parabolic(-2);
case bd_up_right:
return xpush(-log(2)) * parabolic(1);
return lxpush(-log(2)) * parabolic(2);
default:
throw hr_exception("unknown direction");
}
@ -541,7 +541,7 @@ EX namespace bt {
}
}
~hrmap_binary() { clearfrom(origin); }
~hrmap_binary() { if(origin) clearfrom(origin); }
};
EX hrmap *new_map() { return new hrmap_binary; }
@ -604,6 +604,7 @@ EX namespace bt {
/** \brief by what factor do the lengths expand after moving one level in hr::bt::expansion_coordinate() */
EX ld expansion() {
if(WDIM == 2) return area_expansion_rate();
else if(mproduct) return PIU( area_expansion_rate() );
else return sqrt(area_expansion_rate());
}
@ -633,9 +634,9 @@ EX namespace bt {
auto &x = h[0], &y = h[1], &z = h[2];
switch(geometry) {
case gBinaryTiling: case gBinary4:
return bt::parabolic(y/2) * xpush(x*z2);
return bt::parabolic(y) * lxpush(x*z2*2);
case gTernary:
return bt::parabolic(y/2) * xpush(x*z3);
return bt::parabolic(y) * lxpush(x*z3*2);
#if CAP_SOLV
case gSol:
return xpush(bwh*x) * ypush(bwh*y) * zpush(z2*z);
@ -699,18 +700,18 @@ EX namespace bt {
use_direct = (1 << (S7-1)) - 1;
if(geometry == gBinary4) {
use_direct = 3;
direct_tmatrix[0] = xpush(-log(2)) * parabolic(-0.5);
direct_tmatrix[1] = xpush(-log(2)) * parabolic(+0.5);
direct_tmatrix[2] = parabolic(1);
direct_tmatrix[4] = parabolic(-1);
direct_tmatrix[0] = lxpush(-log(2)) * parabolic(-1);
direct_tmatrix[1] = lxpush(-log(2)) * parabolic(+1);
direct_tmatrix[2] = parabolic(2);
direct_tmatrix[4] = parabolic(-2);
use_direct = 1+2+4+16;
}
if(geometry == gTernary) {
direct_tmatrix[0] = xpush(-log(3)) * parabolic(-1);
direct_tmatrix[1] = xpush(-log(3));
direct_tmatrix[2] = xpush(-log(3)) * parabolic(+1);
direct_tmatrix[3] = parabolic(1);
direct_tmatrix[5] = parabolic(-1);
direct_tmatrix[0] = lxpush(-log(3)) * parabolic(-2);
direct_tmatrix[1] = lxpush(-log(3));
direct_tmatrix[2] = lxpush(-log(3)) * parabolic(+2);
direct_tmatrix[3] = parabolic(2);
direct_tmatrix[5] = parabolic(-2);
use_direct = 1+2+4+8+32;
}
if(geometry == gBinary3) {
@ -725,20 +726,20 @@ EX namespace bt {
}
if(geometry == gHoroTris) {
ld r3 = sqrt(3);
direct_tmatrix[0] = xpush(-log(2)) * cspin(1,2, M_PI);
direct_tmatrix[0] = xpush(-log(2)) * cspin180(1,2);
direct_tmatrix[1] = parabolic3(0, +r3/3) * xpush(-log(2));
direct_tmatrix[2] = parabolic3(-0.5, -r3/6) * xpush(-log(2));
direct_tmatrix[3] = parabolic3(+0.5, -r3/6) * xpush(-log(2));
direct_tmatrix[4] = parabolic3(0, -r3*2/3) * cspin(1,2, M_PI);
direct_tmatrix[5] = parabolic3(1, r3/3) * cspin(1,2,M_PI);
direct_tmatrix[6] = parabolic3(-1, r3/3) * cspin(1,2,M_PI);
direct_tmatrix[4] = parabolic3(0, -r3*2/3) * cspin180(1,2);
direct_tmatrix[5] = parabolic3(1, r3/3) * cspin180(1,2);
direct_tmatrix[6] = parabolic3(-1, r3/3) * cspin180(1,2);
}
if(geometry == gHoroRec) {
ld r2 = sqrt(2);
ld l = -log(2)/2;
ld z = hororec_scale;
direct_tmatrix[0] = parabolic3(0, -z) * xpush(l) * cspin(2,1,M_PI/2);
direct_tmatrix[1] = parabolic3(0, +z) * xpush(l) * cspin(2,1,M_PI/2);
direct_tmatrix[0] = parabolic3(0, -z) * xpush(l) * cspin90(2,1);
direct_tmatrix[1] = parabolic3(0, +z) * xpush(l) * cspin90(2,1);
direct_tmatrix[2] = parabolic3(+2*r2*z, 0);
direct_tmatrix[3] = parabolic3(0, +4*z);
direct_tmatrix[4] = parabolic3(-2*r2*z, 0);
@ -748,9 +749,9 @@ EX namespace bt {
// also generated with the help of hexb.cpp
ld l = log(3)/2;
auto& t = direct_tmatrix;
t[0] = parabolic3(horohex_scale, 0) * xpush(-l) * cspin(1, 2, M_PI/2);
t[1] = cspin(1, 2, 2*M_PI/3) * t[0];
t[2] = cspin(1, 2, 4*M_PI/3) * t[0];
t[0] = parabolic3(horohex_scale, 0) * xpush(-l) * cspin(1, 2, 90._deg);
t[1] = cspin(1, 2, 120*degree) * t[0];
t[2] = cspin(1, 2, 240*degree) * t[0];
auto it = iso_inverse(t[0]);
t[5] = it * t[1] * t[1];
@ -809,12 +810,14 @@ EX namespace bt {
}
#endif
EX ld xy_mul() { return vid.binary_width * log(2) / 2; }
EX transmatrix parabolic(ld u) {
return parabolic1(u * vid.binary_width / log(2) / 2);
return parabolic1(u * xy_mul());
}
EX transmatrix parabolic3(ld y, ld z) {
ld co = vid.binary_width / log(2) / 4;
ld co = xy_mul();
return hr::parabolic13(y * co, z * co);
}
@ -827,14 +830,23 @@ EX namespace bt {
return log(2) + log(-h[0]);
}
EX hyperpoint deparabolic3(hyperpoint h) {
h /= (1 + h[3]);
hyperpoint one = point3(1,0,0);
h -= one;
h /= sqhypot_d(3, h);
h[0] += .5;
ld co = vid.binary_width / log(2) / 8;
return point3(log(2) + log(-h[0]), h[1] / co, h[2] / co);
/** \brief convert BT coordinates to Minkowski coordinates
in the BT coordinates, h[2] is vertical; the center of the horosphere in Klein model is (1,0,0)
*/
EX hyperpoint bt_to_minkowski(hyperpoint h) {
ld yy = log(2) / 2;
ld co = xy_mul();
return hr::parabolic13(h[0] * co, h[1] * co) * xpush0(yy*h[2]);
}
/** \brief inverse of bt_to_minkowski */
EX hyperpoint minkowski_to_bt(hyperpoint h) {
h = deparabolic13(h);
ld co = xy_mul();
ld yy = log(2) / 2;
h = point31(h[1] / co, h[2] / co, h[0] / yy);
return h;
}
#if CAP_COMMANDLINE
@ -842,14 +854,35 @@ auto bt_config = arg::add2("-btwidth", [] {arg::shift_arg_formula(vid.binary_wid
#endif
EX bool pseudohept(cell *c) {
if(WDIM == 2)
return c->type & c->master->distance & 1;
else if(geometry == gHoroRec)
return c->c.spin(S7-1) == 0 && (c->master->distance & 1) && c->cmove(S7-1)->c.spin(S7-1) == 0;
else if(geometry == gHoroTris)
return c->c.spin(S7-1) == 0 && (c->master->distance & 1);
else
return (c->master->zebraval == 1) && (c->master->distance & 1);
switch(geometry) {
case gBinary4:
c->cmove(3);
return (c->master->distance & 1) && (c->c.spin(3) == 0);
case gBinaryTiling:
return c->master->distance & c->type & 1;
case gTernary: {
return c->master->emeraldval & 1;
/* auto m = dynamic_cast<hrmap_binary*> (current_map());
auto o = m->origin;
int flips = 0;
while(m != o) {
if(m->master->distance >= o->master->distance) { if(m->c.spin(4) == 1) flips++; m = m->cmove(4); }
}
heptagon *origin;
c->cmove(4); return (c->c.spin(4) == 1); */
}
case gHoroRec:
return c->c.spin(S7-1) == 0 && (c->master->distance & 1) && c->cmove(S7-1)->c.spin(S7-1) == 0;
case gHoroTris:
return c->c.spin(S7-1) == 0 && (c->master->distance & 1);
default:
return (c->master->zebraval == 1) && (c->master->distance & 1);
}
}
EX pair<gp::loc, gp::loc> gpvalue(heptagon *h) {
@ -966,7 +999,7 @@ EX int celldistance3_hex(heptagon *c1, heptagon *c2) {
while(isize(d1)) {
xsteps -= 2;
T = euscalezoom(hpxy(0,sqrt(3))) * eupush(1,0) * spin(-d2.back() * 2 * M_PI/3) * T * spin(d1.back() * 2 * M_PI/3) * eupush(-1,0) * euscalezoom(hpxy(0,-1/sqrt(3)));
T = euscalezoom(hpxy(0,sqrt(3))) * eupush(1,0) * spin(-d2.back() * 120._deg) * T * spin(d1.back() * 2 * M_PI/3) * eupush(-1,0) * euscalezoom(hpxy(0,-1/sqrt(3)));
d1.pop_back(); d2.pop_back();
@ -1015,25 +1048,30 @@ EX int celldistance3(heptagon *c1, heptagon *c2) {
EX int celldistance3(cell *c1, cell *c2) { return celldistance3(c1->master, c2->master); }
EX hyperpoint get_horopoint(ld y, ld x) {
return xpush(-y) * bt::parabolic(x) * C0;
return bt::parabolic(x*2) * lxpush(-y) * C0;
}
EX hyperpoint get_horopoint(hyperpoint h) {
return get_horopoint(h[0], h[1]);
}
EX hyperpoint inverse_horopoint(hyperpoint h) {
hyperpoint h1 = deparabolic13(h);
h1[1] /= 2 * bt::xy_mul(); h1[0] *= -1;
return h1;
}
EX hyperpoint get_corner_horo_coordinates(cell *c, int i) {
ld yx = log(2) / 2;
ld yy = yx;
ld xx = 1 / sqrt(2)/2;
ld yy = log(2) / 2;
ld xx = 1 / 2.;
switch(geometry) {
case gBinaryTiling:
switch(gmod(i, c->type)) {
case 0: return point2(-yy, xx);
case 1: return point2(yy, 2*xx);
case 2: return point2(yy, xx);
case 3: return point2(yy, -xx);
case 4: return point2(yy, -2*xx);
case 1: return point2(yy, xx);
case 2: return point2(yy, xx/2);
case 3: return point2(yy, -xx/2);
case 4: return point2(yy, -xx);
case 5: return point2(-yy, -xx);
case 6: return point2(-yy, 0);
default: return point2(0, 0);
@ -1041,9 +1079,9 @@ EX hyperpoint get_corner_horo_coordinates(cell *c, int i) {
case gBinary4:
switch(gmod(i, c->type)) {
case 0: return point2(yy, -2*xx);
case 0: return point2(yy, -xx);
case 1: return point2(yy, +0*xx);
case 2: return point2(yy, +2*xx);
case 2: return point2(yy, +xx);
case 3: return point2(-yy, xx);
case 4: return point2(-yy, -xx);
default: return point2(0, 0);
@ -1051,12 +1089,11 @@ EX hyperpoint get_corner_horo_coordinates(cell *c, int i) {
case gTernary:
yy = log(3) / 2;
xx = 1 / sqrt(3) / 2;
switch(gmod(i, c->type)) {
case 0: return point2(yy, -3*xx);
case 1: return point2(yy, -1*xx);
case 2: return point2(yy, +1*xx);
case 3: return point2(yy, +3*xx);
case 0: return point2(yy, -xx);
case 1: return point2(yy, -xx/3);
case 2: return point2(yy, +xx/3);
case 3: return point2(yy, +xx);
case 4: return point2(-yy, xx);
case 5: return point2(-yy, -xx);
default: return point2(0, 0);
@ -1154,7 +1191,7 @@ EX void create_faces() {
hyperpoint down = point3(0,0,2*z);
for(int j=0; j<4; j++) for(int i=0; i<3; i++) {
transmatrix T = cspin(0, 1, 2*M_PI*i/3);
transmatrix T = cspin(0, 1, 120._deg * i);
hyperpoint hcenter = point3(0,0,-z);
hyperpoint hu0 = T*point3(+h, +r3,-z);
@ -1177,8 +1214,7 @@ EX void create_faces() {
if(kite::in()) {
auto kv = kite::make_walls();
for(auto& v: kv.first) for(auto& h: v) {
h = bt::deparabolic3(h);
h = point3(h[1], h[2], h[0] / (log(2)/2));
h = minkowski_to_bt(h);
}
for(int i=0; i<isize(kv.first); i++) {
add_wall(i, kv.first[i]);

View File

@ -241,7 +241,7 @@ EX void drawArrowTraps() {
hyperpoint trel = inverse_shift(tu, tC0(tv));
shiftmatrix tpartial = tu * rspintox(trel) * xpush(hdist0(trel) * tt / 401.0);
tpartial = tpartial * ypush(.05);
if(GDIM == 3) tpartial = tpartial * cspin(1, 2, M_PI/2);
if(GDIM == 3) tpartial = tpartial * cspin90(1, 2);
queuepoly(tpartial, cgi.shTrapArrow, 0xFFFFFFFF);
}
}

552
cell.cpp
View File

@ -20,24 +20,16 @@ struct hrmap {
virtual vector<cell*>& allcells();
virtual void verify() { }
virtual void on_dim_change() { }
virtual void link_alt(const cellwalker& hs) { }
virtual void generateAlts(heptagon *h, int levs = default_levs(), bool link_cdata = true);
virtual bool link_alt(heptagon *h, heptagon *alt, hstate firststate, int dir);
virtual void extend_altmap(heptagon *h, int levs = default_levs(), bool link_cdata = true);
heptagon *may_create_step(heptagon *h, int direction) {
if(h->move(direction)) return h->move(direction);
return create_step(h, direction);
}
virtual heptagon *create_step(heptagon *h, int direction) {
printf("create_step called unexpectedly\n"); exit(1);
return NULL;
}
private:
virtual transmatrix relative_matrixh(heptagon *h2, heptagon *h1, const hyperpoint& hint) {
printf("relative_matrixh called unexpectedly\n");
return Id;
}
virtual transmatrix relative_matrixc(cell *c2, cell *c1, const hyperpoint& hint) {
return relative_matrixh(c2->master, c1->master, hint);
}
virtual heptagon *create_step(heptagon *h, int direction);
protected:
virtual transmatrix relative_matrixh(heptagon *h2, heptagon *h1, const hyperpoint& hint);
virtual transmatrix relative_matrixc(cell *c2, cell *c1, const hyperpoint& hint);
public:
transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) { return relative_matrixh(h2, h1, hint); }
transmatrix relative_matrix(cell *h2, cell *h1, const hyperpoint& hint) { return relative_matrixc(h2, h1, hint); }
@ -51,10 +43,7 @@ public:
virtual void draw_all();
virtual void draw_at(cell *at, const shiftmatrix& where);
virtual void virtualRebase(heptagon*& base, transmatrix& at) {
printf("virtualRebase called unexpectedly\n");
return;
}
virtual void virtualRebase(heptagon*& base, transmatrix& at);
static constexpr ld SPIN_NOT_AVAILABLE = 1e5;
virtual ld spin_angle(cell *c, int d) { return SPIN_NOT_AVAILABLE; }
@ -62,7 +51,7 @@ public:
virtual transmatrix spin_to(cell *c, int d, ld bonus=0);
virtual transmatrix spin_from(cell *c, int d, ld bonus=0);
virtual double spacedist(cell *c, int i) { return hdist0(tC0(adj(c, i))); }
virtual double spacedist(cell *c, int i);
virtual bool strict_tree_rules() { return false; }
@ -73,28 +62,26 @@ public:
virtual transmatrix master_relative(cell *c, bool get_inverse = false) { return Id; }
virtual int wall_offset(cell *c);
virtual transmatrix ray_iadj(cell *c, int i) {
if(WDIM == 2) {
return to_other_side(get_corner(c, i), get_corner(c, (i+1)));
}
return currentmap->iadj(c, i);
}
virtual transmatrix ray_iadj(cell *c, int i);
virtual subcellshape& get_cellshape(cell *c) {
if(cgi.heptshape) return *cgi.heptshape;
throw hr_exception("get_cellshape called unexpectedly");
}
virtual subcellshape& get_cellshape(cell *c);
/** \brief in 3D honeycombs, returns a cellwalker res at cw->move(j) such that the face pointed at by cw and res share an edge */
virtual cellwalker strafe(cellwalker cw, int j) { throw hr_exception("strafe called unexpectedly"); }
virtual cellwalker strafe(cellwalker cw, int j);
/** \brief in 3D honeycombs, returns a vector<bool> v, where v[j] iff faces i and j are adjacent */
const vector<char>& dirdist(cellwalker cw) { return get_cellshape(cw.at).dirdist[cw.spin]; }
/** \brief the sequence of heptagon movement direction to get from c->master to c->move(i)->master; implemented only for reg3 */
virtual const vector<int>& get_move_seq(cell *c, int i) {
throw hr_exception("get_move_seq not implemented for this map class");
}
virtual const vector<int>& get_move_seq(cell *c, int i);
/** generate a new map that is disconnected from what we already have, disconnected from the map we have so far */
virtual cell* gen_extra_origin(int fv) { throw hr_exception("gen_extra_origin not supported on this map"); }
transmatrix adjmod(cell *c, int i) { return adj(c, gmod(i, c->type)); }
transmatrix adjmod(heptagon *h, int i) { return adj(h, gmod(i, h->type)); }
transmatrix iadjmod(cell *c, int i) { return iadj(c, gmod(i, c->type)); }
transmatrix iadjmod(heptagon *h, int i) { return iadj(h, gmod(i, h->type)); }
};
/** hrmaps which are based on regular non-Euclidean 2D tilings, possibly quotient
@ -112,9 +99,11 @@ struct hrmap_standard : hrmap {
ld spin_angle(cell *c, int d) override;
double spacedist(cell *c, int i) override;
void find_cell_connection(cell *c, int d) override;
virtual int shvid(cell *c) override;
virtual hyperpoint get_corner(cell *c, int cid, ld cf) override;
virtual transmatrix master_relative(cell *c, bool get_inverse) override;
int shvid(cell *c) override;
hyperpoint get_corner(cell *c, int cid, ld cf) override;
transmatrix master_relative(cell *c, bool get_inverse) override;
bool link_alt(heptagon *h, heptagon *alt, hstate firststate, int dir) override;
void on_dim_change() override;
};
void clearfrom(heptagon*);
@ -135,10 +124,65 @@ struct hrmap_hyperbolic : hrmap_standard {
};
#endif
void hrmap_standard::on_dim_change() {
for(auto& p: gp::gp_swapped) swapmatrix(gp::gp_adj[p]);
gp::gp_swapped.clear();
}
double hrmap::spacedist(cell *c, int i) { return hdist(tile_center(), adj(c, i) * tile_center()); }
heptagon *hrmap::create_step(heptagon *h, int direction) {
throw hr_exception("create_step called unexpectedly");
return NULL;
}
transmatrix hrmap::relative_matrixh(heptagon *h2, heptagon *h1, const hyperpoint& hint) {
println(hlog, "relative_matrixh called unexpectedly\n");
return Id;
}
transmatrix hrmap::relative_matrixc(cell *c2, cell *c1, const hyperpoint& hint) {
return relative_matrixh(c2->master, c1->master, hint);
}
bool hrmap::link_alt(heptagon *h, heptagon *alt, hstate firststate, int dir) {
return true;
}
bool hrmap_standard::link_alt(heptagon *h, heptagon *alt, hstate firststate, int dir) {
altmap::relspin(alt) = 3;
return true;
}
void hrmap::virtualRebase(heptagon*& base, transmatrix& at) {
printf("virtualRebase called unexpectedly\n");
return;
}
transmatrix hrmap::ray_iadj(cell *c, int i) {
if(WDIM == 2) {
return to_other_side(get_corner(c, i), get_corner(c, (i+1)));
}
return currentmap->iadj(c, i);
}
subcellshape& hrmap::get_cellshape(cell *c) {
if(cgi.heptshape) return *cgi.heptshape;
throw hr_exception("get_cellshape called unexpectedly");
}
cellwalker hrmap::strafe(cellwalker cw, int j) {
throw hr_exception("strafe called unexpectedly");
}
const vector<int>& hrmap::get_move_seq(cell *c, int i) {
throw hr_exception("get_move_seq not implemented for this map class");
}
transmatrix hrmap::spin_to(cell *c, int d, ld bonus) {
ld sa = spin_angle(c, d);
if(sa != SPIN_NOT_AVAILABLE) { return spin(bonus + sa); }
transmatrix T = rspintox(tC0(adj(c, d)));
transmatrix T = lrspintox(tC0(adj(c, d)));
if(WDIM == 3) return T * cspin(2, 0, bonus);
return T * spin(bonus);
}
@ -146,7 +190,7 @@ transmatrix hrmap::spin_to(cell *c, int d, ld bonus) {
transmatrix hrmap::spin_from(cell *c, int d, ld bonus) {
ld sa = spin_angle(c, d);
if(sa != SPIN_NOT_AVAILABLE) { return spin(bonus - sa); }
transmatrix T = spintox(tC0(adj(c, d)));
transmatrix T = lspintox(tC0(adj(c, d)));
if(WDIM == 3) return T * cspin(2, 0, bonus);
return T * spin(bonus);
}
@ -155,7 +199,8 @@ transmatrix hrmap::adj(heptagon *h, int i) { return relative_matrix(h->cmove(i),
vector<cell*>& hrmap::allcells() {
static vector<cell*> default_allcells;
if(bounded && !(cgflags & qHUGE_BOUNDED) && !(hybri && hybrid::csteps == 0)) {
if(disksize) return all_disk_cells;
if(closed_manifold && !(cgflags & qHUGE_BOUNDED) && !(mhybrid && hybrid::csteps == 0)) {
celllister cl(gamestart(), 1000000, 1000000, NULL);
default_allcells = cl.lst;
return default_allcells;
@ -200,9 +245,11 @@ EX vector<hrmap*> allmaps;
EX hrmap *newAltMap(heptagon *o) {
#if MAXMDIM >= 4
if(reg3::in_rule())
if(reg3::in_hrmap_rule_or_subrule())
return reg3::new_alt_map(o);
#endif
if(currentmap->strict_tree_rules())
return rulegen::new_hrmap_rulegen_alt(o);
return new hrmap_hyperbolic(o);
}
// --- hyperbolic geometry ---
@ -237,12 +284,14 @@ void hrmap_standard::find_cell_connection(cell *c, int d) {
if(IRREGULAR) {
irr::link_cell(c, d);
}
#else
if(0) {}
#endif
#if CAP_GP
else if(GOLDBERG) {
gp::extend_map(c, d);
if(!c->move(d)) {
printf("extend failed to create for %p/%d\n", hr::voidp(c), d);
println(hlog, "extend failed to create for ", cellwalker(c, d));
exit(1);
}
hybrid::link();
@ -298,26 +347,241 @@ EX void eumerge(cell* c1, int s1, cell *c2, int s2, bool mirror) {
EX hookset<hrmap*()> hooks_newmap;
#if HDR
enum eDiskShape { dshTiles, dshVertices, dshGeometric };
#endif
/** requested disk size */
EX int req_disksize;
/** currently used disk size */
EX int disksize;
/** all the cells in the disk */
EX vector<cell*> all_disk_cells;
/** for quick test of membership */
EX vector<cell*> all_disk_cells_sorted;
/** the disk shape to use */
EX eDiskShape diskshape;
EX void init_disk_cells() {
disksize = req_disksize;
all_disk_cells.clear();
all_disk_cells_sorted.clear();
if(!disksize) return;
if(diskshape == dshTiles) {
celllister cl(currentmap->gamestart(), 1000000, disksize, NULL);
all_disk_cells = cl.lst;
}
else {
struct tileinfo {
ld dist;
cell *c;
transmatrix T;
bool operator < (const tileinfo& t2) const { return -dist < -t2.dist - 1e-6; }
};
set<cell*> seen;
std::priority_queue<tileinfo> tiles;
tiles.push(tileinfo{0, currentmap->gamestart(), Id});
ld last_dist = 0;
dynamicval<int> dmar(mine_adjacency_rule, 1);
while(isize(tiles)) {
auto ti = tiles.top();
tiles.pop();
println(hlog, "dist=", ti.dist, " for c=", ti.c);
if(seen.count(ti.c)) continue;
seen.insert(ti.c);
if(ti.dist > last_dist + 1e-6 && isize(all_disk_cells) >= disksize) break;
last_dist = ti.dist;
all_disk_cells.push_back(ti.c);
for(auto p: adj_minefield_cells_full(ti.c)) {
tileinfo next;
next.c = p.c;
next.T = ti.T * p.T;
if(diskshape == dshVertices) next.dist = ti.dist + 1;
else next.dist = hdist0(tC0(next.T));
println(hlog, ti.c, " -> ", p.c, " at ", next.dist);
tiles.push(next);
}
}
}
all_disk_cells_sorted = all_disk_cells;
sort(all_disk_cells_sorted.begin(), all_disk_cells_sorted.end());
}
EX bool is_in_disk(cell *c) {
auto it = lower_bound(all_disk_cells_sorted.begin(), all_disk_cells_sorted.end(), c);
if(it == all_disk_cells_sorted.end()) return false;
return *it == c;
}
bool sierpinski3(gp::loc g) {
int x = g.first;
int y = g.second;
set<pair<int, int>> visited;
while(true) {
if(visited.count({x,y})) return false;
visited.insert({x,y});
// if(x == -1 && y == -2) return false;
// if(x == -2 && y == -3) return false;
if(x == 0 && y == 0) return true;
if((x&1) == 1 && (y&1) == 1) return false;
x >>= 1;
y >>= 1;
// x--; y++;
tie(x, y) = make_pair(-x-y, x);
}
}
bool sierpinski46(gp::loc g) {
int x = g.first;
int y = g.second;
set<pair<int, int>> visited;
if(S7 == 6)
x += 2785684, y += 289080;
else
x += 75239892, y += 7913772;
while(true) {
if(visited.count({x,y})) return false;
visited.insert({x,y});
if(x == 0 && y == 0) return true;
int dx = gmod(x, 3);
int dy = gmod(y, 3);
if(dx == 1 && dy == 1) return false;
if(S7 == 6 && dx == dy) return false;
x = (x-dx) / 3;
y = (y-dy) / 3;
}
}
bool menger_sponge(euc::coord c) {
c[0] += 528120*9; c[1] += 438924*9; c[2] += 306712*9;
set<euc::coord> visited;
while(true) {
if(visited.count(c)) return false;
visited.insert(c);
if(c[0] == 0 && c[1] == 0 && c[2] == 0) return true;
int ones = 0;
for(int i=0; i<3; i++) {
int d = gmod(c[i], 3);
c[i] = (c[i] - d) / 3;
if(d == 1) ones++;
}
if(ones >= 2) return false;
}
}
bool sierpinski_tet(euc::coord c) {
set<euc::coord> visited;
c[0] += 16 * (1+8+64+512);
c[1] += 16 * (1+8+64+512);
c[1] += 32 * (1+8+64+512);
c[2] += 32 * (1+8+64+512);
c[0] += 64 * (1+8+64+512);
c[1] += 64 * (1+8+64+512);
while(true) {
if(visited.count(c)) return false;
visited.insert(c);
if(c[0] == 0 && c[1] == 0 && c[2] == 0) return true;
int ones = 0;
for(int i=0; i<3; i++) {
int d = gmod(c[i], 2);
c[i] = (c[i] - d) / 2;
if(d == 1) ones++;
}
if(ones & 1) return false;
}
}
EX bool is_in_fractal(cell *c) {
if(fake::in()) return FPIU(is_in_fractal(c));
if(mhybrid) { c = hybrid::get_where(c).first; return PIU(is_in_fractal(c)); }
switch(geometry) {
case gSierpinski3:
return sierpinski3(euc::full_coords2(c));
case gSierpinski4:
case gSixFlake:
return sierpinski46(euc::full_coords2(c));
case gMengerSponge:
return menger_sponge(euc::get_ispacemap()[c->master]);
case gSierpinskiTet: {
return sierpinski_tet(euc::get_ispacemap()[c->master]);
}
default:
return true;
}
}
EX cell *fractal_rep(cell *c) {
switch(geometry) {
case gSierpinski3: {
auto co = euc::full_coords2(c);
co.first += 4;
co.first &= ~15;
co.first -= 4;
co.second += 2;
co.second &= ~15;
co.second -= 2;
if(co.first == -4 && co.second == -2) co.first = 0, co.second = 0;
return euc::get_at(euc::to_coord(co))->c7;
}
case gSierpinski4:
case gSixFlake: {
auto co = euc::full_coords2(c);
if(S7 == 6) co.first += 4;
co.first -= gmod(co.first, 9);
co.second -= gmod(co.second, 9);
return euc::get_at(euc::to_coord(co))->c7;
}
case gSierpinskiTet: {
auto co = euc::get_ispacemap()[c->master];
co[0] &=~7;
co[1] &=~7;
co[2] &=~7;
return euc::get_at(co)->c7;
}
case gMengerSponge: {
auto co = euc::get_ispacemap()[c->master];
for(int i=0; i<3; i++) co[i] = co[i] - gmod(co[i], 9);
return euc::get_at(co)->c7;
}
default:
throw hr_exception("unknown fractal");
}
}
/** create a map in the current geometry */
EX void initcells() {
DEBB(DF_INIT, ("initcells"));
if(embedded_plane) {
geom3::swap_direction = -1;
check_cgi();
for(auto& m: cgi.heptmove) swapmatrix(m);
IPF(initcells());
check_cgi();
geom3::swap_direction = +1;
for(auto& m: cgi.heptmove) swapmatrix(m);
currentmap->on_dim_change();
return;
}
hrmap* res = callhandlers((hrmap*)nullptr, hooks_newmap);
if(res) currentmap = res;
#if CAP_SOLV
else if(asonov::in()) currentmap = asonov::new_map();
#endif
else if(nonisotropic || hybri) currentmap = nisot::new_map();
else if(nonisotropic || mhybrid) currentmap = nisot::new_map();
else if(INVERSE) currentmap = gp::new_inverse();
else if(fake::in()) currentmap = fake::new_map();
#if CAP_CRYSTAL
else if(cryst) currentmap = crystal::new_map();
#endif
else if(arb::in() && rulegen::known()) currentmap = rulegen::new_hrmap_rulegen();
else if(arb::in()) currentmap = arb::new_map();
#if CAP_ARCM
else if(arcm::in()) currentmap = arcm::new_map();
#endif
else if(euc::in()) currentmap = euc::new_map();
else if(hat::in()) currentmap = hat::new_map();
#if CAP_BT
else if(kite::in()) currentmap = kite::new_map();
#endif
@ -343,19 +607,19 @@ EX void initcells() {
EX void clearcell(cell *c) {
if(!c) return;
DEBB(DF_MEMORY, (format("c%d %p\n", c->type, hr::voidp(c))));
DEBB(DF_MEMORY, (hr::format("c%d %p\n", c->type, hr::voidp(c))));
for(int t=0; t<c->type; t++) if(c->move(t)) {
DEBB(DF_MEMORY, (format("mov %p [%p] S%d\n", hr::voidp(c->move(t)), hr::voidp(c->move(t)->move(c->c.spin(t))), c->c.spin(t))));
DEBB(DF_MEMORY, (hr::format("mov %p [%p] S%d\n", hr::voidp(c->move(t)), hr::voidp(c->move(t)->move(c->c.spin(t))), c->c.spin(t))));
if(c->move(t)->move(c->c.spin(t)) != NULL &&
c->move(t)->move(c->c.spin(t)) != c) {
DEBB(DF_MEMORY | DF_ERROR, (format("cell error: type = %d %d -> %d\n", c->type, t, c->c.spin(t))));
exit(1);
DEBB(DF_MEMORY | DF_ERROR, (hr::format("cell error: type = %d %d -> %d\n", c->type, t, c->c.spin(t))));
if(worst_precision_error < 1e-3) exit(1);
}
c->move(t)->move(c->c.spin(t)) = NULL;
}
DEBB(DF_MEMORY, (format("DEL %p\n", hr::voidp(c))));
destroy_cell(c);
DEBB(DF_MEMORY, (hr::format("DEL %p\n", hr::voidp(c))));
gp::delete_mapped(c);
destroy_cell(c);
}
EX heptagon deletion_marker;
@ -407,7 +671,7 @@ EX void clearfrom(heptagon *at) {
// if(q.size() > maxq) maxq = q.size();
q.pop();
DEBB(DF_MEMORY, ("from %p", at));
if(!at->c7) {
if(!at->c7 && !ls::voronoi_structure()) {
heptagon *h = dynamic_cast<heptagon*> ((cdata_or_heptagon*) at->cdata);
if(h) {
if(h->alt != at) { DEBB(DF_MEMORY | DF_ERROR, ("alt error :: h->alt = ", h->alt, " expected ", at)); }
@ -483,11 +747,12 @@ EX int compdist(int dx[]) {
EX int celldist(cell *c) {
if(experimental) return 0;
if(hybri)
if(mhybrid)
return hybrid::celldistance(c, currentmap->gamestart());
if(nil && !quotient) return DISTANCE_UNKNOWN;
if(hat::in()) return clueless_celldistance(currentmap->gamestart(), c);
if(euc::in()) return celldistance(currentmap->gamestart(), c);
if(sphere || bt::in() || WDIM == 3 || cryst || sn::in() || kite::in() || bounded) return celldistance(currentmap->gamestart(), c);
if(sphere || bt::in() || WDIM == 3 || cryst || sn::in() || aperiodic || closed_manifold) return celldistance(currentmap->gamestart(), c);
#if CAP_IRR
if(IRREGULAR) return irr::celldist(c, false);
#endif
@ -507,17 +772,17 @@ EX int celldist(cell *c) {
}
#if HDR
static const int ALTDIST_BOUNDARY = 99999;
static const int ALTDIST_UNKNOWN = 99998;
static const int ALTDIST_ERROR = 90000;
static constexpr int ALTDIST_BOUNDARY = 99999;
static constexpr int ALTDIST_UNKNOWN = 99998;
static constexpr int ALTDIST_ERROR = 90000;
#endif
EX int celldistAlt(cell *c) {
if(experimental) return 0;
if(hybri) {
if(mhybrid) {
if(in_s2xe()) return hybrid::get_where(c).second;
auto w = hybrid::get_where(c);
int d = c->master->alt && c->master->alt->alt ? c->master->alt->alt->fieldval : 0;
int d = c->master->alt && c->master->alt->alt ? hybrid::altmap_heights[c->master->alt->alt] : 0;
d = sl2 ? 0 : abs(w.second - d);
PIU ( d += celldistAlt(w.first) );
return d;
@ -535,7 +800,7 @@ EX int celldistAlt(cell *c) {
}
#if MAXMDIM >= 4
if(euc::in()) return euc::dist_alt(c);
if(hyperbolic && WDIM == 3 && !reg3::in_rule())
if(hyperbolic && WDIM == 3 && !reg3::in_hrmap_rule_or_subrule())
return reg3::altdist(c->master);
#endif
if(!c->master->alt) return 0;
@ -573,13 +838,13 @@ EX int updir(heptagon *h) {
if(bt::in()) return bt::updir();
#endif
#if MAXMDIM >= 4
if(WDIM == 3 && reg3::in_rule()) {
for(int i=0; i<S7; i++) if(h->move(i) && h->move(i)->distance < h->distance)
if(WDIM == 3 && reg3::in_hrmap_rule_or_subrule()) {
for(int i=0; i<h->type; i++) if(h->move(i) && h->move(i)->distance < h->distance)
return i;
return -1;
}
#endif
if(h->distance == 0) return -1;
if(h->s == hsOrigin) return -1;
return 0;
}
@ -587,26 +852,23 @@ EX int updir(heptagon *h) {
EX int updir_alt(heptagon *h) {
if(euclid || !h->alt) return -1;
#if MAXMDIM >= 4
if(WDIM == 3 && reg3::in_rule()) {
if(WDIM == 3 && reg3::in_hrmap_rule_or_subrule()) {
for(int i=0; i<S7; i++) if(h->move(i) && h->move(i)->alt && h->move(i)->alt->distance < h->alt->distance)
return i;
return -1;
}
#endif
for(int i=0; i<S7; i++)
if(h->move(i) && h->move(i)->alt == h->alt->move(0))
return i;
return -1;
return gmod(updir(h->alt) + altmap::relspin(h->alt), h->type);
}
#if HDR
static const int RPV_MODULO = 5;
static const int RPV_RAND = 0;
static const int RPV_ZEBRA = 1;
static const int RPV_EMERALD = 2;
static const int RPV_PALACE = 3;
static const int RPV_CYCLE = 4;
static constexpr int RPV_MODULO = 5;
static constexpr int RPV_RAND = 0;
static constexpr int RPV_ZEBRA = 1;
static constexpr int RPV_EMERALD = 2;
static constexpr int RPV_PALACE = 3;
static constexpr int RPV_CYCLE = 4;
#endif
// x mod 5 = pattern type
@ -731,8 +993,9 @@ EX bool randpatternMajority(cell *c, int ival, int iterations) {
cdata orig_cdata;
EX bool geometry_supports_cdata() {
if(hybri) return PIU(geometry_supports_cdata());
return among(geometry, gEuclid, gEuclidSquare, gNormal, gOctagon, g45, g46, g47, gBinaryTiling) || (arcm::in() && !sphere);
if(mhybrid) return PIU(geometry_supports_cdata());
if(embedded_plane) return IPF( geometry_supports_cdata() );
return among(geometry, gEuclid, gEuclidSquare, gNormal, gOctagon, g45, g46, g47, gBinaryTiling) || (arcm::in() && !sphere) || (currentmap && currentmap->strict_tree_rules());
}
void affect(cdata& d, short rv, signed char signum) {
@ -825,7 +1088,8 @@ cdata *getHeptagonCdata_legacy(heptagon *h) {
cdata *getHeptagonCdata(heptagon *h) {
if(hybri) return PIU ( getHeptagonCdata(h) );
if(mhybrid) return PIU ( getHeptagonCdata(h) );
if(embedded_plane) return IPF( getHeptagonCdata(h) );
if(geometry == gNormal && BITRUNCATED) return getHeptagonCdata_legacy(h);
if(h->cdata) return h->cdata;
@ -839,6 +1103,8 @@ cdata *getHeptagonCdata(heptagon *h) {
}
#endif
if(currentmap->strict_tree_rules()) starting = h->distance <= 0;
if(starting) {
h->cdata = new cdata(orig_cdata);
for(int& v: h->cdata->val) v = 0;
@ -847,7 +1113,7 @@ cdata *getHeptagonCdata(heptagon *h) {
return h->cdata;
}
int dir = bt::in() ? 5 : 0;
int dir = updir(h);
cdata mydata = *getHeptagonCdata(h->cmove(dir));
@ -855,6 +1121,30 @@ cdata *getHeptagonCdata(heptagon *h) {
setHeptagonRval(h);
affect(mydata, h->rval0, 1);
}
else if(currentmap->strict_tree_rules()) {
for(eLand ws: {NOWALLSEP, NOWALLSEP_SWAP}) {
lalign(0, h->c7);
int dir = 1;
cellwalker hs(h->c7, dir, false);
eLand dummy = laNone;
vector<cell*> lpath, rpath;
while(true) {
int d = hs.at->master->distance;
general_barrier_advance(hs, dir, dummy, dummy, ws, false);
lpath.push_back(hs.at);
if(hs.at->master->distance > d) break;
}
dir = -dir;
while(true) {
int d = hs.at->master->distance;
general_barrier_advance(hs, dir, dummy, dummy, ws, false);
rpath.push_back(hs.at);
if(hs.at->master->distance > d) break;
}
setHeptagonRval(hs.at->master);
affect(mydata, ws == NOWALLSEP_SWAP ? hs.at->master->rval1 : hs.at->master->rval0, 1);
}
}
else if(S3 == 4) {
heptspin hs(h, 0);
while(dmeq((hs+1).cpeek()->dm4, (hs.at->dm4 - 1))) hs = hs + 1 + wstep + 1;
@ -945,7 +1235,7 @@ int ld_to_int(ld x) {
#if CAP_ARCM
EX gp::loc pseudocoords(cell *c) {
transmatrix T = arcm::archimedean_gmatrix[c->master].second;
return {ld_to_int(T[0][LDIM]), ld_to_int((spin(60*degree) * T)[0][LDIM])};
return {ld_to_int(T[0][LDIM]), ld_to_int((spin(60._deg) * T)[0][LDIM])};
}
EX cdata *arcmCdata(cell *c) {
@ -964,8 +1254,9 @@ EX cdata *arcmCdata(cell *c) {
EX int getCdata(cell *c, int j) {
if(fake::in()) return FPIU(getCdata(c, j));
if(embedded_plane) return IPF(getCdata(c, j));
if(experimental) return 0;
if(hybri) { c = hybrid::get_where(c).first; return PIU(getBits(c)); }
if(mhybrid) { c = hybrid::get_where(c).first; return PIU(getBits(c)); }
else if(INVERSE) {
cell *c1 = gp::get_mapped(c);
return UIU(getCdata(c1, j));
@ -974,7 +1265,7 @@ EX int getCdata(cell *c, int j) {
#if CAP_ARCM
else if(arcm::in() && euclid)
return getEuclidCdata(pseudocoords(c))->val[j];
else if(arcm::in() && hyperbolic)
else if(arcm::in() && (hyperbolic || sl2))
return arcmCdata(c)->val[j]*3;
#endif
else if(!geometry_supports_cdata()) return 0;
@ -990,8 +1281,9 @@ EX int getCdata(cell *c, int j) {
EX int getBits(cell *c) {
if(fake::in()) return FPIU(getBits(c));
if(embedded_plane) return IPF(getBits(c));
if(experimental) return 0;
if(hybri) { c = hybrid::get_where(c).first; return PIU(getBits(c)); }
if(mhybrid) { c = hybrid::get_where(c).first; return PIU(getBits(c)); }
else if(INVERSE) {
cell *c1 = gp::get_mapped(c);
return UIU(getBits(c1));
@ -1137,9 +1429,11 @@ EX int clueless_celldistance(cell *c1, cell *c2) {
EX int celldistance(cell *c1, cell *c2) {
if(embedded_plane) return IPF(celldistance(c1, c2));
if(fake::in()) return FPIU(celldistance(c1, c2));
if(hybri) return hybrid::celldistance(c1, c2);
if(mhybrid) return hybrid::celldistance(c1, c2);
#if CAP_FIELD
if(geometry == gFieldQuotient && (PURE || BITRUNCATED)) {
@ -1148,7 +1442,7 @@ EX int celldistance(cell *c1, cell *c2) {
}
#endif
if(bounded) return bounded_celldistance(c1, c2);
if(closed_manifold) return bounded_celldistance(c1, c2);
#if CAP_CRYSTAL
if(cryst) return crystal::precise_distance(c1, c2);
@ -1158,7 +1452,7 @@ EX int celldistance(cell *c1, cell *c2) {
return euc::cyldist(euc2_coordinates(c1), euc2_coordinates(c2));
}
if(arcm::in() || quotient || sn::in() || (kite::in() && euclid) || experimental || sl2 || nil || arb::in())
if(arcm::in() || quotient || sn::in() || (aperiodic && euclid) || experimental || sl2 || nil || arb::in())
return clueless_celldistance(c1, c2);
if(S3 >= OINF) return inforder::celldistance(c1, c2);
@ -1175,12 +1469,15 @@ EX int celldistance(cell *c1, cell *c2) {
if(hyperbolic && WDIM == 3) return reg3::celldistance(c1, c2);
#endif
if(INVERSE) {
/* if(INVERSE) {
c1 = gp::get_mapped(c1);
c2 = gp::get_mapped(c2);
return UIU(celldistance(c1, c2)) / 2;
/* TODO */
}
// that does not seem to work
} */
if(euclid) return clueless_celldistance(c1, c2);
if(INVERSE) return clueless_celldistance(c1, c2);
return hyperbolic_celldistance(c1, c2);
}
@ -1239,6 +1536,12 @@ EX vector<cell*> build_shortest_path(cell *c1, cell *c2) {
}
EX void clearCellMemory() {
#if CAP_PORTALS
if(intra::in) {
intra::erase_all_maps();
return;
}
#endif
for(int i=0; i<isize(allmaps); i++)
if(allmaps[i])
delete allmaps[i];
@ -1271,33 +1574,48 @@ EX int neighborId(cell *ofWhat, cell *whichOne) {
EX int mine_adjacency_rule = 0;
EX map<cell*, vector<cell*>> adj_memo;
#if HDR
struct adj_data {
cell *c;
bool mirrored;
transmatrix T;
};
#endif
EX array<map<cell*, vector<adj_data>>, 2> adj_memo;
EX bool geometry_has_alt_mine_rule() {
if(S3 >= OINF) return false;
if(aperiodic) return true;
if(WDIM == 2) return valence() > 3;
if(WDIM == 3) return !among(geometry, gHoroHex, gCell5, gBitrunc3, gCell8, gECell8, gCell120, gECell120);
return true;
}
EX vector<cell*> adj_minefield_cells(cell *c) {
vector<cell*> res;
if(mine_adjacency_rule == 0 || !geometry_has_alt_mine_rule())
forCellCM(c2, c) res.push_back(c2);
EX vector<adj_data> adj_minefield_cells_full(cell *c) {
auto& am = adj_memo[mine_adjacency_rule];
if(am.count(c)) return am[c];
if(isize(am) > 10000) am.clear();
auto& res = am[c];
if(mine_adjacency_rule == 0 || !geometry_has_alt_mine_rule()) {
forCellIdCM(c2, i, c) res.emplace_back(adj_data{c2, c->c.mirror(i), currentmap->adj(c, i)});
}
else if(WDIM == 2) {
cellwalker cw(c, 0);
transmatrix T = Id;
T = T * currentmap->adj(c, 0);
cw += wstep;
cw++;
cellwalker cw1 = cw;
do {
res.push_back(cw.at);
res.emplace_back(adj_data{cw.at, cw.mirrored, T});
T = T * currentmap->adj(cw.at, cw.spin);
cw += wstep;
cw++;
if(cw.cpeek() == c) cw++;
}
while(cw != cw1);
}
else if(adj_memo.count(c)) return adj_memo[c];
else {
auto& ss = currentmap->get_cellshape(c);
const vector<hyperpoint>& vertices = ss.vertices_only_local;
@ -1313,22 +1631,32 @@ EX vector<cell*> adj_minefield_cells(cell *c) {
auto& vertices1 = ss1.vertices_only_local;
for(hyperpoint h: vertices) for(hyperpoint h2: vertices1)
if(hdist(h, T * h2) < 1e-6) shares = true;
if(shares) res.push_back(c1);
if(shares) res.emplace_back(adj_data{c1, det(T) < 0, T});
}
if(shares || c == c1) forCellIdEx(c2, i, c1) {
if(shares || c == c1) forCellIdCM(c2, i, c1) {
if(cl.listed(c2)) continue;
cl.add(c2);
M.push_back(T * currentmap->adj(c1, i));
}
}
// println(hlog, "adjacent to ", c, " = ", isize(res), " of ", isize(M));
adj_memo[c] = res;
}
return res;
}
EX vector<cell*> adj_minefield_cells(cell *c) {
vector<cell*> res;
auto ori = adj_minefield_cells_full(c);
for(auto p: ori) res.push_back(p.c);
if(hat::in()) {
// reduce repetitions
sort(res.begin(), res.end());
res.erase(std::unique(res.begin(), res.end()), res.end());
}
return res;
}
EX vector<int> reverse_directions(cell *c, int dir) {
if(PURE && !(kite::in() && WDIM == 2)) return reverse_directions(c->master, dir);
if(PURE && !(aperiodic && WDIM == 2)) return reverse_directions(c->master, dir);
int d = c->degree();
if(d & 1)
return { gmod(dir + c->type/2, c->type), gmod(dir + (c->type+1)/2, c->type) };
@ -1380,7 +1708,7 @@ EX vector<int> reverse_directions(heptagon *c, int dir) {
}
EX bool standard_tiling() {
return !arcm::in() && !kite::in() && !bt::in() && !arb::in() && !nonisotropic && !hybri;
return !arcm::in() && !aperiodic && !bt::in() && !arb::in() && (WDIM == 2 || !nonisotropic) && !mhybrid;
}
EX int valence() {
@ -1389,14 +1717,38 @@ EX int valence() {
#if CAP_ARCM
if(arcm::in()) return arcm::valence();
#endif
if(arb::in()) return arb::current.min_valence;
return S3;
}
/** portalspaces are not defined outside of a boundary */
EX bool is_boundary(cell *c) {
return (cgflags & qPORTALSPACE) && isWall(c->wall);
if(c == &out_of_bounds) return true;
return ((cgflags & qPORTALSPACE) || intra::in) && isWall(c->wall);
}
/** compute the distlimit for a tessellation automatically */
EX int auto_compute_range(cell *c) {
if(sphere) {
cgi.base_distlimit = SEE_ALL;
return SEE_ALL;
}
cgi.base_distlimit = 0;
const int expected_count = 400;
celllister cl(c, 1000, expected_count, NULL);
int z = isize(cl.dists);
int d = cl.dists.back();
while(cl.dists[z-1] == d) z--;
if(true) { // if(cgflags & DF_GEOM) {
println(hlog, "last distance = ", cl.dists.back());
println(hlog, "ball size = ", isize(cl.dists));
println(hlog, "previous ball size = ", z);
}
if(isize(cl.dists) * z > expected_count * expected_count) d--;
return ginf[geometry].distlimit[0] = cgi.base_distlimit = d;
}
EX cell out_of_bounds;
EX heptagon oob;
}

File diff suppressed because it is too large Load Diff

View File

@ -4453,3 +4453,829 @@ Bugfixes:
- Irradiated Field: bull generation no longer breaks ivy
- Fix several Friendly Ivy interactions
2021-08-01 11:19 Update 12.0e:
New features:
* better land boundaries in all (hyperbolic) 2D geometries, including Great Walls-like ones
* improved CR4 and Camelot generation
* tes files now support aperiodic (tree-based) tessellations and some other features, see "horotiling.tes" in samples
* HyperRogue is now able to generate strict tree-based rules to generate periodic tessellations
(including tes files and Archimedean, which previously were generated using other methods).
This way of generation avoids numerical precision errors and lets us understand the growth patterns
(experiment with geometry -> size of the world) and generate horocycles and Camelot. This
is currently disabled by default, but can be enabled in experiment with geometry -> size of the world -> strict.
* Dice hover map now indicates hardness with color (thanks to @jruderman)
* minor Russian translation updates (thanks to blargdag)
Bugfixes:
* fixed some issues with sky rendering in FPP (better stars and Palace ceiling)
* fixed incorrect graphics in binary tilings
* fixed bugs with moving the key with boats
* Princess Quest no longer shows fail screen merely due to the princess being in peril
2021-08-05 13:23 Update 12.0f:
* fixed fake geometry with 2D tessellations (many fixes)
* fractal landscapes for strict tree-based rules
* improved the memory performance of strict tree rules generator (see 12.0e)
* crossing Great Walls (CR3/Elemental Planes) for all 2D tessellations, fixed some bugs with Great Walls
* fixed switching places (message shown correctly, can't switch with saved tortoises and dice in peace mode)
* fixed possible bugs with Brownian colors, snake colors, interactions of arrow traps and terracotta warriors (thanks to @jruderman)
* fixed 3-dimensional elliptic space
* tes files: fixed a bug with 'ended at wrong edge determining vertex_valence'
2021-09-30 17:55 Update 12.0g:
Geometries/projections:
* new manifold (projective Bring surface)
* fixed the interesting dodecahedral quotient spaces (535c, 535s, 533s)
* fixed rotation spaces
* fixed a possible crash in Crystal
* fixes to the tree rule generator
* some Euclidean lands are now available only in single land mode
* two-sided display of hyperbolic disk with -1<projection<0
* load maps with intra-geometric portals
Gameplay bugfixes:
* Erase rosemap entries for deleted cells
* Orb of Trickery messages no longer reveal underwater items
* Add Orb error messages for Phasing and Vaulting
* improved ranged Orb error messages
* warning protection no longer evokes Flash/Lightning
* no more fatigue cost checking when the Curse is gone
* cleaned up where summoned creature appears for Orb of Life and Orb of Friendship
Other fixes:
* fixed PAGEDOWN rotating in the same direction as PAGEUP
* wall shadows no longer drawn with noshadow
* an option to disable sky drawing
* improved the CLI option to set the resolution
* mimics now destroyed correctly in the map editor
* parallel linepattern is now configurable
* fixed message about 9 treasure types in casual
2021-10-10 01:13 Update 12.0h:
- improvements to intra portals
- Solv maps and subdivided 3D maps are now saved correctly
- fixed a crash when generating daily, also Dice Reserve, Cursed Canyon, and the new walls should appear soon
- do not switch variation to pure when switching to Archimedean product
- fixed Archimedean dual product
- raycaster now works correctly in binary products
- binary product spaces now use curved shapes
- fixed some formulas in binary spaces, and made the default width equal to Solv
2021-12-12 23:06 Update 12.0i:
Gameplay:
- Hyperbugs now ignore the player in peace mode
- fixed the Nature + movement orb combo, without Empathy
- fixed the Nature + Slaying + Empathy combo
- Krakens no longer destroy player boats in peaceful mode
- fixed allies affecting Terracotta Warriors without actually moving next to them
- fixed reporting the Gardener achievement
Other:
- fixed grammar error 'Orb of the Love'
- fixed a bug in parsing unary -
- perf/edit setting in intra-geometric portals
- do not remove faraway treasures in 3D geometries (they are not that far away...)
- reduced the other land range for currentLocalTreasure in 3D geometries
- fixed openplains in nowalls mode
- fixed raycaster in 2dim geometries crashing
- the problem of moving in Cat geometry should be fixed
- stop crashing in Solv if coordinates are NAN
- fixed weird colors in coxeter
- fixes to rulegen
- refer to color by HTML name in commandline arguments, and an option to allocate more colors via CLI
- pseudohedral display mode in 2.5D
- TES files: a feature to add commandline options, and stars
2021-12-13 22:32 Update 12.0j:
- fixed the victory leaderboards (turns/time to Orb of Yendor/Hyperstones)
- fixed the starting land selection feature for equidistant-based lands
2022-02-03 01:07 Update 12.0k:
Orb-related fixes:
- Lazurite Figurines no longer appear immediately after using an Orb of Safety
- Orb of Chaos is now forbidden in the Dungeon
- Stunning from the Orb of Chaos now destroys birds/shadows just like the other sources of stunning
- Shadows are now affected by the Orb of Beauty
- Stunning the Shadow now temporarily destroys it
- draining Orb of Choice now happens after gaining the Purity extras
- Orb of Slaying now works against big trees
- draw fishtails on friends with empathy
Achievement fixes:
- fixed racing (official tracks are generated again and acknowledged)
- Princess Challenge and Heptagonal Knight achievements should be fixed
Geometry:
- more distinct colors in 'eight domains'
- improvements to tree rule generator
- Goldberg-Coxeter improvements (larger limits supported, warn if outside of the supported limits, some are fixed)
- fixed fat edges in some H3 honeycombs
- fixed some bugs with Multi-dimensional Crystal quotient space
2022-03-01 09:39 Update 12.0l:
Orb-related fixes:
- Curse of Repulsion now correctly marked when used
- when having Orb of Freedom + Orb of Time, other orbs are no longer drained by Freedom checks
- Valentine's Easter Egg: Add +1 extra charge to Orb of Love
Geometry:
- fixed VR in product geometries
- portals between geometries: fixed some formulas, walking mode
- fixed dark lines in binary tiling x R raycasting which happened when we got a=0 in quadratic equation
- made Yendor/Haunted sight radius consistent when the tiling is changed
- infinite generation for single-land Camelot now only happens in hyperbolic geometry (also fixes the missing Grail in Crystal)
- additions and fixes to RogueViz
Other:
- fixed Crossroads wiki links
- fixed some settings incorrectly showing a warning on editing (this also brings back the 'play music when out of focus' option)
2022-03-27 20:51 Update 12.0m:
Improvements to multiplayer:
- "split screen mode" can now be set explicitly (don't lose the other player, and don't tell the other player to go right, holonomy matters ;)
- an option to automatically adjust dual-focus projections to focus on both players (try it with inverted Joukowsky, two-point equidistant/azimuthal and band projections)
- an option to toggle friendly fire and self-hits in wrapped spaces
- an option to toggle player-vs-player (this disables limited lives)
- fixed the radar and cool fog in splitscreen
New options thanks to lottieratworld:
- idle animation option
- extra canvas-specific options (map editor->settings)
Other new features:
- mouse snapping feature in shape editor -- can be used to precisely measure distances and angles (press 'o' to select the point to measure from)
- when the player is hidden (e.g. in RogueViz visualizations) and the user tries to use WASD, display a hint that they should be using arrow keys instead
- prevent a crash when entering '(0,0)' in Archimedean
Rendering fixes:
- fixed levellines in hyperbolic
- in non-fake 2.5D the raycaster is now disabled by default
- fixed scale_at for cylindrical projections
- fixed the orientation of two-point azimuthal and two-point hybrid
Gameplay fixes:
- fixed the Orb of Safety not disappearing upon use in shmup+OSM
- fixed the displayed unlock rule for Crossroads III in Casual
2022-04-26 16:19 Update 12.0n:
Gameplay:
- Viziers were immune to some attacks in illogical circumstances -- this is no longer the case
- mirrors and non-orientable spaces now flip Alchemist Lab colors
- slime spills should now have deterministic effect when a cell is hit with slimes of both color simultaneously
- fixed Zebra-patterned lands in Zebra quotient space
- fixed Prairie in field quotient space
Graphical/writing bugfixes:
- the hyperboloid model of S2 (as an anolog of the hemisphere model of H2)
- fixed hadoken missiles not displaying correctly in shmup 3D
- fixed some floors scaled incorrectly when 'creature scale' is changed
- floating bubbles now should work correctly for Mirror Shards, Elemental Gems and Ancient Jewelry
- fixed the dice layering issue
- paper model designer and spiral renderer could crash because they were implemented without OpenGL -- should be fixed now
- "run away from the lava"
- Hell is no longer "the Hell"
Tes file format:
- repeat can now be declared before conway or c
- (unit)tile now accepts the last argument written as "*x", which copies the list x times and also automatically sets repeat (see regular.tes)
- as a special case, "*inf" produces apeirogonal or pseudogonal tiles with hidden splitting edges (regular.tes, pseudogons.tes, fake-inf-polygon.tes)
- arcmedge accepts "x:^q" which means that x can be repeated q times. Both x and q can be real, and x can be infinite (see regular.tes)
- new geometry definition "c2(v)" which automatically selects geometry based on the sign of v -- also arcmcurv command which produces appropriate v (see regular.tes)
- ideal vertices can now be with the bracket format (see inf.tes or ultratriangle.tes)
- min, max, ifz (if zero) functions and inf, MAX_EDGE, MAX_VALENCE constants in the parser
- integer sliders: change the integer values of sliders in the 'experiment with geometry' menu (contrary to real-value sliders, this resets the map) (see e.g. regular.tes)
CLI options:
- -animformula [formula] to change the timing of an animation
- -canvasfloor [f] sets the canvas floor type
- -keys [key list] simulates a list of keypresses
2022-04-28 00:03 Update 12.0o:
Fixed some bugs in the new features for tes, and also fixed spherical geometry.
2022-05-10 08:55 Update 12.0p:
- draw the side walls between shallow water and chasms
- the smooth movement option now works in the map editor (and some other special screens)
- "movement along geodesics" off now means that the movement is based on the Lie group exponentials (e.g. straight lines in simple view in rotiationally symmetric model of Nil)
- buggy window resizing should be fixed
- simplified display option for tes tilings with apeirogons
- RogueViz: fixed the VR for the portal demo, and some improvements to the impossibility presentation
2022-05-21 17:16 Update 12.0q:
- In 'experiments with geometry', added an option to play on a disk. This lets you use the "bounded space" rules on infinite manifolds. Especially useful with Minefield and Halloween.
- also improved the Halloween generation (outside of spheres)
- teleportation in bounded minesweeper no longer follows the limited range rule
- you can now display Minefield clues as numbers (right-click minefield to get its help screen where you can change this option)
- new projections mostly for Solv: Lie perspective and Lie orthogonal
2022-06-17 12:17 Update 12.0r:
Gameplay:
- ghosts prioritize attacking players over attacking allies
- fixed some Orbs not affecting slime
- Orb of the Sword can now kill yourself through mirror or topology
- sword attacks reflect in mirrors
- swords in mirrors are now displayed correctly
- mimic movements are now affected by Empathy, and no longer can reverse slime colors by going through mirror
- Woods+Time: do not waste charge on attacking monsters in trees
- fixed help for life Orbs in the shmup mode
- Halloween:: fixed the jack-o-lantern
- the Racing mode now loads pre-generated files instead of trusting the track will be generated in the same way
- you can also edit the Racing tracks and save them ()
- Hall of Mirror maps should now be saved correctly
- fixed a crash bug in computing minefield neighborhoods in some tilings
- fixed sl2 rendering
Menu improvements:
- unified the quest status (previously ESC) and main menu (previously V) into a single screen ("game menu")
- 'creative mode' is moved to the game menu
- a cleanup to some menus (special modes, highlights, peace&exploration)
- dual geometry puzzle removed (will still be available in RogueViz)
- switching shmup mode no longer invokes keyboard configuration
2022-06-23 10:50 Update 12.0s:
- fixed Minesweeper in the highlights menu
- fixed the racers keeping their speed when restarting
- when generating strict tree maps for Archimedean/regular tessellation, you now have an option to have all the symmetries of the tessellation taken into account (to minimize the tree)
- tes files with tree data (tessellations/sample/horotiling.tes) and star tes files (tessellations/sample/star-7-72.tes) should load correctly again
- show treasure bubbles in the Dice Reserve
- Shift+A key leaves the map editor, also all options are now displayed in the cheat menu (some obsolete ones are removed)
2022-07-05 14:12 Update 12.0t:
Tranlations and bugfixes:
- French translation by 3raven (42% complete and untested yet)
- fixed the Polish translation of the description of False Princess
- a bug where some racing times are set to 0 should now be fixed
Menu improvements:
- fixed the help button in the pause menu
- you can now configure by how much you want to darken the background in the menu
- menu display should be more consistent now
- in sidescreen menus, the background under the menu is now darkened
- start animations now can be disabled
- nicer sliders and color selectors (unless the ASCII mode is on)
2022-07-12 14:47 Update 12.0u:
- honeycomb tree rules for 345 and 355 (better performance, variations work)
- some fixes to the French translation
- options to show less items/kills in the portrait/landscape mode
- an option to have menus centered even in widescreen
- mobile fixes: fixed an incorrect button shown in the mobile game menu, and items/kills going over buttons
2022-07-17 14:47 Update 12.0v:
- fixes for new Android
- preliminary work on tree structures for 3D honeycombs
- auto-rotation (Ivory Tower etc.) now works on devices who know their orientation
- nicer "pipes" (fat grid lines) in 3D
- fixed some crash bugs related to the memory saving mode
2022-08-07 03:03 Update 12.0w:
- fixed a bug with 'world overview' breaking ESC menu
- racing fixed (hopefully)
- minor changes to HyperRogue help: now directly offered when displaying context help; do not suggest to try the Guided Tour if already in the Guided Tour
- made the RogueViz presentations which contain no HyperRogue PC easier to control (control the camera by using the keys which usually move the PC)
- added some more demos to RogueViz
2022-08-07 15:01 Update 12.0x:
- yet another fix to racing
- fixed a crash when deleting 3-sphere maps
2022-08-26 13:46 Update 12.0y:
- new implemenatation of hyperbolic honeycombs in action
- field quotients in 3D now finds more honeycombs
- variations now work for Euclidean cube tiling
- tessellation, texture, etc. files can now be found via HYPERPATH
- fixed the Slaying+side attack combo
- Pearls now use the Disk graphics
- Added some land incompatibilities
- updates to French translation
- fixes to stereographic projection (as a way to get high FOV)
2022-09-06 14:20 Update 12.0z:
- various fixes related to 'orb used' rollback
- fixed Sol geometry (a bug caused the map to change incorrectly when moving)
- fixed variations of hyperbolic honeycombs (when a ruleset was available only for the pure honeycomb, loading it would reset variation to pure)
2022-09-15 12:40 Update 12.1:
- documentation for TES files added
- an option to select the savefile on startup (settings -> other settings)
- fixed missing 'too far' messages on Frog-like orbs
- fixed Teleport and Illusion draining Aether etc on mousing (disregarding Time)
- fixed a crash problem with tes files in 2.5D
- fixed a possible crash in raytracer
- when tes files are loaded, football-colorability is now detected (and used to improve the graphics and gameplay)
- GPU glitches when rendering long bands should be no more
- fixed the loading of tessellations/affine/affine-square.tes
- fixed the crash on converting regular/Archimedean tilings to tes format and generating tree rules
- improvements to line patterns
- fixed a possible crash when saving images
2022-09-17 12:12 Update 12.1a:
- fixed Orb of Teleport/Illusion thinking that they are unusable
- Orb of Earth no longer marked useless in Wetland
- some fixes for the treasure/kill list: fixed the Onyx graphics; made some icons larger; dark stuff have their text brightened (or use the auxiliary orb color)
- the monster movement order is more random now (no preference for clockwise)
2022-10-06 13:13 Update 12.1b:
- Orb icons thanks to Jacob Mandelson. (Can be disabled in general settings)
- hostile dice are highlighted
- racing mode fixes: the menu shows whether an official track is on; the settings are set correctly, and land structure is ignored for the achievement
- Orb of Choice now works with Orb of Safety
- an option to arbitrarily change the width of tile boundaries (in 'patterns' menu)
- the option to debug tile/edge/vertexs IDs in the 'experiments with geometry' menu (if a tes file is on, but it works in general)
- tes format now supports declaring a tile as having a mirror symmetry
- tile-type display now displays mirror images as the same color (or slightly different colors, depending on settings)
- tile-type display no longer assigns different colors depending on football type
- when editing color tables, it is now possible to add more colors
- Crystal World and Snake Nest were legal in some tilings but they did not actually appear -- should be fixed
- vertical strafe in walkingmode no longer brings eye level below 0
2022-10-08 02:14 Update 12.1c:
- some improvements to tes file support. Mirrored tiles should now work for apeirogons. Valence check and thus football colorability should now work with affine/star tessellations.
- also included more tes samples
2022-10-27 15:53 Update 12.1d:
- Various menus displaying lists now use a nicer list widget (including the file dialog and map editor selection).
- Map editor improvements:
- - "building mode", which allows Minecraft-style building in 3D geometries
- - shift-clicking in the map editor now deletes stuff
- - improvements to portal spaces, including easier creation (convert to portal space from the map editor -> settings, then you can add new worlds from save files)
- improvements to SL(2,R) and similar:
- - nonisotropic range parameters now work in all perspective modes
- - Panini in all perspective modes
- - more projections possible for SL(2,R)
- - fixed the 'penrose staircases' on wall blocks in rotation spaces
- 'load from file' appears directly in the geometry menu in 'experiments with geometry'
- achievements disabled in ineligible starting lands
- limit on pauses in the racing mode
- fixed the ogg files
2022-11-04 23:58 Update 12.1e:
- fixed some bugs with editing portal spaces
- some fixes in help text
- page buttons in PTM are back
- layout in Yendor should be improved
- fixed buggy generation when setting Elemental Wall as cheat destination
- file dialog improvements (more options, automatically set position, search mode)
- fixes to the shmup mode:
- - Gadflies no longer appear forever with high Spinel counts
- - pause count is no longer displayed in non-racing; also reset to 0
- - fixed pink tortoises appearing in Galápagos
- - Bulls now correctly destroy walls they crash into
- - fixed wrong time used in some places (running time instead of game time)
- - fixed the Flail Guards
2022-12-09 02:38 Update 12.1f:
- WIP: In '3d settings' menu for 2D maps, you can now select the way how the 2D map will be embedded into a 3D space (space of the same curvature as flat/concave/convex eequidistant, space of lower curvature, product space).
The basic functionality should work, but there are probably some bugs and lots of missing features (to do: shmup, raycasting, fog, radar, more intuitive menu, better default settings, embedding into nonisotropic geometries).
On the way also some bugs with 2.5D should be fixed ("draw sky" disabled now also disables Euclidean sky; correct movement if the surface the camera moves on is not flat; fixed sky colors; fixed the radar transform computation in 2.5D which also affected fog rendering).
- fixed: inventory glyphs were missing outlines due to a bug
- improved the display in OSM when using orb icons
- Give the Plane of Fire a redder floor than CR4 (thanks to jlm)
- Draw mimics with sword in left hand if PC's sword in left hand (thanks to jlm)
2022-12-18 00:59 Update 12.1g:
Further improvements to the "3D style" (embed 2D in a 3D geometry) feature:
- more intuitive settings
- kite-and-dart and tes should now work correctly
- Lower and Much Lower curvature settings are now respected even if it was already hyperbolic
- pure regular Euclidean hex/square tilings can now be embedded in Nil and Sol/NIH
- binary tiling and similar can now be embedded in Nil and Sol/NIH
- shmup should work now
- fixed sky over irregular map
- fixed slime size
There are still some bugs to fix, but it should mostly work now. And there are more embeddings coming :)
Other bugfixes:
- fixed coloring of info items
- fixed centering on reset
- disabling geodesic movement in Sol/Nil now also assumes that light moves along Lie lines, and shmup monsters move correctly too
- fixed grid drawing for binary variants
2023-01-08 00:59 Update 12.1h:
Bug fixes:
- fixed context help getting stuck in corner stats mode
- fixed Princess AI using boat
- shallow water is no longer glitched when the 3D settings are illegal
Further improvements to the "3D style" (embed 2D in a 3D geometry) feature:
- four new embeddings of Euclidean space: Clifford torus (S3), product space (H2xR, S2xR), and SL2
- Hypersian Rug options are now linked in 3D settings
- fixed movement animations
- better diagnostics when an embedding does not work
- fixed a bug rendering band model without shader
2023-02-05 11:27 Update 12.1i:
Further improvements to the "3D style" (embed 2D in a 3D geometry) feature:
- Overall better design fixes various small errors, including nicer floor shapes, radar, shmup, and 3D models.
- Six new embeddings of the Euclidean cylinder.
- Hints how to change settings if the current embedding does not work.
- some crashes have been fixed (in Zebra/ Reptiles, thanks to Masala for the report; also crashes related to possible missing shadow models)
Also fixed a bug generating Dice in some tessellations.
2023-02-22 00:31 Update 12.1j:
Further fixes and improvements to the "3d style" (embed 2D in a 3D geometry) feature:
- more settings (regarding altitudes) are now configurable
- fixed VR (correct gravity alignment and eye position computation), also added new headset setting "holonomy Z" for embedded planes (also fixed a bug causing spinning in VR)
- fixed some minor bugs with "same curvature" and "product" embeddings
- fixed "SL(2,R) cylinder" (it was not actually implemented)
- full floors now used by default (also floor shape setting has other options now)
- when you change the settings, the engine now tries to keep as much as possible (e.g., remap the camera position)
- no shadow option now disables monster shadows
- fixed a bug with Goldberg embeddings
Other fixes:
- fixed key conflict for the cell boundaries option
- fixed an error computing distances in bitruncated {5,4} causing crashes
- when you die in the racing mode, you just die without obtaining etherality (possible when you change the land e.g. to Rose Garden or Land of Storms)
- fixed single tile pattern for texture mode in spherical geometry; also changing the pattern in texture mode no longer affects map editor pattern
2023-03-23 09:34 Update 12.1k:
Aperiodic tilings:
- "Aperiodic Hat" tiling [ https://arxiv.org/pdf/2303.10798.pdf ]
- adjacency rule (for Minefield) now changeable in aperiodic tilings
- patched chaos now works in aperiodic tilings
- nicer tile borders in aperiodic tilings
New projections:
- nicer Conformal Square projection (with transition and shader, and all 2D geometries)
- horocyclic equal-area projection
- change axe angle in axial-like projections
Line patterns:
- more configuration for meridian/parallel patterns
- new linepattern "tessellation walls"
Other:
- better fog color in 3D ball model
2023-03-25 09:28 Update 12.1l:
Improvements to the "aperiodic hat":
- better centering
- fixed a bug creating bad tiles
- "hat parameter" transforms continuously (as in Section 6 of https://arxiv.org/pdf/2303.10798.pdf)
- better pseudo-heptagon assignment (for Graveyard/RRV/etc)
- improved Jungle, Land of Storms, Palace
- "fake curvature" works with hat now
Other fixes:
- do not display relativistic modes in model list
- an option to not display default help (in "basic interface")
2023-03-26 09:41 Update 12.1m:
- Fixed some crashes when changing the hat parameter, embedding hat, while embedding tessellation from file, using hat with fake geometry. Also fake geometry now appears in the menu for hat.
2023-03-28 22:58 Update 12.1n:
- Aperiodic Hat fixes:
- - fixed Frog Park (jump rules and graphics)
- - fixed the Terracotta display (lines displayed, but they are not accurate, so cells are marked too)
- - interesting values of the hat parameter are displayed in hat parameter config
- - special welcome message
- fixed crashes and floor graphics in Zebra in some geometries (hat, kite-and-dart)
- Swap the Red Troll's hair & fur colors (thanks to @jlmjlm)
- Experimental fractal geometries (experiment with geometry -> Euclidean)
- fixed Terracotta in Euclidean disk
2023-03-29 09:10 Update 12.1o:
- fixed the orientation in the hat tiling
- fixed bugs when regenerating a map in the hat tiling + embedding
- fixed variation not showing in some geometries
2023-05-19 01:15 Update 12.1p:
Mostly embedding-related improvements:
- embedding scale parameter now works in "lower curvature" (horospher) embedding (redundant, but useful)
- better wall shading in EuclidSquare embeddings
- many embedding-related fixes
- "Non-Euclidean Third Dimension" demo (of embeddings) in RogueViz
(also, the "imaginary" hat parameter)
2023-05-31 02:18 Update 12.1q:
- Aperiodic Spectre tiling [https://arxiv.org/abs/2305.17743]
- fixed embeddings of Archimedean tilings
- Berger sphere should now work correctly with subdivided cells
- new options mostly for 3D visualizations: circumscribed pseudohedra (a new option in 'make the tiles flat' in 3D config), use plain non-textured floors with alpha transparency (not in menus, find setting 'draw_plain_floors' and 'floor_alpha'); 'big triangular grid' line pattern should now work in Euclidean "Goldberg"
2023-07-21 09:32 Update 12.1r -- mostly minor bugfixes:
- fixed a bug with apeirogonal tiles
- fixed some bugs with the "ball projection" of anisotropic geometries
- fixed stereo_alpha in some geometries
- fixed the combinations of Archimedean, fake, and embedding
- "pipes" (fat grid lines) for anisotropic geometries
2023-08-16 09:32 Update 12.1s
- Most angles are now specified using a special dialog (rather than degrees, or a bunch of degree values in the 3D case). This is more powerful (more intuitive in 3D cases; 3D rotations like 'camera angle' and '3D model rotation' became 3D).
- Fixes to how hyperboloid/hemisphere/ball models are rendered
- Minor improvements to the number dialogs (immediately visible effects, etc.) and parameter (animation formulas allowed in more places)
- Fixed centering in multiplayer
- Fixed a bug which caused the screen to disappear on switch-to-fpp
- Fixed the movement in Nil geometry
- Fixed a crash when changing sight range while in rug
2023-09-15 07:48 Update 12.1t
- fixed a crash on projection changing
- two new land structure options: horodisk and ideal Voronoi
2023-09-19 08:01 Update 12.1u
Fixes to the Horodisk/ideal Voronoi land structures:
- horodisk mode now has a parameter controlling perfection vs density, and is set by default to generate less dense but perfect horocycles
- Ivory Tower, Hive, and Galápagos join the H/V modes (also getting some interesting modifications from standard)
- fixed some lands (Ocean/Lost Memory/Space Rocks/Eclectic) spilling when restarted in Safety in h/v mode
- fixed a part of generation not being executed, or being executed for the starting land rather than the actual land, in some lands (e.g. Krakens not appearing)
- more careful land incompatibility handling in voronoi
2023-09-22 13:00 Update 12.1v
- fixed land generation becoming glitched in standard modes when Lost Mountain or Clearing becomes unlocked
- fixed some lands not appearing in horodisk (Caribbean, Kraken, Whirlpool, Rlyeh, Temple, Haunted)
- fixed roses and dragons not appearing in h/v
- horocyclic variants of Warped Coast and Elemental Plains
- the "random walk" land structure now has a parameter controlling the land size
2023-10-05 14:12 Update 12.1w:
- reverted the unintentional change which caused holes to appear in the platforms on Ivory Tower
- fixed model color not taken into account in sphere stereographic projection
- Prairie joins the horodisk land structure
- fixed Hives missing in ideal Voronoi land structure
- fixed some tiles pre-marked as mines in Minefield next to Ivory Tower in Voronoi land structure
- fixed burial mounds not appearing in chaos/h/v land structures
2023-10-29 09:13 Update 12.1x:
- a new alternative mode where the Rogue fights with a crossbow. Currently testing, so no achievements yet.
- friendly ghosts are now flagged as non-living (thanks to @jlm)
2023-10-30 10:16 Update 12.1y:
Updates to the crossbow mode:
- no time passes when shooting while unstable
- graves, shrubs, and Round Table no longer block the line of fire (but shooting through half-vines do)
- fixed the 3D graphics
- fixed some bugs with fire mode not disabling correctly
- crossbows mimics no longer attack in melee, and it is also no longer possible to swing at mirrors with crossbow
- crossbow moves are no longer considered valid moves for the checkmate rule when the crossbow is not loaded
- improved messages
- in fire mode, no longer display ranged orb icons on mousing
- crossbow now shoots the targets in the logical order
- fire mode now can be enabled even while reloading, for more consistency and examination
- clarify that the Water Elemental special case only affects melee
- fixed the bug which made the crossbow not pierce dragons
- fixed the bug which made saving tortoises not possible
- attacking guarding dogs now wakes up all other existing guarding dogs, and causes a small ambush (this fix also affects other ranged attacks)
- fixed crossbow mode not changing the PTM/etc. scoreboards
- mode change confirmation is now only required when actually changing a relevant option
- new aim style 'geometric'
2023-12-02 12:54 Update 12.1z:
Gameplay (mostly crossbow modes)
- an option to automatically shoot when clicking a tile with mouse
- press 'f' + direction for auto fire at distant enemies in the given direction
- bulls are now enraged by crossbow shots
- ratlings no longer move when shooting pointlessly
- the warped space distracts you from reloading while staying in place
- Warped Coast/Sea now prevents crossbow bolts from moving between triangles
- clarified that only direct melee attacks trigger Storms/Flash
- fixed Horns in the crossbow mode; the unarmed Princess is now also able to use Empathy+Thorns and Empathy+Horns
- reduced CR3 land requirement to 20 in casual
Other
- fixed the drawing mode on quotient spaces (including torus display)
- fixed point recognition in rug mode
- cleaned up high-FOV and stereo modes into one setting
2023-12-27 12:54 Update 13.0:
Summary post: https://zenorogue.blogspot.com/2023/12/hyperrogue-130.html
Voronoi mode fixes:
- fixed Caribbean
- made Rlyeh and Temple appear, and Haunted and Free Fall are now unavailable
- better land compatibility
- fixed CR2
- fixed Land of Storms (in Horodisk and Voronoi)
Crossbow fixes:
- in shmup, crossbow bolts now pierce multi-tile monsters, and fire-on-mouse is disabled
- remove crossbow paths on orb use
- pressing ESC key while in fire mode now disables the fire mode
- geometric crossbow can now hit monsters on the edge of vision and inside walls
- crossbow achievements and leaderboards
- fixed false game over messages after shooting a bow
other updates:
- updated the Czech and Polish translations
- display achievement eligiblity
- make the Key fireproof; make tortoise if first 21/21 tile created in > 100 turns (thanks to jlm)
Other fixes:
- fixed restoring golems in casual mode
- fixed a crash while loading races
- fixed a bug with embedded maps (i.e., 2D maps in 3D) being destroyed when the game is restarted
- fixed the drawing of half-vines and mirror walls in spatial
- fixed the bug where tides may move on orb use
- fixed Sol, NIH and SolN embeddings being always displayed as legal
- fixed the name displayed on mouseover for slime
2024-01-12 08:59 Update 13.0a:
- fixed some bugs with high-FOV modes (reset shaders, show upper FOV ranges correctly, buggy two-eye rendering)
- as a new positive, the Curse of Fatigue makes you not care about roses when very fatigued
- changed one Prince(ss) message
- crossbow leaderboards should be fixed
- fixed button placement on Android once more
- fixed mirrors in crossbow fire mode
- the bump-to-shoot flag now actually works
- fixed a bug in "memory saving" mode to not remove the current altmap
- variant fisheye projection
- fixed tides in shmup and when scrolling
- the dipping rule no longer affects Tiger's Eyes
- screenshots were sometimes not correctly centered
2024-02-23 01:34 Update 13.0b:
When you are checkmated or die, a message explaining the cause is now displayed in the quit screen and saved in the local score file.
Crossbow fixes:
- opening inventory mode when you can just shoot should be fixed
- rusaÅka curses now work
- fixed tricking Pikemen with a bow
- while rosed, you can now only shoot when this kills a monster at point blank in the rose direction
Crash fixes:
- fixed crash when e.g. entering 'ma' as a value, or when editing some settings such as sight range bonus
- fixed a crash when viewing help on tide tiles (thanks to jlm)
- fixed a crash with too large band
- fixed some cases where untruncated/unrectified/warped maps would freeze when computing distances or crash due to trees are not known
Gameplay fixes:
- restarting a race now resets pause counter
- World Turtle kills are recorded (thanks to jlm)
- boat can go thru non-adjacent using Orb of Warp in shmup
- fixed the items (key, OoY, baby tortoise) moved by the Orb of Chaos and Curse of Repulsion
- fixed the Yard bug (graveless graveyard when you somehow used Orb of Safety in the Haunted Woods strip)
- Trollheim no longer generates adjacent non-unlocked troll lands
- alternative land unlock rules when monster/item requested is not available due to geometry etc
Other:
- in Goldberg variation, x/y limit is now based on what the engine allows, and 'dual of current' no longer can circumvent the limits
- New projection: polar coordinates
2024-02-24 09:54 Update 13.0c:
- fixed the off-by-one error in thehelp line displayed for tides and lava
- fixed a bug with rusalka-cursing the first tile when you shoot
- when you press ESC in the gameover screen, the YASC message is displayed
- special YASC message for pinches, and being on the Round Table
- in YASC messages, mention the knights blocking the way, and also mention their names
2024-03-24 11:32 Update 13.0d:
System:
* itch.io Windows binaries and Steam Windows/Linux binaries now use SDL2 instead of SDL1.2
Custom mode:
* A new mode where you can select the lands to be used.
* Another menu can be used to save a mode to a file.
* Enabling Halloween or Space Rocks in infinite geometries now produces something that makes sense.
* Previously changing the creature scale was disabled in non-cheat shmup. Now it can be changed (but it counts as a cheat).
* New land structure 'landscape'.
Graphics:
* Font scale used in ASCII maps now can be changed.
* Items moved by Orb of Water, Magnetism, Winter, Space, and Repulsion are now animated.
* VR: fixed items, Ivy, compasses, etc. being placed incorrectly in 2.5D.
* VR: compass/Yendor targets now should be displayed.
Gameplay:
* Void Beasts are now pulled by Orb of Air.
* Changed the electrical properties of some walls to make Eclectic City more friendly.
* Trees etc are now mentioned as blockers in YASC messages.
* YASC codes work better if killed on a 10+ tile.
Alternate geometries:
* Clear more walls when generating Wild West in high GP.
* Better Emerald in Octagon chamfered.
* Fixed Emerald Mine and Vineyard generating very bad in {n,oo} and binary tiling.
* Fixed the lack of non-trapdoors in Zebra 435.
* Better 'pseudohept' tiles in INVERSE tilings.
* In grid mode, don't try to draw greatwall lines outside of normal geometry pure/bitruncated.
* Nicer cell boundaries used in Archimedean and irregular tilings.
* When you save an irregular map using Orb of Safety or map editor (or custom mode), it should now save the irregular map used.
Bug fixes:
* Fixed dice hints over different heights.
* Fixed troll nests in Horodisk/Voronoi.
* Fixed a crash when running away from Clearing in single-land mode.
* Some values are tracked in savefiles while previously they did not (fatigue, snake oil, crossbow reload time, gun ammo, etc.) (Thanks to jlm)
2024-03-24 20:10 Update 13.0e:
* in Steam, option `-achievement-always` to always display achievements, even if you already got them.
* rosebushes now show up on the radar in 3D geometries, and they now blink if they are close to going off
* if you are in water (and have no Fish), you can now see Orbs of Fish and Aether in adjacent water tiles, and also you can move there and pick them up
* crossbow bolt now ignore rose restrictions on attack
* migrating to SDL2 caused crashes in shmup, with the game_keys_scroll option, and with the shift-target option -- this should be fixed
* 'custom' land list mode is now mentioned in the watermark (bottom left of the screen)
2024-03-27 23:47 Update 13.0f:
* new messages on Orb of Phasing, Slaying, and Weakness
* more accurate messages on dice pushing
* when loading save, load full mode data including custom lands
* irregular maps no longer change on every load due to floating point precision
* [custom lands list] Space Rock monsters now drop treasure only if in Space Rock land
* ineligible starting land also if land is not in game
* [custom lands list] do not freeze if no new sealand is available
* in countHyperstones, two variants of Mirror are counted once
* specially generated lands (horocycles, Brown Islands) now respect Unlocked and LandIngame rules
* fixed some more crashes related to SDL2 (e.g., right-click in shmup)
2024-04-09 02:46 Update 13.0g:
- New land structures: CR2-like, CR3-like, and "cursed"
- Space Rocks and Halloween stuff are now saved correctly (thanks to jlm)
- since the Aether users now see adjacent items in water, they can also pick them up
- fixed the bug where moving a boat with Compass would cause items to be picked up
- pushing an exploding barrel on a mine now causes an explosion
- fixed pressing numpad keys with numpad on acting both as moves and quick-keys
- a new pseudoheptagon pattern in standard binary and ternary tiling
- fixed the Free Fall being not inaccessible from some lands
- auto-pause shmup game when it loses focus
- fixed some possible crashes: with keys being generated on ivy, when using Orb of Space on Orb of Safety, Ocean in the chaos modes, after killing 400 mutants, when generating YASC message
2024-05-09 10:45 Update 13.0h
- Orb of Summoning now works on deep water, shallow water, and Camelot moat tiles
- more settings for minefield graphics
- removed Haunted and Elemental from the landscape mode
- stone gargoyles and statues are now non-blocking for missiles
- Orb of Earth now cancels Invisibility only if it is doing something
- new line pattern 'wall highlight', and also line patterns are now easier to reach (via creative mode)
- fixed the Yendor beacon to appear in the correct place (usually on the boundary, not the closest visible tile)
Minor bug fixes:
- some leaderboards still activated when custom_land_list was used
- fixed CR3 generated in CR2 layout
- fixed CR2 generated in CR3/CR4 layouts
- fixed single wrong tile of the first land when safetying in landscape etc
- fixed 534 distance computation
- fixed CLI -picload
- clear boats from removed Orbs of Water
- fixed a crash setting landscape_div to 0
- fixed a crash with irregular spherical maps
- show weapon watermark with geometric xbow (thanks to @jlm)
2024-05-10 19:36 Update 13.0i
- reverted numlock fix on MAC since it apparently does not work as expected
- right shift no longer assumes mouse-strafe if no mouse moved
- fixed the "display zeros in minefield" option
- fixed crashes when adding/deleting colors
- rosewaves no longer go through the fake cells in Crystal World
- changed the guarding in Power landscape
- display Compass and Orb of Yendor beacon on radar
- fixed some problems with tides (thanks to jlm)
2024-05-28 19:35 Update 13.0j
- display charge count for all orbs, and activation costs for frog-like orbs
- "(v) menu" can now be replaced to show turn count or another parameter/formula
- Orb of Luck now removes the blue bug bias
- fixed the shape pattern for converted tilings
- fixed a bug in the tessellation converter
- the game spent 5s on startup initializing SDL joysticks -- this now can be avoided
- chainspilling lava slimes
- more explanation is now available for ON/OFF parameters
- fixed product rendering
- fixed model orientation for spiral
- fixed a crash when changing the 'race angle' setting
- fixed a possible crash when trying to build CR2 or CR5 next to CR4
Changes to the parameter/formula system:
- more values and functions are now available in formulas (including the new color formulas, including the 'formula' canvas pattern)
2024-05-28 20:21 Update 13.0k
- fixed orb change display
- fixed backward incompatible color reading from config
- fixed symbol changed enable archimedean unexpectedly
2024-05-29 13:54 Update 13.0l
- fixed some more errors with the config file
- show charges for Orb of Air, also fixed the line for Orb Energy
- fixed some characters not being enterable in SDL2

View File

@ -27,29 +27,49 @@ EX bool canmove = true;
// how many monsters are near
EX eMonster who_kills_me;
EX cell *who_kills_me_cell;
EX int lastkills;
EX vector<bool> legalmoves;
/* why is a move illegal */
EX vector<int> move_issues;
#if HDR
static const int miVALID = 10000;
static const int miENTITY = 11000;
static const int miRESTRICTED = 10100;
static const int miTHREAT = 10010;
static const int miWALL = 10001;
struct moveissue {
int type;
int subtype;
eMonster monster;
cell *where;
};
static constexpr int miVALID = 10000;
static constexpr int miENTITY = 11000;
static constexpr int miRESTRICTED = 10100;
static constexpr int miTHREAT = 10010;
static constexpr int miWALL = 10001;
static constexpr int siWALL = 1;
static constexpr int siMONSTER = 2;
static constexpr int siGRAVITY = 3;
static constexpr int siROSE = 4;
static constexpr int siITEM = 5;
static constexpr int siWIND = 6;
static constexpr int siCURRENT = 7;
static constexpr int siFATIGUE = 8;
static constexpr int siWARP = 9;
static constexpr int siUNKNOWN = 10;
#endif
EX int checked_move_issue;
/* why is a move illegal */
EX vector<moveissue> move_issues;
EX moveissue checked_move_issue;
EX moveissue stay_issue;
EX int yasc_code;
EX void check_if_monster() {
eMonster m = cwt.peek()->monst;
if(m && m != passive_switch && !isFriendly(m))
checked_move_issue = miENTITY;
checked_move_issue = moveissue { miENTITY, siMONSTER, m, cwt.peek() };
}
EX bool hasSafeOrb(cell *c) {
@ -108,14 +128,14 @@ EX bool monstersnear(cell *c, eMonster who) {
bool kraken_will_destroy_boat = false;
elec::builder b;
if(elec::affected(c)) { who_kills_me = moLightningBolt; res++; }
if(elec::affected(c)) { who_kills_me = moLightningBolt; who_kills_me_cell = nullptr; res++; }
if(c->wall == waArrowTrap && c->wparam == 2) {
who_kills_me = moArrowTrap; res++;
who_kills_me = moArrowTrap; who_kills_me_cell = nullptr; res++;
}
for(auto c1: crush_now) if(c == c1) {
who_kills_me = moCrusher; res++;
who_kills_me = moCrusher; who_kills_me_cell = nullptr; res++;
}
if(who == moPlayer || items[itOrbEmpathy]) {
@ -126,7 +146,7 @@ EX bool monstersnear(cell *c, eMonster who) {
if(havewhat&HF_OUTLAW) {
for(cell *c1: gun_targets(c))
if(c1->monst == moOutlaw && !c1->stuntime) {
res++; who_kills_me = moOutlaw;
res++; who_kills_me = moOutlaw; who_kills_me_cell = c1;
}
}
@ -157,18 +177,16 @@ EX bool monstersnear(cell *c, eMonster who) {
}
// flashwitches cannot attack if it would kill another enemy
if(c3->monst == moWitchFlash && flashWouldKill(c3, 0)) continue;
res++, who_kills_me = c3->monst;
res++, who_kills_me = c3->monst; who_kills_me_cell = c3;
}
// consider normal monsters
if(c2 &&
isArmedEnemy(c2, who) &&
(c2->monst != moLancer || isUnarmed(who) || !logical_adjacent(c, who, c2))) {
if(c2 && isArmedEnemy(c2, who)) {
eMonster m = c2->monst;
if(elec::affected(c2)) continue;
if(fast && c2->monst != moWitchSpeed) continue;
// Krakens just destroy boats
if(who == moPlayer && c2->monst == moKrakenT && c->wall == waBoat) {
if(who == moPlayer && c2->monst == moKrakenT && c->wall == waBoat && !peace::on) {
kraken_will_destroy_boat = true;
continue;
}
@ -179,12 +197,12 @@ EX bool monstersnear(cell *c, eMonster who) {
eaten = true;
else if(c2->monst != moHexSnake) continue;
}
res++, who_kills_me = m;
res++, who_kills_me = m; who_kills_me_cell = c2;
}
}
if(kraken_will_destroy_boat && !krakensafe(c) && warningprotection(XLAT("This move appears dangerous -- are you sure?"))) {
if (res == 0) who_kills_me = moWarning;
if (res == 0) who_kills_me = moWarning; who_kills_me_cell = nullptr;
res++;
} else {
if(who == moPlayer && res && (markOrb2(itOrbShield) || markOrb2(itOrbShell)) && !eaten)
@ -200,8 +218,6 @@ EX bool monstersnear_aux() {
changes.value_set(passive_switch, (gold() & 1) ? moSwitch1 : moSwitch2);
multi::cpid++;
bool b = false;
bool recorduse[ittypes];
for(int i=0; i<ittypes; i++) recorduse[i] = orbused[i];
if(multi::cpid == multi::players || multi::players == 1 || multi::checkonly) {
if(shmup::delayed_safety) return false;
@ -235,12 +251,15 @@ EX bool monstersnear_aux() {
}
else b = !multimove();
multi::cpid--;
for(int i=0; i<ittypes; i++) orbused[i] = recorduse[i];
return b;
}
/** like monstersnear but add the potential moves of other players into account */
EX bool monstersnear_add_pmi(player_move_info pmi0) {
if(suicidal) {
who_kills_me = moPlayer; who_kills_me_cell = nullptr;
return true;
}
pmi.push_back(pmi0);
bool b = monstersnear_aux();
pmi.pop_back();
@ -279,6 +298,110 @@ EX bool swordConflict(const player_move_info& sm1, const player_move_info& sm2)
return false;
}
EX string yasc_message;
EX string blocking_monster_name(const moveissue& mi) {
if(mi.monster == moKnight && mi.where)
return XLAT("%1 the Knight", camelot::knight_name(mi.where));
else
return dnameof(mi.monster);
}
EX void create_yasc_message() {
set<pair<cell*, string>> captures;
auto all = move_issues;
all.push_back(stay_issue);
for(auto c: all) if(c.type == miTHREAT) captures.emplace(c.where, blocking_monster_name(c));
vector<string> context;
if(!captures.empty()) {
string msg = "captured by ";
map<string, int> qties;
for(auto ca: captures) qties[ca.second]++;
int iqties = 0;
for(auto q: qties) {
if(iqties && iqties == isize(qties) - 1) msg += " and ";
else if(iqties) msg += ", ";
msg += q.first;
if(q.second > 1) msg += " (x" + its(q.second) + ")";
iqties++;
}
context.push_back(msg);
}
int idx = 0;
for(auto c: all) if(idx == 0 && c.subtype == siROSE) context.push_back("rosed"), idx = 1;
for(auto c: all) if(idx < 2 && c.subtype == siWIND) context.push_back("blown away"), idx = 2;
for(auto c: all) if(idx < 3 && c.subtype == siGRAVITY) context.push_back("falling"), idx = 3;
for(auto c: all) if(idx < 4 && c.subtype == siFATIGUE) context.push_back("fatigued"), idx = 4;
for(auto c: all) if(idx < 5 && c.subtype == siCURRENT) context.push_back("whirled"), idx = 5;
bool in_ctx = true;
set<string> blocks;
int index = 0;
for(auto c: all) {
if(c.type == miENTITY && !captures.count({c.where, blocking_monster_name(c)})) blocks.insert(blocking_monster_name(c));
else if(c.type == miWALL && c.subtype == siMONSTER && !captures.count({c.where, blocking_monster_name(c)})) blocks.insert(blocking_monster_name(c));
else if(c.subtype == siITEM) blocks.insert("item");
else if(c.subtype == siWALL) {
if(c.where == cwt.at) {
if(in_ctx) {
if(c.where->wall == waNone && c.where->land == laBrownian)
context.push_back("on level 3");
else if(c.where->wall == waRoundTable)
context.push_back("being polite");
else
context.push_back(winf[c.where->wall].flags & WF_ON ? XLAT("on %the1", c.where->wall) : XLAT("in %the1", c.where->wall));
}
in_ctx = false;
}
else if(c.where && c.where->wall != cwt.at->wall) blocks.insert(dnameof(c.where->wall));
}
else if(c.type == siWARP) blocks.insert("warp");
index++;
}
if(!blocks.empty()) {
string block = "blocked by ";
int iqties = 0;
for(auto& q: blocks) {
if(iqties && iqties == isize(blocks) - 1) block += " and ";
else if(iqties) block += ", ";
block += q;
iqties++;
}
context.push_back(block);
}
yasc_message = "";
int iqties = 0;
for(auto& ctx: context) {
if(iqties == 0) ;
else if(iqties == 1) yasc_message += " while ";
else if(iqties == isize(context) - 1) yasc_message += " and ";
else yasc_message += ", ";
yasc_message += ctx;
iqties++;
}
if(captures.size() == 2 && context.size() == 1 && cwt.at->type == 6) {
vector<int> dirs;
forCellIdEx(c1, i, cwt.at) for(auto cap: captures) if(cap.first == c1) dirs.push_back(i);
if(isize(dirs) == 2 && abs(dirs[0]-dirs[1]) == 3) {
auto c1 = captures.begin(); c1++;
yasc_message = XLAT("pinched by %the1 and %the2", captures.begin()->second, c1->second);
}
}
println(hlog, "YASC_MESSAGE: ", yasc_message);
}
int yasc_recode(int x) {
if(cwt.at->type < 10 || x == 0) return x;
return yasc_recode(x / 10) * 100 + (x % 10);
};
EX void checkmove() {
if(dual::state == 2) return;
@ -292,21 +415,19 @@ EX void checkmove() {
if(multi::players > 1 && !multi::checkonly) return;
if(hardcore) return;
bool orbusedbak[ittypes];
// do not activate orbs!
for(int i=0; i<ittypes; i++) orbusedbak[i] = orbused[i];
legalmoves.clear(); legalmoves.resize(cwt.at->type+1, false);
move_issues.clear(); move_issues.resize(cwt.at->type, 0);
move_issues.clear(); move_issues.resize(cwt.at->type);
canmove = haveRangedTarget();
items[itWarning]+=2;
if(movepcto(-1, 0, true))
canmove = legalmoves[cwt.at->type] = true;
stay_issue = checked_move_issue;
if(true) {
for(int i=0; i<cwt.at->type; i++) {
dynamicval<bool> fm(bow::fire_mode, false);
if(movepcto(1, -1, true)) {
canmove = legalmoves[cwt.spin] = true;
}
@ -325,7 +446,9 @@ EX void checkmove() {
yasc_code = 0;
for(int i=0; i<cwt.at->type; i++)
yasc_code += move_issues[i];
yasc_code += yasc_recode(move_issues[i].type);
if(!canmove && bow::crossbow_mode() && !items[itCrossbow]) canmove = bow::have_bow_target();
#if CAP_INV
if(inv::on && !canmove && !inv::incheck) {
@ -342,9 +465,11 @@ EX void checkmove() {
#endif
if(!canmove) {
create_yasc_message();
achievement_final(true);
if(cmode & sm::NORMAL) showMissionScreen();
}
else yasc_message = "";
if(canmove && timerstopped) {
timerstart = time(NULL);
@ -352,7 +477,6 @@ EX void checkmove() {
}
items[itWarning]-=2;
for(int i=0; i<ittypes; i++) orbused[i] = orbusedbak[i];
if(recallCell.at && !markOrb(itOrbRecall)) activateRecall();
}

View File

@ -426,59 +426,59 @@ enum eSlimegroup { sgNone, sgCave, sgWater, sgFloorA, sgFloorB, sgVine, sgTree }
#if HDR
// we use CF not MF to avoid confusion with MF_ movement flags
static const flagtype CF_NOGHOST = Flag(0);
static const flagtype CF_RAIDER = Flag(1);
static const flagtype CF_PRINCESS = Flag(2);
static const flagtype CF_MIMIC = Flag(3);
static const flagtype CF_GOK = Flag(4);
static const flagtype CF_NONLIVING = Flag(5);
static const flagtype CF_METAL = Flag(6);
static const flagtype CF_STUNNABLE = Flag(7);
static const flagtype CF_HP = Flag(8);
static const flagtype CF_MOUNTABLE = Flag(9);
static const flagtype CF_FRIENDLY = Flag(10);
static const flagtype CF_PLAYER = Flag(11);
static const flagtype CF_BUG = Flag(12);
static const flagtype CF_IVY = Flag(13);
static const flagtype CF_PART = Flag(14);
static const flagtype CF_MUTANTIVY = Flag(15);
static const flagtype CF_ANYIVY = Flag(16);
static const flagtype CF_BULLET = Flag(17);
static const flagtype CF_DEMON = Flag(18);
static const flagtype CF_WORM = Flag(19);
static const flagtype CF_WITCH = Flag(20);
static const flagtype CF_BIRD = Flag(21);
static const flagtype CF_SLOWMOVER = Flag(22);
static const flagtype CF_MAGNETIC = Flag(23);
static const flagtype CF_SWITCH = Flag(24);
static const flagtype CF_GHOST = Flag(25);
static const flagtype CF_SHARK = Flag(26);
static const flagtype CF_SLIME = Flag(27);
static const flagtype CF_DRAGON = Flag(28);
static const flagtype CF_KRAKEN = Flag(29);
static const flagtype CF_NOBLOW = Flag(30);
static const flagtype CF_MULTITILE = Flag(31);
static const flagtype CF_LEADER = Flag(32);
static const flagtype CF_FLYING = Flag(33);
static const flagtype CF_ATTACK_THRU_VINE = Flag(34);
static const flagtype CF_ATTACK_NONADJACENT = Flag(35);
static const flagtype CF_NOHIGHLIGHT = Flag(36);
static const flagtype CF_INACTIVE = Flag(37);
static const flagtype CF_UNARMED = Flag(38);
static const flagtype CF_IGNORE_PLATE = Flag(39);
static const flagtype CF_BULL = Flag(40);
static const flagtype CF_TROLL = Flag(41);
static const flagtype CF_IGNORE_SMELL = Flag(42);
static const flagtype CF_RATLING = Flag(43);
static const flagtype CF_POWER = Flag(44);
static const flagtype CF_GHOSTMOVER = Flag(45);
static const flagtype CF_TECHNICAL = Flag(46);
static const flagtype CF_MOVED = Flag(47);
static const flagtype CF_FACING = Flag(48);
static const flagtype CF_FACE_UP = Flag(49);
static const flagtype CF_FACE_SIDE = Flag(50);
static const flagtype CF_HIGH_THREAT = Flag(51);
static const flagtype CF_SPAM = Flag(52);
static constexpr flagtype CF_NOGHOST = Flag(0);
static constexpr flagtype CF_RAIDER = Flag(1);
static constexpr flagtype CF_PRINCESS = Flag(2);
static constexpr flagtype CF_MIMIC = Flag(3);
static constexpr flagtype CF_GOK = Flag(4);
static constexpr flagtype CF_NONLIVING = Flag(5);
static constexpr flagtype CF_METAL = Flag(6);
static constexpr flagtype CF_STUNNABLE = Flag(7);
static constexpr flagtype CF_HP = Flag(8);
static constexpr flagtype CF_MOUNTABLE = Flag(9);
static constexpr flagtype CF_FRIENDLY = Flag(10);
static constexpr flagtype CF_PLAYER = Flag(11);
static constexpr flagtype CF_BUG = Flag(12);
static constexpr flagtype CF_IVY = Flag(13);
static constexpr flagtype CF_PART = Flag(14);
static constexpr flagtype CF_MUTANTIVY = Flag(15);
static constexpr flagtype CF_ANYIVY = Flag(16);
static constexpr flagtype CF_BULLET = Flag(17);
static constexpr flagtype CF_DEMON = Flag(18);
static constexpr flagtype CF_WORM = Flag(19);
static constexpr flagtype CF_WITCH = Flag(20);
static constexpr flagtype CF_BIRD = Flag(21);
static constexpr flagtype CF_SLOWMOVER = Flag(22);
static constexpr flagtype CF_MAGNETIC = Flag(23);
static constexpr flagtype CF_SWITCH = Flag(24);
static constexpr flagtype CF_GHOST = Flag(25);
static constexpr flagtype CF_SHARK = Flag(26);
static constexpr flagtype CF_SLIME = Flag(27);
static constexpr flagtype CF_DRAGON = Flag(28);
static constexpr flagtype CF_KRAKEN = Flag(29);
static constexpr flagtype CF_NOBLOW = Flag(30);
static constexpr flagtype CF_MULTITILE = Flag(31);
static constexpr flagtype CF_LEADER = Flag(32);
static constexpr flagtype CF_FLYING = Flag(33);
static constexpr flagtype CF_ATTACK_THRU_VINE = Flag(34);
static constexpr flagtype CF_ATTACK_NONADJACENT = Flag(35);
static constexpr flagtype CF_NOHIGHLIGHT = Flag(36);
static constexpr flagtype CF_INACTIVE = Flag(37);
static constexpr flagtype CF_UNARMED = Flag(38);
static constexpr flagtype CF_IGNORE_PLATE = Flag(39);
static constexpr flagtype CF_BULL = Flag(40);
static constexpr flagtype CF_TROLL = Flag(41);
static constexpr flagtype CF_IGNORE_SMELL = Flag(42);
static constexpr flagtype CF_RATLING = Flag(43);
static constexpr flagtype CF_POWER = Flag(44);
static constexpr flagtype CF_GHOSTMOVER = Flag(45);
static constexpr flagtype CF_TECHNICAL = Flag(46);
static constexpr flagtype CF_MOVED = Flag(47);
static constexpr flagtype CF_FACING = Flag(48);
static constexpr flagtype CF_FACE_UP = Flag(49);
static constexpr flagtype CF_FACE_SIDE = Flag(50);
static constexpr flagtype CF_HIGH_THREAT = Flag(51);
static constexpr flagtype CF_SPAM = Flag(52);
enum eMonster {
#define MONSTER(a,b,c,d,e,f,g,h) d,
@ -536,16 +536,16 @@ EX genderswitch_t genderswitch[NUM_GS] = {
#if HDR
enum eOrbshape { osNone, osLove, osRanged, osOffensive, osFriend, osUtility, osDirectional, osWarping, osFrog, osPowerUtility, osProtective, osMovement, osTerraform };
static const flagtype ZERO = 0;
static constexpr flagtype ZERO = 0;
static const flagtype IF_SHARD = Flag(0);
static const flagtype IF_FIREPROOF = Flag(1);
static const flagtype IF_PROTECTION = Flag(2);
static const flagtype IF_EMPATHY = Flag(3);
static const flagtype IF_RANGED = Flag(4);
static const flagtype IF_SHMUPLIFE = Flag(5);
static const flagtype IF_REVIVAL = Flag(6);
static const flagtype IF_CURSE = Flag(7);
static constexpr flagtype IF_SHARD = Flag(0);
static constexpr flagtype IF_FIREPROOF = Flag(1);
static constexpr flagtype IF_PROTECTION = Flag(2);
static constexpr flagtype IF_EMPATHY = Flag(3);
static constexpr flagtype IF_RANGED = Flag(4);
static constexpr flagtype IF_SHMUPLIFE = Flag(5);
static constexpr flagtype IF_REVIVAL = Flag(6);
static constexpr flagtype IF_CURSE = Flag(7);
// 0 = basic treasure, 1 = other item, 2 = power orb, 3 = not an item
#define IC_TREASURE 0
@ -578,28 +578,30 @@ EX itemtype iinf[ittypes] = {
// --- wall types ---
#if HDR
static const flagtype WF_WATER = Flag(0);
static const flagtype WF_BOAT = Flag(1);
static const flagtype WF_CHASM = Flag(2);
static const flagtype WF_NOFLIGHT = Flag(3);
static const flagtype WF_FIRE = Flag(4);
static const flagtype WF_THUMPER = Flag(5);
static const flagtype WF_ACTIVABLE = Flag(6);
static const flagtype WF_ALCHEMY = Flag(7);
static const flagtype WF_RED = Flag(8);
static const flagtype WF_WALL = Flag(9);
static const flagtype WF_PUSHABLE = Flag(10);
static const flagtype WF_CONE = Flag(11);
static const flagtype WF_STDTREE = Flag(12);
static const flagtype WF_GRAVE = Flag(13);
static const flagtype WF_REPTILE = Flag(14);
static const flagtype WF_HEATCOLOR = Flag(15);
static const flagtype WF_HIGHWALL = Flag(16);
static const flagtype WF_THORNY = Flag(17);
static const flagtype WF_TIMEOUT = Flag(18);
static const flagtype WF_CISLAND = Flag(19);
static const flagtype WF_SULPHURIC = Flag(20);
static const flagtype WF_HALFVINE = Flag(21);
static constexpr flagtype WF_WATER = Flag(0);
static constexpr flagtype WF_BOAT = Flag(1);
static constexpr flagtype WF_CHASM = Flag(2);
static constexpr flagtype WF_NOFLIGHT = Flag(3);
static constexpr flagtype WF_FIRE = Flag(4);
static constexpr flagtype WF_THUMPER = Flag(5);
static constexpr flagtype WF_ACTIVABLE = Flag(6);
static constexpr flagtype WF_ALCHEMY = Flag(7);
static constexpr flagtype WF_RED = Flag(8);
static constexpr flagtype WF_WALL = Flag(9);
static constexpr flagtype WF_PUSHABLE = Flag(10);
static constexpr flagtype WF_CONE = Flag(11);
static constexpr flagtype WF_STDTREE = Flag(12);
static constexpr flagtype WF_GRAVE = Flag(13);
static constexpr flagtype WF_REPTILE = Flag(14);
static constexpr flagtype WF_HEATCOLOR = Flag(15);
static constexpr flagtype WF_HIGHWALL = Flag(16);
static constexpr flagtype WF_THORNY = Flag(17);
static constexpr flagtype WF_TIMEOUT = Flag(18);
static constexpr flagtype WF_CISLAND = Flag(19);
static constexpr flagtype WF_SULPHURIC = Flag(20);
static constexpr flagtype WF_HALFVINE = Flag(21);
static constexpr flagtype WF_NONBLOCK = Flag(22);
static constexpr flagtype WF_ON = Flag(23); // just for grammar: 'on' not 'in'
struct walltype {
char glyph;
@ -626,23 +628,28 @@ EX walltype winf[walltypes] = {
// -- land types ---
#if HDR
static const flagtype LF_GENERATE_ALL = Flag(0);
static const flagtype LF_ICY = Flag(1);
static const flagtype LF_GRAVITY = Flag(2);
static const flagtype LF_EQUI = Flag(3);
static const flagtype LF_WARPED = Flag(4);
static const flagtype LF_CYCLIC = Flag(5);
static const flagtype LF_TECHNICAL = Flag(6);
static const flagtype LF_MIRROR = Flag(7);
static const flagtype LF_SEA = Flag(8);
static const flagtype LF_COASTAL = Flag(9);
static const flagtype LF_PURESEA = Flag(10);
static const flagtype LF_ELEMENTAL = Flag(11);
static const flagtype LF_HAUNTED = Flag(12);
static const flagtype LF_TROLL = Flag(13);
static const flagtype LF_INMIRROR = Flag(14);
static const flagtype LF_INMIRRORORWALL = Flag(15);
static const flagtype LF_ELECTRIC = Flag(17);
enum eCanvasFloor { caflNone, caflM, caflFull, caflWarp, caflStar, caflCloud, caflCross, caflCharged,
caflSStar, caflOver, caflTri, caflFeather, caflBarrow, caflNew, caflTroll, caflButterfly, caflLava,
caflPalace, caflDemon, caflCave, caflDesert, caflPower, caflRose, caflTurtle, caflDragon, caflReptile,
caflHive, caflSwitch, caflTower, caflEND };
static constexpr flagtype LF_GENERATE_ALL = Flag(0);
static constexpr flagtype LF_ICY = Flag(1);
static constexpr flagtype LF_GRAVITY = Flag(2);
static constexpr flagtype LF_EQUI = Flag(3);
static constexpr flagtype LF_WARPED = Flag(4);
static constexpr flagtype LF_CYCLIC = Flag(5);
static constexpr flagtype LF_TECHNICAL = Flag(6);
static constexpr flagtype LF_MIRROR = Flag(7);
static constexpr flagtype LF_SEA = Flag(8);
static constexpr flagtype LF_COASTAL = Flag(9);
static constexpr flagtype LF_PURESEA = Flag(10);
static constexpr flagtype LF_ELEMENTAL = Flag(11);
static constexpr flagtype LF_HAUNTED = Flag(12);
static constexpr flagtype LF_TROLL = Flag(13);
static constexpr flagtype LF_INMIRROR = Flag(14);
static constexpr flagtype LF_INMIRRORORWALL = Flag(15);
static constexpr flagtype LF_ELECTRIC = Flag(17);
struct landtype {
color_t color;
@ -661,6 +668,13 @@ enum eLand {
extern color_t floorcolors[landtypes];
#endif
EX const char *canvasFloorNames[caflEND] = {
"default", "smaller", "full", "warped", "star", "cloud", "cross", "charged",
"saloon", "overgrown", "triangle", "feather", "barrow", "elemental", "troll", "butterfly", "lava",
"palace", "demon", "cave", "desert", "power", "rose", "turtle", "dragon", "reptile",
"hive", "jelly", "tower"
};
EX const landtype linf[landtypes] = {
#define LAND(a,b,c,d,e,f,g) {a,b,d,e,g},
#include "content.cpp"
@ -737,9 +751,13 @@ enum eGeometry {
gSpace535, gSpace536, gSeifertCover, gSeifertWeber, gHomologySphere,
gInfOrderMixed, gSpace436, gFake,
gSpace345, gSpace353, gSpace354, gSpace355,
gHalfBring,
gAperiodicHat,
gSierpinski3, gSierpinski4, gSixFlake, gMengerSponge, gSierpinskiTet,
gAperiodicSpectre,
gGUARD};
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProduct, gcSL2 };
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSol, gcNIH, gcSolN, gcNil, gcProduct, gcSL2 };
enum class eVariation { bitruncated, pure, goldberg, irregular, dual, untruncated, warped, unrectified, subcubes, coxeter, dual_subcubes, bch, bch_oct };
@ -772,69 +790,77 @@ struct geometryinfo {
eVariation default_variation;
};
static const flagtype qBOUNDED = 1;
static const flagtype qANYQ = 2;
static const flagtype qNONORIENTABLE = 4;
static const flagtype qSMALL = 8;
static constexpr flagtype qCLOSED = 1;
static constexpr flagtype qANYQ = 2;
static constexpr flagtype qNONORIENTABLE = 4;
static constexpr flagtype qSMALL = 8;
static const flagtype qFIELD = 16;
static const flagtype qDOCKS = 32;
static const flagtype qZEBRA = 64;
static constexpr flagtype qFIELD = 16;
static constexpr flagtype qDOCKS = 32;
static constexpr flagtype qZEBRA = 64;
static const flagtype qELLIPTIC = 128;
static constexpr flagtype qELLIPTIC = 128;
static const flagtype qBINARY = 256;
static const flagtype qKITE = 512;
static constexpr flagtype qBINARY = 256;
static constexpr flagtype qKITE = 512;
static const flagtype qREGULAR = 1024; /* not set! */
static const flagtype qARCHI = 2048;
static const flagtype qHYBRID = 4096;
static const flagtype qCRYSTAL = 8192;
static const flagtype qSOL = 16384;
static const flagtype qEXPERIMENTAL = 32768;
static const flagtype qNIH = 65536;
static constexpr flagtype qREGULAR = 1024; /* not set! */
static constexpr flagtype qARCHI = 2048;
static constexpr flagtype qHYBRID = 4096;
static constexpr flagtype qCRYSTAL = 8192;
static constexpr flagtype qSOL = 16384;
static constexpr flagtype qEXPERIMENTAL = 32768;
static constexpr flagtype qNIH = 65536;
static const flagtype qIDEAL = 131072;
static const flagtype qHUGE_BOUNDED = 262144;
static const flagtype qOPTQ = Flag(19);
static const flagtype qSINGLE = Flag(20);
static constexpr flagtype qIDEAL = 131072;
static constexpr flagtype qHUGE_BOUNDED = 262144;
static constexpr flagtype qOPTQ = Flag(19);
static constexpr flagtype qSINGLE = Flag(20);
static const flagtype qDEPRECATED = Flag(21);
static const flagtype qINFMIXED = Flag(22);
static constexpr flagtype qDEPRECATED = Flag(21);
static constexpr flagtype qINFMIXED = Flag(22);
static const flagtype qRAYONLY = Flag(23);
static const flagtype qAFFINE = Flag(24);
static constexpr flagtype qRAYONLY = Flag(23);
static constexpr flagtype qAFFINE = Flag(24);
static const flagtype qULTRA = Flag(25);
static constexpr flagtype qULTRA = Flag(25);
static const flagtype qPORTALSPACE = Flag(26);
static constexpr flagtype qPORTALSPACE = Flag(26);
static const flagtype qSTRETCHABLE = Flag(27);
static constexpr flagtype qSTRETCHABLE = Flag(27);
static const flagtype qCAT = Flag(28);
static constexpr flagtype qCAT = Flag(28);
static constexpr flagtype qAPERIODIC = Flag(29);
static constexpr flagtype qHAT = Flag(30);
static constexpr flagtype qFRACTAL = Flag(31);
// note: dnext assumes that x&7 equals 7
static const int SEE_ALL = 50;
static const int OINF = 100;
static constexpr int SEE_ALL = 50;
// note: check_football_colorability in arbitrile.cpp assumes OINF is divisible by 3
static constexpr int OINF = 123;
extern eGeometry geometry;
extern eVariation variation;
#endif
static const flagtype qsNONOR = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE;
static const flagtype qsNONORE = qsNONOR | qELLIPTIC;
static const flagtype qsBQ = qANYQ | qSMALL | qBOUNDED;
static const flagtype qsSMALL = qANYQ | qSMALL | qBOUNDED;
static const flagtype qsSMALLN = qANYQ | qSMALL | qBOUNDED | qNONORIENTABLE;
static const flagtype qsZEBRA = qANYQ | qSMALL | qBOUNDED | qZEBRA;
static const flagtype qsFIELD = qANYQ | qFIELD | qBOUNDED;
static const flagtype qsDOCKS = qANYQ | qSMALL | qBOUNDED | qDOCKS;
static const flagtype qsSMALLB = qSMALL | qBOUNDED;
static const flagtype qsSMALLBF = qsSMALLB | qsFIELD | qANYQ;
static const flagtype qsSMALLBE = qsSMALLB | qELLIPTIC | qANYQ;
static const flagtype qsBP = qBINARY | qKITE;
#if HDR
static constexpr flagtype qsNONOR = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE;
static constexpr flagtype qsNONORE = qsNONOR | qELLIPTIC;
static constexpr flagtype qsBQ = qANYQ | qSMALL | qCLOSED;
static constexpr flagtype qsSMALL = qANYQ | qSMALL | qCLOSED;
static constexpr flagtype qsSMALLN = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE;
static constexpr flagtype qsZEBRA = qANYQ | qSMALL | qCLOSED | qZEBRA;
static constexpr flagtype qsFIELD = qANYQ | qFIELD | qCLOSED;
static constexpr flagtype qsDOCKS = qANYQ | qSMALL | qCLOSED | qDOCKS;
static constexpr flagtype qsSMALLB = qSMALL | qCLOSED;
static constexpr flagtype qsSMALLBF = qsSMALLB | qsFIELD | qANYQ;
static constexpr flagtype qsSMALLBE = qsSMALLB | qELLIPTIC | qANYQ;
static constexpr flagtype qsBP = qBINARY | qKITE;
static const flagtype qsSINGLE = qANYQ | qSMALL | qBOUNDED | qSINGLE;
static constexpr flagtype qsSINGLE = qANYQ | qSMALL | qCLOSED | qSINGLE;
#endif
EX geometryinfo1 giEuclid2 = { gcEuclid, 2, 2, 3, {1,1, 0,0 } };
EX geometryinfo1 giHyperb2 = { gcHyperbolic, 2, 2, 3, {1,1,-1,0 } };
@ -844,9 +870,14 @@ EX geometryinfo1 giEuclid3 = { gcEuclid, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giHyperb3 = { gcHyperbolic, 3, 3, 4, {1,1, 1,-1} };
EX geometryinfo1 giSphere3 = { gcSphere, 3, 3, 4, {1,1, 1,+1} };
EX geometryinfo1 giSolNIH = { gcSolNIH, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giSol = { gcSol, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giNIH = { gcNIH, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giSolN = { gcSolN, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giNil = { gcNil, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giProduct = { gcSL2, 3, 3, 4, {1,1, 1,0 } /* will be filled in product::configure() */ };
EX geometryinfo1 giProductH= { gcProduct, 3, 3, 3, {1,1,-1,0 } };
EX geometryinfo1 giProductS= { gcProduct, 3, 3, 3, {1,1, 1,0 } };
EX geometryinfo1 giProduct = { gcProduct, 3, 3, 3, {1,1, 1,0 } /* will be filled in product::configure() */ };
EX geometryinfo1 giSL2 = { gcSL2, 3, 3, 4, {1,1,-1,-1} };
EX modecode_t no_code = 0x1;
@ -903,20 +934,20 @@ EX vector<geometryinfo> ginf = {
{"{4,3,5}","field", "{4,3,5} field quotient space", "f435", 6, 5, qsSMALLBF | qDEPRECATED, giHyperb3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{5,3,4}","field", "{5,3,4} field quotient space", "f435", 12, 4, qsSMALLBF | qDEPRECATED, giHyperb3, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"binary4","none", "standard binary tiling", "binary4", 5, 3, qBINARY, giHyperb2, {{7, 5}}, eVariation::pure},
{"sol", "none", "Solv geometry", "sol", 8, 3, qBINARY|qSOL, giSolNIH, {{7, 5}}, eVariation::pure},
{"kd2", "none", "kite-and-dart", "kd2", 4, 3, qKITE, giEuclid2, {{7, 7}}, eVariation::pure},
{"sol", "none", "Solv geometry", "sol", 8, 3, qBINARY|qSOL, giSol, {{7, 5}}, eVariation::pure},
{"kd2", "none", "kite-and-dart", "kd2", 4, 3, qKITE | qAPERIODIC, giEuclid2, {{7, 7}}, eVariation::pure},
{"kd3", "none", "kite-and-dart on horospheres", "kd3", 12, 3, qsBP, giHyperb3, {{7, 3}}, eVariation::pure},
{"nil", "none", "Nil geometry", "nil", 6, 3, qOPTQ, giNil, {{7, 5}}, eVariation::pure},
{"product","none", "product space", "product", 7, 3, qHYBRID, giProduct, {{7, 3}}, eVariation::pure},
{"twisted","none", "rotation space", "twisted", 7, 3, qHYBRID, giSL2, {{6, 4}}, eVariation::pure},
{"ternary","none", "standard ternary tiling", "ternary", 6, 3, qBINARY, giHyperb2, {{6, 4}}, eVariation::pure},
{"3x2", "none", "stretched hyperbolic", "3:2", 11, 3, qBINARY|qNIH, giSolNIH, {{6, 3}}, eVariation::pure},
{"3x1/2", "none", "stretched Solv", "3:1/2", 9, 3, (qBINARY|qSOL|qNIH), giSolNIH, {{7, 3}}, eVariation::pure},
{"3x2", "none", "stretched hyperbolic", "3:2", 11, 3, qBINARY|qNIH, giNIH, {{6, 3}}, eVariation::pure},
{"3x1/2", "none", "stretched Solv", "3:1/2", 9, 3, (qBINARY|qSOL|qNIH), giSolN, {{7, 3}}, eVariation::pure},
{"{3,oo}", "none", "{3,∞} (infinite triangles)", "oox3", 3, OINF, qIDEAL, giHyperb2, {{7, 7}}, eVariation::pure},
{"{3,3,6}","none", "{3,3,6} hyperbolic honeycomb", "336", 4, 6, qIDEAL, giHyperb3, {{7, 2}}, eVariation::pure},
{"{3,4,4}","none", "{3,4,4} hyperbolic honeycomb", "344", 8, 4, qIDEAL, giHyperb3, {{7, 2}}, eVariation::pure},
{"{3,4,4}","Crystal", "4D crystal in H3", "Cryst3" , 8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, {{7, 3}}, eVariation::pure},
{"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ | qCAT, giSolNIH, {{6, 4}}, eVariation::pure},
{"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ | qCAT, giSol, {{6, 4}}, eVariation::pure},
{"file", "none", "load from file", "file", 7, 3, 0, giEuclid2, {{7, 5}}, eVariation::pure},
{"{4,oo}", "none", "{4,∞} (infinite squares)", "oox4", 4, OINF, qIDEAL, giHyperb2, {{5, 5}}, eVariation::pure},
{"{5,3,4}","Crystal", "6D crystal in H3", "Cryst6" , 12, 4, qANYQ | qCRYSTAL, giHyperb3, {{7, 3}}, eVariation::pure},
@ -932,28 +963,44 @@ EX vector<geometryinfo> ginf = {
{"{3,5,3}","none", "{3,5,3} hyperbolic honeycomb", "353", 20, 5, 0, giHyperb3, {{7, 2}}, eVariation::pure},
{"{3,5,4}","none", "{3,5,4} hyperbolic honeycomb", "354", 20, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure},
{"{3,5,5}","none", "{3,5,5} hyperbolic honeycomb", "355", 20, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure},
{"{5,4}", "pBring", "projective Bring's Surface", "pBring", 5, 4, qsSMALLN, giHyperb2, {{6, 4}}, eVariation::bitruncated},
{"hat", "none", "aperiodic hat", "hat", 14, 3, qAPERIODIC | qHAT, giEuclid2, {{7, 7}}, eVariation::pure},
{"triangle","none", "Sierpiński triangle", "S3", 6, 3, qFRACTAL, giEuclid2, {{10, 10}}, eVariation::pure},
{"carpet", "none", "Sierpiński carpet", "S4", 4, 4, qFRACTAL, giEuclid2, {{10, 10}}, eVariation::pure},
{"6-flake","none", "6-flake fractal", "S6", 6, 3, qFRACTAL, giEuclid2, {{10, 10}}, eVariation::pure},
{"{4,3,4}","none", "Menger sponge", "S8", 6, 4, qFRACTAL, giEuclid3, {{10, 10}}, eVariation::pure},
{"rh{4,3,4}","none", "Sierpiński tetrahedron", "S4b", 12, 3, qFRACTAL, giEuclid3, {{10, 10}}, eVariation::pure},
{"spectre","none", "aperiodic spectre", "spectre", 14, 3, qAPERIODIC | qHAT, giEuclid2, {{7, 7}}, eVariation::pure},
};
// bits: 9, 10, 15, 16, (reserved for later) 17, 18
#if HDR
namespace mf {
static const flagtype azimuthal = 1;
static const flagtype cylindrical = 2;
static const flagtype equiarea = 4;
static const flagtype equidistant = 8;
static const flagtype conformal = 16;
static const flagtype euc_boring = 32;
static const flagtype space = 64;
static const flagtype hyper_only = 128;
static const flagtype hyper_or_torus = 256;
static const flagtype pseudocylindrical = 512; /* includes cylindrical */
static const flagtype equivolume = 1024;
static const flagtype twopoint = 2048;
static const flagtype uses_bandshift = 4096;
static const flagtype broken = 8192; /* in spherical case, these are broken along the meridian 180 deg */
static constexpr flagtype azimuthal = 1;
static constexpr flagtype cylindrical = 2; /* usually you want 'band' */
static constexpr flagtype equiarea = 4;
static constexpr flagtype equidistant = 8;
static constexpr flagtype conformal = 16;
static constexpr flagtype euc_boring = 32;
static constexpr flagtype space = 64;
static constexpr flagtype hyper_only = 128;
static constexpr flagtype hyper_or_torus = 256;
static constexpr flagtype pseudocylindrical = 512; /* includes cylindrical; usually you want 'band' or 'pseudoband' */
static constexpr flagtype equivolume = 1024;
static constexpr flagtype twopoint = 2048;
static constexpr flagtype uses_bandshift = 4096;
static constexpr flagtype broken = 8192; /* in spherical case, these are broken along the meridian 180 deg */
static constexpr flagtype technical = 16384; /* don't display in the list */
static constexpr flagtype product_special = (1<<15);
static constexpr flagtype axial = (1<<16);
static constexpr flagtype perspective = (1<<17);
static constexpr flagtype orientation = (1<<18);
static constexpr flagtype transition = (1<<19);
static constexpr flagtype werner = (1<<20);
static constexpr flagtype horocyclic = (1<<21);
static const flagtype band = (cylindrical | pseudocylindrical | uses_bandshift);
static const flagtype pseudoband = (pseudocylindrical | uses_bandshift);
static constexpr flagtype band = (cylindrical | pseudocylindrical | uses_bandshift | orientation);
static constexpr flagtype pseudoband = (pseudocylindrical | uses_bandshift | orientation);
}
struct modelinfo {
@ -962,13 +1009,6 @@ struct modelinfo {
const char *name_spherical;
flagtype flags;
int is_azimuthal;
int is_band;
int is_equiarea;
int is_equidistant;
int is_conformal;
const char* name;
};
enum eModel : int {
@ -989,9 +1029,11 @@ enum eModel : int {
mdHorocyclic, mdQuadrant, mdAxial, mdAntiAxial,
// 32..38
mdWerner, mdAitoff, mdHammer, mdLoximuthal, mdMiller, mdGallStereographic, mdWinkelTripel,
// 39..
mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint,
// 45..
// 39..48
mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint, mdLiePerspective, mdLieOrthogonal, mdRelPerspective, mdRelOrthogonal,
// 49..50
mdHorocyclicEqa, mdConformalSquare, mdFisheye2, mdPolar,
// 51..
mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
};
#endif
@ -1000,67 +1042,85 @@ enum eModel : int {
// (other bits are used for other information)
#define X3(x) x, x, x
#define DEFAULTS 0, 0, 0, 0, 0, nullptr
/** list of available models (i.e., projections) */
EX vector<modelinfo> mdinf = {
{"disk/Gans", "general perspective", "general perspective", mf::azimuthal | mf::conformal, DEFAULTS},
{"half-plane", "inversion", "stereographic projection [VR]", mf::conformal, DEFAULTS},
{"band", "band", "Mercator", mf::band | mf::conformal, DEFAULTS},
{X3("polygonal"), mf::conformal, DEFAULTS},
{X3("formula"), 0, DEFAULTS},
{X3("azimuthal equidistant"), mf::azimuthal | mf::equidistant | mf::euc_boring, DEFAULTS},
{X3("azimuthal equi-area"), mf::azimuthal | mf::equiarea | mf::euc_boring, DEFAULTS},
{X3("ball model"), mf::conformal | mf::azimuthal | mf::space, DEFAULTS},
{"Minkowski hyperboloid", "plane", "sphere", mf::conformal | mf::space | mf::euc_boring, DEFAULTS},
{"hemisphere", "sphere", "sphere", mf::conformal | mf::space, DEFAULTS},
{X3("band equidistant"), mf::band | mf::equidistant | mf::euc_boring, DEFAULTS},
{X3("band equi-area"), mf::band | mf::equiarea | mf::euc_boring, DEFAULTS},
{X3("sinusoidal"), mf::pseudoband | mf::equiarea | mf::euc_boring, DEFAULTS},
{X3("two-point equidistant"), mf::equidistant | mf::euc_boring | mf::twopoint, DEFAULTS},
{X3("fisheye"), 0, DEFAULTS},
{X3("Joukowsky transform"), mf::hyper_only | mf::conformal, DEFAULTS},
{X3("Joukowsky+inversion"), mf::hyper_only | mf::conformal, DEFAULTS},
{X3("rotated hyperboles"), mf::hyper_only, DEFAULTS},
{X3("spiral/ring"), mf::hyper_or_torus | mf::uses_bandshift, DEFAULTS},
{X3("native perspective"), 0, DEFAULTS},
{X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring, DEFAULTS},
{X3("central inversion"), mf::azimuthal | mf::conformal, DEFAULTS},
{X3("two-point azimuthal"), mf::euc_boring | mf::twopoint, DEFAULTS},
{X3("two-point hybrid"), mf::euc_boring | mf::twopoint, DEFAULTS},
{X3("geodesic"), 0, DEFAULTS},
{X3("Mollweide"), mf::euc_boring | mf::pseudoband | mf::equiarea, DEFAULTS},
{X3("central cylindrical"), mf::euc_boring | mf::band, DEFAULTS},
{X3("Collignon"), mf::pseudoband | mf::equiarea, DEFAULTS},
{X3("horocyclic coordinates"), mf::euc_boring, DEFAULTS},
{X3("quadrant coordinates"), mf::euc_boring, DEFAULTS},
{X3("axial coordinates"), mf::euc_boring, DEFAULTS},
{X3("anti-axial coordinates"), mf::euc_boring, DEFAULTS},
{X3("Werner projection"), mf::euc_boring | mf::broken, DEFAULTS}, // keep distances from pole, and distances along parallels
{X3("Aitoff projection"), mf::euc_boring | mf::broken, DEFAULTS}, // halve longitudes, do azequid, double x
{X3("Hammer projection"), mf::euc_boring | mf::broken, DEFAULTS}, // halve longitudes, do azequia, double x
{X3("loximuthal projection"), mf::euc_boring | mf::broken, DEFAULTS}, // map loxodromes azimuthally and equidistantly
{X3("Miller projection"), mf::euc_boring | mf::band, DEFAULTS}, // scale latitude 4/5 -> Mercator -> 5/4
{X3("Gall stereographic"), mf::euc_boring | mf::band, DEFAULTS}, // like central cylindrical but stereographic
{X3("Winkel tripel"), mf::euc_boring | mf::broken, DEFAULTS}, // mean of equirec and Aitoff
{X3("Poor man's square"), mf::euc_boring, DEFAULTS}, //
{X3("Panini projection"), mf::euc_boring, DEFAULTS}, //
{X3("Craig retroazimuthal"), mf::euc_boring | mf::broken, DEFAULTS}, // retroazimuthal cylindrical
{X3("Littrow retroazimuthal"), mf::euc_boring | mf::broken, DEFAULTS}, // retroazimuthal conformal
{X3("Hammer retroazimuthal"), mf::euc_boring, DEFAULTS}, // retroazimuthal equidistant
{X3("three-point equidistant"), mf::euc_boring, DEFAULTS},
{X3("guard"), 0, DEFAULTS},
{X3("polynomial"), mf::conformal, DEFAULTS},
{"disk/Gans", "general perspective", "general perspective", mf::azimuthal | mf::conformal},
{"half-plane", "inversion", "stereographic projection [VR]", mf::conformal | mf::orientation | mf::horocyclic},
{"band", "band", "Mercator", mf::band | mf::conformal | mf::transition},
{X3("polygonal"), mf::conformal | mf::orientation},
{X3("formula"), 0},
{X3("azimuthal equidistant"), mf::azimuthal | mf::equidistant | mf::euc_boring | mf::product_special},
{X3("azimuthal equi-area"), mf::azimuthal | mf::equiarea | mf::euc_boring},
{X3("ball model"), mf::conformal | mf::azimuthal | mf::space},
{"Minkowski hyperboloid", "plane", "sphere", mf::conformal | mf::space | mf::euc_boring},
{"hemisphere", "sphere", "Minkowski hyperboloid", mf::conformal | mf::space},
{X3("band equidistant"), mf::band | mf::equidistant | mf::euc_boring},
{X3("band equi-area"), mf::band | mf::equiarea | mf::euc_boring},
{X3("sinusoidal"), mf::pseudoband | mf::equiarea | mf::euc_boring},
{X3("two-point equidistant"), mf::equidistant | mf::euc_boring | mf::twopoint | mf::orientation},
{X3("fisheye"), 0},
{X3("Joukowsky transform"), mf::hyper_only | mf::conformal | mf::transition | mf::orientation},
{X3("Joukowsky+inversion"), mf::hyper_only | mf::conformal | mf::transition | mf::orientation},
{X3("rotated hyperboles"), mf::hyper_only | mf::orientation},
{X3("spiral/ring"), mf::hyper_or_torus | mf::uses_bandshift | mf::orientation},
{X3("native perspective"), mf::perspective | mf::product_special},
{X3("azimuthal equi-volume"), mf::azimuthal | mf::equivolume | mf::euc_boring},
{X3("central inversion"), mf::azimuthal | mf::conformal},
{X3("two-point azimuthal"), mf::euc_boring | mf::azimuthal | mf::twopoint | mf::orientation},
{X3("two-point hybrid"), mf::euc_boring | mf::azimuthal | mf::equidistant | mf::twopoint | mf::orientation},
{X3("geodesic"), mf::perspective | mf::product_special},
{X3("Mollweide"), mf::euc_boring | mf::pseudoband | mf::equiarea},
{X3("central cylindrical"), mf::euc_boring | mf::band},
{X3("Collignon"), mf::pseudoband | mf::equiarea},
{X3("horocyclic coordinates"), mf::euc_boring | mf::orientation | mf::horocyclic},
{X3("quadrant coordinates"), mf::euc_boring | mf::orientation},
{X3("axial coordinates"), mf::euc_boring | mf::transition | mf::orientation},
{X3("anti-axial coordinates"), mf::euc_boring | mf::orientation},
{X3("Werner projection"), mf::euc_boring | mf::broken | mf::werner | mf::orientation}, // keep distances from pole, and distances along parallels
{X3("Aitoff projection"), mf::euc_boring | mf::broken | mf::orientation}, // halve longitudes, do azequid, double x
{X3("Hammer projection"), mf::euc_boring | mf::broken | mf::orientation}, // halve longitudes, do azequia, double x
{X3("loximuthal projection"), mf::euc_boring | mf::broken | mf::orientation}, // map loxodromes azimuthally and equidistantly
{X3("Miller projection"), mf::euc_boring | mf::band}, // scale latitude 4/5 -> Mercator -> 5/4
{X3("Gall stereographic"), mf::euc_boring | mf::band}, // like central cylindrical but stereographic
{X3("Winkel tripel"), mf::euc_boring | mf::broken | mf::orientation}, // mean of equirec and Aitoff
{X3("Poor man's square"), mf::euc_boring | mf::orientation}, // https://archive.bridgesmathart.org/2018/bridges2018-59.html
{X3("Panini projection"), mf::euc_boring | mf::orientation},
{X3("Craig retroazimuthal"), mf::euc_boring | mf::broken | mf::pseudoband}, // retroazimuthal cylindrical
{X3("Littrow retroazimuthal"), mf::euc_boring | mf::broken | mf::pseudoband}, // retroazimuthal conformal
{X3("Hammer retroazimuthal"), mf::euc_boring | mf::pseudoband}, // retroazimuthal equidistant
{X3("three-point equidistant"), mf::euc_boring | mf::equidistant | mf::orientation | mf::product_special | mf::twopoint},
{X3("Lie perspective"), mf::euc_boring | mf::perspective},
{X3("Lie orthogonal"), mf::euc_boring},
{X3("relativistic perspective"), mf::euc_boring | mf::perspective},
{X3("relativistic orthogonal"), mf::euc_boring},
{X3("horocyclic equal-area"), mf::euc_boring | mf::equiarea | mf::orientation | mf::horocyclic},
{X3("conformal square"), mf::orientation | mf::broken | mf::transition},
{X3("variant fisheye"), 0},
{X3("polar coordinates"), mf::orientation},
{X3("guard"), mf::technical},
{X3("pixel"), mf::technical},
{X3("hypflat"), mf::technical},
{X3("polynomial"), mf::technical | mf::conformal | mf::orientation},
{X3("manual"), mf::technical},
};
#undef X3
#undef DEFAULTS
#if HDR
static inline bool orbProtection(eItem it) { return false; } // not implemented
// these markers use lands which never appear on barrier sides
const eLand NOWALLSEP = laNone;
const eLand NOWALLSEP_SWAP = laMountain;
const eLand NOWALLSEP_WALL = laHauntedWall;
const eLand NOWALLSEP_USED = laWhirlpool;
const eLand NOWALLSEP_WALL_CPOS = laBarrier;
const eLand NOWALLSEP_WALL_CNEG = laOceanWall;
const eLand NOWALLSEP_WALL_EPOS = laClearing;
const eLand NOWALLSEP_WALL_ENEG = laPrincessQuest;
#endif
}

View File

@ -25,13 +25,17 @@ EX unsigned char& part(color_t& col, int i) {
}
#if HDR
static const color_t NOCOLOR = 0;
static constexpr color_t NOCOLOR = 0;
struct colortable: vector<color_t> {
color_t& operator [] (int i) { i %= size(); if(i<0) i += size(); return ((vector<color_t>&)(*this)) [i]; }
const color_t& operator [] (int i) const { i %= size(); if(i<0) i += size(); return ((vector<color_t>&)(*this)) [i]; }
colortable(std::initializer_list<color_t> v) : vector(v) {}
colortable() : vector({0}) {}
void allocate(int num) {
int q = size();
for(int i=q; i<num; i++) push_back((*this)[i % q]);
}
};
#endif
@ -107,7 +111,7 @@ EX color_t rainbow_color(ld sat, ld hue) {
else if(hue<3) res = gradient(0x00FF00, 0x00FFFF, 2, hue, 3);
else if(hue<4) res = gradient(0x0000FF, 0x00FFFF, 4, hue, 3);
else if(hue<5) res = gradient(0x0000FF, 0xFF00FF, 4, hue, 5);
else if(hue<6) res = gradient(0xFF0000, 0xFF00FF, 6, hue, 5);
else if(hue<=6) res = gradient(0xFF0000, 0xFF00FF, 6, hue, 5);
return gradient(0xFFFFFF, res, 0, sat, 1);
}
@ -243,13 +247,15 @@ EX int cloakcolor(int rtr) {
EX int firegradient(double p) {
return gradient(0xFFFF00, 0xFF0000, 0, p, 1);
}
constexpr ld PI1000 = 0.001 / A_PI;
EX int firecolor(int phase IS(0), int mul IS(1)) {
return gradient(0xFFFF00, 0xFF0000, -1, sintick(100*mul, phase/200./M_PI), 1);
return gradient(0xFFFF00, 0xFF0000, -1, sintick(100*mul, phase * 5 * PI1000), 1);
}
EX int watercolor(int phase) {
return 0x0080C0FF + 256 * int(63 * sintick(50, phase/100./M_PI));
return 0x0080C0FF + 256 * int(63 * sintick(50, phase * 10 * PI1000));
}
EX int aircolor(int phase) {
@ -266,8 +272,41 @@ EX int fghostcolor(cell *c) {
}
EX int weakfirecolor(int phase) {
return gradient(0xFF8000, 0xFF0000, -1, sintick(500, phase/1000./M_PI), 1);
return gradient(0xFF8000, 0xFF0000, -1, sintick(500, phase * PI1000), 1);
}
/* HTML color names */
EX vector<pair<const char*, color_t>> color_names = {
{"aliceblue", 0xf0f8ff}, {"antiquewhite", 0xfaebd7}, {"aqua", 0x00ffff}, {"aquamarine", 0x7fffd4}, {"azure", 0xf0ffff},
{"beige", 0xf5f5dc}, {"bisque", 0xffe4c4}, {"black", 0x000000}, {"blanchedalmond", 0xffebcd}, {"blue", 0x0000ff}, {"blueviolet", 0x8a2be2}, {"brown", 0xa52a2a}, {"burlywood", 0xdeb887},
{"cadetblue", 0x5f9ea0}, {"chartreuse", 0x7fff00}, {"chocolate", 0xd2691e}, {"coral", 0xff7f50}, {"cornflowerblue", 0x6495ed}, {"cornsilk", 0xfff8dc}, {"crimson", 0xdc143c}, {"cyan", 0x00ffff},
{"darkblue", 0x00008b}, {"darkcyan", 0x008b8b}, {"darkgoldenrod", 0xb8860b}, {"darkgray", 0xa9a9a9}, {"darkgreen", 0x006400}, {"darkkhaki", 0xbdb76b}, {"darkmagenta", 0x8b008b}, {"darkolivegreen", 0x556b2f},
{"darkorange", 0xff8c00}, {"darkorchid", 0x9932cc}, {"darkred", 0x8b0000}, {"darksalmon", 0xe9967a}, {"darkseagreen", 0x8fbc8f}, {"darkslateblue", 0x483d8b}, {"darkslategray", 0x2f4f4f}, {"darkturquoise", 0x00ced1},
{"darkviolet", 0x9400d3}, {"deeppink", 0xff1493}, {"deepskyblue", 0x00bfff}, {"dimgray", 0x696969}, {"dodgerblue", 0x1e90ff},
{"firebrick", 0xb22222}, {"floralwhite", 0xfffaf0}, {"forestgreen", 0x228b22}, {"fuchsia", 0xff00ff},
{"gainsboro", 0xdcdcdc}, {"ghostwhite", 0xf8f8ff}, {"gold", 0xffd700}, {"goldenrod", 0xdaa520}, {"gray", 0x808080}, {"green", 0x008000}, {"greenyellow", 0xadff2f},
{"honeydew", 0xf0fff0}, {"hotpink", 0xff69b4},
{"indianred ", 0xcd5c5c}, {"indigo", 0x4b0082}, {"ivory", 0xfffff0}, {"khaki", 0xf0e68c},
{"lavender", 0xe6e6fa}, {"lavenderblush", 0xfff0f5}, {"lawngreen", 0x7cfc00}, {"lemonchiffon", 0xfffacd}, {"lightblue", 0xadd8e6}, {"lightcoral", 0xf08080}, {"lightcyan", 0xe0ffff}, {"lightgoldenrodyellow", 0xfafad2},
{"lightgrey", 0xd3d3d3}, {"lightgreen", 0x90ee90}, {"lightpink", 0xffb6c1}, {"lightsalmon", 0xffa07a}, {"lightseagreen", 0x20b2aa}, {"lightskyblue", 0x87cefa}, {"lightslategray", 0x778899}, {"lightsteelblue", 0xb0c4de},
{"lightyellow", 0xffffe0}, {"lime", 0x00ff00}, {"limegreen", 0x32cd32}, {"linen", 0xfaf0e6},
{"magenta", 0xff00ff}, {"maroon", 0x800000}, {"mediumaquamarine", 0x66cdaa}, {"mediumblue", 0x0000cd}, {"mediumorchid", 0xba55d3}, {"mediumpurple", 0x9370d8}, {"mediumseagreen", 0x3cb371}, {"mediumslateblue", 0x7b68ee},
{"mediumspringgreen", 0x00fa9a}, {"mediumturquoise", 0x48d1cc}, {"mediumvioletred", 0xc71585}, {"midnightblue", 0x191970}, {"mintcream", 0xf5fffa}, {"mistyrose", 0xffe4e1}, {"moccasin", 0xffe4b5},
{"navajowhite", 0xffdead}, {"navy", 0x000080},
{"oldlace", 0xfdf5e6}, {"olive", 0x808000}, {"olivedrab", 0x6b8e23}, {"orange", 0xffa500}, {"orangered", 0xff4500}, {"orchid", 0xda70d6},
{"palegoldenrod", 0xeee8aa}, {"palegreen", 0x98fb98}, {"paleturquoise", 0xafeeee}, {"palevioletred", 0xd87093}, {"papayawhip", 0xffefd5}, {"peachpuff", 0xffdab9}, {"peru", 0xcd853f}, {"pink", 0xffc0cb}, {"plum", 0xdda0dd}, {"powderblue", 0xb0e0e6}, {"purple", 0x800080},
{"rebeccapurple", 0x663399}, {"red", 0xff0000}, {"rosybrown", 0xbc8f8f}, {"royalblue", 0x4169e1},
{"saddlebrown", 0x8b4513}, {"salmon", 0xfa8072}, {"sandybrown", 0xf4a460}, {"seagreen", 0x2e8b57}, {"seashell", 0xfff5ee}, {"sienna", 0xa0522d}, {"silver", 0xc0c0c0}, {"skyblue", 0x87ceeb}, {"slateblue", 0x6a5acd}, {"slategray", 0x708090}, {"snow", 0xfffafa}, {"springgreen", 0x00ff7f}, {"steelblue", 0x4682b4},
{"tan", 0xd2b48c}, {"teal", 0x008080}, {"thistle", 0xd8bfd8}, {"tomato", 0xff6347}, {"turquoise", 0x40e0d0},
{"violet", 0xee82ee},
{"wheat", 0xf5deb3}, {"white", 0xffffff}, {"whitesmoke", 0xf5f5f5},
{"yellow", 0xffff00}, {"yellowgreen", 0x9acd32}
};
EX pair<const char*, color_t>* find_color_by_name(const string& s) {
for(auto& c: color_names) if(c.first == s) return &c;
return nullptr;
}
}

View File

@ -17,7 +17,7 @@ EX string rsrcdir = "";
#endif
#if CAP_COMMANDLINE
EX const char *scorefile = "hyperrogue.log";
EX string scorefile = "hyperrogue.log";
EX namespace arg {
EX eLand readland(const string& ss) {
@ -63,7 +63,7 @@ EX void initializeCLI() {
if(getenv("HOME")) {
sbuf = getenv("HOME"); sbuf += "/."; sbuf += scorefile;
cbuf = getenv("HOME"); cbuf += "/."; cbuf += conffile;
scorefile = sbuf.c_str();
scorefile = sbuf;
conffile = cbuf.c_str();
}
#endif
@ -87,6 +87,7 @@ EX namespace arg {
EX const string& args() { return argument[pos]; }
EX const char* argcs() { return args().c_str(); }
EX int argi() { return atoi(argcs()); }
EX long long argll() { return atoll(argcs()); }
EX int shift_argi() { shift(); return argi(); }
EX const string& shift_args() { shift(); return args(); }
@ -102,15 +103,20 @@ EX namespace arg {
}
}
EX bool argis(const string& s) { if(args()[0] == '-' && args()[1] == '-') return args().substr(1) == s; return args() == s; }
EX void shift_arg_formula(ld& x, const reaction_t& r IS(reaction_t())) {
shift(); ld old = x; x = argf();
#if CAP_ANIMATIONS
anims::animate_parameter(x, args(), r);
#endif
if(old != x && r) r();
EX color_t argcolor(int bits) {
return parsecolor(args(), bits == 32);
}
int parameter_id;
EX void shift_arg_formula(ld& x, const reaction_t& r IS(reaction_t())) {
shift();
auto par = anims::find_param(&x);
if(!par) par = param_f(x, "tmp_parameter_" + its(parameter_id++))->set_reaction(r);
par->load_as_animation(args());
}
#if HDR
// an useful macro
@ -126,6 +132,12 @@ EX namespace arg {
EX void cheat() { autocheat = true; cheater++; timerghost = false; }
EX void run_arguments(const vector<string> vec) {
dynamicval<int> p(pos, 0);
dynamicval<vector<string>> orig(argument, vec);
read(3);
}
EX void init(int argc, char **argv) { for(int i=0; i<argc; i++) argument.push_back(argv[i]); lshift(); }
EX void phaseerror(int x) {
@ -154,12 +166,20 @@ int arg::readCommon() {
// first phase options
if(argis("-s")) { PHASE(1); shift(); scorefile = argcs(); }
if(argis("-s")) { PHASE(2); shift(); scorefile = args(); savefile_selection = false; }
else if(argis("-no-s")) { PHASE(2); scorefile = ""; savefile_selection = false; }
else if(argis("-rsrc")) { PHASE(1); shift(); rsrcdir = args(); }
else if(argis("-nogui")) { PHASE(1); noGUI = true; }
#ifndef EMSCRIPTEN
#if CAP_SDL
else if(argis("-font")) { PHASE(1); shift(); fontpath = args(); }
else if(argis("-font")) { PHASE(1); shift(); fontpath = args();
#ifdef FONTCONFIG
font_to_find = "";
#endif
}
#ifdef FONTCONFIG
else if(argis("-find-font")) { PHASE(1); shift(); font_to_find = args(); }
#endif
#endif
#endif
@ -236,35 +256,54 @@ int arg::readCommon() {
else if(argis("-draw")) {
PHASE(3); start_game(); drawscreen();
}
else if(argis("-rotate")) {
else if(argis("-sview")) {
PHASE(3); start_game();
shift(); ld a = argf();
shift(); ld b = argf();
View = View * spin(M_PI * 2 * a / b);
playermoved = false;
transmatrix T = View;
shift(); View = parsematrix(args());
println(hlog, "View is set to ", View);
current_display->which_copy = View * inverse(T) * current_display->which_copy;
}
else if(argis("-rotate3")) {
PHASE(3); start_game();
shift(); ld a = argf();
shift(); ld b = argf();
View = View * cspin(1, 2, M_PI * 2 * a / b);
else if(argis("-rotate-up")) {
start_game();
shiftmatrix S = ggmatrix(cwt.at->master->move(0)->c7);
View = spin90() * spintox(S.T*C0) * View;
playermoved = false;
}
else if(argis("-face-vertex")) {
PHASE(3); start_game();
auto &ss = currentmap->get_cellshape(cwt.at);
View = cspin(0, 2, M_PI/2) * spintox(ss.vertices_only_local[0]);
View = cspin90(0, 2) * spintox(ss.vertices_only_local[0]);
playermoved = false;
}
else if(argis("-face-face")) {
PHASE(3); start_game();
View = cspin(0, 2, M_PI/2);
View = cspin90(0, 2);
}
else if(argis("-grotate")) {
PHASE(3); start_game();
shift(); int i = argi();
else if(argis("-center-vertex")) {
PHASE(3); shift(); int i = argi();
shift(); int j = argi();
shift(); View = View * cspin(i, j, argf());
shift(); int k = argi();
start_game();
auto fh = currentmap->get_cellshape(cwt.at).faces[j][k];
hyperpoint h = View * fh;
if(i == 0) {
shift_view_to(shiftless(h));
playermoved = false;
}
if(i == 1) {
rotate_view(spintox(h));
rotate_view(cspin90(0, 2));
}
}
else if(argis("-exit")) {
PHASE(3); printf("Success.\n");
PHASE(3);
int t = SDL_GetTicks();
if(t > 1800 * 1000)
println(hlog, "Great Success!\n");
else
println(hlog, "Success.\n");
fflush(stdout);
exit(0);
}
@ -292,38 +331,58 @@ int arg::readCommon() {
clearMessages();
}
else if(argis("-save-mode")) {
save_mode_to_file(shift_args());
}
else if(argis("-load-mode")) {
try {
load_mode_from_file(shift_args());
}
catch(hstream_exception& e) {
println(hlog, "exception!");
}
}
// informational
else if(argis("-version") || argis("-v")) {
printf("HyperRogue version " VER "\n");
exit(0);
}
else if(argis("-L")) {
printf("Treasures:\n");
printf("+ Treasures:\n");
int qty = 0;
for(int i=1; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE)
printf(" %s\n", iinf[i].name);
printf(" %s\n", iinf[i].name), qty++;
printf(" total = %d\n", qty); qty = 0;
printf("\n");
printf("Orbs:\n");
printf("+ Orbs:\n");
for(int i=1; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_ORB)
printf(" %s\n", iinf[i].name);
printf(" %s\n", iinf[i].name), qty++;
printf(" total = %d\n", qty); qty = 0;
printf("\n");
printf("Other items:\n");
printf("+ Other items:\n");
for(int i=1; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_OTHER)
printf(" %s\n", iinf[i].name);
printf(" %s\n", iinf[i].name), qty++;
printf(" total = %d\n", qty); qty = 0;
printf("\n");
printf("Monsters:\n");
printf("+ Monsters:\n");
for(int i=1; i<motypes; i++)
printf(" %s\n", minf[i].name);
printf(" %s\n", minf[i].name), qty++;
printf(" total = %d\n", qty); qty = 0;
printf("\n");
printf("Lands:\n");
for(int i=1; i<landtypes; i++)
printf(" %s\n", linf[i].name);
printf("+ Lands:\n");
for(int i=1; i<landtypes; i++)
printf(" %s\n", linf[i].name), qty++;
printf(" total = %d\n", qty); qty = 0;
printf("\n");
printf("Walls:\n");
printf("+ Walls:\n");
for(int i=0; i<walltypes; i++)
printf(" %s\n", winf[i].name);
printf(" %s\n", winf[i].name), qty++;
printf(" total = %d\n", qty); qty = 0;
printf("\n");
exit(0);
}
@ -382,6 +441,8 @@ EX hookset<int()> hooks_args;
EX map<string, pair<int, reaction_t>> *added_commands;
EX bool delayed_start;
EX namespace arg {
int read_added_commands() {
@ -414,6 +475,7 @@ EX namespace arg {
void read(int phase) {
curphase = phase;
callhooks(hooks_config);
dynamicval<bool> ds(delayed_start, true);
while(pos < isize(argument)) {
int r = callhandlers(1, hooks_args);
switch (r) {

View File

@ -15,7 +15,7 @@ EX namespace whirlwind {
EX int fzebra3(cell *c) {
if(arcm::in()) return 0;
if(euclid) {
if(bounded) return 0;
if(closed_manifold) return 0;
auto co = euc2_coordinates(c);
int y = co.second;
return 1+((((signed short)(y)+int(50000))/3)%3);
@ -102,6 +102,7 @@ EX namespace whirlwind {
again:
cell *at = whirlline[isize(whirlline)-1];
cell *prev = whirlline[isize(whirlline)-2];
if(looped(whirlline)) return;
for(int i=0; i<at->type; i++)
if(at->move(i) && (euclid || at->move(i)->master->alt) && celldistAlt(at->move(i)) == d && at->move(i) != prev) {
whirlline.push_back(at->move(i));
@ -144,7 +145,7 @@ EX namespace whirlwind {
animateMovement(match(whirlline[i+1], whirlline[i]), LAYER_BOAT);
}
for(int i=0; i<z; i++)
pickupMovedItems(whirlline[i]);
pickupMovedItems(whirlline[i], i==z-1 ? whirlline[0] : whirlline[i+1]);
}
EX void move() {
@ -214,10 +215,14 @@ EX namespace elec {
if(c->wall == waSea || c->wall == waGrounded) return ecGrounded;
if(c->wall == waSandstone || c->wall == waDeadTroll ||
c->wall == waDeadTroll2 ||
among(c->wall, waBigTree, waSmallTree, waExplosiveBarrel, waRed1, waRed2, waRed3) ||
c->wall == waExplosiveBarrel ||
c->wall == waVinePlant ||
c->wall == waMetal || isAlchAny(c))
return isElectricLand(c) ? ecConductor : ecGrounded;
if(c->wall == waBigTree || c->wall == waSmallTree)
return ecGrounded;
if(among(c->wall, waRed1, waRed2, waRed3, waRubble, waDeadfloor2))
return ecIsolator;
if(c->wall == waBarrier)
return ecIsolator;
if(c->wall == waChasm)
@ -642,8 +647,8 @@ struct info {
}
if(newdist == OUT_OF_PRISON && princess::challenge) {
addMessage(XLAT("Congratulations! Your score is %1.", its(i->value)));
achievement_gain_once("PRINCESS2");
if(!cheater) achievement_score(36, i->value);
achievement_gain_once("PRINCESS2", rg::princess);
if(!cheater) achievement_score(LB_PRINCESS, i->value);
LATE( showMissionScreen(); )
}
}
@ -737,7 +742,7 @@ struct info {
if(m == moPrincess)
addMessage(XLAT("\"I want my revenge. Stun a guard and leave him for me!\"", m));
else
addMessage(XLAT("\"That felt great. Thanks!\"", m));
addMessage(XLAT("\"I wouldn't say killing that guard was not pleasant...\"", m));
}
else if(msgid == 2 && d >= 70 && inpalace) {
addMessage(XLAT("\"Bring me out of here please!\"", m));
@ -906,6 +911,9 @@ EX namespace clearing {
c->mondir = 0;
return;
}
if(c->land == laClearing && ls::horodisk_structure() && celldistAlt(c) >= -1) return;
if(c->land == laClearing && ls::voronoi_structure() && celldistAlt(c) >= -20) return;
if(!eubinary && !horo_ok()) return;
// cell *oc = c;
@ -1002,6 +1010,7 @@ EX namespace clearing {
cell *c1 = c;
if(c->mondir < c->type)
c1 = c->move(c->mondir);
auto& expansion = get_expansion();
return make_tuple(
celldistAlt(c), type_in(expansion, c, celldistAlt),
celldistAlt(c1), type_in(expansion, c1, celldistAlt)
@ -1009,7 +1018,7 @@ EX namespace clearing {
}
EX void imput(cell *c) {
if(bounded) return;
if(closed_manifold) return;
if(score.count(c)) return;
changes.map_value(score, c);
auto& is = score[c];
@ -1062,10 +1071,9 @@ EX namespace whirlpool {
again:
cell *at = whirlline[isize(whirlline)-1];
cell *prev = whirlline[isize(whirlline)-2];
if(looped(whirlline)) return;
for(int i=0; i<at->type; i++)
if(at->move(i) && (eubinary || at->move(i)->master->alt) && celldistAlt(at->move(i)) == d && at->move(i) != prev) {
if(at->move(i) == whirlline[0]) return; // loops in weird geometries?
if(at->move(i) == whirlline[isize(whirlline)/2]) return; // even weirder geometry?
whirlline.push_back(at->move(i));
goto again;
}
@ -1119,8 +1127,8 @@ EX namespace whirlpool {
if(wfrom->item == itKey || wfrom->item == itOrbYendor)
for(int i=0; i<wto->type; i++) createMov(wto, i);
moveItem(wfrom, wto, false);
pickupMovedItems(wfrom);
pickupMovedItems(wto);
pickupMovedItems(wfrom, wto);
pickupMovedItems(wto, wfrom);
}
if(wto && !wfrom)
@ -1171,14 +1179,14 @@ EX namespace whirlpool {
EX namespace mirror {
#if HDR
static const int SPINSINGLE = 1;
static const int SPINMULTI = 2;
static const int GO = 4;
static const int ATTACK = 8;
static constexpr int SPINSINGLE = 1;
static constexpr int SPINMULTI = 2;
static constexpr int GO = 4;
static constexpr int ATTACK = 8;
#endif
EX bool build(cell *c) {
if(kite::in() || sol) return false;
if(aperiodic || sol) return false;
#if CAP_GP
if(GOLDBERG) {
if(c == c->master->c7) {
@ -1209,13 +1217,14 @@ EX namespace mirror {
return false;
}
/* int is the owner's cpid */
EX vector<pair<int, cellwalker>> mirrors;
#if HDR
constexpr int LIGHTNING = -1; // passed instead of cpid
#endif
bool noMirrorOn(cell *c) {
return c->monst || (!shmup::on && isPlayerOn(c)) || (!bounded && c->cpdist > gamerange());
return c->monst || (!shmup::on && isPlayerOn(c)) || (!closed_or_bounded && c->cpdist > gamerange());
}
bool cellMirrorable(cell *c) {
@ -1229,7 +1238,7 @@ EX namespace mirror {
c->wall == waMirrorWall || c->wall == waPetrifiedBridge;
}
void destroyKilled() {
EX void destroyKilled() {
int j = 0;
for(int i=0; i<isize(mirrors); i++)
if(mirrors[i].second.at->monst == moMimic)
@ -1310,7 +1319,7 @@ EX namespace mirror {
EX void createMirrors(cellwalker cw, int cpid) {
if(kite::in() || sol) return;
if(aperiodic || sol) return;
#if CAP_ARCM
if(arcm::in()) {
@ -1445,13 +1454,14 @@ EX namespace mirror {
changes.ccell(c);
if(!m.second.mirrored) nummirage++;
auto cw2 = m.second + wstep;
if(inmirror(cw2)) cw2 = reflect(cw2);
bool thru = inmirror(cw2);
if(thru) cw2 = reflect(cw2);
cell *c2 = cw2.at;
changes.ccell(c2);
if(c2->monst) {
c->monst = moMimic;
eMonster m2 = c2->monst;
if(!peace::on && canAttack(c,moMimic,c2,m2, 0)) {
if(!peace::on && !bow::crossbow_mode() && canAttack(c,moMimic,c2,m2, 0)) {
attackMonster(c2, AF_NORMAL | AF_MSG, moMimic);
if(!fwd) produceGhost(c2, m2, moMimic);
sideAttack(c, m.second.spin, m2, 0);
@ -1463,7 +1473,11 @@ EX namespace mirror {
else if(c2->wall == waSmallTree)
c2->wall = waNone;
if(fwd) {
if(noMirrorOn(c2) || !passable_for(moMimic, c2, c, P_MONSTER | P_MIRROR | P_MIRRORWALL)) {
if(thru && c == c2 && isAlchAny(c) && !checkflags(P_ISFRIEND | P_MONSTER | P_MIRROR | P_MIRRORWALL, P_AETHER)) {
survive = false;
continue;
}
if(noMirrorOn(c2) || !passable_for(moMimic, c2, c, P_ISFRIEND | P_MONSTER | P_MIRROR | P_MIRRORWALL)) {
survive = false;
continue;
}
@ -1627,8 +1641,8 @@ EX namespace mirror {
return cw;
}
static const int CACHESIZE = 1<<12; // must be a power of 2
static const int CACHEMASK = CACHESIZE-1;
static constexpr int CACHESIZE = 1<<12; // must be a power of 2
static constexpr int CACHEMASK = CACHESIZE-1;
pair<cell*, cellwalker> cache[CACHESIZE];
int nextcache;
@ -1674,6 +1688,7 @@ EX namespace hive {
EX eMonster randomHyperbug() {
int h = hivehard();
if(h && markOrb(itOrbLuck)) h /= 4;
if(hrand(200) < h)
return moBug2;
return eMonster(moBug0 + hrand(BUGCOLORS));
@ -1709,7 +1724,7 @@ EX namespace hive {
EX int bugcount[BUGCOLORS];
bool isBugEnemy(cell *c, int k) {
if(isPlayerOn(c) && !invismove) return true;
if(isPlayerOn(c) && !invismove && !peace::on) return true;
if(!c->monst) return false;
if(c->monst == moBug0+k) return false;
if(isIvy(c)) return false;
@ -1864,13 +1879,16 @@ EX namespace hive {
int gmoves[8], q=0, bqual = -1;
if(againstRose(c, NULL)) bqual = -40;
auto getplayer = peace::on ? AF_GETPLAYER : 0;
for(int dir=0; dir<c->type; dir++) {
cell *c2 = c->move(dir);
int qual = -10;
if(!c2) continue;
else if(againstRose(c, c2)) qual = -50;
else if(canAttack(c, m, c2, c2->monst, AF_GETPLAYER))
else if(isPlayerOn(c2) && peace::on) qual = -45;
else if(canAttack(c, m, c2, c2->monst, getplayer))
qual = c2->monst == moDeadBug ? -60: isBugEnemy(c2,k) ? 2 : -20;
else if(!passable(c2, c, 0))
qual = passable(c2, c, P_DEADLY) ? -30 : -60;
@ -1889,13 +1907,13 @@ EX namespace hive {
int d = gmoves[hrand(q)];
movei mi(c, d);
auto& c2 = mi.t;
if(c2->monst || isPlayerOn(c2)) {
if(c2->monst || (isPlayerOn(c2) && !peace::on)) {
eMonster killed = c2->monst;
if(isPlayerOn(c2)) killed = moPlayer;
if(isPlayerOn(c2) && !peace::on) killed = moPlayer;
if(isBug(killed)) battlecount++;
else if(killed != moPlayer && !fightspam(c2))
addMessage(XLAT("%The1 fights with %the2!", c->monst, killed));
attackMonster(c2, AF_NORMAL | AF_GETPLAYER, c->monst);
attackMonster(c2, AF_NORMAL | getplayer, c->monst);
// killMonster(c);
if(isBug(killed)) {
c2->monst = moDeadBug, deadbug.push_back(c2);
@ -1981,21 +1999,23 @@ EX namespace hive {
if(ls::any_chaos() && getDistLimit() <= 5) radius = 4;
if(getDistLimit() <= 3) radius = 3;
for(int i=(ls::any_chaos()?0:2); i<radius; i++)
for(int i=(ls::any_chaos()?0:2); i<radius; i++) {
bf += revstep;
if(ls::hv_structure()) moreBigStuff(bf.at);
}
cell *citycenter = bf.at;
buginfo.clear();
// mark the area with BFS
bugcitycell(citycenter, 0);
for(int i=0; i<isize(buginfo); i++) {
buginfo_t& b(buginfo[i]);
cell *c = b.where;
int d = b.dist[0];
if(ls::hv_structure()) moreBigStuff(c);
// ERRORS!
if(c->land != laHive && c->land != laNone) return;
if(c->bardir != NODIR) return;
if(ls::horodisk_structure() ? c->bardir != NOBARRIERS : c->bardir != NODIR) return;
if(c->land == laHive && c->landparam >= 100) return;
// bfs
if(d < radius) for(int t=0; t<c->type; t++)
@ -2009,7 +2029,8 @@ EX namespace hive {
int d = b.dist[0];
if(d <= 1 && c->wall == waNone)
c->item = itRoyalJelly;
preventbarriers(c);
if(ls::horodisk_structure()) c->bardir = NOBARRIERS2;
else preventbarriers(c);
if(d == 9 || d == 6 || d == 3)
c->barleft = eLand(d/3),
c->barright = eLand(k);
@ -2073,7 +2094,7 @@ EX namespace heat {
}
}
offscreen_heat = move(offscreen2);
offscreen_heat = std::move(offscreen2);
for(int i=0; i<numplayers(); i++) {
cell *c = playerpos(i);
@ -2110,6 +2131,8 @@ EX namespace heat {
if(c->monst == moDesertman) hmod += 4 * xrate;
if(c->monst == moAngryDie) hmod += 4 * xrate;
if(c->monst == moMonkey) hmod += xrate;
if(c->wall == waCharged) hmod += xrate * .25;
if(c->wall == waGrounded) hmod -= xrate * .25;
if(c->wall == waDeadTroll) hmod -= 2 * xrate;
if(c->wall == waDeadTroll2) hmod -= 1.5 * xrate;
if(c->wall == waBigStatue) hmod -= .5 * xrate;
@ -2320,13 +2343,11 @@ EX namespace heat {
}
}
offscreen_fire = move(offscreen2);
offscreen_fire = std::move(offscreen2);
}
EX }
bool gardener = false;
EX void livecaves() {
vector<cell*>& allcells = currentmap->allcells();
int dcs = isize(allcells);
@ -2455,10 +2476,8 @@ EX void livecaves() {
if(hv > 0) c->wall = waCavefloor;
if(hv < 0) {
c->wall = waCavewall;
if(c->land != laCaves && c->land != laDeadCaves && c->land != laEmerald && !gardener) {
gardener = true;
if(c->land != laCaves && c->land != laDeadCaves && c->land != laEmerald)
achievement_gain_once("GARDENER");
}
}
}
else if(c->land == laLivefjord) {
@ -2466,7 +2485,9 @@ EX void livecaves() {
if(hv > 0 && c->wall == waNone) {
if(c->item && c->cpdist == 1 && markOrb(itOrbWater)) {
bool saf = c->item == itOrbSafety;
collectItem(c);
eItem it = c->item;
collectItem(c, c);
if(it && !c->item) animate_item_throw(c, cwt.at, it);
if(saf) return;
}
c->wall = waSea;
@ -2501,6 +2522,7 @@ EX namespace tortoise {
EX map<cell*, int> emap;
EX map<cell*, int> babymap;
EX int last;
EX int last21tort;
#if HDR
enum tflag {
@ -2704,6 +2726,7 @@ EX namespace dragon {
total += c->hitpoints;
if(c->mondir == NODIR) return total;
c = c->move(c->mondir);
if(!c) return total;
}
return total;
}
@ -2732,6 +2755,7 @@ EX namespace dragon {
}
while(c->mondir != NODIR) {
c = c->move(c->mondir);
if(!c) return;
c->stuntime = 2;
}
break;
@ -2789,7 +2813,7 @@ EX namespace sword {
};
/** dimensions available to the Sword */
#define SWORDDIM (hybri ? 2 : WDIM)
#define SWORDDIM (mhybrid ? 2 : WDIM)
#endif
@ -2822,14 +2846,16 @@ EX namespace sword {
EX cell *pos2(cell *c, int s) {
int t = c->type;
if(hybri) t -= 2;
if(mhybrid) t -= 2;
s *= 2;
s += sword_angles/t;
s %= (2 * sword_angles);
if(s<0) s += sword_angles * 2;
s *= t;
s /= (sword_angles * 2);
return c->move(s);
auto c1 = c->move(s);
if(inmirror(c1)) c1 = mirror::reflect(c1).at;
return c1;
}
EX cell *pos(cell *c, const sworddir& sd, bool rev) {
@ -2878,9 +2904,10 @@ EX namespace sword {
neighborId(c2, c1);
if(s1 < 0 || s2 < 0) return d;
if(SWORDDIM == 2) {
int sub = (hybri) ? 2 : 0;
int sub = (mhybrid) ? 2 : 0;
int t2 = c2->type - sub;
int t1 = c1->type - sub;
if(t1 == 0 || t2 == 0) return d;
if(c1->c.mirror(s1))
d.angle = ((s2*sword_angles/t2 - d.angle + s1*sword_angles/t1) + sword_angles/2) % sword_angles;
else
@ -2926,6 +2953,8 @@ EX }
EX namespace kraken {
EX map<cell*, bool> half_killed;
EX cell *head(cell *c) {
if(c->monst == moKrakenH) return c;
if(c->monst == moKrakenT) return c->move(c->mondir);
@ -2971,7 +3000,6 @@ EX namespace kraken {
}
EX void attacks() {
pathdata pd(2);
bool offboat[MAXPLAYER];
for(int i=0; i<MAXPLAYER; i++) offboat[i] = false;
for(int i=0; i<isize(dcal); i++) {
@ -2983,7 +3011,7 @@ EX namespace kraken {
attackMonster(c2, AF_NORMAL | AF_MSG, c->monst);
sleep(c);
}
else for(int i=0; i<numplayers(); i++) if(playerpos(i) == c2) {
else for(int i=0; i<numplayers(); i++) if(playerpos(i) == c2 && !peace::on) {
if(isPlayerInBoatOn(c2, i)) {
addMessage(XLAT("%The1 destroys your boat!", moKrakenH));
dboat = true;
@ -3028,10 +3056,13 @@ EX namespace kraken {
c3->monst = moNone;
}
c->monst = moKrakenH;
if(half_killed.count(c2)) { half_killed[c] = half_killed[c2]; half_killed.erase(c2); }
vector<pair<cell*, cell*> > acells;
acells.push_back(make_pair(c2, c));
forCellIdEx(c3, i, c) {
c3->monst = moKrakenT, c3->mondir = c->c.spin(i), c3->monmirror = c->monmirror ^ c->c.mirror(i), onpath(c3, 0);
c3->monst = moKrakenT;
c3->mondir = c->c.spin(i);
c3->monmirror = c->monmirror ^ c->c.mirror(i);
int i0 = (i+c->c.spin(c->mondir)-c->mondir+96+c->type/2) % c2->type;
c3->hitpoints = hpcount[i0];
acells.push_back(make_pair(c2->move(i0), c3));
@ -3063,7 +3094,6 @@ EX namespace kraken {
}
commitAnimations(LAYER_BIG);
sleep(c);
onpath(c, 0);
return;
}
@ -3093,7 +3123,7 @@ EX namespace prairie {
if(ls::any_chaos()) {
c->LHU.fi.rval = 0;
}
else if(quotient) { // fix cylinder
else if(quotient && geometry != gFieldQuotient) { // fix cylinder
c->LHU.fi.rval = 0;
}
else if(euclid) {
@ -3166,49 +3196,63 @@ EX namespace prairie {
#define RLOW (sphere?(PURE?7:6):PURE?4:2)
#define RHIGH (sphere?(PURE?8:9):PURE?11:13)
EX int get_val(cell *c) {
if(ls::hv_structure()) {
int a = celldistAlt(c);
if(a >= 2) a = 2;
a = gmod(18 - a, 20);
return a;
}
return c->LHU.fi.rval;
}
EX bool no_worms(cell *c) {
if(c->land != laPrairie) return false;
int rv = c->LHU.fi.rval;
int rv = get_val(c);
return rv > RLOW+1 && rv < RHIGH-1;
}
EX bool isriver(cell *c) {
return c->land == laPrairie && c->LHU.fi.rval <= RHIGH && c->LHU.fi.rval >= RLOW;
int rv = get_val(c);
return c->land == laPrairie && rv <= RHIGH && rv >= RLOW;
}
bool mainriver(cell *c) {
return c->LHU.fi.rval <= 8 && c->LHU.fi.rval >= 7;
int rv = get_val(c);
return rv <= 8 && rv >= 7;
}
EX bool nearriver(cell *c) {
return c->LHU.fi.rval == RHIGH+1 || c->LHU.fi.rval == RLOW-1;
int rv = get_val(c);
return rv == RHIGH+1 || rv == RLOW-1;
}
cell *enter;
bool opposite(cell *c) {
return (c->LHU.fi.rval ^ enter->LHU.fi.rval) & 8;
return (get_val(c) ^ get_val(enter)) & 8;
}
bool isleft(cell *c) {
return c->LHU.fi.rval & 8;
return get_val(c) & 8;
}
int towerleft(cell *c) {
return c->LHU.fi.rval;
return get_val(c);
}
int towerright(cell *c) {
return 15^c->LHU.fi.rval;
return 15^get_val(c);
}
EX cell *next(cell *c, int pv IS(1)) {
for(int i=0; i<c->type; i++) {
cell *c1 = createMov(c, i);
cell *c2 = createMov(c, (i+pv+c->type)%c->type);
if(c1 && c1->LHU.fi.rval == c->LHU.fi.rval)
if(c2 && c2->LHU.fi.rval == c->LHU.fi.rval+1)
int rv = get_val(c);
if(c1 && get_val(c1) == rv)
if(c2 && get_val(c2) == rv+1)
if(isNeighbor(c1,c2))
return c1;
}
@ -3312,20 +3356,37 @@ EX namespace prairie {
return true;
}
EX void generateTreasure_here(cell *c) {
int hr = hrand(100);
if(hr == 0 && items[itGreenGrass] >= 10 && !inv::on) {
c->item = itOrbBull;
// orbs.push_back(c);
}
else if(hr < 1+PRIZEMUL) {
placePrizeOrb(c);
// if(c->item) orbs.push_back(c);
}
else if(!ls::hv_structure())
tchoices.push_back(c);
}
EX void generateTreasure(cell *c) {
// if(nearriver(c) && op
if(enter && nearriver(c) && opposite(c) && thisriver(c)) {
int hr = hrand(100);
if(hr == 0 && items[itGreenGrass] >= 10 && !inv::on) {
c->item = itOrbBull;
// orbs.push_back(c);
if(ls::hv_structure()) {
if(get_val(c) == RHIGH + 1) {
int cd = celldist(c);
int min_cd = cd;
cell *c1;
c1 = c; for(int a=0; a<3; a++) { forCellEx(c2, c1) setdist(c2, 9, nullptr); c1 = next(c1); if(!c1) return; min_cd = min(min_cd, celldist(c1)); }
c1 = c; for(int a=0; a<3; a++) { forCellEx(c2, c1) setdist(c2, 9, nullptr); c1 = prev(c1); if(!c1) return; min_cd = min(min_cd, celldist(c1)); }
if(min_cd >= cd-1) forCellEx(c1, c) if(isriver(c1) && celldist(c1) < cd)
c->item = itGreenGrass;
}
else if(hr < 1+PRIZEMUL) {
placePrizeOrb(c);
// if(c->item) orbs.push_back(c);
}
else tchoices.push_back(c);
}
if(get_val(c) == 18 && hrand(100) < 50) c->item = itOrbSafety;
if(get_val(c) == 17) generateTreasure_here(c);
return;
}
if(enter && nearriver(c) && opposite(c) && thisriver(c)) generateTreasure_here(c);
}
EX void treasures() {
@ -3359,7 +3420,7 @@ namespace prairie {
EX namespace ca {
EX ld prob = .2;
static const int MAX_NEIGHBOR = 60; /* may be larger than MAX_EDGE due to mineadj */
static constexpr int MAX_NEIGHBOR = 60; /* may be larger than MAX_EDGE due to mineadj */
string carule[MAX_NEIGHBOR][2];
EX eWall wlive = waFloorA;
@ -3446,6 +3507,7 @@ EX namespace ca {
}
for(int i=0; i<dcs; i++) {
cell *c = allcells[i];
if(c->land != laCA) continue;
auto last = c->wall;
c->wall = willlive[i] ? wlive : waNone;
if(c->wall != last) {
@ -3467,6 +3529,7 @@ auto ccm = addHook(hooks_clearmemory, 0, [] () {
clearing::stats.clear();
clearing::score.clear();
tortoise::emap.clear();
kraken::half_killed.clear();
tortoise::babymap.clear();
dragon::target = NULL;
#if CAP_FIELD
@ -3498,6 +3561,8 @@ auto ccm = addHook(hooks_clearmemory, 0, [] () {
}) +
addHook(hooks_removecells, 0, [] () {
for(cell *c: removed_cells) clearing::score.erase(c);
for(auto& am: adj_memo) am.clear();
for(cell *c: removed_cells) kraken::half_killed.erase(c);
eliminate_if(heat::offscreen_heat, is_cell_removed);
eliminate_if(heat::offscreen_fire, is_cell_removed);
eliminate_if(princess::infos, [] (princess::info*& i) {
@ -3531,8 +3596,8 @@ int windcodes5676[] = {152,138,172,172,141,158,157,124,119,130,125,143,190,206,2
EX namespace windmap {
#if HDR
static const int NOWINDBELOW = 8;
static const int NOWINDFROM = 120;
static constexpr int NOWINDBELOW = 8;
static constexpr int NOWINDFROM = 120;
#endif
map<int, int> getid;
@ -3568,7 +3633,9 @@ EX namespace windmap {
}
EX void create() {
if(disable_bigstuff) return;
if(cgflags & qPORTALSPACE) return;
if(hat::in()) return;
samples.clear();
neighbors.clear();
getid.clear();
@ -3578,7 +3645,7 @@ EX namespace windmap {
// cw.spin = 0;
neighbors.emplace_back();
auto &v = neighbors.back();
if(NONSTDVAR && !sphere && !arcm::in() && !hybri && !INVERSE)
if(NONSTDVAR && !sphere && !arcm::in() && !mhybrid && !INVERSE)
for(int l=0; l<S7; l++) {
v.push_back(getId(cw + cth + l + wstep + cth));
}
@ -3595,7 +3662,7 @@ EX namespace windmap {
if(N == 18920) precomp = windcodes18920;
if(N == 5676) precomp = windcodes5676;
if(precomp && (hyperbolic || hybri) && isize(currfp.matrices)) {
if(precomp && (hyperbolic || mhybrid) && isize(currfp.matrices)) {
int randval = hrand(isize(currfp.matrices));
for(int i=0; i<N; i++)
windcodes[i] = precomp[getid[fieldpattern::fieldval_uniq_rand(samples[i].at, randval)]-1];
@ -3669,6 +3736,53 @@ EX namespace halloween {
EX cell *dragoncells[4];
vector<cell*> srch;
EX void generate() {
auto lst = currentmap->allcells();
for(cell *c: lst)
setdist(c, 7, nullptr);
halloween::dragoncells[0] = NULL;
if(sphere && geometry == gSphere) {
for(cell *c: lst) {
if(GOLDBERG) {
int fv = c->master->fiftyval;
if(fv == 1 || fv == 4 || fv == 10)
c->wall = waChasm;
if(c == c->master->c7 && fv == 3)
c->item = itTreat;
}
else if(!BITRUNCATED) {
int fv = c->master->fiftyval;
if(fv == 1 || fv == 4 || fv == 2)
c->wall = waChasm;
if(fv == 3) c->item = itTreat;
}
else {
if(c->type == 5) {
int fv = c->master->fiftyval;
if(fv == 3 || fv == 4 || fv == 2 || fv == 5)
c->wall = waChasm;
if(fv == 2) halloween::dragoncells[0] = c;
if(fv == 5) halloween::dragoncells[3] = c;
if(fv == 1) c->item = itTreat;
}
if(c->type == 6) {
int fvset = 0;
for(int i=0; i<6; i+=2) fvset |= 1 << createMov(c, i)->master->fiftyval;
if(fvset == 35 || fvset == 7) c->wall = waChasm;
if(fvset == 7) halloween::dragoncells[1] = c;
if(fvset == 35) halloween::dragoncells[2] = c;
}
}
}
}
else {
for(int i=1; i<isize(lst); i+=60) lst[i]->item = itTreat;
for(int i=2; i<isize(lst); i+=6) lst[i]->wall = waChasm;
}
}
cell *farempty(bool lastresort = false) {
int maxdist = 0;
vector<cell*> validcells;
@ -3936,12 +4050,25 @@ EX }
EX namespace dungeon {
/* use coastvalEdge normally, but celldistAlt in hv_structure */
int cvfun(cell *c) {
if(ls::hv_structure()) return celldistAltPlus(c);
return coastvalEdge(c);
}
void towerError(cell *c) {
// only care in the standard geometry -- weird ones are intentionally left buggy
if(!weirdhyperbolic && !sphere && !quotient)
if(!weirdhyperbolic && !sphere && !quotient && !ls::hv_structure())
raiseBuggyGeneration(c, "ivory tower/dungeon generation error");
}
/** for some reason standard generate_around does not work in hv_structure */
void gen_around(cell *c) {
if(ls::hv_structure()) {
forCellEx(c2, c) setdist(c2, 8, c);
}
else generate_around(c);
}
void buildIvoryTower(cell *c) {
/* if(int(c->landparam) % 5 == 0)
c->wall = waCamelot;
@ -3988,27 +4115,27 @@ EX namespace dungeon {
cl.add(c);
for(int i=0; i<isize(cl.lst); i++) {
cell *c1 = cl.lst[i];
generate_around(c1);
if(coastvalEdge(c1) == coastvalEdge(c) - 3) {
gen_around(c1);
if(cvfun(c1) == cvfun(c) - 3) {
if(c1->landflags == 3) cnt++;
continue;
}
if(c1->landflags == 3) below++;
forCellEx(c2, c1) if(coastvalEdge(c2) < coastvalEdge(c1))
forCellEx(c2, c1) if(cvfun(c2) < cvfun(c1))
cl.add(c2);
}
if(cnt) c->wall = waPlatform;
else if(below && coastvalEdge(c) < 3) c->wall = waPlatform;
else if(below && cvfun(c) < 3) c->wall = waPlatform;
}
else if(true) {
cell *c2 = c;
cell *c3 = c;
bool rdepths[5];
for(int i=0; i<5; i++) {
if(coastvalEdge(c2) == 0) {
if(cvfun(c2) == 0) {
rdepths[i] = false;
}
else {
@ -4018,10 +4145,11 @@ EX namespace dungeon {
c4 = c2->move(i);
}
rdepths[i] = c2 && c3 && c4 && (c2->landflags == 3 || c3->landflags == 3 || c4->landflags == 3);
if(c2) generate_around(c2);
if(c3) generate_around(c3);
c2 = ts::left_parent(c2, coastvalEdge);
c3 = ts::right_parent(c3, coastvalEdge);
if(c2) gen_around(c2);
if(c3) gen_around(c3);
c2 = ts::left_parent(c2, cvfun);
c3 = ts::right_parent(c3, cvfun);
if(!c2) { towerError(c); return; }
if(!c3) { towerError(c); return; }
}
@ -4029,27 +4157,26 @@ EX namespace dungeon {
if(rdepths[3]) {
c->wall = waPlatform;
// if(!c4->item) c4->item = itPalace;
}
else if(!rdepths[2] && !rdepths[4] && !rdepths[1]) {
c2 = c;
c3 = c;
generate_around(c);
cell *c4 = ts::left_of(c, coastvalEdge);
cell *c5 = ts::right_of(c, coastvalEdge);
gen_around(c);
cell *c4 = ts::left_of(c, cvfun);
cell *c5 = ts::right_of(c, cvfun);
for(int i=0; i<3; i++) {
if(coastvalEdge(c2) == 0) break;
for(cell *cx: {c2, c3, c4, c5}) if(cx) generate_around(cx);
if(cvfun(c2) == 0) break;
for(cell *cx: {c2, c3, c4, c5}) if(cx) gen_around(cx);
if(c2 && c4 && c4->landflags == 3 && c2->landflags != 3 && c4 == ts::left_of(c2, coastvalEdge))
if(c2 && c4 && c4->landflags == 3 && c2->landflags != 3 && c4 == ts::left_of(c2, cvfun))
c->wall = waLadder;
if(c3 && c5 && c5->landflags == 3 && c3->landflags != 3 && c5 == ts::right_of(c3, coastvalEdge))
if(c3 && c5 && c5->landflags == 3 && c3->landflags != 3 && c5 == ts::right_of(c3, cvfun))
c->wall = waLadder;
buildEquidistant(c4); buildEquidistant(c5);
if(c2) c2 = ts::left_parent(c2, coastvalEdge);
if(c3) c3 = ts::right_parent(c3, coastvalEdge);
if(c4) c4 = ts::left_parent(c4, coastvalEdge);
if(c5) c5 = ts::right_parent(c5, coastvalEdge);
if(!ls::hv_structure()) { buildEquidistant(c4); buildEquidistant(c5); }
if(c2) c2 = ts::left_parent(c2, cvfun);
if(c3) c3 = ts::right_parent(c3, cvfun);
if(c4) c4 = ts::left_parent(c4, cvfun);
if(c5) c5 = ts::right_parent(c5, cvfun);
}
}
}
@ -4067,16 +4194,17 @@ EX namespace dungeon {
manual_celllister cl;
cl.add(c);
int d = coastvalEdge(c);
int d = cvfun(c);
for(int i=0; i<isize(cl.lst); i++) {
cell *c1 = cl.lst[i];
if(ls::hv_structure()) forCellEx(c4, c1) moreBigStuff(c4);
generate_around(c1);
int d1 = d - coastvalEdge(c);
int d1 = d - cvfun(c);
if(c1->landflags == 3) rdepths[d1] = true;
if(c1->landflags == 1) switchcount++;
if(d1 == 4) break;
forCellEx(c2, c1) if(coastvalEdge(c2) < coastvalEdge(c1))
forCellEx(c2, c1) if(cvfun(c2) < cvfun(c1))
cl.add(c2);
}
}
@ -4087,7 +4215,7 @@ EX namespace dungeon {
cell *c3 = c;
for(int i=0; i<5; i++) {
if(coastvalEdge(c2) == 0) {
if(cvfun(c2) == 0) {
rdepths[i] = false;
}
else {
@ -4099,10 +4227,14 @@ EX namespace dungeon {
rdepths[i] = c2 && c3 && c4 && (c2->landflags == 3 || c3->landflags == 3 || c4->landflags == 3);
if((c2&&c2->landflags == 1) || (c3&&c3->landflags == 1) || (c4&&c4->landflags == 1))
switchcount++;
if(ls::hv_structure()) {
forCellEx(c4, c2) moreBigStuff(c4);
forCellEx(c4, c3) moreBigStuff(c3);
}
generate_around(c2);
generate_around(c3);
c2 = ts::left_parent(c2, coastvalEdge);
c3 = ts::right_parent(c3, coastvalEdge);
c2 = ts::left_parent(c2, cvfun);
c3 = ts::right_parent(c3, cvfun);
if(!c2) { towerError(c); return 0; }
if(!c3) { towerError(c); return 0; }
}
@ -4138,6 +4270,7 @@ EX namespace dungeon {
}
cell *random_child(cell *c, const cellfunction& cf) {
if(ls::hv_structure()) forCellEx(c4, c) moreBigStuff(c4);
generate_around(c);
vector<cell*> children;
forCellEx(c2, c) if(cf(c2) > cf(c)) children.push_back(c2);
@ -4152,7 +4285,7 @@ EX namespace dungeon {
if(true) {
if(coastvalEdge(c) == 1) forCellEx(c2, c)
if(cvfun(c) == 1) forCellEx(c2, c)
if(c2->land != laBarrier && c2->land != laDungeon) {
c->wall = waLadder;
c->wparam = 3;
@ -4161,9 +4294,10 @@ EX namespace dungeon {
int df = dungeonFlags(c);
if(df&1) {
if(ls::hv_structure()) forCellEx(c4, c) moreBigStuff(c4);
generate_around(c);
int df1 = WDIM == 3 ? 0 : dungeonFlags(ts::left_of(c, coastvalEdge));
int df2 = WDIM == 3 ? 0 : dungeonFlags(ts::right_of(c, coastvalEdge));
int df1 = WDIM == 3 ? 0 : dungeonFlags(ts::left_of(c, cvfun));
int df2 = WDIM == 3 ? 0 : dungeonFlags(ts::right_of(c, cvfun));
c->wparam = 0;
if(hrand(100) < (c->landparam % 5 == 0 ? 80 : 20)) {
@ -4183,11 +4317,11 @@ EX namespace dungeon {
if(c->wparam) {
cell *c2 =
WDIM == 3 ? random_child(c, coastvalEdge) :
c->wparam == 1 ? ts::add(c, 1, 2, coastvalEdge) :
c->wparam == 2 ? ts::add(c, -1, -2, coastvalEdge) :
c->wparam == 3 ? ts::add(c, 1, 3, coastvalEdge) :
c->wparam == 4 ? ts::add(c, -1, -3, coastvalEdge) :
WDIM == 3 ? random_child(c, cvfun) :
c->wparam == 1 ? ts::add(c, 1, 2, cvfun) :
c->wparam == 2 ? ts::add(c, -1, -2, cvfun) :
c->wparam == 3 ? ts::add(c, 1, 3, cvfun) :
c->wparam == 4 ? ts::add(c, -1, -3, cvfun) :
NULL;
if(c2) {
@ -4209,7 +4343,7 @@ EX namespace dungeon {
int neargateEq = 0;
int qup = 0;
forCellEx(c2, c) {
int d = coastvalEdge(c2) - coastvalEdge(c);
int d = cvfun(c2) - cvfun(c);
if(isGate(c2->wall)) {
neargate++;
if(d>0) neargateDown++;

View File

@ -8,10 +8,10 @@
*/
#include "hyper.h"
#if CAP_COMPLEX2
namespace hr {
#if CAP_COMPLEX2
EX namespace brownian {
#if HDR
@ -44,7 +44,7 @@ EX namespace brownian {
c->landparam += val;
}
static const int FAT = (-100); // less than 0
static constexpr int FAT = (-100); // less than 0
void recurse(cell *c, int fatten_from) {
int dl = getDistLimit();
@ -148,7 +148,7 @@ EX namespace brownian {
EX void apply_futures(cell *c) {
if(futures.count(c)) {
auto m = move(futures[c]);
auto m = std::move(futures[c]);
futures.erase(c);
for(auto p: m)
recurse(p.first, p.second);
@ -161,16 +161,16 @@ EX namespace brownian {
if(!hyperbolic) c->wall = waNone, c->landparam = 256;
if(c->landparam == 0 && ls::single()) c->land = laOcean;
if(c->landparam == 0 && (ls::single() || ls::hv_structure())) c->land = laOcean;
ONEMPTY {
if(hrand(10000) < min(250, 100 + 2 * PT(kills[moAcidBird] + kills[moBrownBug], 50)) * (25 + min(items[itBrownian], 100)) / 25 && c->landparam >= 4 && c->landparam < 24)
c->item = itBrownian;
if(hrand_monster(8000) < 15 + items[itBrownian])
if(hrand_monster_in(laBrownian, 8000) < 15 + items[itBrownian])
c->monst = moAcidBird;
else if(hrand_monster(8000) < 15)
else if(hrand_monster_in(laBrownian, 8000) < 15)
c->monst = moAlbatross;
else if(hrand_monster(8000) < 15 + items[itBrownian]) {
else if(hrand_monster_in(laBrownian, 8000) < 15 + items[itBrownian]) {
c->monst = moBrownBug;
c->hitpoints = 3;
}
@ -225,6 +225,7 @@ EX namespace westwall {
again:
cell *at = whirlline[isize(whirlline)-1];
cell *prev = whirlline[isize(whirlline)-2];
if(looped(whirlline)) return;
for(int i=0; i<at->type; i++)
if(at->move(i) && coastvalEdge1(at->move(i)) == d && at->move(i) != prev) {
whirlline.push_back(at->move(i));
@ -254,7 +255,7 @@ EX namespace westwall {
animateMovement(match(whirlline[i+1], whirlline[i]), LAYER_BOAT);
}
for(int i=0; i<z; i++)
pickupMovedItems(whirlline[i]);
pickupMovedItems(whirlline[i], i<z-1 ? whirlline[i+1] : whirlline[0]);
}
EX void move() {
@ -290,7 +291,7 @@ extern array<feature, 21> features;
#define VF [] (cell *c)
bool hrand_var(int i) { return hrand_monster(i) < 25 + items[itVarTreasure] + yendor::hardness(); }
bool hrand_var(int i) { return hrand_monster_in(laVariant, i) < 25 + items[itVarTreasure] + yendor::hardness(); }
array<feature, 21> features {{
feature{(color_t)(-0x202020), 5, moNecromancer, VF {
@ -353,6 +354,8 @@ vector<string> knight_names = {
"JeLomun", "kip", "Warmonger", "Fooruman", "Zyalin", "Prezombie", "ashley89", "bjobae", "MFErtre", "Roaringdragon2", "howilovepi", "Yulgash", "Sir Endipitous", "Roshlev",
"BTernaryTau", "HiGuy", "coper", "Tirear", "qoala _", "Tyzone", "Tiegon", "Airin", "Metroid26", "Sklorg", "Fumblestealth", "Toph", "Tzaphqiel", "jruderman", "ray",
"Deathroll", "Sinquetica", "mootmoot", "Noobinator", "freeofme", "Helyea", "Snakebird Priestess", "brisingre", "Khashishi", "Shiny", "kabado", "Berenthas", "Misery", "Altripp", "Aldrenean",
// via itch.io and reports on Discord
"AntiRogue"
};
map<cell*, int> knight_id;
@ -459,7 +462,7 @@ EX void knightFlavorMessage(cell *c2) {
s = crystal::get_table_boundary();
#endif
else if(!quotient && rad)
s = expansion.get_descendants(rad).get_str(100);
s = get_expansion().get_descendants(rad).get_str(100);
if(s == "") { msgid++; goto retry; }
addMessage(XLAT("\"Our Table seats %1 Knights!\"", s));
}
@ -471,7 +474,7 @@ EX void knightFlavorMessage(cell *c2) {
s = crystal::get_table_volume();
#endif
else if(!quotient && rad)
s = expansion.get_descendants(rad-1, expansion.diskid).get_str(100);
s = get_expansion().get_descendants(rad-1, get_expansion().diskid).get_str(100);
if(s == "") { msgid++; goto retry; }
addMessage(XLAT("\"There are %1 floor tiles inside our Table!\"", s));
}
@ -525,12 +528,12 @@ EX void count_status() {
for(cell *c: currentmap->allcells()) if(among(c->wall, waMineMine, waMineUnknown) && mine::marked_mine(c)) kills[moTameBomberbird]++;
if(last && !kills[moBomberbird]) {
mine::victory_time = getgametime();
pushScreen(showMission);
showMissionScreen();
}
}
EX bool in_minesweeper() {
return bounded && specialland == laMinefield;
return closed_or_bounded && specialland == laMinefield;
}
EX bool uncoverMines(cell *c, int lev, int dist, bool just_checking) {
@ -580,6 +583,8 @@ EX bool mightBeMine(cell *c) {
EX hookset<bool(cell*)> hooks_mark;
EX bool mark_always = true;
EX void performMarkCommand(cell *c) {
if(!c) return;
if(callhandlers(false, hooks_mark, c)) return;
@ -595,6 +600,7 @@ EX void performMarkCommand(cell *c) {
if(c->item) return;
if(!mightBeMine(c)) return;
bool adj = false;
if(mark_always) adj = true;
forCellEx(c2, c) if(c2->wall == waMineOpen) adj = true;
if(adj) c->landparam ^= 1;
}
@ -619,7 +625,7 @@ EX bool safe() {
EX void uncover_full(cell *c2) {
int mineradius =
bounded ? 3 :
closed_or_bounded ? 3 :
(items[itBombEgg] < 1 && !tactic::on) ? 0 :
items[itBombEgg] < 20 ? 1 :
items[itBombEgg] < 30 ? 2 :
@ -652,17 +658,18 @@ static constexpr bool randterra = false;
EX void check(cell *c) {
if(c->wall == waTerraWarrior && !c->monst && !racing::on) {
changes.ccell(c);
bool live = false;
if(randterra) {
c->landparam++;
if((c->landparam == 3 && hrand(3) == 0) ||
(c->landparam == 4 && hrand(2) == 0) ||
c->landparam == 5)
c->wparam++;
if((c->wparam == 3 && hrand(3) == 0) ||
(c->wparam == 4 && hrand(2) == 0) ||
c->wparam == 5)
live = true;
}
else {
c->landparam--;
live = !c->landparam;
c->wparam--;
live = !c->wparam;
}
if(live)
c->monst = moTerraWarrior,
@ -900,6 +907,12 @@ EX void ambush(cell *c, int dogs) {
addMessage(XLAT("You are ambushed!"));
}
EX void guard_attack() {
addMessage(XLAT("%The1 alarms other dogs as it dies!", moHunterDog));
for(cell *c: dcal) if(c->monst == moHunterGuard) c->monst = moHunterDog;
ambush(cwt.at, 7);
}
EX }
EX namespace dice {
@ -911,6 +924,7 @@ EX namespace dice {
int faces;
int facesides;
int order;
int highest_hardness;
die_structure(int ord, const vector<vector<int>>& v) {
sides = v;
spins = sides;
@ -933,6 +947,9 @@ EX namespace dice {
for(int i=0; i<faces; i++)
for(int j: sides[i])
hardness[i] = min(hardness[i], hardness[j]+1);
highest_hardness = 0;
for(int i=0; i<faces; i++)
highest_hardness = max(highest_hardness, hardness[i]);
}
};
@ -1051,7 +1068,7 @@ EX namespace dice {
c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie;
generate_specific(c, &d6, 1, 2);
}
if(pct2 < 40 + hard) {
else if(pct2 < 40 + hard) {
c->monst = moAnimatedDie;
generate_specific(c, &d6, 0, 99);
}
@ -1062,7 +1079,7 @@ EX namespace dice {
c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie;
generate_specific(c, &d12, 2, 3);
}
if(pct2 < 40 + hard) {
else if(pct2 < 40 + hard) {
c->monst = moAnimatedDie;
generate_specific(c, &d12, 0, 99);
}
@ -1153,6 +1170,12 @@ EX namespace dice {
return isDie(c->wall) || isDie(c->monst);
}
EX string describe(cell *c) {
if (!data.count(c)) return "BUG: die data missing";
else if (!data[c].which) return "BUG: die data default-initialized";
else return XLAT("d%1 rolled %2", its(data[c].which->faces), its(data[c].val + 1));
}
EX void roll(movei mi) {
auto &cto = mi.t;
auto &th = mi.s;
@ -1169,6 +1192,9 @@ EX namespace dice {
return;
}
/* priority used for dice */
const auto prio = PPR::BIGSTATUE;
eGeometry orig = geometry;
bool fpp = GDIM == 3;
@ -1179,7 +1205,8 @@ EX namespace dice {
int si = dw->facesides;
if(c == lmouseover_distant) {
if(inHighQual) ;
else if(c == lmouseover_distant) {
set<cell*> visited;
struct celldata_t {
cell* c;
@ -1195,7 +1222,11 @@ EX namespace dice {
visit(c, dd, V);
for(int i=0; i<isize(data); i++) {
auto dat = data[i];
queuestr(fpp ? dat.V * zpush(cgi.FLOOR) : dat.V, .5, its(dat.dd.val+1), 0xFF8000FF);
int wa = dw->hardness[dat.dd.val];
int wb = dw->highest_hardness;
unsigned int red = ((wa * 0x00) + ((wb-wa) * 0xff)) / wb;
color_t col = 0xFF0000FF + (red << 16);
queuestr(fpp ? dat.V * zpush(cgi.FLOOR) : dat.V, .5, its(dat.dd.val+1), col);
if(i <= 22)
forCellIdEx(c2, id, dat.c) if(can_roll(si, dat.dd.dir, movei(dat.c, id)) && !visited.count(c2)) {
auto re = roll_effect(movei(dat.c, id), dat.dd);
@ -1217,7 +1248,7 @@ EX namespace dice {
}
}
shiftmatrix V1 = V * ddspin(c, dir) * spin(M_PI);
shiftmatrix V1 = V * ddspin(c, dir, M_PI);
if(dd.mirrored) V1 = V1 * MirrorY;
// loop:
@ -1238,8 +1269,8 @@ EX namespace dice {
if(1) {
dynamicval<eGeometry> g(geometry, gSphere);
ld alpha = 360 * degree / dw->order;
ld beta = 180 * degree / dw->facesides;
ld alpha = TAU / dw->order;
ld beta = M_PI / dw->facesides;
inradius = edge_of_triangle_with_angles(alpha, beta, beta);
outradius = edge_of_triangle_with_angles(beta, alpha, beta);
}
@ -1251,11 +1282,13 @@ EX namespace dice {
dynamicval<eGeometry> g(geometry, gSphere);
hyperpoint de = direct_exp(log_shift);
S = rgpushxto0(de);
#if MAXMDIM >= 4
if(GDIM == 3) {
for(int i=0; i<4; i++) swap(S[i][2], S[i][3]);
for(int i=0; i<4; i++) swap(S[2][i], S[3][i]);
for(int i=0; i<MAXMDIM; i++) swap(S[i][2], S[i][3]);
for(int i=0; i<MAXMDIM; i++) swap(S[2][i], S[3][i]);
}
for(int i=0; i<4; i++) S[i][1] *= -1;
#endif
for(int i=0; i<MAXMDIM; i++) S[i][1] *= -1;
}
add_to_queue(S, val);
@ -1298,7 +1331,7 @@ EX namespace dice {
for(int d=0; d<si; d++) {
dynamicval<eGeometry> g(geometry, highdim);
add_to_queue(T * cspin(0, 1, 2*M_PI*d/si) * cspin(2, 0, inradius) * cspin(0, 1, M_PI-2*M_PI*dw->spins[ws][d]/si), dw->sides[ws][d]);
add_to_queue(T * cspin(0, 1, TAU*d/si) * cspin(2, 0, inradius) * cspin(0, 1, M_PI-TAU*dw->spins[ws][d]/si), dw->sides[ws][d]);
}
if(1) {
@ -1326,22 +1359,28 @@ EX namespace dice {
auto sphere_to_space = [&] (hyperpoint h) {
if(fpp) return h;
if(osphere) {
h[2] = 1 - h[2]; h[3] = 0;
h[2] = 1 - h[2];
#if MAXMDIM > 3
h[3] = 0;
#endif
return h;
}
if(oeuclid) { h[2] = 1-h[2]; return h; }
ld z = asin_auto(h[2]);
h = zpush(-z) * h;
h[2] = h[3]; h[3] = 0;
#if MAXMDIM > 3
h[2] = h[3];
h[3] = 0;
#endif
dynamicval<eGeometry> g(geometry, orig);
return zshift(h, geom3::scale_at_lev(z));
return orthogonal_move(h, z);
};
for(int d=0; d<=si; d++) {
hyperpoint h, hs;
if(1) {
dynamicval<eGeometry> g(geometry, highdim);
h = zpush(base_to_base) * T * cspin(0, 1, 2*M_PI*(d+.5)/si) * cspin(2, 0, outradius) * zpush0(dieradius);
h = zpush(base_to_base) * T * cspin(0, 1, TAU*(d+.5)/si) * cspin(2, 0, outradius) * zpush0(dieradius);
if(d < si) face[d] = h;
hs = sphere_to_space(h);
}
@ -1371,10 +1410,11 @@ EX namespace dice {
cy = face[1] - (face[3] + face[4]) * .4;
}
queuecurve(V1, 0xFFFFFFFF, color & 0xFFFFFF9F, PPR::WALL);
queuecurve(V1, (poly_outline == OUTLINE_NONE) ? 0xFFFFFFFF : poly_outline, color & 0xFFFFFF9F, prio);
#if !CAP_EXTFONT
if(!vid.usingGL) continue;
#if CAP_GL
pointfunction pf = [&] (ld x, ld y) {
dynamicval<eGeometry> g(geometry, highdim);
return sphere_to_space(normalize(ctr + cx * x + cy * y));
@ -1392,7 +1432,7 @@ EX namespace dice {
cx = (face[j2] - face[j]) / 2;
cy = face[j1] - (face[j] + face[j2]) / 4;
}
write_in_space(V1, max_glfont_size, -1.2, its(1+dw->sides[q][j]), 0xFFFFFFFF, 0, 8, PPR::WALL, pf);
write_in_space(V1, max_glfont_size, -1.2, its(1+dw->sides[q][j]), 0xFFFFFFFF, 0, 8, prio, pf);
}
}
else {
@ -1401,9 +1441,10 @@ EX namespace dice {
if(fid == 6) s = "6.";
else if(fid == 9) s = "9.";
else s = its(fid);
write_in_space(V1, max_glfont_size, dw->faces < 10 ? -1.2 : -.75, s, 0xFFFFFFFF, 0, 8, PPR::WALL, pf);
write_in_space(V1, max_glfont_size, dw->faces < 10 ? -1.2 : -.75, s, 0xFFFFFFFF, 0, 8, prio, pf);
}
#endif
#endif
}
}
@ -1429,5 +1470,17 @@ EX namespace dice {
int hook = addHook(hooks_clearmemory, 0, [] () { data.clear(); });
EX }
}
#endif
#if !CAP_COMPLEX2
EX namespace dice {
EX bool on(cell *c) { return false; }
EX bool swap_forbidden(cell *a, cell *b) { return false; }
EX void chaos_swap(cellwalker wa, cellwalker wb) {}
EX }
EX namespace mine {
EX bool in_minesweeper() { return false; }
EX }
#endif
}

2812
config.cpp

File diff suppressed because it is too large Load Diff

View File

@ -260,7 +260,7 @@ MONSTER( 'T', 0x00FFFF, "Fjord Troll", moFjordTroll, CF_FACE_UP | CF_TROLL, RESE
MONSTER( 'E', 0x0000FF, "Water Elemental", moWaterElemental, CF_FACE_UP | CF_NOBLOW | CF_NONLIVING | CF_HIGH_THREAT, RESERVED, moWaterElemental,
"Wherever this powerful being goes, the living fjord "
"sinks below water, non-magical boats are destroyed, and fires are extinguished.\n\n"
"As a special case, you can attack the Water Elemental from the water, without drowning immediately."
"As a special case, you can attack the Water Elemental from the water with your blade, without drowning immediately."
)
MONSTER( 'M', 0xD0D0D0, "Mouse", moMouse, CF_FACE_SIDE | CF_NOGHOST | CF_GOK | CF_FRIENDLY | CF_FACING | CF_UNARMED | CF_IGNORE_PLATE, RESERVED, moNone, princessdesc)
MONSTER( 'M', 0xD0D0D0, "Mouse", moMouseMoved, CF_FACE_SIDE | CF_NOGHOST | CF_GOK | CF_FRIENDLY | CF_FACING | CF_UNARMED | CF_MOVED, RESERVED, moNone, princessdesc)
@ -295,7 +295,7 @@ MONSTER( 'F', 0xC35817, "Giant Fox", moRedFox, CF_FACE_SIDE | CF_HIGH_THREAT, RE
MONSTER( 'C', 0x8080FF, "Wind Crow", moWindCrow, CF_FACE_SIDE | CF_BIRD | CF_FLYING | CF_IGNORE_PLATE | CF_HIGH_THREAT, RESERVED, moEagle,
"A large bird who likes strong winds. Just as you, it can fly quickly in the wind."
)
MONSTER( 'G', 0xC0FFC0, "Friendly Ghost", moFriendlyGhost, CF_FACE_SIDE | CF_NOGHOST | CF_GOK | CF_FRIENDLY | CF_FACING | CF_GHOST | CF_FLYING | CF_ATTACK_THRU_VINE | CF_ATTACK_NONADJACENT | CF_IGNORE_PLATE, RESERVED, moFriendlyGhost,
MONSTER( 'G', 0xC0FFC0, "Friendly Ghost", moFriendlyGhost, CF_FACE_SIDE | CF_NOGHOST | CF_GOK | CF_FRIENDLY | CF_FACING | CF_GHOST | CF_FLYING | CF_ATTACK_THRU_VINE | CF_ATTACK_NONADJACENT | CF_IGNORE_PLATE | CF_NONLIVING, RESERVED, moFriendlyGhost,
"Friendly ghosts are friendly beings who can go through any obstacles. However, "
"unlike most friends, they tend to fly away from you."
)
@ -458,7 +458,7 @@ ITEM( '*', 0x8080FF, "Ice Sapphire", itSapphire, IC_TREASURE, ZERO, RESERVED, os
ITEM( '*', 0xEEFF20, "Hyperstone", itHyperstone, IC_TREASURE, ZERO, RESERVED, osNone,
"These bright yellow gems can be found only by those who have mastered the Crossroads."
)
ITEM( '[', 0x8080FF, "Key", itKey, IC_OTHER, ZERO, RESERVED, osNone,
ITEM( '[', 0x8080FF, "Key", itKey, IC_OTHER, ZERO | IF_FIREPROOF, RESERVED, osNone,
"That's all you need to unlock the Orb of Yendor! Well... as long as you are able to return to the Orb that this key unlocks...\n\n"
"Each key unlocks only the Orb of Yendor which led you to it."
)
@ -779,7 +779,7 @@ ITEM( 'o', 0xC00040, "Orb of Recall", itOrbRecall, IC_ORB, ZERO, RESERVED, osUti
"When the charges on this Orb expire, "
"you will be automatically returned to the place where you have found it. "
"Extra Orbs of Recall delay this without changing the recall location. "
"Pick up an Orb of Safety causes an immediate recall.")
"Picking up an Orb of Safety causes an immediate recall.")
ITEM( ']', 0x8080FF, "Dodecahedron", itDodeca, IC_TREASURE, ZERO, RESERVED, osNone,
"These dodecahedra made of a mysterious material are the Reptiles' favorite toy."
)
@ -873,8 +873,8 @@ WALL( '#', 0x8080FF, "ice wall", waIcewall, WF_WALL | WF_HIGHWALL | WF_HEATCOLOR
"Ice Walls melt after some time has passed."
)
WALL( '#', 0xC06000, "great wall", waBarrier, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, barrierhelp)
WALL( '+', 0x900030, "red slime", waFloorA, ZERO | WF_ALCHEMY, RESERVED, 0, sgFloorA, slimehelp )
WALL( '+', 0x300090, "blue slime", waFloorB, ZERO | WF_ALCHEMY, RESERVED, 0, sgFloorB, slimehelp )
WALL( '+', 0x900030, "red slime", waFloorA, ZERO | WF_ALCHEMY | WF_ON, RESERVED, 0, sgFloorA, slimehelp )
WALL( '+', 0x300090, "blue slime", waFloorB, ZERO | WF_ALCHEMY | WF_ON, RESERVED, 0, sgFloorB, slimehelp )
WALL( '#', 0xA0D0A0, "living wall", waCavewall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgCave, cavehelp)
WALL( '.', 0x306060, "living floor", waCavefloor, ZERO, RESERVED, 0, sgNone,cavehelp)
WALL( '#', 0xD03030, "dead rock troll", waDeadTroll, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, trollhelp)
@ -888,13 +888,13 @@ WALL( '%', 0xFFC0C0, "Cloud of Mirage", waCloud, WF_WALL, RESERVED, 0, sgNone,
"Tiny droplets of magical water. You see images of yourself inside them. "
"Go inside the cloud, to make these images help you.")
WALL( '^', 0x8D694F, "Thumper", waThumperOff, WF_WALL | WF_ACTIVABLE | WF_THUMPER, RESERVED, 0, sgNone, thumpdesc)
WALL( '^', 0x804000, "Fire", waFire, WF_FIRE | WF_TIMEOUT, RESERVED, 0, sgNone,
WALL( '^', 0x804000, "Fire", waFire, WF_FIRE | WF_TIMEOUT | WF_ON, RESERVED, 0, sgNone,
"This cell is on fire. Most beings and items cannot survive."
)
WALL( '+', 0xC0C0C0, "ancient grave", waAncientGrave, WF_WALL | WF_HIGHWALL | WF_GRAVE, RESERVED, 0, sgNone,
WALL( '+', 0xC0C0C0, "ancient grave", waAncientGrave, WF_WALL | WF_HIGHWALL | WF_GRAVE | WF_NONBLOCK, RESERVED, 0, sgNone,
"An ancient grave."
)
WALL( '+', 0xD0D080, "fresh grave", waFreshGrave, WF_WALL | WF_HIGHWALL | WF_GRAVE, RESERVED, 0, sgNone,
WALL( '+', 0xD0D080, "fresh grave", waFreshGrave, WF_WALL | WF_HIGHWALL | WF_GRAVE | WF_NONBLOCK, RESERVED, 0, sgNone,
"A fresh grave. Necromancers like those."
)
WALL( '#', 0x00FFFF, "column", waColumn, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone,
@ -917,10 +917,10 @@ WALL( '#', 0x006000, "tree", waSmallTree, WF_WALL | WF_HIGHWALL | WF_STDTREE | W
WALL( '#', 0x421C52*2, "vine", waVinePlant, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgVine, vinehelp)
WALL( ':', 0x006000, "vine", waVineHalfA, ZERO | WF_NOFLIGHT | WF_HALFVINE, RESERVED, 0, sgVine, hvinehelp)
WALL( ';', 0x006000, "vine", waVineHalfB, ZERO | WF_NOFLIGHT | WF_HALFVINE, RESERVED, 0, sgVine, hvinehelp)
WALL( '^', 0x804000, "partial fire", waPartialFire, WF_FIRE | WF_TIMEOUT, RESERVED, 0, sgNone, "This cell is partially on fire.")
WALL( '#', 0xA07070, "dead wall", waDeadwall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgCave, deadcavehelp)
WALL( '.', 0x401010, "dead floor", waDeadfloor, ZERO, RESERVED, 0, sgNone,deadcavehelp)
WALL( '.', 0x905050, "rubble", waDeadfloor2, ZERO, RESERVED, 1, sgNone, "Dead floor, with some rubble.")
WALL( '^', 0x804000, "partial fire", waPartialFire, WF_FIRE | WF_TIMEOUT | WF_ON, RESERVED, 0, sgNone, "This cell is partially on fire.")
WALL( '#', 0xA07070, "dead wall", waDeadwall, WF_WALL | WF_HIGHWALL | WF_ON, RESERVED, 0, sgCave, deadcavehelp)
WALL( '.', 0x401010, "dead floor", waDeadfloor, ZERO | WF_ON, RESERVED, 0, sgNone,deadcavehelp)
WALL( '.', 0x905050, "rubble", waDeadfloor2, ZERO | WF_ON, RESERVED, 1, sgNone, "Dead floor, with some rubble.")
WALL( '#', 0xD0D010, "weird rock", waWaxWall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone,
"A weirdly colored rock. Hyperentomologists claim that the "
"Hyperbug armies use these rocks to navigate back home after a victorious battle."
@ -932,7 +932,7 @@ WALL( '#', 0x8080C0, "crystal cabinet", waGlass, WF_WALL, RESERVED, 0, sgNone,
"using an Orb of Aether, your Aether power will be completely drained."
)
WALL( '#', 0xC0C0C0, "wall of Camelot", waCamelot, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, camelothelp )
WALL( '+', 0xA06000, "Round Table", waRoundTable, WF_WALL, RESERVED, 1, sgNone, camelothelp )
WALL( '+', 0xA06000, "Round Table", waRoundTable, WF_WALL | WF_NONBLOCK | WF_ON, RESERVED, 1, sgNone, camelothelp )
WALL( '=', 0x0000A0, "moat of Camelot", waCamelotMoat, WF_WATER, RESERVED, 0, sgWater, camelothelp)
WALL( '+', 0x606060, "big statue of Cthulhu", waBigStatue, WF_WALL, RESERVED, 0, sgNone,
"These statues of Cthulhu are too large to carry, and they don't look too "
@ -941,24 +941,24 @@ WALL( '+', 0x606060, "big statue of Cthulhu", waBigStatue, WF_WALL, RESERVED, 0,
"a statue, you push the statue to the cell you left.\n"
)
WALL( '=', 0x0000A0, "sea", waSea, WF_WATER, RESERVED, 0, sgWater, caribbeanhelp)
WALL( '+', 0x0000A0, "boat", waBoat, ZERO | WF_BOAT | WF_NOFLIGHT, RESERVED, 0, sgNone,
WALL( '+', 0x0000A0, "boat", waBoat, ZERO | WF_BOAT | WF_NOFLIGHT | WF_ON, RESERVED, 0, sgNone,
"Hyperbolic pirates do not need huge ships, since so many lands to conquest "
"are so close. These small boats are enough for them.\n\n"
"Boats allow you to go through water. If you are in a boat, you can move into "
"a water cell (and the boat will come with you)."
)
WALL( '.', 0x00FF00, "island", waCIsland, ZERO | WF_CISLAND, RESERVED, 0, sgNone, cislandhelp)
WALL( '.', 0x80C060, "island", waCIsland2, ZERO | WF_CISLAND, RESERVED, 0, sgNone, cislandhelp)
WALL( '.', 0x00FF00, "island", waCIsland, ZERO | WF_CISLAND | WF_ON, RESERVED, 0, sgNone, cislandhelp)
WALL( '.', 0x80C060, "island", waCIsland2, ZERO | WF_CISLAND | WF_ON, RESERVED, 0, sgNone, cislandhelp)
WALL( '#', 0x006000, "tree", waCTree, WF_WALL | WF_HIGHWALL | WF_CONE | WF_CISLAND, RESERVED, 0, sgTree,
"The forests of Caribbean are too dense to be traversed by humans, "
"and they are hard to burn. Many colorful parrots can be found there."
)
WALL( ',', 0x800000, "rock I", waRed1, ZERO | WF_RED, RESERVED, 1, sgNone, redrockhelp)
WALL( ':', 0xC00000, "rock II", waRed2, ZERO | WF_RED, RESERVED, 2, sgNone, redrockhelp)
WALL( ';', 0xFF0000, "rock III", waRed3, ZERO | WF_RED, RESERVED, 3, sgNone, redrockhelp)
WALL( ',', 0x800000, "rock I", waRed1, ZERO | WF_RED | WF_ON, RESERVED, 1, sgNone, redrockhelp)
WALL( ':', 0xC00000, "rock II", waRed2, ZERO | WF_RED | WF_ON, RESERVED, 2, sgNone, redrockhelp)
WALL( ';', 0xFF0000, "rock III", waRed3, ZERO | WF_RED | WF_ON, RESERVED, 3, sgNone, redrockhelp)
WALL( '.', 0xD0D0D0, "minefield", waMineUnknown, ZERO, RESERVED, 0, sgNone, minedesc)
WALL( '.', 0xD0D0D0, "minefield", waMineMine, ZERO, RESERVED, 0, sgNone, minedesc)
WALL( '.', 0x909090, "cell without mine", waMineOpen, ZERO, RESERVED, 0, sgNone, minedesc)
WALL( '.', 0x909090, "cell without mine", waMineOpen, ZERO | WF_ON, RESERVED, 0, sgNone, minedesc)
WALL( '+', 0x808000, "stranded boat", waStrandedBoat, ZERO | WF_BOAT | WF_NOFLIGHT, RESERVED, 0, sgNone,
"This boat cannot go through the sand. But if you sit inside and "
"wait for the tide, you will be able to use it to travel through the Ocean."
@ -966,17 +966,17 @@ WALL( '+', 0x808000, "stranded boat", waStrandedBoat, ZERO | WF_BOAT | WF_NOFLIG
WALL( '#', 0xFFD500, "palace wall", waPalace, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, palacedesc )
WALL( '+', 0xFFFFFF, "closed gate", waClosedGate, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, gatedesc )
WALL( '-', 0x404040, "open gate", waOpenGate, ZERO, RESERVED, 0, sgNone, gatedesc )
WALL( '_', 0xC00000, "closing plate", waClosePlate, ZERO, RESERVED, 0, sgNone, gatedesc )
WALL( '_', 0x00C050, "opening plate", waOpenPlate, ZERO, RESERVED, 0, sgNone, gatedesc )
WALL( '_', 0x202020, "trapdoor", waTrapdoor, ZERO, RESERVED, 0, sgNone, "This floor will fall after someone goes there. Go quickly!" )
WALL( '+', 0xFF0000, "giant rug", waGiantRug, ZERO, RESERVED, 0, sgNone,
WALL( '_', 0xC00000, "closing plate", waClosePlate, ZERO | WF_ON, RESERVED, 0, sgNone, gatedesc )
WALL( '_', 0x00C050, "opening plate", waOpenPlate, ZERO | WF_ON, RESERVED, 0, sgNone, gatedesc )
WALL( '_', 0x202020, "trapdoor", waTrapdoor, ZERO | WF_ON, RESERVED, 0, sgNone, "This floor will fall after someone goes there. Go quickly!" )
WALL( '+', 0xFF0000, "giant rug", waGiantRug, ZERO | WF_ON, RESERVED, 0, sgNone,
"This is the biggest Hypersian Rug you have ever seen! "
"Unfortunately, it is too large to take it as a trophy." )
WALL( '#', 0xfffff0, "platform", waPlatform, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "You can stand here.")
WALL( '#', 0x909090, "stone gargoyle", waGargoyle, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, gargdesc)
WALL( '.', 0xB0B0B0, "stone gargoyle floor", waGargoyleFloor, ZERO, RESERVED, 1, sgNone, gargdesc)
WALL( '.', 0x909090, "rubble", waRubble, ZERO, RESERVED, 1, sgNone, "Some rubble.")
WALL( '+', 0x804000, "ladder", waLadder, ZERO, RESERVED, 0, sgNone,
WALL( '#', 0x909090, "stone gargoyle", waGargoyle, WF_WALL | WF_HIGHWALL | WF_NONBLOCK, RESERVED, 0, sgNone, gargdesc)
WALL( '.', 0xB0B0B0, "stone gargoyle floor", waGargoyleFloor, ZERO | WF_ON, RESERVED, 1, sgNone, gargdesc)
WALL( '.', 0x909090, "rubble", waRubble, ZERO | WF_ON, RESERVED, 1, sgNone, "Some rubble.")
WALL( '+', 0x804000, "ladder", waLadder, ZERO | WF_ON, RESERVED, 0, sgNone,
"You can use this ladder to climb the Tower."
)
WALL( '#', 0xC0C0C0, "limestone wall", waStone, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "Simply a wall. Mostly.")
@ -985,13 +985,13 @@ WALL( '^', 0x804000, "Bonfire", waBonfireOff, WF_WALL | WF_ACTIVABLE, RESERVED,
)
WALL( '^', 0x8D694F, "Thumper", waThumperOn, WF_WALL | WF_TIMEOUT | WF_PUSHABLE | WF_THUMPER, RESERVED, 0, sgNone,
"A device that attracts sandworms and other enemies. You need to activate it.")
WALL( '^', 0x804000, "Eternal Fire", waEternalFire, WF_FIRE, RESERVED, 0, sgNone,
WALL( '^', 0x804000, "Eternal Fire", waEternalFire, WF_FIRE | WF_ON, RESERVED, 0, sgNone,
"This fire never burns out."
)
WALL( '.', 0x909090, "stone gargoyle bridge", waGargoyleBridge, ZERO, RESERVED, 1, sgNone, gargdesc)
WALL( '.', 0x909090, "stone gargoyle bridge", waGargoyleBridge, ZERO | WF_ON, RESERVED, 1, sgNone, gargdesc)
WALL( '#', 0x309060, "temporary wall", waTempWall, WF_WALL | WF_HIGHWALL | WF_TIMEOUT, RESERVED, 0, sgNone, twdesc)
WALL( '.', 0x309060, "temporary floor", waTempFloor, ZERO | WF_TIMEOUT, RESERVED, 1, sgNone, twdesc)
WALL( '.', 0x309060, "temporary bridge", waTempBridge, ZERO | WF_TIMEOUT, RESERVED, 1, sgNone, twdesc)
WALL( '.', 0x309060, "temporary floor", waTempFloor, ZERO | WF_TIMEOUT | WF_ON, RESERVED, 1, sgNone, twdesc)
WALL( '.', 0x309060, "temporary bridge", waTempBridge, ZERO | WF_TIMEOUT | WF_ON, RESERVED, 1, sgNone, twdesc)
WALL( '#', 0x3030FF, "charged wall", waCharged, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, elecdesc)
WALL( '#', 0xFF3030, "grounded wall", waGrounded, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, elecdesc)
WALL( '#', 0xA0A060, "sandstone wall", waSandstone, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, elecdesc)
@ -1009,8 +1009,8 @@ WALL( '#', 0x764e7c, "rosebush", waRose, WF_WALL | WF_HIGHWALL | WF_THORNY, RESE
WALL( '#', 0xC0C000, "warp gate", waWarpGate, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone,
"This gate separates the warped area from the normal land.")
WALL( '+', 0x804000, "trunk", waTrunk, ZERO | WF_NOFLIGHT, RESERVED, 0, sgNone, "The skeleton of a tree.")
WALL( '-', 0x402000, "solid branch", waSolidBranch, ZERO, RESERVED, 0, sgNone, "Branches here could bear your weight easily.")
WALL( ':', 0x804000, "weak branch", waWeakBranch, ZERO, RESERVED, 0, sgNone,
WALL( '-', 0x402000, "solid branch", waSolidBranch, ZERO | WF_ON, RESERVED, 0, sgNone, "Branches here could bear your weight easily.")
WALL( ':', 0x804000, "weak branch", waWeakBranch, ZERO | WF_ON, RESERVED, 0, sgNone,
"Branches here will bear you weight, but if you use them to move (not fall) to an unstable place, they will break.")
WALL( '+', 0x60C060, "canopy", waCanopy, ZERO, RESERVED, 0, sgNone,
"Only thin twigs and leaves here. They may bear fruits, but for you, these cells count "
@ -1018,33 +1018,33 @@ WALL( '+', 0x60C060, "canopy", waCanopy, ZERO, RESERVED, 0, sgNone,
)
WALL( '#', 0xD0C060, "barrow wall", waBarrowWall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "This wall is quite strong. You will need another way in.")
WALL( '#', 0x90A060, "barrow", waBarrowDig, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "Your Orb of the Sword can be used to dig here.")
WALL( '#', 0xE0E0E0, "stone statue", waPetrified, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, "A petrified creature.")
WALL( '#', 0xE0E0E0, "stone statue", waPetrified, WF_WALL | WF_HIGHWALL | WF_NONBLOCK, RESERVED, 0, sgNone, "A petrified creature.")
WALL( '.', 0xE8E8E8, "tower of Camelot", waTower, ZERO, RESERVED, 3, sgNone, camelothelp)
WALL( '-', 0x402000, "big bush", waBigBush, ZERO | WF_NOFLIGHT, RESERVED, 0, sgNone,
WALL( '-', 0x402000, "big bush", waBigBush, ZERO | WF_NOFLIGHT | WF_ON, RESERVED, 0, sgNone,
"You can hold this bush to climb the Lost Mountain. "
"Bushes block the movement of birds."
)
WALL( ':', 0x804000, "small bush", waSmallBush, ZERO | WF_NOFLIGHT, RESERVED, 0, sgNone,
WALL( ':', 0x804000, "small bush", waSmallBush, ZERO | WF_NOFLIGHT | WF_ON, RESERVED, 0, sgNone,
"You can hold this bush to climb the Lost Mountain, "
"but it is not very strong -- it will get destroyed "
"if you climb from it into an unstable location. "
"Bushes block the movement of birds.")
WALL( '.', 0xFFFF00, "Reptile floor", waReptile, ZERO | WF_REPTILE, RESERVED, 0, sgNone, reptiledesc)
WALL( '.', 0xFFFF00, "Reptile bridge", waReptileBridge, ZERO | WF_REPTILE, RESERVED, 0, sgNone, reptiledesc)
WALL( '.', 0xFFFF00, "invisible floor", waInvisibleFloor, ZERO, RESERVED, 0, sgNone, NODESCYET)
WALL( '.', 0xFFFF00, "Reptile floor", waReptile, ZERO | WF_REPTILE | WF_ON, RESERVED, 0, sgNone, reptiledesc)
WALL( '.', 0xFFFF00, "Reptile bridge", waReptileBridge, ZERO | WF_REPTILE | WF_ON, RESERVED, 0, sgNone, reptiledesc)
WALL( '.', 0xFFFF00, "invisible floor", waInvisibleFloor, ZERO | WF_ON, RESERVED, 0, sgNone, NODESCYET)
WALL( '#', 0xC0C0FF, "mirror wall", waMirrorWall, WF_WALL, RESERVED, 0, sgNone, mirroreddesc)
WALL( '.', 0xE0E0E0, "stepping stones", waPetrifiedBridge, ZERO, RESERVED, 1, sgNone, "A petrified creature.")
WALL( '.', 0xE0E0E0, "stepping stones", waPetrifiedBridge, WF_ON, RESERVED, 1, sgNone, "A petrified creature.")
WALL( '#', 0x309060, "temporary wall", waTempBridgeBlocked, WF_WALL | WF_HIGHWALL | WF_TIMEOUT, RESERVED, 0, sgNone, twdesc)
WALL( 'S', 0xB0B0B0, "warrior statue", waTerraWarrior, WF_WALL, RESERVED, 0, sgNone, terradesc)
WALL( '=', 0xB0B0B0, "bubbling slime", waBubble, ZERO | WF_CHASM, RESERVED, 0, sgNone, NODESC)
WALL( '^', 0xD00000, "arrow trap", waArrowTrap, ZERO, RESERVED, 0, sgNone, arrowtrapdesc)
WALL( '^', 0xD00000, "arrow trap", waArrowTrap, WF_ON, RESERVED, 0, sgNone, arrowtrapdesc)
WALL( '=', 0xE2E2E2, "mercury river", waMercury, ZERO | WF_CHASM, RESERVED, 0, sgNone, "A river of mercury.")
WALL( '&', 0xD00000, "lava", waMagma, ZERO, RESERVED, 1, sgNone, lavadesc)
WALL( '=', 0x804000, "dock", waDock, ZERO, RESERVED, 0, sgNone, "A dock.")
WALL( '^', 0xFF8000, "burning dock", waBurningDock, WF_FIRE | WF_TIMEOUT, RESERVED, 0, sgNone, "A burning dock.")
WALL( '=', 0x804000, "dock", waDock, ZERO | WF_ON, RESERVED, 0, sgNone, "A dock.")
WALL( '^', 0xFF8000, "burning dock", waBurningDock, WF_FIRE | WF_TIMEOUT | WF_ON, RESERVED, 0, sgNone, "A burning dock.")
WALL( '#', 0xE04030, "ruin wall", waRuinWall, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, ruindesc)
WALL( '#', 0xA04060, "Brownian generator", waBrownian, WF_WALL | WF_HIGHWALL, RESERVED, 0, sgNone, NODESC)
WALL( '^', 0xC05000, "fire trap", waFireTrap, ZERO, RESERVED, 0, sgNone,
WALL( '^', 0xC05000, "fire trap", waFireTrap, ZERO | WF_ON, RESERVED, 0, sgNone,
"This trap will explode when stepped on, setting all the adjacent cells on fire. However, this happens on the next turn, "
"so you can safely escape if you are fast enough.")
WALL( '^', 0xFD692F, "Explosive Barrel", waExplosiveBarrel, WF_WALL | WF_PUSHABLE, RESERVED, 0, sgNone,
@ -1256,7 +1256,7 @@ LAND( 0x606060, "Zebra", laZebra, ZERO, itZebra, RESERVED, "Everything in this L
NATIVE((m == moOrangeDog) ? 2 : 0)
REQ(GOLD(R30) ITEMS(itFeather, U10))
LAND( 0xC08080, "Plane of Fire", laEFire, ZERO | LF_ELEMENTAL, itElemental, RESERVED, elemdesc)
LAND( 0xFFA080, "Plane of Fire", laEFire, ZERO | LF_ELEMENTAL, itElemental, RESERVED, elemdesc)
NATIVE(m == moFireElemental ? 2 : isNative(laElementalWall, m))
REQAS(laElementalWall,)
@ -1276,7 +1276,7 @@ LAND( 0x4040FF, "Crossroads III", laCrossroads3, ZERO, itHyperstone, RESERVED,
"An alternate layout of the Crossroads. Great Walls cross here at right angles."
)
NATIVE(0)
REQ(NUMBER(orbsUnlocked(), 9, XLAT("Finished lands required: %1 (collect %2 treasure)\n", "9", its(R10))))
REQ(NUMBER(orbsUnlocked(), lands_for_cr3(), XLAT("Finished lands required: %1 (collect %2 treasure)\n", "9", its(R10))))
LAND( 0x4040C0, "Sea Border", laOceanWall, ZERO | LF_TECHNICAL | LF_SEA, itNone, RESERVED, "Border between seas.")
// REQAS(laOcean,)
@ -1285,7 +1285,12 @@ LAND( 0x4040C0, "Sea Border", laOceanWall, ZERO | LF_TECHNICAL | LF_SEA, itNone,
LAND( 0x4040C0, "Elemental Planes", laElementalWall, ZERO | LF_ELEMENTAL, itElemental, RESERVED, elemdesc)
NATIVE((m == moAirElemental || m == moEarthElemental || m == moWaterElemental || m == moFireElemental) ? 1 : 0)
REQ(KILL(moAirElemental, laWhirlwind) KILL(moWaterElemental, laLivefjord) KILL(moEarthElemental, laDeadCaves) KILL(moFireElemental, laDragon))
REQ(
IFINGAME(laWhirlwind, KILL(moAirElemental, laWhirlwind), ITEMS(itDiamond, U10))
IFINGAME(laLivefjord, KILL(moWaterElemental, laLivefjord), ITEMS(itElixir, U10))
IFINGAME(laDeadCaves, KILL(moEarthElemental, laDeadCaves), ITEMS(itGold, U10))
IFINGAME(laDragon, KILL(moFireElemental, laDragon), ITEMS(itSpice, U10))
)
LAND( 0xE08020, "Canvas", laCanvas, ZERO | LF_TECHNICAL, itNone, RESERVED, "A fake Land with colored floors.")
NATIVE(0)
@ -1293,11 +1298,11 @@ LAND( 0xE08020, "Canvas", laCanvas, ZERO | LF_TECHNICAL, itNone, RESERVED, "A fa
LAND( 0x00C000, "Palace Quest", laPrincessQuest, ZERO, itSavedPrincess, RESERVED, princessdesc) // fake
NATIVE(isNative(laPalace, m))
REQ(ACCONLY(laPalace) KILL(moVizier, laPalace))
REQ(ACCONLY(laPalace) INMODE(princess::challenge) KILL(moVizier, laPalace))
LAND( 0xD0D060, "Wild West", laWildWest, ZERO, itBounty, RESERVED, wildwestdesc)
NATIVE((m == moOutlaw) ? 2 : 0)
REQ( NEVER )
REQ( ALWAYS )
LAND( 0x80A080, "Land of Storms", laStorms, ZERO | LF_TROLL | LF_ELECTRIC, itFulgurite, RESERVED, elecdesc)
NATIVE((m == moMetalBeast || m == moMetalBeast2 || m == moStormTroll) ? 1 : 0)
@ -1388,7 +1393,14 @@ LAND( 0x90A548, "Trollheim", laTrollheim, ZERO, itTrollEgg, RESERVED,
"these Trolls yourself?"
)
NATIVE(isTroll(m) ? 1 : 0)
REQ( KILL(moTroll, laCaves) KILL(moDarkTroll, laDeadCaves) KILL(moRedTroll, laRedRock) KILL(moStormTroll, laStorms) KILL(moForestTroll, laOvergrown) KILL(moFjordTroll, laLivefjord) )
REQ(
IFINGAME(laCaves, KILL(moTroll, laCaves), ITEMS(itSpice, 10))
IFINGAME(laDeadCaves, KILL(moDarkTroll, laDeadCaves), ITEMS(itGold, 10))
IFINGAME(laRedRock, KILL(moRedTroll, laRedRock), ITEMS(itSpice, 10))
IFINGAME(laStorms, KILL(moStormTroll, laStorms), ITEMS(itElixir, 10))
IFINGAME(laOvergrown, KILL(moForestTroll, laOvergrown), ITEMS(itRuby, 10))
IFINGAME(laLivefjord, KILL(moFjordTroll, laLivefjord), ITEMS(itGold, 10))
)
LAND( 0xFF7518, "Halloween", laHalloween, ZERO, itTreat, RESERVED, halloweendesc)
NATIVE((m == moGhost || m == moZombie || m == moWitch ||
@ -1400,13 +1412,16 @@ LAND( 0xFF7518, "Halloween", laHalloween, ZERO, itTreat, RESERVED, halloweendesc
m == moLancer || m == moFireFairy ||
m == moBomberbird || m == moRatlingAvenger ||
m == moVineBeast || m == moDragonHead || m == moDragonTail) ? 1 : 0)
REQ( NEVER )
REQ( ALWAYS )
LAND( 0x605040, "Dungeon", laDungeon, ZERO | LF_GRAVITY | LF_EQUI, itSlime, RESERVED,
"The result of a collaboration of the Great Vizier and the Wizard of the Ivory Tower."
)
NATIVE(m == moBat ? 2 : m == moSkeleton || m == moGhost ? 1 : 0)
REQ(ITEMS(itPalace, U5) ITEMS(itIvory, U5))
REQ(
IFINGAME(laPalace, ITEMS(itPalace, U5), ITEMS(itDiamond, U10))
IFINGAME(laIvoryTower, ITEMS(itIvory, U5), ITEMS(itElixir, U10))
)
LAND( 0x603000, "Lost Mountain", laMountain, ZERO | LF_GRAVITY | LF_CYCLIC, itAmethyst, RESERVED,
"Gravitational anomalies in the Jungle create mountains "
@ -1415,7 +1430,11 @@ LAND( 0x603000, "Lost Mountain", laMountain, ZERO | LF_GRAVITY | LF_CYCLIC, itAm
"Cells adjacent to Ivies count as stable (but Ivies "
"cannot climb themselves or other Ivies).")
NATIVE(m == moEagle || m == moMonkey || isIvy(m) || m == moFriendlyIvy ? 1 : 0)
REQ(ITEMS(itRuby, U5) ITEMS(itIvory, U5) ACCONLY(laJungle))
REQ(
ITEMS(itRuby, U5)
IFINGAME(laIvoryTower, ITEMS(itIvory, U5), ITEMS(itElixir, U10))
ACCONLY(laJungle)
)
LAND( 0xFFFF00, "Reptiles", laReptile, ZERO, itDodeca, RESERVED, reptiledesc)
NATIVE(m == moReptile ? 1 : 0)
@ -1435,7 +1454,7 @@ LAND( 0xC000C0, "Crossroads V", laCrossroads5, ZERO, itHyperstone, RESERVED, "Ex
LAND( 0xC0C0C0, "Cellular Automaton", laCA, ZERO | LF_TECHNICAL, itNone, RESERVED, cadesc)
NATIVE(0)
REQ(NEVER)
REQ(ALWAYS)
LAND( 0xC0C0FF, "Mirror Wall", laMirrorWall, ZERO | LF_TECHNICAL | LF_INMIRRORORWALL, itShard, RESERVED, mirroreddesc)
NATIVE(isNative(laMirror, m))
@ -1463,7 +1482,7 @@ LAND( 0xA06000, "Volcanic Wasteland", laVolcano, ZERO, itLavaLily, RESERVED, lav
LAND( 0x8080FF, "Blizzard", laBlizzard, ZERO | LF_ICY, itBlizzard, RESERVED, blizzarddesc)
NATIVE((m == moVoidBeast || m == moIceGolem) ? 2 : 0)
REQ(ITEMS(itDiamond, U5) ITEMS(itWindstone, U5))
REQ(IFINGAME(laWhirlwind, ITEMS(itDiamond, U5) ITEMS(itWindstone, U5), ITEMS(itDiamond, 10) GOLD(R60)))
LAND( 0x207068, "Hunting Ground", laHunting, ZERO, itHunting, RESERVED, huntingdesc)
NATIVE(m == moHunterDog ? 1 : 0)
@ -1491,7 +1510,9 @@ LAND( 0x80FF00, "Docks", laDocks, ZERO | LF_SEA, itDock, RESERVED, NODESCYET)
LAND( 0x306030, "Ruined City", laRuins, ZERO, itRuins, RESERVED, ruindesc)
NATIVE(among(m, moPair, moHexDemon, moAltDemon, moMonk, moCrusher) ? 2 : m == moSkeleton ? 1 : 0)
REQ(KILL(moSkeleton, laPalace))
REQ(
IFINGAME(laPalace, KILL(moSkeleton, laPalace), ITEMS(itRuby, U10))
)
LAND( 0x306030, "Magnetosphere", laMagnetic, ZERO, itMagnet, RESERVED, NODESCYET)
NATIVE(isMagneticPole(m) ? 2 : 0)
@ -1548,9 +1569,9 @@ LAND( 0x30FF30, "Irradiated Field", laVariant, ZERO, itVarTreasure, RESERVED,
LAND( 0x202020, "Space Rocks", laAsteroids, ZERO, itAsteroid, RESERVED, rock_description)
ITEM( '!', 0xFFD0D0, "Fuel", itAsteroid, IC_TREASURE, ZERO, RESERVED, osNone, rock_description)
MONSTER('A', 0x606040, "Space Rock", moAsteroid, ZERO, RESERVED, moAsteroid, rock_description)
MONSTER('A', 0x606040, "Space Rock", moAsteroid, ZERO, RESERVED, moYeti, rock_description)
NATIVE(m == moAsteroid ? 2 : 0)
REQ( NEVER )
REQ( ALWAYS )
LAND( 0x00C0C0, "Wetland", laWet, ZERO, itWet, RESERVED,
"Some people have definitely drowned in this treacherous area. Better be careful!"
@ -1591,7 +1612,7 @@ ITEM( 'o', 0x808080, "Orb of Impact", itOrbImpact, IC_ORB, ZERO, RESERVED, osUti
"Whenever you use a ranged Orb to achieve an effect, all the single-tile monsters adjacent to the target "
"location are stunned."
)
WALL( '#', 0x00C000, "shrub", waShrub, WF_WALL | WF_HIGHWALL | WF_STDTREE | WF_CONE, RESERVED, 0, sgNone,
WALL( '#', 0x00C000, "shrub", waShrub, WF_WALL | WF_HIGHWALL | WF_STDTREE | WF_CONE | WF_NONBLOCK, RESERVED, 0, sgNone,
"A strange small tree that cannot be attacked with mundane weapons nor phased though. "
"It can be vaulted over, though."
)
@ -1638,7 +1659,7 @@ WALL( '$', 0xFD692F, "Crate", waCrateCrate, WF_WALL | WF_PUSHABLE, RESERVED, 0,
"These crates can be pushed."
)
WALL( '.', 0x40FD40, "Target", waCrateTarget, 0, RESERVED, 0, sgNone,
WALL( '.', 0x40FD40, "Target", waCrateTarget, 0 | WF_ON, RESERVED, 0, sgNone,
"Push all your crates on targets."
)
@ -1729,6 +1750,11 @@ MONSTER('d', 0x901020, "Angry Die", moAngryDie, ZERO, RESERVED, moAnimatedDie,
"You have made a die unhappy. Taste the revenge! This one won't forgive you, no matter what you do."
)
ITEM('}', 0xFFFF80, "Crossbow", itCrossbow, IC_NAI, ZERO, RESERVED, osNone,
"Your crossbow. Press 'f' or click it in the inventory to toggle firing mode. In firing mode, select a tile to see the trajectory, then "
"click again to fire. After firing, the crossbow takes some time to reload."
)
//shmupspecials
MONSTER( '@', 0xC0C0C0, "Rogue", moPlayer, CF_FACE_UP | CF_PLAYER, RESERVED, moNone, "In the Shoot'em Up mode, you are armed with thrown Knives.")
MONSTER( '*', 0xC0C0C0, "Knife", moBullet, ZERO | CF_BULLET, RESERVED, moNone, "A simple, but effective, missile, used by rogues.")
@ -1771,3 +1797,5 @@ MONSTER( '*', 0, "vertex", moRogueviz, ZERO | CF_TECHNICAL, RESERVED, moN
#undef ACCONLY2
#undef ACCONLY3
#undef ACCONLYF
#undef IFINGAME
#undef INMODE

View File

@ -0,0 +1,8 @@
[Desktop Entry]
Name=HyperRogue
Comment=Roguelike in a non-euclidean world
Exec=hyperrogue
Icon=hyperrogue
Terminal=false
Type=Application
Categories=Game;AdventureGame;

View File

@ -26,6 +26,7 @@ EX bool holdmouse;
EX int getcstat, lgetcstat;
EX ld getcshift;
EX bool inslider;
EX bool invslider;
EX int slider_x;
EX function <void(int sym, int uni)> keyhandler = [] (int sym, int uni) {};
@ -33,7 +34,7 @@ EX function <bool(SDL_Event &ev)> joyhandler = [] (SDL_Event &ev) {return false;
#if HDR
// what part of the compass does 'skip turn'
static const auto SKIPFAC = .4;
static constexpr auto SKIPFAC = .4;
#endif
// is the player using mouse? (used for auto-cross)
@ -66,6 +67,7 @@ EX ld shiftmul = 1;
EX cell *mouseover, *mouseover2, *lmouseover, *lmouseover_distant;
EX ld modist, modist2;
EX shiftmatrix mouseoverV;
EX int lastt;
@ -82,7 +84,7 @@ EX bool mouseout2() {
EX movedir vectodir(hyperpoint P) {
transmatrix U = unshift(ggmatrix(cwt.at));
if(GDIM == 3 && WDIM == 2) U = radar_transform * U;
if(embedded_plane && cgi.emb->is_same_in_same()) U = current_display->radar_transform_post * current_display->radar_transform * U;
P = direct_exp(lp_iapply(P));
@ -93,12 +95,13 @@ EX movedir vectodir(hyperpoint P) {
vector<ld> dirdist(cwt.at->type);
auto TC0 = tile_center();
for(int i=0; i<cwt.at->type; i++) {
transmatrix T = currentmap->adj(cwt.at, (cwt + i).spin);
ld d1 = geo_dist(U * T * C0, Centered * P);
ld d2 = geo_dist(U * T * C0, Centered * C0);
ld d1 = geo_dist(U * T * TC0, Centered * P);
ld d2 = geo_dist(U * T * TC0, Centered * C0);
dirdist[i] = d1 - d2;
//xspinpush0(-i * 2 * M_PI /cwt.at->type, .5), P);
}
movedir res;
@ -117,15 +120,13 @@ EX movedir vectodir(hyperpoint P) {
}
EX void remission() {
if(!canmove && (cmode & sm::NORMAL)) showMissionScreen();
if(!canmove && (cmode & sm::NORMAL) && !game_keys_scroll) showMissionScreen();
}
EX hyperpoint move_destination_vec(int d) {
if(WDIM == 2) return spin(-d * M_PI/4) * smalltangent();
// else if(WDIM == 2 && pmodel == mdPerspective) return cspin(0, 2, d * M_PI/4) * tC0(pushone());
// else if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone());
else if(d&1) return cspin(0, 1, d > 4 ? M_PI/2 : -M_PI/2) * smalltangent();
else return cspin(0, 2, d * M_PI/4) * smalltangent();
if(WDIM == 2 && (!embedded_plane || cgi.emb->is_same_in_same())) return spin(-d * 45._deg) * smalltangent();
else if(d&1) return cspin(0, 1, d > 4 ? 45._deg : -45._deg) * smalltangent();
else return cspin(0, 2, d * 45._deg) * smalltangent();
}
EX void movepckeydir(int d) {
@ -211,16 +212,30 @@ EX void mousemovement() {
EX SDL_Joystick* sticks[8];
EX int numsticks;
EX void initJoysticks() {
EX bool joysticks_initialized;
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
printf("Failed to initialize joysticks.\n");
numsticks = 0;
return;
#if HDR
enum eJoystickInit { jiNoJoystick, jiFast, jiWait };
#endif
EX eJoystickInit joy_init = jiFast;
#if CAP_THREAD
EX std::thread *joythread;
std::atomic<bool> joystick_done(false);
#endif
EX void initJoysticks_async() {
if(joy_init == jiNoJoystick) return;
#if CAP_THREAD
if(joy_init == jiWait) { initJoysticks(); return; }
joythread = new std::thread([] { initJoysticks(); joystick_done = true; });
#else
initJoysticks();
#endif
}
DEBB(DF_INIT, ("init joysticks"));
EX void countJoysticks() {
DEBB(DF_INIT, ("opening joysticks"));
numsticks = SDL_NumJoysticks();
if(numsticks > 8) numsticks = 8;
for(int i=0; i<numsticks; i++) {
@ -234,6 +249,22 @@ EX void initJoysticks() {
}
}
EX void initJoysticks() {
DEBBI(DF_INIT, ("init joystick"));
DEBB(DF_INIT, ("init joystick subsystem"));
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
printf("Failed to initialize joysticks.\n");
numsticks = 0;
return;
}
countJoysticks();
joysticks_initialized = true;
}
EX void closeJoysticks() {
DEBB(DF_INIT, ("close joysticks"));
for(int i=0; i<numsticks; i++) {
@ -356,15 +387,26 @@ EX void full_forward_camera(ld t) {
}
}
EX void full_strafe_camera(ld t) {
EX void full_cstrafe_camera(int dir, ld t) {
if(GDIM == 3) {
shift_view(ctangent(0, t * camera_speed));
shift_view(ctangent(dir, t * camera_speed));
didsomething = true;
playermoved = false;
}
}
EX void full_strafe_camera(ld t) { full_cstrafe_camera(0, t); }
EX void full_ystrafe_camera(ld t) {
if(walking::on) { walking::eye_level += t; if(walking::eye_level < 1e-3) walking::eye_level = 1e-3; }
else full_cstrafe_camera(1, t);
}
EX ld third_person_rotation = 0;
EX void full_rotate_camera(int dir, ld val) {
if(!val) return;
if(rug::rug_control() && lshiftclick) {
val *= camera_rot_speed;
hyperpoint h;
@ -389,20 +431,29 @@ EX void full_rotate_camera(int dir, ld val) {
#endif
else if(GDIM == 3) {
val *= camera_rot_speed;
if(keep_vertical()) {
if(third_person_rotation) shift_view(ctangent(2, -third_person_rotation)), didsomething = true, playermoved = false;
ld max_angle = 90._deg - 1e-4;
ld max_angle1 = 90._deg - 0.5e-4;
if(walking::on && dir == 1) {
max_angle /= degree;
walking::eye_angle += val * walking::eye_angle_scale / degree;
if(walking::eye_angle > max_angle) walking::eye_angle = max_angle;
if(walking::eye_angle < -max_angle) walking::eye_angle = -max_angle;
}
else if(keep_vertical()) {
hyperpoint vv = vertical_vector();
ld alpha = -atan2(vv[2], vv[1]);
rotate_view(cspin(2, 1, alpha));
ld max_angle = quarter_circle - 1e-4;
if(dir == 1 && alpha + val > max_angle)
if(dir == 1 && alpha <= max_angle1 && alpha + val > max_angle)
val = max_angle - alpha;
if(dir == 1 && alpha + val < -max_angle)
if(dir == 1 && alpha >= -max_angle1 && alpha + val < -max_angle)
val = -max_angle - alpha;
rotate_view(cspin(dir, 2, val));
rotate_view(cspin(1, 2, alpha));
}
else
rotate_view(cspin(dir, 2, val));
if(third_person_rotation) shift_view(ctangent(2, third_person_rotation));
if(!rug::rug_control()) didsomething = true;
}
else
@ -411,9 +462,9 @@ EX void full_rotate_camera(int dir, ld val) {
EX void full_rotate_view(ld h, ld v) {
if(history::on && !rug::rug_control())
models::rotation += h * camera_rot_speed;
models::rotation = spin(h * camera_rot_speed) * models::rotation;
else {
rotate_view(spin(v * camera_rot_speed));
rotate_view(cspin(0, 1, v * camera_rot_speed));
didsomething = true;
if(isGravityLand(cwt.at->land) && !rug::rug_control())
playermoved = false;
@ -442,8 +493,8 @@ EX void handlePanning(int sym, int uni) {
}
#endif
if(!smooth_scrolling) {
if(sym == SDLK_PAGEUP) full_rotate_view(1, M_PI/cgi.S21/2*shiftmul);
if(sym == SDLK_PAGEDOWN) full_rotate_view(-1, -M_PI/cgi.S21/2*shiftmul);
if(sym == SDLK_PAGEUP) full_rotate_view(1, cgi.S_step*shiftmul);
if(sym == SDLK_PAGEDOWN) full_rotate_view(-1, -cgi.S_step*shiftmul);
if(sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN)
if(isGravityLand(cwt.at->land) && !rug::rug_control()) playermoved = false;
}
@ -488,7 +539,7 @@ EX array<int, 8> keys_numpad = {{SDLK_KP6, SDLK_KP3, SDLK_KP2, SDLK_KP1, SDLK_KP
EX void handleKeyNormal(int sym, int uni) {
if(cheater && sym < 256 && sym > 0) {
if(applyCheat(uni, mouseover))
if(applyCheat(uni))
uni = sym = 0;
}
@ -502,9 +553,9 @@ EX void handleKeyNormal(int sym, int uni) {
if(handleTune(sym, uni)) return;
#endif
if(!(uni >= 'A' && uni <= 'Z') && DEFAULTCONTROL) {
if(!(uni >= 'A' && uni <= 'Z') && DEFAULTCONTROL && !game_keys_scroll) {
for(int i=0; i<8; i++)
if(among(sym, keys_vi[i], keys_wasd[i], keys_numpad[i]))
if(among(sym, keys_vi[i], keys_wasd[i], (uni >= '0' && uni <= '9' && !ISMAC) ? -1 : keys_numpad[i]))
movepckeydir(i);
}
@ -525,22 +576,24 @@ EX void handleKeyNormal(int sym, int uni) {
}
#endif
if(DEFAULTCONTROL) {
if(DEFAULTCONTROL && !game_keys_scroll) {
if(sym == '.' || sym == 's') movepcto(-1, 1);
if((sym == SDLK_DELETE || sym == SDLK_KP_PERIOD || sym == 'g') && uni != 'G' && uni != 'G'-64)
movepcto(MD_DROP, 1);
if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove) {
if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove) {
cell *target = GDIM == 3 ? mouseover : centerover;
if(playermoved && items[itStrongWind]) {
cell *c = whirlwind::jumpDestination(cwt.at);
if(c) target = c;
}
targetRangedOrb(target, roKeyboard);
if(bow::fire_mode) bow::add_fire(target);
else targetRangedOrb(target, roKeyboard);
sym = 0; uni = 0;
}
if(sym == 'f') bow::switch_fire_mode();
}
if(sym == SDLK_KP5 && DEFAULTCONTROL) movepcto(-1, 1);
if(sym == SDLK_KP5 && DEFAULTCONTROL && !game_keys_scroll) movepcto(-1, 1);
if(sym == SDLK_F5) {
#if CAP_DAILY
@ -548,12 +601,14 @@ EX void handleKeyNormal(int sym, int uni) {
else
#endif
if(needConfirmation())
pushScreen(showMission);
pushScreen(showGameMenu);
else restart_game();
}
if(sym == SDLK_ESCAPE) {
if(viewdists)
if(bow::fire_mode)
bow::switch_fire_mode();
else if(viewdists)
viewdists = false;
else
showMissionScreen();
@ -564,13 +619,13 @@ EX void handleKeyNormal(int sym, int uni) {
if(daily::on) daily::handleQuit(2);
else
#endif
if(needConfirmation()) pushScreen(showMission);
if(needConfirmation()) pushScreen(showGameMenu);
else quitmainloop = true;
}
if(uni == 'o' && DEFAULTNOR(sym)) get_o_key().second();
#if CAP_INV
if(uni == 'i' && DEFAULTNOR(sym) && inv::on)
if(uni == 'i' && DEFAULTNOR(sym) && inv::on && !game_keys_scroll)
pushScreen(inv::show);
#endif
@ -582,18 +637,25 @@ EX void handleKeyNormal(int sym, int uni) {
}
if(sym == 'v' && DEFAULTNOR(sym))
pushScreen(showMainMenu);
showMissionScreen();
if(sym == PSEUDOKEY_MENU)
pushScreen(showMainMenu);
showMissionScreen();
if(sym == PSEUDOKEY_NOHINT)
no_find_player = true;
if(sym == '-' || sym == PSEUDOKEY_WHEELDOWN) {
actonrelease = false;
multi::cpid = 0;
if(mouseover &&
if(bow::fire_mode) {
if(mouseover) bow::add_fire(mouseover);
}
else if(mouseover &&
targetclick && (shmup::on ? numplayers() == 1 && !shmup::pc[0]->dead : true) && targetRangedOrb(mouseover, forcetarget ? roMouseForce : roMouse)) {
}
else if(bow::fire_on_mouse(mouseover)) ;
else if(forcetarget)
;
else if(rug::rugged && rug::renderonce)
@ -652,6 +714,9 @@ EX void resize_screen_to(int x, int y);
EX void mainloopiter() { printf("(compiled without SDL -- no action)\n"); quitmainloop = true; }
#endif
/* visualization only -- the HyperRogue movement keys should move the camera */
EX bool game_keys_scroll;
#if CAP_SDL
// Warning: a very long function! todo: refactor
@ -676,13 +741,15 @@ EX void resize_screen_to(int x, int y) {
int lastframe;
EX int sc_ticks;
EX int sc_ticks, sc_ticks2;
EX bool mouseaiming(bool shmupon) {
return
(GDIM == 3 && !shmupon) || (rug::rugged && (lctrlclick ^ rug::mouse_control_rug));
(GDIM == 3 && !shmupon) || (rug::rugged && (lctrlclick ^ rug::mouse_control_rug)) || (cmode & sm::MOUSEAIM);
}
EX purehookset hooks_control;
EX void mainloopiter() {
GLWRAP;
DEBB(DF_GRAPH, ("main loop\n"));
@ -694,7 +761,10 @@ EX void mainloopiter() {
#if CAP_VR
vrhr::vr_shift();
#endif
#endif
check_cgi();
cgi.require_basics();
optimizeview();
@ -722,7 +792,9 @@ EX void mainloopiter() {
}
mousepan = cmode & sm::NORMAL;
if((cmode & (sm::DRAW | sm::MAP)) && !hiliteclick) mousepan = true;
if((cmode & sm::PANNING) && !hiliteclick) mousepan = true;
if(cmode & sm::MOUSEAIM) mousepan = true;
if(cmode & sm::SHOWCURSOR) mousepan = false;
mousepan = mousepan && mouseaiming(false) && mouseaim_sensitivity;
if(mousepan != oldmousepan) {
oldmousepan = mousepan;
@ -744,7 +816,7 @@ EX void mainloopiter() {
SDL_ShowCursor(SDL_ENABLE);
SDL_WarpMouse(vid.xres/2, vid.yres/2);
#endif
mouseaim_x = mouseaim_y = 0;
mouseaim_x = mouseaim_y = 0;
}
#endif
}
@ -831,7 +903,7 @@ EX void mainloopiter() {
targetclick = pandora_leftclick | pandora_rightclick;
pandora_leftclick = pandora_rightclick = 0;
#else
targetclick = keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT];
targetclick = keystate[SDL12(SDLK_RSHIFT, SDL_SCANCODE_RSHIFT)] | keystate[SDL12(SDLK_LSHIFT, SDL_SCANCODE_LSHIFT)];
#endif
}
else {
@ -876,7 +948,7 @@ EX void mainloopiter() {
}
#endif
if(mouseaiming(shmup::on)) {
if(mouseaiming(shmup::on) && !(cmode & sm::MOUSEAIM)) {
#if CAP_MOUSEGRAB
rug::using_rugview urv;
dynamicval<bool> ds(didsomething, didsomething);
@ -886,26 +958,23 @@ EX void mainloopiter() {
#endif
}
if(smooth_scrolling && !shmup::on && (cmode & sm::NORMAL)) {
if(smooth_scrolling && !shmup::on && (cmode & (sm::NORMAL | sm::PANNING))) {
rug::using_rugview urv;
auto& lastticks = sc_ticks;
ld t = (ticks - lastticks) * shiftmul / 1000.;
lastticks = ticks;
#if CAP_SDL2
const Uint8 *keystate = SDL_GetKeyboardState(NULL);
if(keystate[SDL_SCANCODE_END] && GDIM == 3 && DEFAULTNOR(SDL_SCANCODE_END)) full_forward_camera(-t);
if(keystate[SDL_SCANCODE_HOME] && GDIM == 3 && DEFAULTNOR(SDL_SCANCODE_HOME)) full_forward_camera(t);
if(keystate[SDL_SCANCODE_RIGHT] && DEFAULTNOR(SDL_SCANCODE_RIGHT)) full_rotate_camera(0, -t);
if(keystate[SDL_SCANCODE_LEFT] && DEFAULTNOR(SDL_SCANCODE_LEFT)) full_rotate_camera(0, t);
if(keystate[SDL_SCANCODE_UP] && DEFAULTNOR(SDL_SCANCODE_UP)) full_rotate_camera(1, t);
if(keystate[SDL_SCANCODE_DOWN] && DEFAULTNOR(SDL_SCANCODE_DOWN)) full_rotate_camera(1, -t);
if(keystate[SDL_SCANCODE_PAGEUP] && DEFAULTNOR(SDL_SCANCODE_PAGEUP)) full_rotate_view(t * 180 / M_PI, t);
if(keystate[SDL_SCANCODE_PAGEDOWN] && DEFAULTNOR(SDL_SCANCODE_PAGEDOWN)) full_rotate_view(-t * 180 / M_PI, t);
if(keystate[SDL_SCANCODE_PAGEUP] && DEFAULTNOR(SDL_SCANCODE_PAGEUP)) full_rotate_view(t / degree, t);
if(keystate[SDL_SCANCODE_PAGEDOWN] && DEFAULTNOR(SDL_SCANCODE_PAGEDOWN)) full_rotate_view(-t / degree, -t);
#else
Uint8 *keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_END] && GDIM == 3 && DEFAULTNOR(SDLK_END)) full_forward_camera(-t);
if(keystate[SDLK_HOME] && GDIM == 3 && DEFAULTNOR(SDLK_HOME)) full_forward_camera(t);
@ -913,27 +982,55 @@ EX void mainloopiter() {
if(keystate[SDLK_LEFT] && DEFAULTNOR(SDLK_LEFT)) full_rotate_camera(0, t);
if(keystate[SDLK_UP] && DEFAULTNOR(SDLK_UP)) full_rotate_camera(1, t);
if(keystate[SDLK_DOWN] && DEFAULTNOR(SDLK_DOWN)) full_rotate_camera(1, -t);
if(keystate[SDLK_PAGEUP] && DEFAULTNOR(SDLK_PAGEUP)) full_rotate_view(t * 180 / M_PI, t);
if(keystate[SDLK_PAGEDOWN] && DEFAULTNOR(SDLK_PAGEDOWN)) full_rotate_view(-t * 180 / M_PI, t);
if(keystate[SDLK_PAGEUP] && DEFAULTNOR(SDLK_PAGEUP)) full_rotate_view(t / degree, t);
if(keystate[SDLK_PAGEDOWN] && DEFAULTNOR(SDLK_PAGEDOWN)) full_rotate_view(-t / degree, -t);
#endif
}
else sc_ticks = ticks;
if(game_keys_scroll && !shmup::on && (cmode & sm::NORMAL) && !keystate[SDL12(SDLK_LALT, SDL_SCANCODE_LALT)] && !keystate[SDL12(SDLK_RALT, SDL_SCANCODE_RALT)]) {
rug::using_rugview urv;
auto& lastticks = sc_ticks2;
ld t = (ticks - lastticks) * shiftmul / 1000.;
lastticks = ticks;
#define dkey(x) keystate[int(x)] && DEFAULTNOR(x)
if(dkey('d')) full_rotate_camera(0, -t);
if(dkey('a')) full_rotate_camera(0, t);
if(dkey('w')) full_rotate_camera(1, t);
if(dkey('s')) full_rotate_camera(1, -t);
if(dkey('q')) full_rotate_view(t / degree, t);
if(dkey('e')) full_rotate_view(-t / degree, -t);
if(GDIM == 3 && dkey('i')) full_forward_camera(-t);
if(GDIM == 3 && dkey('k')) full_forward_camera(t);
if(GDIM == 3 && dkey('l')) full_strafe_camera(-t);
if(GDIM == 3 && dkey('j')) full_strafe_camera(t);
if(GDIM == 3 && dkey('h')) full_ystrafe_camera(-t);
if(GDIM == 3 && dkey('y')) full_ystrafe_camera(t);
#undef dkey
}
#if CAP_VR
vrhr::vr_control();
#endif
achievement_pump();
callhooks(hooks_control);
for(auto d: dialog::key_queue) {
println(hlog, "handling key ", d);
handlekey(d, d);
dialog::key_queue.erase(dialog::key_queue.begin());
break;
}
dialog::key_queue.clear();
while(SDL_PollEvent(&ev)) handle_event(ev);
fix_mouseh();
#if CAP_SDLJOY
if(joydir.d != -1) checkjoy();
if(joystick_done && joythread) { joythread->join(); delete joythread; joystick_done = false; }
#endif
}
@ -949,8 +1046,7 @@ EX void handle_event(SDL_Event& ev) {
/* if(ev.type == SDL_JOYDEVICEADDED || ev.type == SDL_JOYDEVICEREMOVED) {
joyx = joyy = 0;
panjoyx = panjoyy = 0;
closeJoysticks();
initJoysticks();
countJoysticks();
} */
#if CAP_SDL2
@ -1035,12 +1131,26 @@ EX void handle_event(SDL_Event& ev) {
sym = ev.key.keysym.sym;
#if CAP_SDL2
uni = ev.key.keysym.sym;
if(uni == '=' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '+';
if(uni == '1' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '!';
if(uni == '2' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '@';
if(uni == '3' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '#';
if(uni == '4' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '$';
if(uni == '5' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '%';
if(uni == '6' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '^';
if(uni == '7' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '&';
if(uni == '8' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '*';
if(uni == '9' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = '(';
if(uni == '0' && (ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) uni = ')';
if(uni >= 'a' && uni <= 'z') {
if(ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) uni -= 32;
else if(ev.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) uni -= 96;
}
#else
uni = ev.key.keysym.unicode;
if(uni == 0 && (sym >= 'a' && sym <= 'z')) {
if(ev.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) uni = sym - 96;
}
if(ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) shiftmul = -1;
if(ev.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) shiftmul /= 10;
#endif
@ -1066,13 +1176,14 @@ EX void handle_event(SDL_Event& ev) {
which_pointer = 0;
bool was_holdmouse = holdmouse;
holdmouse = false;
invslider = false;
bool down = ev.type == SDL_MOUSEBUTTONDOWN SDL12(, || ev.type == SDL_MOUSEWHEEL);
bool up = ev.type == SDL_MOUSEBUTTONUP;
bool act = false;
if(vid.quickmouse) {
if(vid.quickmouse || getcstat == PSEUDOKEY_LIST_SLIDER) {
act = down;
}
else {
@ -1089,7 +1200,7 @@ EX void handle_event(SDL_Event& ev) {
if(ev.button.button == SDL_BUTTON_LEFT) {
if(ISPANDORA ? pandora_rightclick : lctrlclick)
ev.button.button = SDL_BUTTON_MIDDLE;
else if((ISPANDORA ? pandora_leftclick : lshiftclick) && !(vid.shifttarget&1))
else if((ISPANDORA ? pandora_leftclick : lshiftclick) && !(vid.shifttarget&1) && !(cmode & sm::MAP))
ev.button.button = SDL_BUTTON_RIGHT;
}
@ -1235,7 +1346,10 @@ EX void displayabutton(int px, int py, string s, int col) {
int rad = (int) realradius();
if(vid.stereo_mode == sLR) rad = 99999;
int vrx = min(rad, vid.xres/2 - 40);
int vry = min(rad, min(current_display->ycenter, vid.yres - current_display->ycenter) - 20);
int maxy = min(current_display->ycenter, vid.yres - current_display->ycenter);
int vry = min(rad, maxy - 20);
vrx = max(vrx, vid.xres/3);
vry = max(vry, maxy * 2/3);
int x = current_display->xcenter + px * vrx;
int y = current_display->ycenter + py * (vry - siz/2);
int vrr = int(hypot(vrx, vry) * sqrt(2.));
@ -1387,7 +1501,7 @@ void delayed_reset() {
EX void show() {
#if CAP_ORIENTATION
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
dialog::init(XLAT("scrolling by device rotation"));

553
crossbow.cpp Normal file
View File

@ -0,0 +1,553 @@
// Hyperbolic Rogue
// Copyright (C) 2011-2019 Zeno Rogue
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/** \file crossbow.cpp
* \brief implementation of the crossbow mode
*/
#include "hyper.h"
namespace hr {
EX namespace bow {
#if HDR
enum eWeapon { wBlade, wCrossbow };
enum eCrossbowStyle { cbBull, cbGeodesic, cbGeometric };
const string bowName[] = { "bull", "geod", "geom" };
#endif
EX eWeapon weapon;
EX eCrossbowStyle style;
EX bool bump_to_shoot = true;
EX bool crossbow_mode() { return weapon == wCrossbow; }
#if HDR
struct bowpoint {
cellwalker prev, next;
flagtype flags;
bowpoint() {}
};
struct bowscore {
int total;
cellwalker last;
int turns;
};
#endif
#if HDR
static constexpr flagtype bpFIRST = 1;
static constexpr flagtype bpLAST = 2;
static constexpr flagtype bpCOPIED = 4;
#endif
EX vector<bowpoint> bowpath;
EX map<cell*, vector<bowpoint>> bowpath_map;
EX map<int, cell*> target_at;
EX int loading_time() {
return style == cbBull ? 3 : 4;
}
EX bool blocks(cell *c) {
if(items[itOrbAether]) return false;
if(isWall(c) && !among(c->wall, waMirrorWall, waMirror, waCloud) && !isNonblock(c->wall)) return true;
// if(c->monst && isMultitile(c->monst)) return true;
return false;
}
EX int qadd(cellwalker a, cellwalker b) {
hassert(a.at == b.at);
for(int i=0; i<a.at->type; i++) if(a+i == b) return i;
return NODIR;
}
int best_score_res;
EX int bolt_score(cellwalker cw2) {
int d = cw2.at->cpdist;
int ntotal = 2;
if(inmirror(cw2.at)) cw2 = mirror::reflect(cw2);
if(blocks(cw2.cpeek())) return -1;
if(thruVine(cw2.at, cw2.cpeek())) return -1;
if(nonAdjacent(cw2.at, cw2.cpeek())) return -1;
if(cw2.at->monst) {
flagtype attackflags = AF_BOW;
if(items[itOrbSpeed]&1) attackflags |= AF_FAST;
if(items[itOrbSlaying]) attackflags |= AF_CRUSH;
if(items[itCurseWeakness]) attackflags |= AF_WEAK;
if(canAttack(cw2.cpeek(), moPlayer, cw2.at, cw2.at->monst, attackflags)) {
ntotal += 10000; ntotal += 1280 >> d;
}
}
for(int t=0; t<cw2.at->type; t++) {
cell *c1 = cw2.at->cmove(t);
if(!logical_adjacent(cw2.cpeek(), moPlayer, c1)) continue;
if(canAttack(cw2.cpeek(),moPlayer,c1,c1->monst,AF_STAB)) {
ntotal += 10000; ntotal += 1280 >> d;
}
}
return ntotal;
}
EX vector<int> create_dirseq() {
map<cell*, bowscore> scores;
scores[cwt.at].total = 0;
int best_score = -1; cell* best_score_at = cwt.at;
for(cell *c: dcal) {
cell *c1 = target_at[c->cpdist];
if(c1 && c != c1) continue;
if(c == c1) { best_score = -1; }
bowscore best;
best.total = -1;
forCellIdEx(c1, i, c) if(c1->cpdist < c->cpdist && scores.count(c1)) {
auto& last = scores[c1];
auto ocw2 = cellwalker(c, i);
int bonus = bolt_score(ocw2);
if(bonus < 0) continue;
int ntotal = last.total + bonus;
int dir = 0;
if(c->cpdist > 1) {
dir = qadd(last.last, ocw2+wstep);
int d = abs(szgmod(dir, c1->type));
if(d != c1->type / 2) {
if(style == cbGeodesic) ntotal--;
if(style == cbBull) continue;
}
}
else {
dir = qadd(cwt, ocw2+wstep);
}
if(ntotal > best.total) {
best.total = ntotal;
best.last = ocw2;
best.turns = dir;
}
best.total = max(best.total, ntotal);
}
if(best.total > best_score) { best_score = best.total; best_score_at = c; }
if(best.total > -1) scores[c] = best;
}
if(best_score == -1) return {};
vector<int> dirseq = { NODIR };
while(best_score_at != cwt.at) {
auto& at = scores[best_score_at];
dirseq.push_back(at.turns);
best_score_at = at.last.cpeek();
}
reverse(dirseq.begin(), dirseq.end());
best_score_res = best_score;
return dirseq;
}
EX vector<int> create_dirseq_geometric() {
cell *tgt = nullptr;
for(auto t: target_at) tgt = t.second;
if(!tgt) return {};
hyperpoint h = tC0(currentmap->relative_matrix(tgt, cwt.at, C0));
transmatrix T = spintox(h);
best_score_res = 0;
cellwalker at = cwt;
vector<int> dirseq;
while(true) {
int best_i = -1;
ld best_y = HUGE_VAL;
for(int i=0; i<at.at->type; i++) {
cellwalker at1 = at + i;
if(at1.cpeek()->cpdist != at.at->cpdist + 1) continue;
transmatrix U = T * currentmap->adj(at.at, at1.spin);
hyperpoint U0 = tC0(U);
hyperpoint T0 = tC0(T);
if(U0[0] < T0[0] + 1e-6) continue;
ld y;
if(GDIM == 3) y = hypot(U0[1], U0[2]); else y = abs(U0[1]) + (U0[1] > 0 ? 1e-6 : 0);
if(y < best_y) { best_y = y; best_i = i; }
}
if(best_i < 0) {
dirseq.push_back(NODIR);
break;
}
at = at + best_i;
int bonus = bolt_score(at + wstep);
best_score_res += bonus;
dirseq.push_back(best_i);
if(bonus < 0) break;
T = T * currentmap->adj(at.at, at.spin);
at = at + wstep;
}
return dirseq;
}
EX int create_path() {
auto dirseq = style == cbGeometric ? create_dirseq_geometric() : create_dirseq();
if(dirseq.empty()) return -1;
struct bolt {
cellwalker at;
flagtype flags;
bolt(cellwalker cw, flagtype f) { at = cw; flags = f; }
};
bowpath.clear();
vector<bolt> bolts = { bolt(cwt, 0) };
for(auto m: mirror::mirrors) bolts.emplace_back(m.second, bpCOPIED);
set<cell*> broken_mirrors;
for(auto d: dirseq) {
bool first = bowpath.empty();
vector<bolt> nbolts;
set<cell*> next_broken_mirrors = broken_mirrors;
for(auto bolt: bolts) {
bowpath.emplace_back();
auto& p = bowpath.back();
p.prev = bolt.at;
p.flags = bolt.flags;
if(first) p.flags |= bpFIRST;
if(d == NODIR || blocks(bolt.at.at)) { p.next = bolt.at; p.flags |= bpLAST; }
else {
if(inmirror(bolt.at.at) || (bolt.at.at->wall == waMirrorWall && inmirror((bolt.at+d).cpeek())))
bolt.at = mirror::reflect(bolt.at);
bolt.at += d;
p.next = bolt.at;
bolt.at += wstep;
if(among(bolt.at.at->wall, waCloud, waMirror) && !broken_mirrors.count(bolt.at.at)) {
auto &mir = mirror::mirrors;
vector<pair<int, cellwalker>> bmir;
swap(mir, bmir);
mirror::createHere(bolt.at, 0);
swap(mir, bmir);
for(auto b: bmir) nbolts.emplace_back(b.second, bolt.flags);
next_broken_mirrors.insert(bolt.at.at);
}
nbolts.push_back(bolt);
}
}
bolts = nbolts;
broken_mirrors = next_broken_mirrors;
}
return best_score_res;
}
EX void clear_bowpath() {
bowpath_map.clear();
}
EX void gen_bowpath_map() {
bowpath_map = {};
for(auto& b: bowpath) bowpath_map[b.next.at].push_back(b);
}
EX bool auto_path() {
target_at = {};
target_at[1] = cwt.cpeek();
return create_path() >= 10000;
}
EX bool fire_mode;
EX void switch_fire_mode() {
if(!crossbow_mode()) { addMessage(XLAT("You fire an angry glance at your enemies.")); return; }
if(!fire_mode) {
addMessage(items[itCrossbow] ? XLAT("Note: cannot fire again yet. Turns to reload: %1.", its(items[itCrossbow])) : XLAT("Fire crossbow! Click to aim, click again to confirm."));
fire_mode = true;
clear_bowpath();
target_at = {};
}
else if(fire_mode) {
addMessage(items[itCrossbow] ? XLAT("Fire mode disabled.") : XLAT("Firing cancelled."));
fire_mode = false;
clear_bowpath();
}
}
EX void add_fire(cell *c) {
bool emp = target_at.empty();
auto& t = target_at[c->cpdist];
if(t == c && !bow::bowpath.empty()) {
if(items[itCrossbow]) {
clear_bowpath();
addMessage(XLAT("Cannot fire again yet. Turns to reload: %1.", its(items[itCrossbow])));
fire_mode = false;
return;
}
clear_bowpath();
checked_move_issue.type = miVALID;
pcmove pcm;
pcm.checkonly = false;
changes.init(false);
addMessage(XLAT("Fire!"));
bool b = pcm.try_shooting(false);
if(!b) changes.rollback();
fire_mode = false;
}
else {
t = c;
if(style == cbGeometric) { target_at = {}; target_at[c->cpdist] = c; }
int res = create_path();
if(res == -1) {
if(!emp) {
target_at = {};
add_fire(c);
}
else {
addMessage(XLAT("No way to hit this place."));
bow::bowpath = {};
}
}
gen_bowpath_map();
}
}
#if HDR
enum eMouseFireMode { mfmNone, mfmPriority, mfmAlways };
#endif
EX eMouseFireMode mouse_fire_mode = mfmPriority;
EX bool fire_on_mouse(cell *c) {
if(!crossbow_mode()) return false;
if(mouse_fire_mode == mfmNone) return false;
if(!mouseover) return false;
if(!mouseover->monst) return false;
if(shmup::on) return false;
if(items[itCrossbow]) {
if(mouse_fire_mode == mfmAlways) {
addMessage(XLAT("Cannot fire again yet. Turns to reload: %1.", its(items[itCrossbow])));
return true;
}
return false;
}
target_at = {};
target_at[mouseover->cpdist] = mouseover;
int res = create_path();
if(res <= 0) {
if(mouse_fire_mode == mfmAlways) {
addMessage(XLAT("Shooting impossible."));
return true;
}
return false;
}
gen_bowpath_map();
checked_move_issue.type = miVALID;
pcmove pcm;
pcm.checkonly = false;
changes.init(false);
addMessage(XLAT("Fire!"));
bool b = pcm.try_shooting(false);
if(!b) changes.rollback();
if(mouse_fire_mode == mfmAlways) return true;
return b;
}
EX int rusalka_curses = 0;
EX void shoot() {
flagtype attackflags = AF_BOW;
if(items[itOrbSpeed]&1) attackflags |= AF_FAST;
if(items[itOrbSlaying]) attackflags |= AF_CRUSH;
if(items[itCurseWeakness]) attackflags |= AF_WEAK;
vector<bowpoint> pushes;
// for achievements
set<eMonster> kills;
vector<pair<cell*, int>> healthy_dragons;
map<cell*, pair<int, int>> kraken_hits;
int dragon_hits = 0;
rusalka_curses = 0;
// for achievements
for(auto& mov: bowpath) {
cell *c = mov.prev.at;
if(c->monst == moDragonHead) {
bool healthy = true;
cell *c1 = c;
int qty = 0;
for(int i=0; i<iteration_limit; i++) {
if(!isDragon(c1)) break;
if(!c1->hitpoints) { healthy = false; break; }
if(c1->mondir == NODIR) break;
c1 = c1->move(c1->mondir);
qty++;
}
if(healthy) healthy_dragons.emplace_back(c, qty);
}
if(c->monst == moKrakenT && c->hitpoints) {
kraken_hits[kraken::head(c)].first++;
}
}
for(auto& mov: bowpath) {
cell *c = mov.prev.at;
cell *cf = mov.prev.cpeek();
if(!c) continue;
eMonster who = (mov.flags & bpCOPIED) ? moMimic : moPlayer;
if(c != cf) for(int t=0; t<cf->type; t++) {
cell *c1 = cf->cmove(t);
if(!c) continue;
bool stabthere = false;
if(logical_adjacent(c, moPlayer, c1)) stabthere = true;
if(stabthere && canAttack(cf,who,c1,c1->monst,AF_STAB)) {
hit_anything = true;
changes.ccell(c1);
eMonster m = c->monst;
if(attackMonster(c1, AF_STAB | AF_MSG, who)) {
achievement_count("STAB", 1, 0);
spread_plague(c1, cf, t, moPlayer);
produceGhost(c, m, moPlayer);
}
}
}
mirror::breakMirror(mov.next, -1);
eMonster m = c->monst;
if(!m || isMimic(m)) continue;
if(m == moKrakenH) continue;
if(!canAttack(cf, who, c, m, attackflags)) {
if(among(m, moSleepBull, moHerdBull)) {
addMessage(XLAT("%The1 is enraged!", m));
c->monst = moRagingBull;
hit_anything = true;
continue;
}
else {
pcmove pcm; pcm.mi = movei(mov.prev).rev();
pcm.tell_why_cannot_attack();
continue;
}
}
changes.ccell(c);
bool push = (items[itCurseWeakness] || (isStunnable(c->monst) && c->hitpoints > 1));
push = push && (!(mov.flags & bpLAST) && monsterPushable(c));
// for achievements
if(isDragon(m)) dragon_hits++;
if(m == moKrakenT && c->hitpoints) kraken_hits[kraken::head(c)].second++;
if(m && attackMonster(c, attackflags | AF_MSG, who)) hit_anything = true;
if(m == moRusalka) rusalka_curses++;
if(!c->monst || isAnyIvy(m)) {
spread_plague(cf, c, movei(mov.prev).rev().d, moPlayer);
produceGhost(c, m, moPlayer);
kills.insert(m);
}
if(push) pushes.push_back(mov);
}
while(!pushes.empty()) {
auto& mov = pushes.back();
cell *c = mov.prev.at;
cell *ct = mov.next.cpeek();
bool can_push = passable(ct, c, P_BLOW);
if(can_push) {
hit_anything = true;
changes.ccell(c);
changes.ccell(ct);
pushMonster(mov.next);
}
pushes.pop_back();
}
reverse(bowpath.begin(), bowpath.end());
// three achievements:
achievement_count("BOWVARIETY", kills.size(), 0);
for(auto p: healthy_dragons) {
cell *c = p.first;
if(c->monst != moDragonHead && dragon_hits >= p.second)
achievement_gain_once("BOWDRAGON");
}
for(auto kh: kraken_hits) {
if(kh.second.first == 3 && kh.second.second == 3) {
if(kraken::half_killed[kh.first]) achievement_gain_once("BOWKRAKEN");
else kraken::half_killed[kh.first] = true;
}
}
gen_bowpath_map();
}
EX bool have_bow_target() {
dynamicval<decltype(bowpath)> bp(bowpath);
dynamicval<decltype(bowpath_map)> bpm(bowpath_map);
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
target_at = {};
target_at[c->cpdist] = {c};
int res = create_path();
if(res == -1) continue;
checked_move_issue.type = miVALID;
pcmove pcm;
pcm.checkonly = true;
changes.init(true);
bool b = pcm.try_shooting(false);
changes.rollback();
if(b) return true;
}
return false;
}
EX void showMenu() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("weapon selection"));
add_edit(weapon);
if(crossbow_mode()) {
add_edit(style);
add_edit(bump_to_shoot);
add_edit(bow::mouse_fire_mode);
}
else dialog::addBreak(200);
dialog::addBack();
dialog::display();
}
EX }
}

View File

@ -11,8 +11,8 @@ namespace hr {
EX namespace crystal {
#if HDR
static const int MAXDIM = 7;
static const int MAX_EDGE_CRYSTAL = 2 * MAXDIM;
static constexpr int MAXDIM = 7;
static constexpr int MAX_EDGE_CRYSTAL = 2 * MAXDIM;
struct coord : public array<int, MAXDIM> {
coord operator + (coord b) { for(int i=0; i<MAXDIM; i++) b[i] += self[i]; return b; }
@ -20,7 +20,7 @@ struct coord : public array<int, MAXDIM> {
coord operator * (int x) { coord res; for(int i=0; i<MAXDIM; i++) res[i] = x * self[i]; return res; }
};
static const coord c0 = {};
static constexpr coord c0 = {};
struct ldcoord : public array<ld, MAXDIM> {
friend ldcoord operator + (ldcoord a, ldcoord b) { ldcoord r; for(int i=0; i<MAXDIM; i++) r[i] = a[i] + b[i]; return r; }
@ -30,7 +30,7 @@ struct ldcoord : public array<ld, MAXDIM> {
friend ld operator | (ldcoord a, ldcoord b) { ld r=0; for(int i=0; i<MAXDIM; i++) r += a[i] * b[i]; return r; }
};
static const ldcoord ldc0 = {};
static constexpr ldcoord ldc0 = {};
#endif
#if CAP_CRYSTAL
@ -269,7 +269,7 @@ struct crystal_structure {
next.resize(4, {2,3,1,0});
next_to_prev();
while(dir < S7) {
crystal_structure csx = move(*this);
crystal_structure csx = std::move(*this);
add_dimension_to(csx);
}
if(dir > S7) remove_half_dimension();
@ -325,7 +325,7 @@ ld sqhypot2(crystal_structure& cs, ldcoord co1, ldcoord co2) {
return result;
}
static const int Modval = 64;
static constexpr int Modval = 64;
struct east_structure {
map<coord, int> data;
@ -639,6 +639,8 @@ struct hrmap_crystal : hrmap_standard {
transmatrix res;
ld gdist = S7 == 12 ? hdist0(tC0(cgi.adjmoves[0])) : cgi.strafedist;
h->cmove(d);
for(auto& cr: cgi.cellrotations) {
transmatrix U = T * cr.M;
@ -674,7 +676,7 @@ struct hrmap_crystal : hrmap_standard {
}
transmatrix relative_matrixc(cell *h2, cell *h1, const hyperpoint& hint) override {
if(!crystal3()) return hrmap_standard::relative_matrix(h2, h1, hint);
if(!crystal3()) return hrmap_standard::relative_matrixc(h2, h1, hint);
if(h2 == h1) return Id;
for(int i=0; i<S7; i++) if(h2 == h1->move(i)) return adj(h1->master, i);
if(gmatrix0.count(h2) && gmatrix0.count(h1))
@ -684,8 +686,8 @@ struct hrmap_crystal : hrmap_standard {
}
transmatrix relative_matrixh(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
if(!crystal3()) return hrmap::relative_matrix(h2, h1, hint);
return relative_matrix(h2->c7, h1->c7, hint);
if(!crystal3()) return hrmap_standard::relative_matrixh(h2, h1, hint);
return relative_matrixc(h2->c7, h1->c7, hint);
}
#endif
};
@ -721,7 +723,7 @@ EX color_t colorize(cell *c, char whichCanvas) {
if(cryst) co = m->get_coord(c), dim = m->cs.dim;
#if MAXMDIM >= 4
else if(geometry == gSpace344) {
co = told(reg3::decode_coord(c->master->fieldval)), dim = 4;
co = told(reg3::decode_coord(reg3::minimize_quotient_maps ? 1 : 2, c->master->fieldval)), dim = 4;
for(int a=0; a<4; a++) if(co[a] > 4) co[a] -= 8;
}
else if(geometry == gSeifertCover) {
@ -799,7 +801,7 @@ EX colortable coordcolors = {0xD04040, 0x40D040, 0x4040D0, 0xFFD500, 0xF000F0, 0
EX ld compass_angle() {
bool bitr = ginf[gCrystal].vertex == 3;
return (bitr ? M_PI/8 : 0) - master_to_c7_angle();
return (bitr ? 22.5_deg : 0) - master_to_c7_angle();
}
EX bool crystal_cell(cell *c, shiftmatrix V) {
@ -811,7 +813,7 @@ EX bool crystal_cell(cell *c, shiftmatrix V) {
queuestr(V, 0.3, its(d), 0xFFFFFF, 1);
}
if(view_coordinates && WDIM == 2 && cheater) {
if(view_coordinates && WDIM == 2 && (cheater || tour::on)) {
auto m = crystal_map();
@ -820,7 +822,7 @@ EX bool crystal_cell(cell *c, shiftmatrix V) {
ld dist = cellgfxdist(c, 0);
for(int i=0; i<S7; i++) {
shiftmatrix T = V * spin(compass_angle() - 2 * M_PI * i / S7) * xpush(dist*.3);
shiftmatrix T = V * spin(compass_angle() - TAU * i / S7) * xpush(dist*.3);
auto co = m->hcoords[c->master];
auto lw = m->makewalker(co, i);
@ -882,7 +884,7 @@ EX vector<cell*> build_shortest_path(cell *c1, cell *c2) {
}
}
println(hlog, "Error: path not found");
println(hlog, "Error: path not found, steps = ", steps);
return p;
}
@ -1116,8 +1118,9 @@ EX void init_rotation() {
if(ho & 1) {
for(int i=(draw_cut ? 2 : cs.dim-1); i>=1; i--) {
ld c = cos(M_PI / 2 / (i+1));
ld s = sin(M_PI / 2 / (i+1));
ld alpha = 90._deg / (i+1);
ld c = cos(alpha);
ld s = sin(alpha);
for(int j=0; j<cs.dim; j++)
tie(crug_rotation[j][0], crug_rotation[j][i]) =
make_pair(
@ -1315,9 +1318,7 @@ EX void set_crystal(int sides) {
set_variation(eVariation::pure);
ginf[gCrystal].sides = sides;
ginf[gCrystal].vertex = 4;
static char buf[20];
sprintf(buf, "{%d,4}", sides);
ginf[gCrystal].tiling_name = buf;
ginf[gCrystal].tiling_name = hr::format("{%d,4}", sides);
ginf[gCrystal].distlimit = distlimit_table[min(sides, MAX_EDGE_CRYSTAL-1)];
}
@ -1356,7 +1357,7 @@ EX void set_crystal_period_flags() {
for(auto& g: ginf)
if(g.flags & qCRYSTAL) {
set_flag(ginf[gNil].flags, qSMALL, crystal_period && crystal_period <= 8);
set_flag(ginf[gNil].flags, qBOUNDED, crystal_period);
set_flag(ginf[gNil].flags, qCLOSED, crystal_period);
}
}
@ -1404,7 +1405,7 @@ int readArgs() {
launch_dialog(show);
else if(argis("-cvcol")) {
shift(); int d = argi();
shift(); coordcolors[d] = arghex();
shift(); coordcolors[d] = argcolor(24);
}
else return 1;
return 0;
@ -1441,7 +1442,8 @@ string make_help() {
}
EX void crystal_knight_help() {
gamescreen(1);
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init();
dialog::addHelp(XLAT(
@ -1465,7 +1467,7 @@ EX void crystal_knight_help() {
EX void show() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
dialog::init(XLAT("dimensional crystal"));
for(int i=5; i<=14; i++) {
string s;
@ -1496,7 +1498,7 @@ EX void show() {
dialog::add_action([]() {
draw_cut = true;
dialog::editNumber(cut_level, -1, 1, 0.1, 0, XLAT("cut level"), "");
dialog::extra_options = [] {
dialog::get_di().extra_options = [] {
dialog::addItem(XLAT("disable"), 'D');
dialog::add_action([] { draw_cut = false; popScreen(); });
};
@ -1508,7 +1510,7 @@ EX void show() {
dialog::add_action([] {
dialog::editNumber(crystal_period, 0, 16, 2, 0, XLAT("Crystal torus"),
XLAT("Z_k^d instead of Z^d. Only works with k even."));
dialog::reaction_final = [] {
dialog::get_di().reaction_final = [] {
if(cryst) stop_game();
set_crystal_period_flags();
if(cryst) start_game();
@ -1558,7 +1560,7 @@ struct shift_data {
bignum& compute(ld rad2) {
if(result.count(rad2)) return result[rad2];
// println(hlog, "compute ", format("%p", this), " [shift=", shift, "], r2 = ", rad2);
// println(hlog, "compute ", hr::format("%p", this), " [shift=", shift, "], r2 = ", rad2);
// indenter i(2);
auto& b = result[rad2];
if(!parent) {
@ -1593,7 +1595,7 @@ EX string get_table_volume() {
if(co[i] < mincoord) mincoord = co[i];
if(co[i] > maxcoord) maxcoord = co[i];
}
static const ld eps = 1e-4;
static constexpr ld eps = 1e-4;
if(mincoord >= 0-eps && maxcoord < PERIOD-eps) {
ld my_rad2 = rad2;
auto cshift = (co - m->camelot_coord) / PERIOD;
@ -1721,8 +1723,8 @@ void transform_crystal_to_euclid () {
clearAnimations();
cwt.spin = neighborId(cwt.at, infront);
View = iddspin(cwt.at, cwt.spin, M_PI/2);
if(!flipplayer) View = cspin(0, 2, M_PI) * View;
View = iddspin(cwt.at, cwt.spin, 90._deg);
if(!flipplayer) View = cspin180(0, 2) * View;
if(pmodel == mdDisk) pmodel = mdPerspective;
}

300
debug.cpp
View File

@ -45,15 +45,10 @@ bool errorReported = false;
EX void describeCell(cell *c) {
if(!c) { printf("NULL\n"); return; }
printf("describe %p: ", hr::voidp(c));
printf("%-15s", linf[c->land].name);
printf("%-15s", winf[c->wall].name);
printf("%-15s", iinf[c->item].name);
printf("%-15s", minf[c->monst].name);
printf("LP%08x", c->landparam);
printf("D%3d", c->mpdist);
printf("MON%3d", c->mondir);
printf("\n");
print(hlog, "describe ", lalign(6, c), ": ");
vector<cell*> nei;
for(int i=0; i<c->type; i++) nei.push_back(c->move(i));
println(hlog, ">> ", nei);
}
static int orbid = 0;
@ -101,21 +96,14 @@ EX void cheatMoveTo(eLand l) {
cheatdest = laNone;
}
EX bool applyCheat(char u, cell *c IS(NULL)) {
struct cheatkey {
int key;
string desc;
reaction_t action;
};
if(u == 'L') {
do {
if(firstland == eLand(landtypes-1))
firstland = eLand(2);
else
firstland = eLand(firstland+1);
}
while(isTechnicalLand(firstland) || isCyclic(firstland));
specialland = firstland;
cheater++; addMessage(XLAT("You will now start your games in %1", firstland));
return true;
}
if(u == 'C') {
vector<cheatkey> cheats = {
cheatkey{'C', "Hyperstone Quest", [] {
cheater++;
cheatMoveTo(laCrossroads);
addMessage(XLAT("Activated the Hyperstone Quest!"));
@ -132,25 +120,22 @@ EX bool applyCheat(char u, cell *c IS(NULL)) {
kills[moMonkey] = qkills;
kills[moCultist] = qkills;
kills[moTroll] = qkills;
return true;
}
if(u == 'M') {
}},
cheatkey{'M', "deplete orb powers", [] {
for(int i=0; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_ORB)
items[i] = 0;
cheater++; addMessage(XLAT("Orb power depleted!"));
return true;
}
if(u == 'O') {
}},
cheatkey{'O', "summon orbs", [] {
cheater++; addMessage(XLAT("Orbs summoned!"));
for(int i=0; i<cwt.at->type; i++)
if(passable(cwt.at->move(i), NULL, 0)) {
eItem it = nextOrb();
cwt.at->move(i)->item = it;
}
return true;
}
if(u == 'F') {
}},
cheatkey{'F', "gain orb powers", [] {
if(hardcore && !canmove) {
canmove = true;
addMessage(XLAT("Revived!"));
@ -165,52 +150,31 @@ EX bool applyCheat(char u, cell *c IS(NULL)) {
cheater++; addMessage(XLAT("Orb power gained!"));
canmove = true;
}
return true;
}
if(u == 'D') {
items[itGreenStone] += 10;
cheater++; addMessage(XLAT("Dead orbs gained!"));
return true;
}
if(u == 'R'-64) buildRosemap();
#if CAP_EDIT
if(u == 'A') {
}},
cheatkey{'R'-64, "advance the rose wave", buildRosemap},
#if CAP_EDIT
cheatkey{'A', "start the Map Editor", [] {
lastexplore = turncount;
pushScreen(mapeditor::showMapEditor);
return true;
}
if(u == 'A'-64) {
}},
cheatkey{'A'-64, "start the Vector Graphics Editor", [] {
mapeditor::drawcell = mouseover ? mouseover : cwt.at;
pushScreen(mapeditor::showDrawEditor);
return true;
}
#elif CAP_SHOT
if(u == 'A') {
}},
#else
cheatkey{'A', "take screenshot", [] {
pushScreen(shot::menu);
return true;
}
#endif
if(u == 'T') {
}},
#endif
cheatkey{'T', "summon treasure", [] {
items[randomTreasure2(10)] += 10;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'T'-64) {
}},
cheatkey{'T'-64, "summon lots of treasure", [] {
items[randomTreasure2(100)] += 100;
cheater++; addMessage(XLAT("Lots of treasure gained!"));
return true;
}
if(u == 'I'-64) {
items[randomTreasure2(10)] += 25;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'U'-64) {
items[randomTreasure2(10)] += 50;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'Z') {
}},
cheatkey{'Z', "rotate the character", [] {
if (flipplayer) {
cwt += cwt.at->type/2;
flipplayer = false;
@ -221,24 +185,21 @@ EX bool applyCheat(char u, cell *c IS(NULL)) {
cwt.at->mondir %= cwt.at->type;
if(shmup::on) shmup::pc[0]->at = Id;
return true;
}
if(u == 'J') {
}},
cheatkey{'J', "lose all treasure", [] {
if(items[localTreasureType()] > 0)
items[localTreasureType()] = 0;
else for(int i=1; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE)
items[i] = 0;
cheater++; addMessage(XLAT("Treasure lost!"));
return true;
}
if(u == 'K') {
}},
cheatkey{'K', "gain kills", [] {
for(int i=0; i<motypes; i++) kills[i] += 10;
kills[moPlayer] = 0;
cheater++; addMessage(XLAT("Kills gained!"));
return true;
}
if(u == 'Y') {
}},
cheatkey{'Y', "unlock Orbs of Yendor", [] {
for(auto& y: yendor::yi) {
if(y.path[YDIST-1]->item == itKey)
y.path[YDIST-1]->item = itNone;
@ -246,67 +207,56 @@ EX bool applyCheat(char u, cell *c IS(NULL)) {
y.found = true;
}
cheater++; addMessage(XLAT("Collected the keys!"));
}
if(u == 'Y'-64) {
}},
cheatkey{'Y'-64, "gain Orb of Yendor", [] {
yendor::collected(cwt.at);
cheater++;
}
if(u == 'P') {
}},
cheatkey{'P', "save a Princess", [] {
items[itSavedPrincess]++;
princess::saved = true;
princess::everSaved = true;
if(inv::on && !princess::reviveAt)
princess::reviveAt = gold(NO_LOVE);
cheater++; addMessage(XLAT("Saved the Princess!"));
}
if(u == 'S') {
}},
cheatkey{'S', "Safety (quick save)", [] {
canmove = true;
cheatMoveTo(cwt.at->land);
items[itOrbSafety] += 3;
cheater++; addMessage(XLAT("Activated Orb of Safety!"));
return true;
}
if(u == 'U') {
canmove = true;
cheatMoveTo(firstland);
cheater++; addMessage(XLAT("Teleported to %1!", firstland));
return true;
}
if(u == 'W'-64) {
}},
cheatkey{'W'-64, "switch web display", [] {
pushScreen(linepatterns::showMenu);
return true;
}
if(u == 'G'-64) {
}},
cheatkey{'G'-64, "switch ghost timer", [] {
timerghost = !timerghost;
cheater++;
addMessage(XLAT("turn count = %1 last exploration = %2 ghost timer = %3",
its(turncount), its(lastexplore), ONOFF(timerghost)));
return true;
}
if(u == 'L'-64) {
}},
cheatkey{'G', "edit cell values", push_debug_screen},
cheatkey{'L'-64, "cell info", [] {
debug_cellnames = !debug_cellnames;
cell *c = mouseover;
if(!c) return;
describeCell(c);
printf("Neighbors:"); for(int i=0; i<c->type; i++) printf("%p ", hr::voidp(c->move(i)));
printf("Barrier: dir=%d left=%d right=%d\n",
c->bardir, c->barleft, c->barright);
return true;
}
if(u == 'C'-64) {
cblind = !cblind;
return true;
}
if(u == 'G') {
push_debug_screen();
return true;
}
if(u == 'P'-64)
}},
cheatkey{'P'-64, "peaceful mode", [] {
peace::on = !peace::on;
}},
#ifdef CHEAT_DISABLE_ALLOWED
if(u == 'D'-64) {
cheatkey{'D'-64, "cheat disable", [] {
cheater = 0; autocheat = 0;
return true;
}
#endif
};
EX bool applyCheat(char u) {
for(auto& ch: cheats) if(u == ch.key) {
ch.action();
return true;
}
return false;
}
@ -330,7 +280,7 @@ int bitfield_v;
template<class T> void bitfield_editor(int val, T setter, string help = "") {
bitfield_v = val;
dialog::editNumber(bitfield_v, 0, 100, 1, bitfield_v, help, "");
dialog::reaction = [setter] () { setter(bitfield_v); };
dialog::get_di().reaction = [setter] () { setter(bitfield_v); };
}
struct debugScreen {
@ -343,7 +293,7 @@ struct debugScreen {
void operator () () {
cmode = sm::SIDE | sm::DIALOG_STRICT_X;
gamescreen(0);
gamescreen();
getcstat = '-';
dialog::init(show_debug_data ? XLAT("debug values") : XLAT("internal details"));
@ -358,8 +308,6 @@ struct debugScreen {
#if CAP_SHAPES
queuepoly(gmatrix[what], cgi.shAsymmetric, 0x80808080);
#endif
char buf[200];
sprintf(buf, "%p", hr::voidp(what));
dialog::addSelItem("mpdist", its(what->mpdist), 'd');
dialog::add_action([what] () {
bitfield_editor(what->mpdist, [what] (int i) { what->mpdist = 0; }, "generation level");
@ -376,7 +324,7 @@ struct debugScreen {
static ld d = HEAT(what);
dialog::editNumber(d, -2, 2, 0.1, d, "landparam",
"Extra value that is important in some lands. The specific meaning depends on the land.");
dialog::reaction = [what] () { HEAT(what) = d; };
dialog::get_di().reaction = [what] () { HEAT(what) = d; };
});
dialog::addSelItem("land flags", its(what->landflags)+"/"+itsh2(what->landflags), 'f');
dialog::add_action([what] () {
@ -403,6 +351,7 @@ struct debugScreen {
dialog::use_hexeditor();
});
}
#if CAP_COMPLEX2
if(dice::on(what)) {
dialog::addSelItem(XLAT("die shape"), dice::die_name(dice::data[what].which), 'A');
dialog::add_action_push([what] {
@ -435,10 +384,11 @@ struct debugScreen {
});
dialog::addBoolItem_action(XLAT("die mirror status"), dice::data[what].mirrored, 'D');
}
#endif
dialog::addBreak(50);
if(show_debug_data) {
dialog::addSelItem("pointer", s0+buf+"/"+index_pointer(what), 0);
dialog::addSelItem("pointer", s0+hr::format("%p", hr::voidp(what))+"/"+index_pointer(what), 0);
dialog::addSelItem("cpdist", its(what->cpdist), 0);
dialog::addSelItem("celldist", its(celldist(what)), 0);
dialog::addSelItem("celldistance", its(celldistance(cwt.at, what)), 0);
@ -469,7 +419,7 @@ struct debugScreen {
dialog::add_action([what] () {
bitfield_editor(what->mondir, [what] (int i) { what->mondir = i; },
"monster direction");
dialog::extra_options = [what] () {
dialog::get_di().extra_options = [what] () {
dialog::addBoolItem(XLAT("mirrored"), what->monmirror, 'M');
};
});
@ -495,10 +445,10 @@ struct debugScreen {
dialog::addBack();
dialog::display();
keyhandler = [this, what] (int sym, int uni) {
keyhandler = [this] (int sym, int uni) {
handlePanning(sym, uni);
dialog::handleNavigation(sym, uni);
if(applyCheat(uni, what)) ;
if(applyCheat(uni)) ;
else if(sym == PSEUDOKEY_WHEELUP || sym == PSEUDOKEY_WHEELDOWN) ;
else if(sym == '-') debugged_cell = mouseover;
else if(doexiton(sym, uni)) {
@ -516,45 +466,16 @@ EX void push_debug_screen() {
/** show the cheat menu */
EX void showCheatMenu() {
gamescreen(1);
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init("cheat menu");
dialog::addItem(XLAT("gain orb powers"), 'F');
dialog::addItem(XLAT("summon treasure"), 'T');
dialog::addItem(XLAT("summon dead orbs"), 'D');
dialog::addItem(XLAT("lose all treasure"), 'J');
dialog::addItem(XLAT("gain kills"), 'K');
dialog::addItem(XLAT("Hyperstone Quest"), 'C');
dialog::addItem(XLAT("summon orbs"), 'O');
dialog::addItem(XLAT("summon lots of treasure"), 'T'-64);
dialog::addItem(XLAT("Safety (quick save)"), 'S');
dialog::addItem(XLAT("Select the land ---"), 'L');
dialog::addItem(XLAT("--- and teleport there"), 'U');
dialog::addItem(XLAT("rotate the character"), 'Z');
dialog::addItem(XLAT("deplete orb powers"), 'M');
dialog::addItem(XLAT("save a Princess"), 'P');
dialog::addItem(XLAT("unlock Orbs of Yendor"), 'Y');
dialog::addItem(XLAT("gain Orb of Yendor"), 'Y'-64);
dialog::addItem(XLAT("switch ghost timer"), 'G'-64);
dialog::addItem(XLAT("switch web display"), 'W'-64);
dialog::addItem(XLAT("peaceful mode"), 'P'-64);
for(auto& ch: cheats) {
dialog::addItem(XLAT(ch.desc), ch.key);
dialog::add_action([ch] { ch.action(); popScreen(); });
}
dialog::addBreak(50);
dialog::addBack();
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni != 0) {
applyCheat(uni);
if(uni == 'F' || uni == 'C' || uni == 'O' ||
uni == 'S' || uni == 'U' || uni == 'G' ||
uni == 'W' || uni == 'I' || uni == 'E' ||
uni == 'H' || uni == 'B' || uni == 'M' ||
uni == 'M' || uni == 'Y'-64 || uni == 'G'-64 ||
uni == ' ' || uni == 8 || uni == 13 ||
uni == SDLK_ESCAPE || uni == 'q' || uni == 'v' || sym == SDLK_ESCAPE ||
sym == SDLK_F10)
popScreen();
}
};
}
/** view all the monsters and items */
@ -688,8 +609,8 @@ int read_cheat_args() {
else if(argis("-g")) {
/* debugging mode */
if(curphase == 1) {
/* use a separate score file */
scorefile = "xx";
/* use no score file */
scorefile = "";
/* set seed for reproducible results */
if(!fixseed) {
fixseed = true; autocheat = true;
@ -718,6 +639,11 @@ int read_cheat_args() {
else if(argis("-W2")) {
shift(); cheatdest = readland(args()); cheat();
showstartmenu = false;
cheatdest_list.clear();
}
else if(argis("-W3")) {
shift(); cheatdest_list.push_back(readland(args())); cheat();
showstartmenu = false;
}
else if(argis("-I")) {
PHASE(3) cheat();
@ -734,6 +660,9 @@ int read_cheat_args() {
PHASEFROM(2);
shift(); vid.stereo_mode = eStereo(argi());
}
else if(argis("-save-cheats")) {
save_cheats = true;
}
else if(argis("-cmove")) {
PHASE(3); shift();
for(char c: args()) cheat_move(c);
@ -793,6 +722,16 @@ int read_cheat_args() {
if(itemclass(eItem(i)) == IC_TREASURE)
items[i] = q;
}
else if(argis("-each-random")) {
PHASEFROM(2); start_game(); cheat();
for(int i=0; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE) {
items[i] = 10 + hrand(21);
if(i == itElemental) items[i] = 12;
}
else
items[i] = 0;
}
else if(argis("-viewall")) {
PHASE(3); start_game();
viewall();
@ -810,12 +749,15 @@ int read_cheat_args() {
shift(); int index = argi();
shift(); whateveri[index] = argi();
}
else if(argis("-W3")) {
else if(argis("-W4")) {
shift(); top_land = readland(args()); cheat();
showstartmenu = false;
}
else if(argis("-top")) {
PHASE(3); View = View * spin(-M_PI/2);
PHASE(3); View = View * spin(-90._deg);
}
else if(argis("-idv")) {
PHASE(3); View = Id;
}
else if(argis("-gencells")) {
PHASEFROM(2); shift(); start_game();
@ -873,7 +815,6 @@ int read_cheat_args() {
}
else if(argis("-lands")) {
PHASEFROM(2);
cheat();
stop_game();
shift(); land_structure = (eLandStructure) (argi());
}
@ -907,6 +848,35 @@ int read_cheat_args() {
cheat();
gen_wandering = false;
}
else if(argis("-canvasfloor")) {
shift(); canvasfloor = argi();
for(int i=0; i<caflEND; i++) if(appears(mapeditor::canvasFloorName(i), args()))
canvasfloor = i;
}
else if(argis("-keys")) {
shift(); string s = args();
bool quote = false;
for(char c: s)
if(quote) {
quote = false;
if(c == '\\') dialog::queue_key(c), quote = false;
else if(c >= '1' && c <= '9') dialog::queue_key(SDLK_F1 + c - '1');
else if(c == 'e') dialog::queue_key(SDLK_ESCAPE);
else if(c == 'r') dialog::queue_key(SDLK_RETURN);
else if(c == 't') dialog::queue_key(SDLK_TAB);
else if(c == 'b') dialog::queue_key(SDLK_BACKSPACE);
else if(c == 'R') dialog::queue_key(SDLK_RIGHT);
else if(c == 'L') dialog::queue_key(SDLK_LEFT);
else if(c == 'U') dialog::queue_key(SDLK_UP);
else if(c == 'D') dialog::queue_key(SDLK_DOWN);
else if(c == 'H') dialog::queue_key(SDLK_HOME);
else if(c == 'E') dialog::queue_key(SDLK_END);
else if(c == 'P') dialog::queue_key(SDLK_PAGEUP);
else if(c == 'Q') dialog::queue_key(SDLK_PAGEDOWN);
}
else if(c == '\\') quote = true;
else dialog::queue_key(c);
}
else if(argis("-hroll")) {
shift();
int i = argi();
@ -916,6 +886,8 @@ int read_cheat_args() {
PHASEFROM(2);
shift();
firstland0 = firstland = specialland = readland(args());
if (!landUnlocked(firstland))
cheat();
stop_game_and_switch_mode(rg::nothing);
showstartmenu = false;
}

View File

@ -0,0 +1,80 @@
336h: D29C2418 p=3, f=3, n=10, q=5,1
336h: 7769A558 p=5, f=25, n=650, q=50
336h: 640FB3D4 p=7, f=7, n=28, q=14,1
336h: C734F868 p=7, f=7, n=28, q=14,1
336h: E3F6B7BC p=7, f=49, n=672, q=336,28,16
336h: 885F1184 p=7, f=49, n=672, q=336,42,28,16
344h: B23AF1F4 p=3, f=3, n=5, q=1
344h: 4F9920E0 p=3, f=3, n=5, q=1
344h: 6DBBAAA0 p=3, f=3, n=10, q=5,1
344h: F81E97B0 p=3, f=3, n=10, q=5,1
344h: F790CEA4 p=3, f=3, n=30, q=6,3
344h: C95EC8B8 p=3, f=3, n=30, q=3
344h: 16518434 p=3, f=9, n=16, q=8,4,2
344h: 558C8ED0 p=5, f=5, n=600, q=20,25
344h: 1EC39944 p=5, f=5, n=600, q=20,25
344h: AF042EA8 p=5, f=25, n=2400, q=1200,600,60,40
344h: EC29DCEC p=5, f=25, n=2600, q=1300,650,100
344h: D26948E0 p=5, f=25, n=2600, q=1300,650,100
345h: F978E264 p=3, f=3, n=30, q=6,3
345h: 02ADCAA4 p=3, f=3, n=30, q=6,3
345h: 7EFE8D98 p=5, f=25, n=650, q=50,25
345h: F447F75C p=11, f=11, n=55, q=5
345h: 58A698B8 p=19, f=19, n=285, q=15
345h: 6FA03030 p=19, f=19, n=285, q=57,15
353h: 1566EBAC p=5, f=25, n=130, q=10
353h: 5A2E2B88 p=11, f=11, n=11, q=1
354h: 58A8E850 p=5, f=5, n=2, q=1
354h: 363D8DA4 p=11, f=11, n=22, q=11,2
354h: 9CD5E744 p=11, f=11, n=22, q=11,2
354h: F04BA28C p=19, f=19, n=114, q=57,6
355h: AF448B14 p=5, f=5, n=1
355h: F42F2904 p=5, f=5, n=1
355h: 47F0C740 p=5, f=5, n=120, q=6,4
355h: 7BAFB45C p=11, f=11, n=11, q=1
355h: 6453A3FC p=11, f=11, n=11, q=1
435h: EB201050 p=5, f=25, n=650, q=25
435h: 65CE0C00 p=11, f=11, n=55, q=11,5
435h: 5641E95C p=11, f=11, n=55, q=11,5
436h: 235F7508 p=2, f=4, n=2, q=1
436h: C02F2A80 p=2, f=4, n=2, q=1
436h: DFC6B8C0 p=2, f=4, n=8, q=4,2
436h: 4D3C8B14 p=3, f=9, n=8, q=1
436h: FF82A214 p=5, f=25, n=650, q=50,25
436h: 4546E270 p=5, f=25, n=650, q=25
436h: C4884090 p=7, f=7, n=28, q=14,4,2
436h: 5230B364 p=7, f=7, n=28, q=14,2
436h: 2D051038 p=7, f=7, n=14, q=7,2
436h: F0997060 p=7, f=7, n=14, q=7,2
436h: 1D1227CC p=7, f=49, n=672, q=336,112,42,14,12
436h: B2B4B3D4 p=7, f=49, n=672, q=336,14,12
436h: 6C29B2A4 p=13, f=13, n=91, q=13,7
436h: 06F4054C p=13, f=13, n=91, q=13,7
436h: DE4912E0 p=13, f=13, n=182, q=91,13,7
436h: 417466F0 p=13, f=13, n=182, q=91,13,7
534h: 0C62E214 p=5, f=25, n=130, q=10
534h: 72414D0C p=5, f=25, n=260, q=10
534h: 831E2D74 p=11, f=11, n=22, q=2
534h: 5FC4CFF0 p=11, f=11, n=22, q=2
535h: DCC3CACE p=5, f=5, n=1
535h: F78E1C56 p=5, f=5, n=1
535h: 9EF7A9C4 p=5, f=5, n=120, q=10,8,6,4
535h: 5254DA16 p=19, f=19, n=57, q=3
535h: A5C8752E p=19, f=19, n=57, q=3
536h: BB5AEE10 p=5, f=5, n=120, q=8,6,4
536h: 61385498 p=5, f=5, n=2, q=1
536h: B009EB44 p=5, f=5, n=2, q=1
536h: 3BA5C5A4 p=5, f=25, n=130, q=10
536h: 9FDE7B38 p=5, f=25, n=260, q=130,10
536h: 885F1184 p=7, f=49, n=672, q=336,28,16

View File

@ -7,8 +7,9 @@
namespace hr {
bool doAutoplay;
eLand autoplayLand;
namespace prairie { extern long long enter; }
namespace prairie { extern cell *enter; }
bool sameland(eLand ll, eLand ln) {
if(ln == laBarrier || ln == laOceanWall)
@ -19,6 +20,111 @@ bool sameland(eLand ll, eLand ln) {
return false;
}
void randomCheat() {
int croll = hrand(50);
if (croll < 25) {
eItem b = (eItem) hrand(ittypes);
printf("Gain item: %s\n", iinf[b].name);
items[b] = (1 << hrand(11)) - 1;
items[itOrbYendor] &= 15;
reduceOrbPowers(); // in particlar, cancel out slaying+weakness, since the combination may confuse shadow
} else if (croll == 25) {
printf("Gain kills\n");
kills[hrand(motypes)] = (1 << hrand(11)) - 1;
} else if (croll == 26) {
printf("Princess soon\n");
princess::saved = true;
princess::everSaved = true;
items[itSavedPrincess]++;
items[itOrbLove] = 1;
items[itOrbTime] = 0;
} else if (croll == 27) {
printf("Gain allies\n");
forCellEx(cz, cwt.at)
if (!cz->monst)
cz->monst = pick(moMouse, moFriendlyGhost, moGolem, moTameBomberbird, moKnight);
} else if (croll == 28) {
printf("Place orbs with pickup effects\n");
forCellEx(cz, cwt.at)
if (!cz->item)
cz->item = pick(itOrbLife, itOrbFriend, itOrbSpeed, itOrbShield, itOrbChaos, itOrbPurity);
} else if (croll == 29) {
printf("Place fun walls\n");
forCellEx(cz, cwt.at)
if (!cz->wall && !cz->monst)
cz->wall = pick(waExplosiveBarrel, waBigStatue, waThumperOff, waBonfireOff, waCloud, waMirror);
} else if (croll == 30) {
cell *ct = dcal[hrand(isize(dcal))];
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
eWall hazard = pick(waRose, waFireTrap, waMineMine, waTrapdoor, waChasm, waCavewall);
printf("Spam a hazard: %s\n", winf[hazard].name);
ct->wall = hazard;
}
} else if (croll == 31 && !memory_saving_mode) {
//printf("Saving memory\n");
//memory_saving_mode = true;
//save_memory();
//memory_saving_mode = false;
} else if (croll == 33) {
cell *ct = dcal[hrand(isize(dcal))];
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
printf("Spam some slime\n");
ct->item = itNone;
ct->wall = hrand(2) ? waFloorA : waFloorB;
switch(hrand(4)) {
case 0: ct->monst = moSlime; break;
case 1: ct->item = itGreenStone; break;
default: ;
}
}
} else if (croll == 37) {
cell *ct = dcal[hrand(isize(dcal))];
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
ct->monst = pick(moRagingBull, moTroll, moAcidBird, moMiner, moReptile, moVineBeast, moBug0, moBug1);
printf("Spam a monster: %s\n", minf[ct->monst].name);
}
// todo: dice
} else if (croll == 38) {
forCellEx(cz, cwt.at) {
if (cz->monst == moPrincessArmed) {
printf("Disarming a princess\n");
cz->monst = moPrincess;
}
}
} else if (croll == 39) {
//forCellEx(cz, cwt.at) {
// if (!cz->monst) {
// printf("Summoning an unarmed princess incorrectly\n");
// cz->monst = moPrincess;
// break;
// }
//}
} else if (croll == 40) {
//forCellEx(cz, cwt.at) {
// if (!cz->monst) {
// printf("Summoning an armed princess incorrectly\n");
// cz->monst = moPrincessArmed;
// break;
// }
//}
} else if (croll == 41) {
cell *ct = dcal[hrand(isize(dcal))];
if (among(ct->wall, waNone, waVinePlant, waFloorA, waFloorB, waTrapdoor, waChasm, waBigStatue)) {
// Set wparam on a cell where it shouldn't matter, so that if this wall is later converted
// to a walltype that does care by some code that assumes wparam was 0,
// we can find out if that causes bugs.
printf("Randomizing wparam on %s at %p\n", winf[ct->wall].name, (void *)ct);
ct->wparam = (unsigned char) hrand(256);
}
} else if (croll == 42) {
vid.wallmode = hrand(7);
printf("Set vid.wallmode to %d: %s\n", vid.wallmode, wdmodes[vid.wallmode]);
} else if (croll == 43) {
vid.monmode = hrand(4);
printf("Set vid.monmode to %d: %s\n", vid.monmode, mdmodes[vid.monmode]);
}
}
cell *cellToTarget() {
if (isCrossroads(cwt.at->land)) {
for (cell *c: dcal) {
@ -49,6 +155,175 @@ cell *cellToTarget() {
return dcal[hrand(isize(dcal))];
}
void randomMove()
{
// don't show warning dialogs
items[itWarning] = 1;
int roll = hrand(50);
if (roll == 0) {
// drop dead orb
bool res = movepcto(MD_DROP, 1);
printf("DROP: %d\n", res);
} else if (roll < 5) {
// skip turn
bool res = movepcto(MD_WAIT, 1);
printf("WAIT: %d\n", res);
} else if (roll < 42) {
// move to or attack a neighbor cell
int i = hrand(cwt.at->type);
cell *c2 = cwt.at->move(i);
cwt.spin = 0;
int d = neighborId(cwt.at, c2);
if (d >= 0) {
int subdir = (roll%2==0)?1:-1;
string c2info = dnameof(c2->wall) + "; " + dnameof(c2->monst) + "; " + dnameof(c2->item);
bool res = movepcto(d, subdir, false);
printf("MOVE %d [%s] sub %d: %d\n", d, c2info.c_str(), subdir, res);
if (!res && c2->monst) {
printf("clearing the monster (%s)\n", minf[c2->monst].name);
killMonster(c2, moNone);
}
} else {
printf("MOVE CONFUSED %d\n", d);
}
} else {
// try to use a ranged orb
cell *ct = cellToTarget();
eItem ti = targetRangedOrb(ct, roMouseForce);
const char *tm = iinf[ti].name;
printf("TARGET %p: %s\n", (void*)ct, tm);
}
}
void noteUnusualSituations()
{
if(cwt.at->monst && !isMultitile(cwt.at->monst)) {
// This is possible in multiple ways
printf("on a non-multitile monster: %s\n", minf[cwt.at->monst].name);
}
else if(isDie(cwt.at->wall)) {
// This is possible with aether + teleport
printf("on a wall-type die: %s\n", winf[cwt.at->wall].name);
}
}
bool isAnythingWrong()
{
uintptr_t ienter = (uintptr_t) prairie::enter;
if(ienter && ienter < 100000) {
printf("ERROR: prairie::enter has incorrect value\n");
return true;
}
if(buggyGeneration || isize(buggycells)) {
println(hlog, "ERROR: buggy generation");
return true;
}
if(isIcyLand(cwt.at)) {
float heat = HEAT(cwt.at);
// Checking for extreme values as well as NaNs and infinities
if (!(-1e10 < heat && heat < 1e10)) {
printf("ERROR: Heat is out of expected range\n");
return true;
}
}
if (cwt.at->land == laCamelot) {
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
if(c->land == laCamelot && celldistAltRelative(c) == 0 && c->wall != waRoundTable) {
printf("ERROR: The round table of camelot is interrupted by a cell of %s\n", winf[c->wall].name);
return true;
}
}
}
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
(void)isChild(c, NULL);
if(childbug) return true;
if(c->land == laNone) {
printf("ERROR: no-land found\n");
return true;
}
if(c->item == itBuggy || c->item == itBuggy2) {
printf("ERROR: buggy item found\n");
return true;
}
if(!euclid && isPrincess(c->monst) && princess::getPrincessInfo(c) == nullptr) {
printf("ERROR: missing princess info\n");
return true;
}
if(dice::on(c)) {
if(dice::data.count(c) == 0) {
c->item = itBuggy;
printf("ERROR: missing dice::data[%p]\n", (void *)c);
return true;
}
else if(!dice::data[c].which) {
// we might get here instead if someone already tried to do data[c], which creates a new element out of nothing
c->item = itBuggy;
printf("ERROR: missing dice::data[%p].which\n", (void *)c);
return true;
}
}
}
return false;
}
void stopIfBug()
{
if(isAnythingWrong()) {
if(noGUI) {
exit(1);
}
else {
kills[moPlayer] = 0;
canmove = true;
doAutoplay = false;
}
}
}
void showAutoplayStats()
{
printf("cells travelled: %d\n", celldist(cwt.at));
printf("\n");
for(int i=0; i<ittypes; i++) if(items[i])
printf("%4dx %s\n", items[i], iinf[i].name);
printf("\n");
for(int i=1; i<motypes; i++) if(kills[i])
printf("%4dx %s <%d>\n", kills[i], minf[i].name, i);
printf("\n\n\n");
}
void resetIfNeeded(int *gcount)
{
if(hrand(5000) == 0 || (isGravityLand(cwt.at->land) && coastvalEdge(cwt.at) >= 100) || *gcount > 2000 || cellcount >= 20000000) {
printf("RESET\n");
*gcount = 0;
cellcount = 0;
activateSafety(autoplayLand ? autoplayLand : landlist[hrand(isize(landlist))]);
if (cellcount < 0) {
//printf("How did cellcount become negative?\n");
cellcount = 1;
}
}
if(cwt.at->land == laWestWall && cwt.at->landparam >= 30) {
printf("Safety generated\n");
forCellEx(c2, cwt.at) c2->item = itOrbSafety;
}
}
/* auto a3 = addHook(hooks_nextland, 100, [] (eLand l) {
eLand l2;
do { l2 = pick(laRuins, laTerracotta, laPrairie); } while(l2 == l);
@ -76,13 +351,7 @@ void autoplay(int num_moves = 1000000000) {
int lastdraw = 0;
#endif
while(doAutoplay) {
long long ienter = (long long) prairie::enter;
if(ienter && ienter < 100000) {
printf("ERROR: enter has incorrect value\n");
exit(1);
}
if(gold() > lastgold) {
lastgold = gold();
gcount = 0;
@ -113,187 +382,12 @@ void autoplay(int num_moves = 1000000000) {
else if(lcount < 50 && c2->item && c2->item != itOrbSafety) break;
} */
// Use a random cheat
int croll = hrand(50);
if (croll < 25) {
eItem b = (eItem) hrand(ittypes);
printf("Gain item: %s\n", iinf[b].name);
items[b] = (1 << hrand(11)) - 1;
items[itOrbYendor] &= 15;
reduceOrbPowers(); // in particlar, cancel out slaying+weakness, since the combination may confuse shadow
} else if (croll == 25) {
printf("Gain kills\n");
kills[hrand(motypes)] = (1 << hrand(11)) - 1;
} else if (croll == 26) {
printf("Princess soon\n");
princess::saved = true;
princess::everSaved = true;
items[itSavedPrincess]++;
items[itOrbLove] = 1;
items[itOrbTime] = 0;
} else if (croll == 27) {
printf("Gain allies\n");
forCellEx(cz, cwt.at)
if (!cz->monst)
cz->monst = pick(moMouse, moFriendlyGhost, moGolem, moTameBomberbird, moKnight);
} else if (croll == 28) {
printf("Place orbs with pickup effects\n");
forCellEx(cz, cwt.at)
if (!cz->item)
cz->item = pick(itOrbLife, itOrbFriend, itOrbSpeed, itOrbShield, itOrbChaos, itOrbPurity);
} else if (croll == 29) {
printf("Place fun walls\n");
forCellEx(cz, cwt.at)
if (!cz->wall)
cz->wall = pick(waExplosiveBarrel, waBigStatue, waThumperOff, waBonfireOff, waCloud, waMirror);
} else if (croll == 30) {
cell *ct = dcal[hrand(isize(dcal))];
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
eWall hazard = pick(waRose, waFireTrap, waMineMine, waTrapdoor, waChasm, waCavewall);
printf("Spam a hazard: %s\n", winf[hazard].name);
ct->wall = hazard;
}
} else if (croll == 31 && !memory_saving_mode) {
//printf("Saving memory\n");
//memory_saving_mode = true;
//save_memory();
//memory_saving_mode = false;
} else if (croll == 33) {
cell *ct = dcal[hrand(isize(dcal))];
if (!isPlayerOn(ct) && !ct->monst && !ct->wall) {
printf("Spam some slime\n");
ct->item = itNone;
ct->wall = hrand(2) ? waFloorA : waFloorB;
ct->monst = hrand(2) ? moSlime : moNone;
}
}
// don't show warning dialogs
items[itWarning] = 1;
// Make a random move
int roll = hrand(50);
if (roll == 0) {
// drop dead orb
bool res = movepcto(MD_DROP, 1);
printf("DROP: %d\n", res);
} else if (roll < 5) {
// skip turn
bool res = movepcto(MD_WAIT, 1);
printf("WAIT: %d\n", res);
} else if (roll < 42) {
// move to or attack a neighbor cell
int i = hrand(cwt.at->type);
cell *c2 = cwt.at->move(i);
cwt.spin = 0;
int d = neighborId(cwt.at, c2);
if (d >= 0) {
int subdir = (roll%2==0)?1:-1;
string c2info = dnameof(c2->wall) + "; " + dnameof(c2->monst) + "; " + dnameof(c2->item);
bool res = movepcto(d, subdir, false);
printf("MOVE %d [%s] sub %d: %d\n", d, c2info.c_str(), subdir, res);
if (!res && c2->monst) {
printf("clearing the monster (%s)\n", minf[c2->monst].name);
killMonster(c2, moNone);
}
} else {
printf("MOVE CONFUSED %d\n", d);
return;
}
} else {
// try to use a ranged orb
cell *ct = cellToTarget();
eItem ti = targetRangedOrb(ct, roMouseForce);
const char *tm = (ti == eItem(-1)) ? "orb cannot be used (see message log)" : iinf[ti].name;
printf("TARGET %p: %s\n", (void*)ct, tm);
}
if(false) if(turncount % 5000 == 0) {
printf("cells travelled: %d\n", celldist(cwt.at));
printf("\n");
for(int i=0; i<ittypes; i++) if(items[i])
printf("%4dx %s\n", items[i], iinf[i].name);
printf("\n");
for(int i=1; i<motypes; i++) if(kills[i])
printf("%4dx %s <%d>\n", kills[i], minf[i].name, i);
printf("\n\n\n");
}
if(hrand(5000) == 0 || (isGravityLand(cwt.at->land) && coastvalEdge(cwt.at) >= 100) || gcount > 2000 || cellcount >= 20000000) {
printf("RESET\n");
gcount = 0;
cellcount = 0;
activateSafety(laCrossroads);
// landlist[hrand(isize(landlist))]);
if (cellcount < 0) {
//printf("How did cellcount become negative?\n");
cellcount = 1;
}
}
if(cwt.at->land == laWestWall && cwt.at->landparam >= 30) {
printf("Safety generated\n");
forCellEx(c2, cwt.at) c2->item = itOrbSafety;
}
if(isIcyLand(cwt.at)) {
float heat = HEAT(cwt.at);
// Checking for extreme values as well as NaNs and infinities
if (!(-1e10 < heat && heat < 1e10)) {
printf("Heat is out of expected range\n");
canmove = true;
doAutoplay = false;
}
}
if (cwt.at->land == laCamelot) {
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
if(c->land == laCamelot && celldistAltRelative(c) == 0 && c->wall != waRoundTable) {
printf("The round table of camelot has been breached!\n");
kills[moPlayer] = 0;
canmove = true;
doAutoplay = false;
}
}
}
if(cwt.at->monst && !isMultitile(cwt.at->monst)) {
printf("on a non-multitile monster: %s\n", minf[cwt.at->monst].name);
}
for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
if(isChild(c, NULL)) {
}
if(childbug) doAutoplay = false;
if(c->land == laNone) {
printf("no-land found\n");
kills[moPlayer] = 0;
canmove = true;
doAutoplay = false;
}
if(c->item == itBuggy || c->item == itBuggy2) {
printf("buggy item found\n");
kills[moPlayer] = 0;
canmove = true;
doAutoplay = false;
}
}
if(buggyGeneration || isize(buggycells)) {
if(noGUI) {
printf("Fatal: buggy generation\n");
exit(1);
}
println(hlog, "buggy generation");
return;
}
randomCheat();
randomMove();
if(false) if(turncount % 5000 == 0) showAutoplayStats();
resetIfNeeded(&gcount);
noteUnusualSituations();
stopIfBug();
if(turncount >= num_moves) return;
}
@ -303,6 +397,13 @@ int readArgs() {
using namespace arg;
if(0) ;
else if(argis("-autoplayW")) {
// Start in this land and reset to this land
PHASE(3);
shift();
autoplayLand = readland(args());
activateSafety(autoplayLand);
}
else if(argis("-autoplay")) {
PHASE(3);
autoplay();

View File

@ -40,25 +40,88 @@ void print_shader(const char *fname, string s) {
bool es_handleKey(int sym, int uni) {
using namespace glhr;
if(sym == SDLK_F2) {
glhr::be_textured();
current_display->set_all(0);
auto p = glhr::get_shaders();
print_shader("devmods/current.vsh", p.first);
print_shader("devmods/current.fsh", p.second);
auto p = current_glprogram;
print_shader("devmods/current.vsh", p->_vsh);
print_shader("devmods/current.fsh", p->_fsh);
addMessage("shaders saved");
return true;
}
if(sym == SDLK_F3) {
if(sym == SDLK_F4) {
println(hlog, "shader program = ", glhr::current_glprogram->_program);
solv_all = !solv_all;
println(hlog, "now solv_all = ", solv_all);
return true;
}
/*if(sym == SDLK_F5) {
drawthemap();
for(auto& p: ptds) {
auto s = dynamic_cast<dqi_poly*> (&*p);
if(!s) continue;
for(int i=0; i<s->cnt; i+=3) {
array<hyperpoint, 3> ps;
for(int k=0; k<3; k++) ps[k] = s->V * gltopoint((*(s->tab))[i+k]);
array<hyperpoint, 3> ie;
for(int k=0; k<3; k++) ie[k] = inverse_exp(ps[k]);
ld iz = 99, az = -99;
for(int k=0; k<3; k++) {
if(ie[k][2] < iz) iz = ie[k][2];
if(ie[k][2] > az) az = ie[k][2];
}
if(iz < 0 && az > 0)
println(hlog, tie(iz, az), ps);
}
}
return true;
} */
if(sym == SDLK_F5) {
/*
for(ld x=1; x<30; x+=.2)
for(ld y=1; y<30; y+=.2)
for(ld z=0; z<=20.1; z+=.02) {
hyperpoint p = point31(x, y, z);
transmatrix T = rgpushxto0(p);
auto ie = inverse_exp(p);
for(ld ax=-0.2; ax<=0.21; ax+=0.2)
for(ld ay=-0.2; ay<=0.21; ay+=0.2)
for(ld az=-0.2; az<=0.21; az+=0.2) {
hyperpoint p1 = T * point31(ax, ay, az);
auto ie1 = inverse_exp(p1);
if(ie[2] * ie1[2] < 0 && abs(ie[2]) > .5 && abs(ie1[2]) > .5)
println(hlog, lalign(30, kz(p)), ": ", lalign(30, kz(ie)), " ", lalign(30, kz(p1)), ": ", lalign(30, kz(ie1)), " @ ",
make_tuple(sn::x_to_ix(p[0]), sn::x_to_ix(p[1]), sn::z_to_iz(p[2])));
}
}
*/
return true;
}
if(sym == SDLK_F3 && !solv_all) {
glhr::be_textured();
current_display->set_all(0);
string vsh = load_whole("devmods/current.vsh");
string fsh = load_whole("devmods/current.fsh");
println(hlog, "loaded vsh:\n", vsh);
glhr::install_shaders(vsh, fsh);
glhr::be_textured();
current_display->set_all(0);
auto p = make_shared<glhr::GLprogram>(vsh, fsh);
println(hlog, "compiled program: ", p->_program);
auto old = current_glprogram;
p->shader_flags = old->shader_flags;
auto replace = [&] (shared_ptr<GLprogram>& s) {
if(s == old) s = p;
};
for(auto& pp: compiled_programs) replace(pp.second);
for(auto& pp: matched_programs) replace(pp.second);
return true;
}

View File

@ -191,7 +191,7 @@ void gentrans() {
DIR *d;
struct dirent *dir;
println(hlog, "// checking all the files");
println(hlog, "\n\n// checking all the files");
d = opendir(".");
@ -204,11 +204,11 @@ void gentrans() {
closedir(d);
}
println(hlog, "// checking configurables");
println(hlog, "\n\n// checking configurables");
for(auto& fs: params) {
auto& sett = fs.second;
if(sett->menu_item_name != sett->config_name)
if(sett->menu_item_name_modified)
check_ex(sett->menu_item_name, "menu_item_name for " + sett->parameter_name);
check_ex(sett->help_text, "help_text for " + sett->parameter_name);
auto ls = dynamic_cast<list_setting*> ( (setting*) &*sett);
@ -222,6 +222,6 @@ void gentrans() {
exit(0);
}
auto ar = arg::add3("-gentrans", gentrans);
auto gtar = arg::add3("-gentrans", gentrans);
}

516
devmods/hatter.cpp Normal file
View File

@ -0,0 +1,516 @@
/**
* This program was used to generate the rule tables in apeirodic-hat.cpp.
*
* Some data was generated by this program itself, based on manual keyboard+mouse control.
* Some of minor manual control tools have been removed, but the process was as follows:
*
* * Run with `-symbol "12,6,4" -dual -canvas 101010 -smart 1 stamplen=0` and draw the hat shape, the table output is hatcorners
* * Place hats into clusters as shown in the paper, obtaining the table hats[0]
* * Place clusters into superclusters as shown in the paper, obtaining the table hats[1]
* * Repeat for hats[2], hats[3], hats[4] and hats[5] (the paper does not specify precisely the coordinates to arrange the clusters; but we can multiply the previous hats by scaling factor
* * for an approximate, and fix manually so that it matches)
* * 'CON Lx' lines state the rules deduced; the rules should be the same for L1 and L2 (except the matrix codes returned by matcode), so we conjecture that this set of rules is complete
* * Fill the table `hatid` to declare the correspondence between L1 and L2 matrices
* * Run again, and we get rules (prefixed by RULE1 and RULE0)
**/
#include "../rogueviz/rogueviz.h"
namespace rogueviz {
int toplev = 5;
vector<hyperpoint> hatcorners_add;
vector<hyperpoint> hatcorners[2];
vector<transmatrix> hats[8];
vector<int> hattype;
hyperpoint pt(ld x, ld y) { return hpxy(x, y); }
transmatrix rot;
transmatrix sca;
transmatrix U;
transmatrix mt(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i) {
transmatrix T = Id;
T[0][0] = a;
T[0][1] = b;
T[0][2] = c;
T[1][0] = d;
T[1][1] = e;
T[1][2] = f;
T[2][0] = g;
T[2][1] = h;
T[2][2] = i;
return T;
}
map<string, int> hatid;
void init() {
rot = Id;
hatcorners[0] = {
pt(-1.1160254038,1.4330127019),
pt(-0.0915063509,2.0245190528),
pt(0.2500000000,1.4330127019),
pt(-0.0915063509,0.8415063509),
pt(0.9330127019,0.2500000000),
pt(0.9330127019,-0.9330127019),
pt(0.2500000000,-0.9330127019),
pt(-0.0915063509,-1.5245190528),
pt(-1.1160254038,-0.9330127019),
pt(-2.1405444566,-1.5245190528),
pt(-2.4820508076,-0.9330127019),
pt(0,0),
pt(-1.7990381057,0.2500000000),
pt(-1.1160254038,0.2500000000),
};
hatcorners[0][11] = mid(hatcorners[0][10], hatcorners[0][12]);
hatcorners[1] = hatcorners[0];
for(auto& h: hatcorners[1]) h = MirrorX * h;
reverse(hatcorners[1].begin(), hatcorners[1].end());
hats[0] = {
mt(0.5000000000,-0.8660254038,-1.3660254038, -0.8660254038,-0.5000000000,-0.0000000000, 0.0000000000,0.0000000000,1.0000000000) * MirrorX,
mt(0.5000000000,-0.8660254038,0.6830127019, 0.8660254038,0.5000000000,1.6830127019, 0.0000000000,0.0000000000,1.0000000000),
mt(-1.0000000000,0.0000000000,-2.2320508076, -0.0000000000,-1.0000000000,-1.8660254038, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,-0.8660254038,-4.5310889132, 0.8660254038,-0.5000000000,-1.6160254038, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-3.4150635095, 0.8660254038,0.5000000000,1.6830127019, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,-0.0000000000,-2.0490381057, 0.0000000000,1.0000000000,3.5490381057, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,0.8660254038,0.2500000000, -0.8660254038,0.5000000000,3.2990381057, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-5.4641016151, 0.8660254038,0.5000000000,0.5000000000, 0.0000000000,0.0000000000,1.0000000000),
};
hats[1] = {
mt(1.0000000000,0.0000000000,0.0000000000, 0.0000000000,1.0000000000,0.0000000000, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,0.8660254038,-0.8660254038, -0.8660254038,-0.5000000000,7.0980762114, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,0.8660254038,-5.8971143170, -0.8660254038,0.5000000000,4.4820508076, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,-0.0000000000,-6.1471143170, 0.0000000000,1.0000000000,-1.1830127019, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,-0.8660254038,-4.5310889132, 0.8660254038,-0.5000000000,-3.9820508076, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-9.5621778265, 0.8660254038,0.5000000000,-6.5980762114, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,-0.0000000000,-14.3432667397, 0.0000000000,1.0000000000,-3.5490381057, 0.0000000000,0.0000000000,1.0000000000),
};
hattype = {7, 8, 8, 8, 8, 8, 8};
ld q7 = 1, q8 = 0;
ld val;
for(int a=0; a<100; a++) {
ld nq7 = q7 + q8;
ld nq8 = q7 * 5 + q8 * 6;
println(hlog, hr::format("%.20f", val = (nq7 + nq8) / (q7 + q8)));
q7 = nq7; q8 = nq8;
}
val = sqrt(val);
println(hlog, "root: ", hr::format("%.20f", val));
for(int a=-50; a<50; a++)
for(int b=1; b<50; b++)
for(int c=-50; c<50; c++)
for(int d=1; d<50; d++) {
ld err = abs(a*1./b + c * sqrt(1./d) - val);
if(err < 1e-6)
println(hlog, tie(a,b,c,d), " : ", err);
}
val = (3 + sqrt(5)) / 2; // scaling each axis
sca = Id; sca[0][0] = sca[1][1] = val;
hats[2] = {
mt(1.0000000000,0.0000000000,0.0000000000, 0.0000000000,1.0000000000,0.0000000000, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,0.8660254038,1.1830127025, -0.8660254038,-0.5000000000,15.3791651251, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,0.8660254038,-12.0442286339, -0.8660254038,0.5000000000,10.3971143173, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-14.3432667399, 0.0000000000,1.0000000000,-3.5490381057, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,-0.8660254038,-12.7272413356, 0.8660254038,-0.5000000000,-13.4461524228, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-25.9544826718, 0.8660254038,0.5000000000,-18.4282032304, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-36.8826859024, 0.0000000000,1.0000000000,-9.4641016152, 0.0000000000,0.0000000000,1.0000000000),
};
hats[3] = {
mt(1.0000000000,0.0000000000,0.0000000000, 0.0000000000,1.0000000000,0.0000000000, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,0.8660254038,7.3301270200, -0.8660254038,-0.5000000000,37.8564064623, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,0.8660254038,-28.4365334803, -0.8660254038,0.5000000000,26.9592921447, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-36.8826859027, 0.0000000000,1.0000000000,-9.4641016152, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,-0.8660254038,-33.2176223915, 0.8660254038,-0.5000000000,-39.4724318658, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-68.9842828915, 0.8660254038,0.5000000000,-50.3695461828, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-96.3047909683, 0.0000000000,1.0000000000,-24.8432667403, 0.0000000000,0.0000000000,1.0000000000),
};
hats[4] = {
mt(1.0000000000,0.0000000000,0.0000000000, 0.0000000000,1.0000000000,0.0000000000, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,0.8660254038,23.7224318656, -0.8660254038,-0.5000000000,97.0070415601, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,0.8660254038,-71.4663337016, -0.8660254038,0.5000000000,70.7307621167, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-96.3047909682, 0.0000000000,1.0000000000,-24.8432667399, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,-0.8660254038,-86.4926131352, 0.8660254038,-0.5000000000,-108.0871685769, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-181.6813787030, 0.8660254038,0.5000000000,-134.3634480195, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-252.0316870025, 0.0000000000,1.0000000000,-65.0656986057, 0.0000000000,0.0000000000,1.0000000000),
};
hats[5] = {
mt(1.0000000000,0.0000000000,0.0000000000, 0.0000000000,1.0000000000,0.0000000000, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,0.8660254038,66.7522320948, -0.8660254038,-0.5000000000,251.9817055201, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,0.8660254038,-184.1634295166, -0.8660254038,0.5000000000,185.4829942043, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-252.0316870019, 0.0000000000,1.0000000000,-65.0656986045, 0.0000000000,0.0000000000,1.0000000000),
mt(-0.5000000000,-0.8660254038,-225.8272043260, 0.8660254038,-0.5000000000,-287.9050992716, 0.0000000000,0.0000000000,1.0000000000),
mt(0.5000000000,-0.8660254038,-476.7428659331, 0.8660254038,0.5000000000,-354.4038105811, 0.0000000000,0.0000000000,1.0000000000),
mt(1.0000000000,0.0000000000,-659.7902700392, 0.0000000000,1.0000000000,-170.3538290768, 0.0000000000,0.0000000000,1.0000000000),
};
hats[6] = hats[5];
auto acs = inverse(sca);
println(hlog, "shifts:");
indenter ind(2);
for(int i=0; i<7; i++) {
transmatrix S = gpushxto0(hats[1][i] * C0) * hats[1][i];
// println(hlog, "S = ", kz(S));
transmatrix S0 = inverse(S);
// transmatrix S1 = S;
auto& t = hats[6][i];
auto& t3 = hats[5][i];
auto& t2 = hats[4][i];
auto& t1 = hats[3][i];
hyperpoint fix2 = t2 * C0 - sca * t1 * C0;
hyperpoint cfix3 = acs * fix2;
hyperpoint rfix3 = t3 * C0 - sca * t2 * C0;
t = sca * t * acs * acs * rgpushxto0(rfix3) * sca;
println(hlog, kz(rfix3-cfix3), " from ", fix2, " .. ", S0 * cfix3 - acs * fix2);
// t = t * rgpushxto0(sca * (t3 * C0 - bt3 * C0));
// t = t *
}
hatid["R0A000L0.000"] = -1;
int nextid = 8;
hatid["R0A011L6.147"] = hatid["R0A014L14.343"] = nextid++;
hatid["R0A016L8.196"] = hatid["R0A015L22.539"] = nextid++;
hatid["R0A016L8.196"] = hatid["R0A015L22.539"] = nextid++;
hatid["R0A191L6.147"] = hatid["R0A194L14.343"] = nextid++;
hatid["R0A196L8.196"] = hatid["R0A195L22.539"] = nextid++;
hatid["R1A023L6.903"] = hatid["R1A019L15.060"] = nextid++;
hatid["R1A126L5.555"] = hatid["R1A131L15.741"] = nextid++;
hatid["R1A185L7.579"] = hatid["R1A191L21.879"] = nextid++;
hatid["R1A238L3.558"] = hatid["R1A232L11.654"] = nextid++;
hatid["R1A327L4.885"] = hatid["R1A320L10.974"] = nextid++;
hatid["R2A037L6.054"] = hatid["R2A025L14.053"] = nextid++;
hatid["R2A092L2.046"] = hatid["R2A096L3.188"] = nextid++;
hatid["R2A138L8.858"] = hatid["R2A145L25.101"] = nextid++;
hatid["R2A221L4.953"] = hatid["R2A226L12.883"] = nextid++;
hatid["R2A300L2.571"] = hatid["R2A279L2.571"] = nextid++;
hatid["R3A226L7.005"] = hatid["R3A233L16.845"] = nextid++;
hatid["R4A000L5.143"] = hatid["R4A339L10.197"] = nextid++;
hatid["R4A097L4.093"] = hatid["R4A085L4.171"] = nextid++;
hatid["R4A152L9.906"] = hatid["R4A156L21.728"] = nextid++;
hatid["R4A198L11.809"] = hatid["R4A205L27.793"] = nextid++;
hatid["R4A281L4.171"] = hatid["R4A286L6.625"] = nextid++;
hatid["R5A087L5.006"] = hatid["R5A080L5.503"] = nextid++;
hatid["R5A143L7.731"] = hatid["R5A139L13.041"] = nextid++;
hatid["R5A246L6.309"] = hatid["R5A251L9.388"] = nextid++;
hatid["R5A305L6.626"] = hatid["R5A311L15.426"] = nextid++;
hatid["R5A358L8.119"] = hatid["R5A352L19.349"] = nextid++;
println(hlog, "nextid = ", nextid);
};
void draw_cross(hyperpoint h) {
transmatrix T = rgpushxto0(h);
shiftmatrix sId = shiftless(Id);
for(int i=0; i<12; i++)
queueline(sId * T * C0, sId * T * xspinpush0(30._deg * i, 0.1), 0xFFFFFFFF);
}
void draw_shape(transmatrix T, vector<hyperpoint> sh, color_t lc, color_t fc) {
for(hyperpoint h: sh) curvepoint(h);
curvepoint(sh[0]);
queuecurve(shiftless(Id) * T, lc, fc, PPR::LINE);
}
/*
void draw_superhat(transmatrix T, const vector<transmatrix>& ms, int q, color_t lc, color_t fc) {
for(auto& m: ms)
draw_shape(T * m, hatcorners, lc, fc);
}
*/
hyperpoint sh;
color_t coltables[8] = { 0xFF000080, 0x00FF0080, 0x0000FF80, 0xFFFF0080, 0xFF00FF80, 0x00FFFF80, 0xFFFFFF80, 0x4080C080 };
vector<int> curlabel;
ld ldist = 9999;
hyperpoint hfound, hfound1;
int connection_mode = 0;
int found_pairs, found_pairs_swap;
using pthash = int;
pthash makehash(hyperpoint h) {
return int(floor(h[0] * 10 + .31)) + int(floor(h[1] * 10 + .31)) * 10000;
}
map<pair<pthash, pthash>, vector<int> > seen_edges;
string name(int x) { return s0 + char('A' + x); }
string matcode(transmatrix T) {
vector<ld> res(3);
hyperpoint h = kz(T * C0);
transmatrix S = gpushxto0(T * C0) * T;
ld alpha = atan2(S * xpush0(1)) / degree;
int ialpha = gmod(floor(alpha + .5), 360);
int hangle = gmod(floor(atan2(h) / degree + .3), 360);
h[2] = ialpha/60;
swap(h[1], h[2]); swap(h[0], h[1]);
// return lalign(0, h);
return hr::format("R%dA%03dL%.3f", ialpha/60, hangle, hypot_d(2, h));
}
int ghatid(string s) {
if(hatid.count(s)) return hatid[s];
return -999;
}
void edge_connect(vector<int> l1, vector<int> l2) {
transmatrix T1 = Id;
transmatrix T2 = Id;
transmatrix W = Id;
int idx = 0;
for(int i=toplev; i>0; i--) {
T1 = T1 * hats[i][l1[idx]];
T2 = T2 * hats[i][l2[idx]];
transmatrix W1 = inverse(T1) * T2;
if(!eqmatrix(W1, Id))
println(hlog, "CON L", i, " ", matcode(W1), " :: ", matcode(W), " ", tie(l1[idx], l2[idx]), " REV ", matcode(inverse(W1)));
if(i == 1) println(hlog, "RULE1 {", l1[idx], ", ", l2[idx], ", ", ghatid(matcode(W1)), ", ", ghatid(matcode(W)), ", ", ghatid(matcode(inverse(W1))), "},");
W = W1;
idx++;
}
println(hlog, "CON L0 ", make_pair(make_pair(l1[idx], name(l1[idx+1])), make_pair(l2[idx], name(l2[idx+1]))), " :: ", matcode(W));
println(hlog, "RULE0 {", l1[idx], ", ", l1[idx+1], ", ", l2[idx], ", ", l2[idx+1], ", ", ghatid(matcode(W)), "},");
}
vector<pair<hyperpoint, hyperpoint> > extedges;
void edge_label(vector<int>& lbl, hyperpoint a, hyperpoint b) {
auto ha = makehash(a);
auto hb = makehash(b);
if(connection_mode >= 2) return;
if(connection_mode == 1) {
if(seen_edges.count({ha, hb})) {
extedges.emplace_back(a, b);
/* vid.linewidth *= 10;
queueline(shiftless(Id) * a, shiftless(Id) * b, 0xFF00FF80);
vid.linewidth /= 10;
*/
}
return;
}
if(seen_edges.count({hb, ha})) {
edge_connect(lbl, seen_edges[{hb, ha}]);
edge_connect(seen_edges[{hb, ha}], lbl);
seen_edges.erase({hb, ha});
found_pairs++;
return;
}
if(seen_edges.count({ha, hb})) {
println(hlog, "CON ", lbl, " TO ", seen_edges[{hb, ha}], " SWAP");
seen_edges.erase({ha, hb});
found_pairs_swap++;
return;
}
seen_edges[{ha, hb}] = lbl;
}
void point_label(vector<int>& lbl, hyperpoint h) {
if(lbl == curlabel) draw_cross(h);
ld dist = hdist(unshift(mouseh), h);
if(dist < ldist) {
ldist = dist;
curlabel = lbl;
hfound = h;
println(hlog, "found: ", lbl, " at: ", dist);
}
}
void draw_superhat_label(transmatrix T, const vector<transmatrix>& ms, int q, color_t lc, color_t fc, vector<int>& label) {
for(int i=0; i<q; i++) {
auto& hc = hatcorners[i == 0];
for(int j=0; j<isize(hc); j++) {
label.push_back(i);
label.push_back(j);
point_label(label, T * ms[i] * hc[j]);
edge_label(label, T * ms[i] * hc[j], T * ms[i] * hc[(j+1)%isize(hc)]);
label.pop_back();
label.pop_back();
}
}
for(int i=0; i<q; i++) {
auto& hc = hatcorners[i == 0];
draw_shape(T * ms[i], hc, lc, fc);
}
}
void draw_recurse_label(transmatrix T, int levs, int t, color_t col, vector<int>& label) {
if(levs == 0) {
draw_superhat_label(T, hats[0], t, 0xFFFFFFFF, col, label);
return;
}
if(connection_mode == 2 && levs == toplev-1) {
int eid = 0;
for(auto e: extedges) {
queueline(shiftless(Id) * T * e.first, shiftless(Id) * T * e.second, col);
label.push_back(eid++);
point_label(label, T * e.first);
label.pop_back();
}
return;
}
transmatrix scap = Id;
for(int i=1; i<levs; i++) scap = scap * sca;
scap = inverse(scap);
for(int i=0; i<t-1; i++) {
auto col1 = col;
if(col == 0) col1 = coltables[i];
label.push_back(i);
draw_recurse_label(T * hats[levs][i], levs-1, hattype[i], col1, label);
label.pop_back();
}
}
int next_hattype = 7;
void hatframe() {
if(isize(hatcorners_add) >= 2) draw_shape(Id, hatcorners_add, 0xFF0000FF, 0xFF000080);
transmatrix B = rgpushxto0( unshift(ggmatrix(cwt.at)) * C0 );
vector<int> glabel;
draw_recurse_label(B, toplev, 8, 0, glabel);
if(connection_mode == 0) {
println(hlog, "CON found = ", found_pairs, " swap = ", found_pairs_swap, " not found = ", isize(seen_edges));
// seen_edges.clear(); found_pairs = 0;
connection_mode = 1;
}
else if(connection_mode == 1) {
connection_mode = 2;
toplev++;
}
draw_cross(C0);
}
string writematrix(transmatrix T) {
return hr::format("mt(%.10f,%.10f,%.10f, %.10f,%.10f,%.10f, %.10f,%.10f,%.10f)",
T[0][0],
T[0][1],
T[0][2],
T[1][0],
T[1][1],
T[1][2],
T[2][0],
T[2][1],
T[2][2]
);
}
void hatter() {
cmode = sm::NORMAL | sm::CENTER | sm::PANNING;
clearMessages();
dialog::init();
gamescreen();
shiftpoint s = mapeditor::full_mouseh();
sh = unshift(s);
dialog::add_key_action('a', [] {
hatcorners_add.push_back(sh);
println(hlog, "hatcorners = {");
for(auto h: hatcorners_add) println(hlog, hr::format(" pt(%.10f,%.10f),", h[0], h[1]));
println(hlog, " }");
});
/* dialog::add_key_action('b', [] {
if(hats.empty()) return;
hats.pop_back();
hattype.pop_back();
}); */
dialog::add_key_action('[', [] {
// hyperpoint h = currentmap->get_corner(cwt.at, 0);
// rot = rot * gpushxto0(h);
rot = rot * spin(60._deg);
// rot = rot * rgpushxto0(h);
});
dialog::add_key_action(']', [] {
// hyperpoint h = currentmap->get_corner(cwt.at, 0);
// rot = rot * gpushxto0(h);
rot = MirrorX * rot;
// rot = rot * rgpushxto0(h);
});
dialog::add_key_action('7', [] { next_hattype = 7; });
dialog::add_key_action('8', [] { next_hattype = 8; });
dialog::add_key_action('f', [] { hfound1 = hfound; });
dialog::add_key_action('b', [] {
int id = curlabel[0];
hats[toplev][id] = rgpushxto0(hfound1 - hfound) * hats[toplev][id];
println(hlog, "hats[", toplev, "] = {");
for(auto h: hats[toplev]) println(hlog, " ", writematrix(h), ",");
println(hlog, " }");
});
dialog::add_key_action('q', [] {
exit(0);
});
dialog::add_key_action('g', [] {
ldist = 9999;
});
keyhandler = [] (int sym, int uni) { dialog::handleNavigation(sym, uni); };
}
void enable_hatter() {
init();
mapeditor::snapping = true;
rv_hook(hooks_frame, 100, hatframe);
pushScreen(hatter);
}
auto hathook = arg::add3("-hatter", enable_hatter);
}

View File

@ -145,7 +145,7 @@ void listnear_compact(cell *c, ext_nei_rules_t& e, const transmatrix& T, int id,
for(int i=0; i<S7; i++) {
bool ok = false;
transmatrix U = T * currentmap->adj(c, i);
for(auto v: cgi.vertices_only) for(auto w: cgi.vertices_only)
for(auto v: cgi.heptshape->vertices_only) for(auto w: cgi.heptshape->vertices_only)
if(hdist(v, U*w) < 1e-3) ok = true;
if(!ok) continue;
cell *c1 = c->cmove(i);
@ -182,7 +182,7 @@ void listnear_exh(cell *c, ext_nei_rules_t& e, int maxdist) {
int di = dist[ca] + 1;
int odi = origdir[ca];
for(int i=0; i<S7; i++) {
if(odi >= 0 && !cgi.dirs_adjacent[i][odi]) continue;
if(odi >= 0 && cgi.heptshape->dirdist[i][odi] != 1) continue;
cell *c1 = ca->cmove(i);
e.from.push_back(k);
e.dir.push_back(i);
@ -268,6 +268,8 @@ void add_candidate(cell *c) {
candidates_list.push_back(c);
}
bool single_origin = false;
/** the main function */
void test_canonical(string fname) {
stop_game();
@ -283,7 +285,8 @@ void test_canonical(string fname) {
if(optimize_344 && geometry == gSpace344) qc = 16;
/* we start from a 'center' in every get_id-type */
if(geometry == gSpace535) {
if(single_origin) c0 = {cwt.at};
else if(geometry == gSpace535) {
c0.resize(qc, cwt.at);
}
else {
@ -501,6 +504,7 @@ void test_canonical(string fname) {
auto& fp = currfp;
hwrite_fpattern(ss, fp);
qc = isize(c0);
vector<int> root(qc, 0);
for(int i=0; i<qc; i++) root[i] = id_of[generate_ext_nei(c0[i])];
println(hlog, "root = ", root);

594
devmods/knuth-bendix.cpp Normal file
View File

@ -0,0 +1,594 @@
#include "../hyper.h"
#include <fstream>
#include <semaphore.h>
namespace hr {
namespace rulegen {
bool set_general(const string& s);
}
struct symbol {
unsigned char sid;
unsigned char eid;
bool operator < (const symbol s1) const { return (int16_t&) (*this) < (int16_t&) s1; }
bool operator == (const symbol s1) const { return (int16_t&) (*this) == (int16_t&) s1; }
bool operator != (const symbol s1) const { return (int16_t&) (*this) != (int16_t&) s1; }
};
using seq = vector<symbol>;
void block(symbol& s) {
s.sid ^= 128;
}
void unblock(symbol& s) {
s.sid ^= 128;
}
bool is_blocked(symbol& s) {
return s.sid & 128;
}
void print(hstream& hs, symbol s) {
print(hs, "[", int(s.sid), ":", int(s.eid), "]");
}
bool reversed;
bool lexless(const seq& a, const seq& b) {
int al = isize(a);
int bl = isize(b);
if(al != bl) return al < bl;
if(reversed) {
for(int i=al-1; i>=0; i--) if(a[i].eid < 120 && a[i] != b[i]) return a[i] < b[i];
return a.back() < b.back();
}
else {
return a < b;
}
}
struct lexless_comparator {
bool operator()(const seq& a, const seq& b) const { return lexless(a, b); }
};
map<seq, seq, lexless_comparator> rules;
seq sub(const seq& s, int a, int l) {
seq result;
for(int i=0; i<l; i++) result.push_back(s[a+i]);
return result;
}
seq cat(const seq& a, const seq& b) {
seq result;
for(auto e: a) result.push_back(e);
for(auto e: b) result.push_back(e);
return result;
}
void catto(seq& a, const seq& b) {
a.reserve(a.size() + b.size());
for(auto e: b) a.push_back(e);
}
void catto_sub(seq& a, const seq& b, int pos, int len) {
a.reserve(a.size() + len);
for(int i=0; i<len; i++) a.push_back(b[pos+i]);
}
int max_rule_length;
set<pair<seq, seq>> rules_checked;
queue<pair<seq, seq>> rulequeue;
void enqueue_rule(seq l, seq r) {
rulequeue.emplace(l, r);
}
cellwalker trace(cellwalker cw, const seq& sq, bool debug) {
for(auto sym: sq) {
if(shvid(cw.at) != sym.sid) println(hlog, "error: wrong type");
if(debug) println(hlog, "at: ", cw);
cw += sym.eid;
cw += wstep;
cw -= cw.spin % arb::current.shapes[shvid(cw.at)].cycle_length;
}
return cw;
}
cell *get_sample(int sid) {
celllister cl(currentmap->gamestart(), 20, 100000, nullptr);
for(cell *c: cl.lst) if(shvid(c) == sid) return c;
println(hlog, "sample not found of ", sid);
exit(1);
}
string verify_rule(const pair<seq, seq>& rule, bool debug = false) {
cell *cstart = get_sample(rule.first[0].sid);
cellwalker cw(cstart);
cellwalker cw1 = trace(cw, rule.first, debug);
cellwalker cw2 = trace(cw, rule.second, debug);
return cw1 == cw2 ? "OK" : lalign(0, "FAIL ", cw1, " VS ", cw2);
}
int add_rule(seq l, seq r) {
indenter ind(2);
if(l == r) return 0;
if(lexless(l, r)) swap(l, r);
again:
if(!rules.count(l)) {
// println(hlog, "rule added: ", l, " -> ", r, " verify: ", verify_rule({l, r}));
rules[l] = r;
return 1;
}
else if(rules[l] == r) return 0;
else if(lexless(r, rules[l])) {
l = rules[l];
goto again;
}
else {
// println(hlog, "rule simplified: ", l, " -> ", r);
auto x = rules[l];
x = r;
l = x;
goto again;
}
}
symbol gen_symbol(int sid, int eid) {
symbol sym;
sym.sid = sid;
sym.eid = eid;
return sym;
}
bool include_rotations = false;
void prepare_rules() {
auto& ac = arb::current;
int N = isize(ac.shapes);
/* move and back and move */
if(!include_rotations) for(int i=0; i<N; i++) {
auto& sh = ac.shapes[i];
int K = sh.size();
for(int k=0; k<K; k++)
for(int l=0; l<K; l++) {
seq sq, sq1;
sq.push_back(gen_symbol(i, k));
auto con = sh.connections[k % sh.cycle_length];
auto& sh1 = ac.shapes[con.sid];
con.eid %= sh1.cycle_length;
sq.push_back(gen_symbol(con.sid, con.eid));
sq.push_back(gen_symbol(i, l));
int k1 = k / sh.cycle_length * sh.cycle_length;
// if(k1)
sq1.push_back(gen_symbol(i, (k1 + l) % K));
enqueue_rule(sq, sq1);
}
}
/* move and back -> nothing or rotate */
if(include_rotations) for(int i=0; i<N; i++) {
auto& sh = ac.shapes[i];
int K = sh.size();
for(int k=0; k<K; k++) {
seq sq, sq1;
sq.push_back(gen_symbol(i, k));
auto con = sh.connections[k % sh.cycle_length];
auto& sh1 = ac.shapes[con.sid];
con.eid %= sh1.cycle_length;
sq.push_back(gen_symbol(con.sid, con.eid));
int k1 = k / sh.cycle_length * sh.cycle_length;
if(k1) sq1.push_back(gen_symbol(i, 120 + k1));
if(k1) sq1.push_back(gen_symbol(255, 255));
if(lexless(sq, sq1)) swap(sq, sq1);
enqueue_rule(sq, sq1);
}
}
/* rotate + move -> move */
if(include_rotations) for(int i=0; i<N; i++) {
auto& sh = ac.shapes[i];
int K = sh.size();
int C = sh.cycle_length;
for(int k=C; k<K; k+=C)
for(int l=0; l<K; l++) {
seq sq, sq1;
sq.push_back(gen_symbol(i, 120+k));
sq.push_back(gen_symbol(255, 255));
sq.push_back(gen_symbol(i, l));
sq1.push_back(gen_symbol(i, (k+l) % K));
if(lexless(sq, sq1)) swap(sq, sq1);
enqueue_rule(sq, sq1);
}
}
/* cycle a vertex */
for(int i=0; i<N; i++) {
auto& sh = ac.shapes[i];
for(int j=0; j<sh.cycle_length; j++) {
int val = sh.vertex_valence[j]; // (j+1) % sh.cycle_length];
int ai = i, aj = j;
seq sq;
// cellwalker cw(get_sample(i), j);
// auto cw0 = cw;
for(int v=0; v<val; v++) {
// println(hlog, "at: ", cw);
/*
cw++;
cw += wstep;
*/
auto& ash = ac.shapes[ai];
aj += 1;
aj %= ash.size();
sq.push_back(gen_symbol(ai, aj));
auto co = ash.connections[aj % ash.cycle_length];
ai = co.sid;
aj = co.eid;
aj %= ac.shapes[ai].cycle_length;
}
// println(hlog, "finish at: ", cw, " from: ", cw0);
aj %= sh.cycle_length;
if(i != ai || j != aj /* || cw != cw0 */) { println(hlog, "bad cycling!"); return; }
enqueue_rule(sq, {});
}
}
for(auto r: rules) println(hlog, r);
}
void final_rules() {
auto& ac = arb::current;
int N = isize(ac.shapes);
for(int i=0; i<N; i++) {
auto& sh = ac.shapes[i];
int K = sh.size();
int C = sh.cycle_length;
for(int k=0; k<K; k++)
for(int l=0; l<K; l+=C) {
seq sq, sq1;
sq.push_back(gen_symbol(i, k));
auto con = sh.connections[k % sh.cycle_length];
auto& sh1 = ac.shapes[con.sid];
con.eid %= sh1.cycle_length;
sq.push_back(gen_symbol(con.sid, con.eid));
sq.push_back(gen_symbol(i, 120 + l));
int k1 = k / sh.cycle_length * sh.cycle_length;
// if(k1)
sq1.push_back(gen_symbol(i, 120 + (k1 + l) % K));
enqueue_rule(sq, sq1);
}
}
}
/* the substring of s starting at pos equals needle */
bool sub_at(const seq& s, int pos, const seq& needle) {
for(int i=0; i<isize(needle); i++)
if(s[i+pos] != needle[i])
return false;
return true;
}
/* the suffix of s1 of length len, and the prefix of s2 of length len, agree */
bool suf_pref_agree(const seq& s1, const seq& s2, int len) {
for(int i=0; i<len; i++)
if(s1[isize(s1)-len+i] != s2[i])
return false;
return true;
}
bool is_reducible(const seq& s, const pair<seq, seq>& r, seq& result) {
int rl = isize(r.first);
int sl = isize(s);
for(int i=0; i<=sl-rl; i++)
if(sub_at(s, i, r.first)) {
result = sub(s, 0, i);
catto(result, r.second);
catto_sub(result, s, i+rl, sl-rl-i);
return true;
}
return false;
}
void find_critical(const pair<seq,seq>& p, const pair<seq,seq>& q) {
int pl = isize(p.first);
int ql = isize(q.first);
for(int i=1; i<pl && i < ql; i++)
if(suf_pref_agree(p.first, q.first, i)) {
seq nleft = sub(p.first, 0, pl-i);
catto(nleft, q.second);
seq nright = p.second;
catto_sub(nright, q.first, i, ql-i);
enqueue_rule(nleft, nright);
}
}
void handle_rule(const pair<seq, seq>& nr) {
auto& lh = nr.first;
auto& rh = nr.second;
for(auto& r: rules) {
seq res;
if(is_reducible(lh, r, res)) {
enqueue_rule(res, rh);
return;
}
if(is_reducible(rh, r, res)) {
enqueue_rule(lh, res);
return;
}
}
vector<seq> to_erase;
for(auto& r: rules) {
seq res;
if(is_reducible(r.first, nr, res)) {
to_erase.push_back(r.first);
enqueue_rule(res, r.second);
}
if(is_reducible(rh, r, res)) {
to_erase.push_back(r.first);
enqueue_rule(r.first, res);
}
}
for(auto s: to_erase) rules.erase(s);
for(auto& r: rules) {
find_critical(r, nr);
find_critical(nr, r);
}
rules[nr.first] = nr.second;
}
int kb_result;
double total_time;
int main_loop(int timelimit = 5, int lenlimit = 300) {
clock_t start = clock();
while(!rulequeue.empty()) {
if(clock() > start + timelimit * CLOCKS_PER_SEC) return 1;
auto p = rulequeue.front();
rulequeue.pop();
if(p.first == p.second) continue;
if(lexless(p.first, p.second)) swap(p.first, p.second);
if(rules_checked.count(p)) continue;
rules_checked.insert(p);
int len = p.first.size() + p.second.size();
if(len > max_rule_length) max_rule_length = len;
if(len > lenlimit) return 2;
handle_rule(p);
}
println(hlog, "finished in ", (clock() - start) * 1. / CLOCKS_PER_SEC);
return 0;
}
void test_knuth_bendix() {
rules.clear();
rulequeue = {};
rules_checked.clear();
max_rule_length = 0;
start_game();
prepare_rules();
clock_t total_start = clock();
println(hlog, "total_start = ", total_start * 1. / CLOCKS_PER_SEC);
kb_result = main_loop(10);
println(hlog, "after first phase = ", clock() * 1. / CLOCKS_PER_SEC);
if(kb_result == 0) {
println(hlog, "intermediate rules:");
for(auto s: rules) println(hlog, s.first, " => ", s.second);
final_rules();
kb_result = main_loop(50, 999999);
if(kb_result) kb_result += 2;
}
println(hlog, "after second phase = ", clock() * 1. / CLOCKS_PER_SEC);
total_time = (clock() - total_start) * 1. / CLOCKS_PER_SEC;
}
bool is_end_reducible(const seq& s1) {
for(auto r: rules)
if(isize(s1) >= isize(r.first) && sub(s1, isize(s1)-isize(r.first), isize(r.first)) == r.first)
return true;
return false;
}
int count_tree_states() {
set<seq> all_prefixes;
for(auto r: rules) {
auto left = r.first;
for(int i=0; i<isize(left); i++) {
seq prefix = sub(left, 0, i);
seq s = prefix;
s.emplace_back(gen_symbol(left[i].eid, 120));
if(!is_end_reducible(s))
all_prefixes.emplace(prefix);
}
}
all_prefixes.erase(seq{});
for(auto x: all_prefixes)
println(hlog, x);
return isize(all_prefixes) + isize(arb::current.shapes);
}
bool forked = false;
int max_children = 7;
void test_all(string setname) {
floorshapes_level = 1;
vector<string> filenames;
std::ifstream is("devmods/rulegen-tests/"+setname+".lst");
string s;
while(getline(is, s)) {
while(s != "" && s[0] == ' ') s = s.substr(1);
if(s != "" && s[0] != '#') filenames.push_back(s);
}
println(hlog, "CSV;kbres;Tp;kbrules;tree;maxlen;file");
int children = 0;
sem_t sem;
if(forked) sem_init(&sem, true, 1);
fflush(stdout);
for(const string& s: filenames) {
if(forked) {
int pid;
if(children >= max_children) {
wait(&pid); children--;
}
if((pid = fork())) children++;
else goto doit;
continue;
}
doit:
if(rulegen::set_general(s)) {
if(!arb::in()) try {
arb::convert::convert();
arb::convert::activate();
}
catch(hr_exception& e) {
println(hlog, "CSV; failed to convert ", s);
return;
}
// println(hlog, "will call test_knuth_bendix");
test_knuth_bendix();
// println(hlog, "after test_knuth_bendix");
if(forked) sem_wait(&sem);
println(hlog, "CSV;",kb_result,";", total_time, ";", isize(rules), ";", kb_result == 0 ? count_tree_states() : 0, ";", max_rule_length, ";", s);
if(forked) sem_post(&sem);
fflush(stdout);
}
if(forked) exit(0);
}
while(children) { int pid; wait(&pid); children--; }
if(forked) sem_destroy(&sem);
}
void kb_merge() {
vector<string> filenames;
std::ifstream is("devmods/rulegen-tests/all.lst");
string s;
while(getline(is, s)) {
while(s != "" && s[0] == ' ') s = s.substr(1);
if(s != "" && s[0] != '#') filenames.push_back(s);
}
map<string, string> cas;
if(std::ifstream is = std::ifstream("devmods/rulegen-tests/kbmerge.txt")) {;
while(getline(is, s)) {
int i = 0, j = 0;
for(char c: s) { i++; if(c == ';') j = i; }
string fname = s.substr(j);
if(cas.count(fname) && cas[fname].substr(0,5) != s.substr(0,5)) {
// println(hlog, "repetition:\n", cas[fname], "\n", s);
s = min(s, cas[fname]);
}
cas[fname] = s;
// println(hlog, "assigned to ", fname, ": ", s);
}
}
println(hlog, "CSV;kbres;Tp;kbrules;tree;maxlen;file");
for(auto ss: filenames)
if(!cas.count(ss))
println(hlog, "MISSING: ", ss);
else
println(hlog, cas[ss]);
}
map<cell*, seq> first_seq_last;
map<cell*, seq> first_seq;
map<cell*, int> qty;
void view_kb_tree(const shiftmatrix& V, cellwalker cw, seq s) {
qty[cw.at]++;
if(cw.at == lmouseover) println(hlog, s, " ; ", cw.spin);
for(int i=0; i<cw.at->type; i++) {
seq s1 = s;
s1.emplace_back(gen_symbol(shvid(cw.at), i));
if(is_end_reducible(s1)) continue;
auto cw1 = cw;
cw1 += i;
int is = cw1.spin;
cw1 += wstep;
if(!gmatrix.count(cw1.at)) continue;
transmatrix A = currentmap->adj(cw.at, is);
int eid = shvid(cw1.at);
int clen = arb::current.shapes[eid].cycle_length;
cw1 -= cw1.spin % clen;
// queueline(V * get_corner_position(cw.at, cw.spin, 6), V * A * get_corner_position(cw1.at, cw1.spin, 6), 0xC00000FF);
seq s2 = s1;
s2.emplace_back(gen_symbol(shvid(cw1.at), 120));
if(!is_end_reducible(s2)) { // first_seq_last[cw1.at] == s1) {
if(cw1.at == lmouseover) println(hlog, "is not end_reducible: ", s2);
vid.linewidth *= 3;
queueline(V * C0, V * mid(tC0(A), mid(C0, tC0(A))), 0xFFC0C0FF, 3);
vid.linewidth /= 3;
}
if(!first_seq.count(cw1.at))
first_seq[cw1.at] = s1;
else
first_seq[cw1.at] = min(s1, first_seq[cw1.at]);
view_kb_tree(V*A, cw1, s1);
}
}
void kb_marker() {
qty.clear();
first_seq_last = std::move(first_seq);
first_seq.clear();
view_kb_tree(gmatrix[cwt.at], cellwalker(cwt.at, 0), {});
for(auto p: qty)
queuestr(gmatrix[p.first], .5, its(p.second), 0xFFFFFFFF, 1);
}
void add_kb_view() {
addHook(hooks_markers, 100, kb_marker);
}
int u = arg::add3("-kb", [] {
test_knuth_bendix();
println(hlog, "result: ", kb_result, " rules: ", isize(rules));
println(hlog, "final rules:");
for(auto s: rules) println(hlog, s.first, " => ", s.second);
if(kb_result == 0) println(hlog, "tree states: ", count_tree_states());
})
+ arg::add3("-kb-test-all", [] { arg::shift(); test_all(arg::args()); })
+ arg::add3("-kb-forked", [] { arg::shift(); max_children = arg::argi(); forked = max_children; })
+ arg::add3("-kb-rev", [] { arg::shift(); reversed = arg::argi(); })
+ arg::add3("-kb-view", add_kb_view)
+ arg::add3("-kb-merge", kb_merge);
}

View File

@ -17,37 +17,100 @@ namespace hr {
bool saving_positions;
bool smooth_aim = true;
int next_pos_tick;
using frame = tuple<transmatrix, transmatrix, cell*>;
struct frame {
transmatrix V;
transmatrix lp;
transmatrix msm;
cell *co;
int steps_to_change;
int step_smoothing;
ld stepdist;
ld stepang;
};
vector<frame> saved;
bool trailer_turn(int delta) {
if(saving_positions)
View = cpush(2, -delta/8000.) * cspin(0, 2, (mousex - current_display->xcenter) * delta / -1000000.) * cspin(1, 2, (mousey - current_display->ycenter) * delta / -1000000.) * View;
return true;
}
int collection;
bool recording;
bool keys_on = false;
ld stepdist = 0.02;
ld stepang = 0.01;
EX int step_smoothing = 1;
EX int steps_to_change;
void move_camera1(transmatrix T);
void recall(frame& f = saved.back()) {
View = f.V;
current_display->local_perspective = f.lp;
stretch::mstretch_matrix = f.msm;
centerover = f.co;
steps_to_change = f.steps_to_change;
step_smoothing = f.step_smoothing;
stepdist = f.stepdist;
stepang = f.stepang;
playermoved = false;
}
frame saveframe() {
frame f;
f.V = View;
f.lp = current_display->local_perspective;
f.msm = stretch::mstretch_matrix;
f.co = centerover;
f.steps_to_change = steps_to_change;
f.step_smoothing = step_smoothing;
f.stepdist = stepdist;
f.stepang = stepang;
playermoved = false;
return f;
}
void trailer_frame() {
// if(saving_positions || !isize(saved))
if(!recording && keys_on) queuestr(current_display->xcenter, current_display->ycenter, 0, 16, "+", 0xFFFFFFFF);
if(!recording && keys_on) queuestr(current_display->xcenter/2, current_display->ycenter, 0, 16, "+", 0xFFFFFFFF);
if(!recording && keys_on) queuestr(current_display->xcenter*3/2, current_display->ycenter, 0, 16, "+", 0xFFFFFFFF);
if(!recording && keys_on) queuestr(mousex, mousey, 0, 16, "+", 0xFFFFFFFF);
}
if(saving_positions && ticks > next_pos_tick) {
next_pos_tick += 66;
saved.emplace_back(View, current_display->local_perspective, centerover);
println(hlog, "frames = ", isize(saved));
ld next_stepdist = stepdist;
ld next_stepang = stepang;
void apply_steps_to_change() {
if(steps_to_change) {
stepang = stepang + (next_stepang-stepang) / steps_to_change;
stepdist = stepdist + (next_stepdist-stepdist) / steps_to_change;
steps_to_change--;
}
}
ld stepdist = 0.02;
ld stepang = 0.01;
bool trailer_turn(int delta) {
if(saving_positions) {
collection += delta * 60;
while(collection > 1000) {
apply_steps_to_change();
collection -= 1000;
View = cpush(2, -stepdist) * View;
if(smooth_aim) {
ld dx = (mousex - current_display->xcenter) * stepang / -50.;
ld dy = (mousey - current_display->ycenter) * stepang / -50.;
View = cspin(0, 2, dx) * cspin(1, 2, dy) * View;
}
optimizeview();
saved.emplace_back(saveframe());
if(isize(saved) % 100 == 0)
println(hlog, "frames = ", isize(saved));
}
}
return true;
}
ld spin_distance = 0;
@ -57,17 +120,14 @@ bool fixed_orientation;
transmatrix orientation_to_fix;
EX int step_smoothing = 1;
EX int steps_to_change;
ld next_stepdist = stepdist;
ld next_stepang = stepang;
string videofile;
void move_camera1(transmatrix T) {
saved.emplace_back(View, current_display->local_perspective, centerover);
// println(hlog, "rayfix: saving frame ", isize(saved));
// optimizeview();
// ray::cast();
optimizeview();
saved.emplace_back(saveframe());
if(spinning_around) {
for(int s=0; s<100; s++)
shift_view(ztangent(-spin_distance/100));
@ -100,11 +160,7 @@ bool move_camera(transmatrix T) {
template<class Type> bool move_camera_smoothchange(const Type& T) {
for(int it=0; it<5; it++) {
println(hlog, "steps_to_change = ", steps_to_change, " stepdist = ", stepdist);
if(steps_to_change) {
stepang = stepang + (next_stepang-stepang) / steps_to_change;
stepdist = stepdist + (next_stepdist-stepdist) / steps_to_change;
steps_to_change--;
}
apply_steps_to_change();
move_camera1(T());
}
println(hlog, "frames = ", isize(saved), " distance = ", spin_distance);
@ -173,31 +229,34 @@ void get_b4_distance() {
}
}
void recall(frame& f = saved.back()) {
tie(View, current_display->local_perspective, centerover) = f;
playermoved = false;
}
void load_animation(string fname) {
fhstream f(fname, "r");
int siz;
f.read<int>(siz);
saved.resize(siz);
for(int i=0; i<isize(saved); i++) {
auto& [a, b, d] = saved[i];
hread_raw(f, a);
hread_raw(f, b);
auto& s = saved[i];
hread_raw(f, s.V);
hread_raw(f, s.lp);
int tmp = 0; hread_raw(f, tmp);
if(cryst) {
crystal::coord co;
hread_raw(f, co);
d = crystal::get_heptagon_at(co)->c7;
s.co = crystal::get_heptagon_at(co)->c7;
}
else
if(nil) {
nilv::mvec co;
hread_raw(f, co);
d = nilv::get_heptagon_at(co)->c7;
s.co = nilv::get_heptagon_at(co)->c7;
}
else if(bounded) {
auto ac = currentmap->allcells();
int i;
hread_raw(f, i);
s.co = ac[i];
}
else s.co = cwt.at;
}
println(hlog, "loaded animation of ", isize(saved), " frames");
recall();
@ -212,9 +271,9 @@ EX transmatrix spintox_good(const hyperpoint& H) {
void denan() {
for(int i=1; i<isize(saved)-1; i++) {
auto& [V, b, co] = saved[i];
if(isnan(V[0][0])) {
println(hlog, "nan at ", i, " @ ", co);
auto& s = saved[i];
if(isnan(s.V[0][0])) {
println(hlog, "nan at ", i, " @ ", s.co);
saved[i] = saved[i-1];
}
}
@ -232,27 +291,27 @@ void smoothen() {
for(int a=1; a<3; a++)
for(int i=1; i<isize(saved)-1; i++) if((a^i)&1) {
auto& [V, b, co] = saved[i];
auto& [Vl, bl, col] = saved[i-1];
auto& [Vn, bn, con] = saved[i+1];
forCellCM(c, co);
hyperpoint hl = V * relm(col, co) * inverse(Vl) * C0;
hyperpoint hn = V * relm(con, co) * inverse(Vn) * C0;
auto& s = saved[i];
auto& sl = saved[i-1];
auto& sn = saved[i+1];
forCellCM(c, s.co);
hyperpoint hl = s.V * relm(sl.co, s.co) * inverse(sl.V) * C0;
hyperpoint hn = s.V * relm(sl.co, s.co) * inverse(sn.V) * C0;
hyperpoint hm = mid(hl, hn);
if(isnan(hm[0])) {
println(hlog, "Vl = ", Vl);
println(hlog, "V = ", V);
println(hlog, "Vn = ", Vn);
println(hlog, "cells ", col, co, con);
println(hlog, "crl= ", relm(col, co));
println(hlog, "crm= ", relm(con, co));
println(hlog, "Vl = ", sl.V);
println(hlog, "V = ", s.V);
println(hlog, "Vn = ", sn.V);
println(hlog, "cells ", sl.co, s.co, sn.co);
println(hlog, "crl= ", relm(sl.co, s.co));
println(hlog, "crm= ", relm(sn.co, s.co));
continue;
}
total += hdist0(hm);
V = gpushxto0(hm) * V;
s.V = gpushxto0(hm) * s.V;
auto xhn = gpushxto0(hm) * hn;
transmatrix T = cspin(0, 2, -M_PI/2) * spintox_good(cspin(0, 2, M_PI/2) * xhn) * cspin(0, 2, M_PI/2);
V = T * V;
s.V = T * s.V;
// println(hlog, hn, " -> ", T * xhn);
}
println(hlog, "total = ", total);
@ -316,10 +375,11 @@ void do_recording() {
auto f = [&] {
for(auto& p: saved) {
recall(p);
println(hlog, "rayfix: render ", i);
ticks = i * 1000 / mrec_fps;
if(i >= mrec_first && i < mrec_last) {
string s = format(mrec_file.c_str(), i);
string s = hr::format(mrec_file.c_str(), i);
println(hlog, "recording frame ", i, "/", isize(saved), " to ", s);
shot::take(s);
}
@ -341,6 +401,71 @@ void do_recording() {
recording = false;
}
void show_man_options() {
gamescreen(2);
dialog::init("manual animation");
dialog::addSelItem("stepdist", fts(next_stepdist), 'd');
dialog::add_action([] {
dialog::editNumber(next_stepdist, 0, 1, 0.001, 0.02, "stepdist", "stepdist");
dialog::reaction = [] { set_stepdist(next_stepdist); };
});
dialog::addSelItem("stepang", fts(next_stepang), 'a');
dialog::add_action([] {
dialog::editNumber(next_stepang, 0, 1, 0.001, 0.02, "stepang", "stepang");
dialog::reaction = [] { set_stepang(next_stepang); };
});
dialog::addItem("b4 distance", 'b');
dialog::add_action(get_b4_distance);
dialog::addSelItem("step smoothing", its(step_smoothing), 's');
dialog::add_action([] {
dialog::editNumber(step_smoothing, 1, 30, 1, 1, "step_smoothing", "step_smoothing");
dialog::reaction = [] { steps_to_change = step_smoothing; };
});
dialog::addItem("save path", '[');
dialog::add_action([] {
fhstream f("devmods/manan-record.mar", "w");
f.write<int>(isize(saved));
for(int i=0; i<isize(saved); i++) {
auto& s = saved[i];
hwrite_raw(f, s.V);
hwrite_raw(f, s.lp);
int tmp = 0; hwrite_raw(f, tmp);
if(cryst) {
auto at = crystal::get_coord(s.co->master);
hwrite_raw(f, at);
}
else if(nil) {
auto at = nilv::get_coord(s.co->master);
hwrite_raw(f, at);
}
else if(bounded) {
auto ac = currentmap->allcells();
for(int i=0; i<isize(ac); i++) if(ac[i] == s.co)
hwrite_raw(f, i);
}
}
println(hlog, "saved animation of ", isize(saved), " frames");
});
dialog::addItem("load path", ']');
dialog::add_action([] {
load_animation("devmods/manan-record.mar");
});
dialog::addItem("do record", 'r');
dialog::add_action(do_recording);
dialog::addItem("clear", 'c');
dialog::add_action([] { saved.clear(); });
dialog::display();
}
bool trailer_handleKey(int sym, int uni) {
if(sym == 'f' && (cmode & sm::NORMAL)) {
@ -349,7 +474,7 @@ bool trailer_handleKey(int sym, int uni) {
return true;
}
if(keys_on) {
if(keys_on && (cmode & sm::NORMAL)) {
if(sym == ',') { vid.fov *= 1.1; mouseaim_sensitivity *= 1.1; println(hlog, "fov = ", vid.fov, " sens = ", mouseaim_sensitivity); }
if(sym == '.') { vid.fov /= 1.1; mouseaim_sensitivity /= 1.1; println(hlog, "fov = ", vid.fov, " sens = ", mouseaim_sensitivity); }
@ -388,7 +513,7 @@ bool trailer_handleKey(int sym, int uni) {
if(sym == '1') { set_stepdist(0); return true; }
if(sym == '2') { set_stepdist(0.005); return true; }
if(sym == '3') { set_stepdist(0.02); return true; }
if(sym == '4') { set_stepang(0); return true; }
if(sym == '5') { set_stepang(0); return true; }
if(sym == '6') { set_stepang(0.001); return true; }
if(sym == '7') { set_stepang(0.003); return true; }
@ -396,11 +521,6 @@ bool trailer_handleKey(int sym, int uni) {
if(sym == '9') { set_stepang(0.03); return true; }
if(sym == '0') { set_stepang(0.1); return true; }
if(sym == 'p') { get_b4_distance(); return true; }
if(sym == 'm') { step_smoothing = 1; println(hlog, "step_smoothing = ", step_smoothing); return true; }
if(sym == 'n') { step_smoothing = 15; println(hlog, "step_smoothing = ", step_smoothing); return true; }
if(sym == 'o') {
println(hlog, "spin_distance = ", spin_distance, " reset to 0, i to spin");
spin_distance = 0;
@ -429,6 +549,7 @@ bool trailer_handleKey(int sym, int uni) {
saving_positions = !saving_positions;
next_pos_tick = ticks;
println(hlog, "saving_positions = ", saving_positions);
mouseaim_sensitivity = 0;
return true;
}
@ -446,38 +567,13 @@ bool trailer_handleKey(int sym, int uni) {
return true;
}
if(sym == '[') {
fhstream f("devmods/manan-record.mar", "w");
f.write<int>(isize(saved));
for(int i=0; i<isize(saved); i++) {
auto& [a, b, d] = saved[i];
hwrite_raw(f, a);
hwrite_raw(f, b);
int tmp = 0; hwrite_raw(f, tmp);
if(cryst) {
auto at = crystal::get_coord(d->master);
hwrite_raw(f, at);
}
else if(nil) {
auto at = nilv::get_coord(d->master);
hwrite_raw(f, at);
}
}
println(hlog, "saved animation of ", isize(saved), " frames");
}
if(sym == ']') load_animation("devmods/manan-record.mar");
if(sym == 'r') {
do_recording();
return true;
}
if(sym == 'r') pushScreen(show_man_options);
}
return false;
}
int readArgs() {
int ma_readArgs() {
using namespace arg;
if(0) ;
@ -521,18 +617,17 @@ int readArgs() {
shift(); mrec_first_opt = pos;
while(args() != cap) shift();
mrec_last_opt = pos;
shift();
}
else return 1;
return 0;
}
auto hook =
auto mahook =
addHook(hooks_handleKey, 100, trailer_handleKey)
+ addHook(hooks_drawmap, 100, trailer_frame)
+ addHook(shmup::hooks_turn, 100, trailer_turn)
+ addHook(hooks_args, 100, readArgs)
+ addHook(hooks_args, 100, ma_readArgs)
+ 0;
}

View File

@ -4,17 +4,29 @@
namespace hr {
string crop(string s) {
string res;
for(char c: s) if(c == '-') res = ""; else res += c;
return res;
}
string cropios(string s) {
string res;
for(char c: s) if(c == '.') return res; else res += c;
return res;
}
auto aec =
arg::add3("-music-ios", [] {
for(int i=0; i<landtypes; i++)
if(musfname[i] == "") printf(" NULL,\n");
else printf(" @\"%s\", // %2d : %s\n", musfname[i].c_str(), i, dnameof(eLand(i)).c_str());
else printf(" @\"%s\", // %2d : %s\n", cropios(musfname[i]).c_str(), i, dnameof(eLand(i)).c_str());
})
+ arg::add3("-music-android", [] {
for(int i=0; i<landtypes; i++)
if(musfname[i] != "") {
string s = musfname[i].substr(4, isize(musfname[i])-8);
printf(" if(curland == %2d) id = R.raw.%s; // %s\n", i, s.c_str(), dnameof(eLand(i)).c_str());
printf(" if(curland == %2d) id = R.raw.%s; // %s\n", i, crop(s).c_str(), dnameof(eLand(i)).c_str());
}
})
+ arg::add3("-music-license", [] {

73
devmods/reps/counter.cpp Normal file
View File

@ -0,0 +1,73 @@
// a float-like type to count operations
namespace reps {
std::map<std::string, int> counts;
#define C(x) {}
std::array<int, 16> cbc;
constexpr int cbcAdd = 1;
constexpr int cbcMul = 2;
constexpr int cbcDiv = 3;
constexpr int cbcTrig = 4;
struct countfloat {
ld x;
countfloat() {}
explicit countfloat(ld _x) : x(_x) {}
explicit operator ld() { return x; }
operator bool() { return x != 0; }
countfloat operator +(countfloat a) const { C("plus"); cbc[1]++; return countfloat(x + a.x); }
countfloat operator -(countfloat a) const { C("plus"); cbc[1]++; return countfloat(x + a.x); }
countfloat operator -() const { return countfloat(-x); }
countfloat operator +() const { return countfloat(+x); }
countfloat operator *(countfloat a) const { C("mul"); cbc[2]++; return countfloat(x * a.x); }
countfloat operator /(countfloat a) const { C("div"); cbc[3]++; return countfloat(x / a.x); }
bool operator <(countfloat a) const { return x < a.x; }
bool operator >(countfloat a) const { return x > a.x; }
bool operator <=(countfloat a) const { return x <= a.x; }
bool operator >=(countfloat a) const { return x >= a.x; }
countfloat& operator +=(countfloat a) { C("plus"); cbc[1]++; x += a.x; return self; }
countfloat& operator -=(countfloat a) { C("plus"); cbc[1]++; x -= a.x; return self; }
countfloat& operator *=(countfloat a) { C("mul"); cbc[2]++; x *= a.x; return self; }
countfloat& operator /=(countfloat a) { C("mul"); cbc[2]++; x /= a.x; return self; }
countfloat& operator *=(int a) { if(a != 1 && a != -1) C("mul"+hr::its(a)); x *= a; return self; }
countfloat& operator /=(int a) { if(a != 1 && a != -1) C("div"+hr::its(a)); x /= a; return self; }
friend countfloat sin(countfloat a) { cbc[4]++; C("sin"); return countfloat(sin(a.x)); }
friend countfloat cos(countfloat a) { cbc[4]++; C("cos"); return countfloat(cos(a.x)); }
friend countfloat tan(countfloat a) { cbc[4]++; C("tan"); return countfloat(tan(a.x)); }
friend countfloat sinh(countfloat a) { cbc[4]++; C("sinh"); return countfloat(sinh(a.x)); }
friend countfloat cosh(countfloat a) { cbc[4]++; C("cosh"); return countfloat(cosh(a.x)); }
friend countfloat tanh(countfloat a) { cbc[4]++; C("cosh"); return countfloat(tanh(a.x)); }
friend countfloat asinh(countfloat a) { cbc[4]++; C("asinh"); return countfloat(asinh(a.x)); }
friend countfloat acosh(countfloat a) { cbc[4]++; C("acosh"); return countfloat(acosh(a.x)); }
friend countfloat acos(countfloat a) { cbc[4]++; C("acos"); return countfloat(acos(a.x)); }
friend countfloat exp(countfloat a) { cbc[4]++; C("exp"); return countfloat(exp(a.x)); }
friend countfloat log(countfloat a) { cbc[4]++; C("log"); return countfloat(log(a.x)); }
friend countfloat sqrt(countfloat a) { cbc[4]++; C("sqrt"); return countfloat(sqrt(a.x)); }
friend countfloat atan2(countfloat a, countfloat b) { cbc[4]++; C("atan"); return countfloat(atan2(a.x, b.x)); }
friend countfloat pow(countfloat a, ld b) { cbc[4]++; C("pow" + hr::fts(b)); return countfloat(pow(a.x, b)); }
friend countfloat abs(countfloat a) { return countfloat(abs(a.x)); }
countfloat operator *(int a) const { if(a != 1 && a != -1) C("mul" + hr::its(a)); return countfloat(x * a); }
countfloat operator /(int a) const { if(a != 1 && a != -1) C("div" + hr::its(a)); return countfloat(x / a); }
friend bool isinf(countfloat a) { return isinf(a.x); }
friend bool isnan(countfloat a) { return isnan(a.x); }
};
template<> countfloat get_deg<countfloat> (int deg) { return countfloat( M_PI * deg / 180 ); }
}
namespace hr {
void print(hr::hstream& hs, ::reps::countfloat b) {
print(hs, b.x);
}
}

View File

@ -0,0 +1,330 @@
namespace reps {
TD struct mvector {
array<typename D::Number, D::Dim> values;
typename D::Number& operator [] (int i) { return values[i]; }
const typename D::Number& operator [] (int i) const { return values[i]; }
mvector operator + (const mvector& M) const {
mvector result;
for(int i=0; i<D::Dim; i++) result[i] = self[i] + M[i];
return result;
}
mvector operator - (const mvector& M) const {
mvector result;
for(int i=0; i<D::Dim; i++) result[i] = self[i] - M[i];
return result;
}
mvector operator * (const typename D::Number& x) const {
mvector result;
for(int i=0; i<D::Dim; i++) result[i] = self[i] * x;
return result;
}
mvector operator / (const typename D::Number& x) const {
mvector result;
for(int i=0; i<D::Dim; i++) result[i] = self[i] / x;
return result;
}
mvector operator * (int x) const {
mvector result;
for(int i=0; i<D::Dim; i++) result[i] = self[i] * x;
return result;
}
mvector operator / (int x) const {
mvector result;
for(int i=0; i<D::Dim; i++) result[i] = self[i] / x;
return result;
}
};
TD struct matrix {
array<array<typename D::Number, D::Dim>, D::Dim> values;
array<typename D::Number, D::Dim>& operator [] (int i) { return values[i]; }
const array<typename D::Number, D::Dim>& operator [] (int i) const { return values[i]; }
matrix operator * (const matrix& M) const {
matrix result;
for(int i=0; i<D::Dim; i++)
for(int k=0; k<D::Dim; k++) {
result[i][k] = typename D::Number(0);
for(int j=0; j<D::Dim; j++) result[i][k] += self[i][j] * M[j][k];
}
return result;
}
mvector<D> operator * (const mvector<D>& V) const {
mvector<D> result;
for(int i=0; i<D::Dim; i++) {
result[i] = typename D::Number(0);
for(int j=0; j<D::Dim; j++) result[i] += self[i][j] * V[j];
}
return result;
}
matrix operator * (const typename D::Number& x) const {
matrix result;
for(int i=0; i<D::Dim; i++) for(int j=0; j<D::Dim; j++) result[i][j] = self[i][j] * x;
return result;
}
matrix operator / (const typename D::Number& x) const {
matrix result;
for(int i=0; i<D::Dim; i++) for(int j=0; j<D::Dim; j++) result[i][j] = self[i][j] / x;
return result;
}
matrix operator * (int x) const {
matrix result;
for(int i=0; i<D::Dim; i++) for(int j=0; j<D::Dim; j++) result[i][j] = self[i][j] * x;
return result;
}
matrix operator / (int x) const {
matrix result;
for(int i=0; i<D::Dim; i++) for(int j=0; j<D::Dim; j++) result[i][j] = self[i][j] / x;
return result;
}
};
TD constexpr mvector<D> zero_vector() {
mvector<D> result;
for(int i=0; i<D::Dim; i++) result[i] = typename D::Number(0);
return result;
}
TD constexpr mvector<D> unit_vector(int id) {
mvector<D> result;
for(int i=0; i<D::Dim; i++) result[i] = typename D::Number(0);
result[id] = typename D::Number(1);
return result;
}
TD struct multivector_data {
using Number = typename D::Number;
static constexpr int Dim = 1<<D::Dim;
static constexpr int Flipped = -1;
};
TD using multivector = mvector<multivector_data<D>>;
TD std::string nz(const multivector<D>& a) {
constexpr int mdim = 1<<D::Dim;
using Number = typename D::Number;
hr::shstream str;
for(int i=0; i<mdim; i++) if(abs(a[i]) > Number(1e-10)) {
if(str.s != "") print(str, " ");
if(a[i] > Number(0)) print(str, "+");
print(str, a[i]);
for(int u=0; u<D::Dim; u++) if(i & (1<<u)) print(str, hr::s0 + char('A'+u));
}
if(str.s == "") return "0";
return str.s;
}
TD constexpr multivector<D> unit(const typename D::Number& a) {
auto res = zero_vector<multivector_data<D>>();
res[0] = a;
return res;
}
TD constexpr multivector<D> embed(const mvector<D>& a) {
auto res = zero_vector<multivector_data<D>>();
for(int i=0; i<D::Dim; i++) res[1<<i] = a[i];
return res;
}
TD constexpr mvector<D> unembed(const multivector<D>& a) {
mvector<D> res;
for(int i=0; i<D::Dim; i++) res[i] = a[1<<i];
return res;
}
/* for clarity */
using mvindex = int;
using signtype = int;
/* mvindex decimal 10 (binary 1010) corresponds to unit_vector(1) * unit_vector(3) */
TD constexpr signtype conj_sign(mvindex mvid) {
int b = __builtin_popcount(mvid);
b = b * (b+1) / 2;
return (b&1) ? -1 : 1;
}
TD constexpr signtype tra_sign(mvindex mvid) {
int b = __builtin_popcount(mvid);
b = b * (b-1) / 2;
return (b&1) ? -1 : 1;
}
TD constexpr signtype mul_sign(mvindex a, mvindex b) {
int flips = 0;
for(int i=0; i<D::Dim; i++) if(b & (1<<i)) {
// we will need to swap it with that many 1-bits of a
flips += __builtin_popcount(a & ((1<<i)-1));
if((i == D::Flipped) && (a & (1<<i))) flips++;
}
return (flips&1) ? -1 : 1;
}
TD struct all {
static constexpr bool check(mvindex a) { return true; }
static constexpr bool isflat(mvindex a) { return false; }
};
TD struct even {
static constexpr bool check(mvindex a) { return __builtin_popcount(a) % 2 == 0; }
static constexpr bool isflat(mvindex a) { return false; }
};
TD struct flat_even {
static constexpr bool check(mvindex a) { return __builtin_popcount(a) % 2 == 0; }
static constexpr bool isflat(mvindex a) { return nm == nmFlatten && a == 0; }
};
TD struct odd {
static constexpr bool check(mvindex a) { return __builtin_popcount(a) % 2 == 1; }
static constexpr bool isflat(mvindex a) { return false; }
};
TD struct units {
static constexpr bool check(mvindex a) { return a == 0; }
static constexpr bool isflat(mvindex a) { return false; }
};
TD struct rotational {
static constexpr bool check(mvindex a) { return __builtin_popcount(a) % 2 == 0 && a < (1<<(D::Dim-1)); }
static constexpr bool isflat(mvindex a) { return false; }
};
TD struct underling {
static constexpr bool check(mvindex a) { return __builtin_popcount(a) == 1; }
static constexpr bool isflat(mvindex a) { return false; }
};
TD struct flat_underling {
static constexpr bool check(mvindex a) { return __builtin_popcount(a) == 1; }
static constexpr bool isflat(mvindex a) { return nm == nmFlatten && a == 1<<(D::Dim-1); }
};
TD struct poincare {
static constexpr bool check(mvindex a) { return __builtin_popcount(a ^ (1<<(D::Dim-1))) == 1; }
static constexpr bool isflat(mvindex a) { return false; }
};
TD multivector<D> multimul(const multivector<D>& a, const multivector<D>& b) {
constexpr int mdim = 1<<D::Dim;
auto res = zero_vector<multivector_data<D>>();
for(mvindex i=0; i<mdim; i++)
for(mvindex j=0; j<mdim; j++) {
res[i^j] += a[i] * b[j] * mul_sign<D>(i, j);
}
return res;
}
template<class A, class B, class C, class D>
multivector<D> chkmul(const multivector<D>& a, const multivector<D>& b) {
constexpr int mdim = 1<<D::Dim;
auto res = zero_vector<multivector_data<D>>();
/* we initialize with 0s and then add stuff, so one add per component is not necessary */
for(mvindex i=0; i<mdim; i++) if(C::check(i)) cbc[cbcAdd]--;
for(mvindex i=0; i<mdim; i++) if(A::check(i))
for(mvindex j=0; j<mdim; j++) if(B::check(j) && C::check(i^j)) {
if(A::isflat(i))
res[i^j] += b[j] * mul_sign<D>(i, j);
else if(B::isflat(j))
res[i^j] += a[i] * mul_sign<D>(i, j);
else
res[i^j] += a[i] * b[j] * mul_sign<D>(i, j);
}
return res;
}
TD multivector<D> conjugate(const multivector<D>& a) {
constexpr int mdim = 1<<D::Dim;
auto res = a;
for(int i=0; i<mdim; i++) res[i] *= conj_sign<D>(i);
return res;
}
TD multivector<D> transpose(const multivector<D>& a) {
constexpr int mdim = 1<<D::Dim;
auto res = a;
for(int i=0; i<mdim; i++) res[i] *= tra_sign<D>(i);
return res;
}
template<class C, class D> multivector<D> apply_nm(multivector<D> a);
TD using poincare_rotation = std::pair<multivector<D>, multivector<D>>;
/** decompose o into the poincare part and the rotational component */
TD poincare_rotation<D> despin2(const multivector<D>& a) {
auto p = a;
for(int i=(1<<(D::Dim-1)); i<(1<<(D::Dim)); i++) p[i] = typename D::Number(0);
p = p * pow(chkmul<rotational<D>,rotational<D>,units<D>>(p, conjugate(p))[0], -0.5);
auto p1 = chkmul<even<D>,rotational<D>,poincare<D>>(a, conjugate(p));
return {apply_nm<poincare<D>, D>(p1), p};
}
/** remove the rotational component of a, leaving only the poincare part */
TD multivector<D> despin(const multivector<D>& a) {
auto p = a;
for(int i=(1<<(D::Dim-1)); i<(1<<(D::Dim)); i++) p[i] = typename D::Number(0);
auto p1 = chkmul<even<D>,rotational<D>,poincare<D>>(a, conjugate(p));
if(nm == nmInvariant) return p1 * pow(chkmul<rotational<D>,rotational<D>,units<D>>(p, conjugate(p))[0], -0.5);
return apply_nm<poincare<D>, D>(p1);
}
TD std::string nzv(const mvector<D>& a) { return "vector(" + nz(embed(a)) + ")"; }
TD std::string nzv(const matrix<D>& a) { return "<matrix>"; }
template<class C, class D>
typename D::Number sqnorm(multivector<D> a) {
using N = typename D::Number;
auto res = chkmul<C, C, units<D>>(a, conjugate(a))[0];
if(res <= N(0) || isinf(res) || isnan(res)) res = N(1);
return res;
}
TD typename D::Number sqnorm(mvector<D> a) {
using N = typename D::Number;
N res(0);
for(int i=0; i<D::Dim; i++) res += a[i] * a[i] * (i == D::Flipped ? -1:1);
if(D::Flipped != -1) res = -res;
if(nm ==nmWeak && (res <= N(0) || isinf(res) || isnan(res))) res = N(1);
return res;
}
/** if nm is set to nmFlatten or nmForced or nmBinary, apply the requested operation */
template<class C, class D> multivector<D> flatten(multivector<D> a) {
using N = typename D::Number;
auto divby = a[0]; a[0] = N(1);
for(int i=1; i<(1<<D::Dim); i++) if(C::check(i)) a[i] /= divby;
return a;
}
template<class C, class D>
multivector<D> apply_nm(multivector<D> a) {
if(nm == nmFlatten) return flatten<C>(a);
if(nm == nmForced || nm == nmWeak) return a * pow(sqnorm<C,D>(a), -0.5);
if(nm == nmBinary) { while(a[0] >= 2) { a = a / 2; } while(a[0] > 0 && a[0] < 0.5) { a = a * 2; } }
return a;
}
TD mvector<D> apply_nm(mvector<D> a) {
if(nm == nmFlatten) { cbc[cbcDiv]--; return a / a[D::Dim-1]; }
if(nm == nmForced || nm == nmWeak) return a * pow(sqnorm<D>(a), -0.5);
if(nm == nmBinary) { while(a[D::Dim-1] >= 2) { a = a / 2; } while(a[D::Dim-1] > 0 && a[D::Dim-1] < 0.5) { a = a * 2; } }
return a;
}
/** get b which is a coordinate of a, but in normalized form. That is, if a is normalized simply return b, otherwise, multiply b appropriately */
template<class C, class D, class E> E get_normalized(multivector<D> a, E b) {
if(nm != nmInvariant && nm != nmForced) return b * pow(sqnorm<C,D>(a), -0.5);
return b;
}
template<class D, class E> E get_normalized(mvector<D> a, E b) {
if(nm != nmInvariant && nm != nmForced) return b * pow(sqnorm<D>(a), -0.5);
return b;
}
}

View File

@ -0,0 +1,182 @@
/** representation based on the halfplane model; assumes Dim=3 */
namespace reps {
template<class F> struct sl2 : public array<F, 4> {
sl2(F a, F b, F c, F d) { self[0] = a; self[1] = b; self[2] = c; self[3] = d; }
sl2 operator * (const sl2& sec) const {
return sl2(
self[0] * sec[0] + self[1] * sec[2],
self[0] * sec[1] + self[1] * sec[3],
self[2] * sec[0] + self[3] * sec[2],
self[2] * sec[1] + self[3] * sec[3]
);
}
std::string print() {
return hr::lalign(0, "[", self[0], ",", self[1], ";", self[2], ",", self[3], "]");
}
};
TD sl2<typename D::Number> split_quaternion_to_sl2(const multivector<D>& h) {
auto h3 = h[0], h2 = h[1 | 2], h1 = h[1 | 4], h0 = h[2 | 4];
return sl2(h3 - h1, h2 + h0, -h2 + h0, h3 + h1);
}
TD multivector<D> sl2_to_split_quaternion(const sl2<typename D::Number>& e) {
auto h0 = (e[1] + e[2]) / 2;
auto h3 = (e[0] + e[3]) / 2;
auto h1 = (e[3] - e[0]) / 2;
auto h2 = (e[1] - e[2]) / 2;
auto res = zero_vector<multivector_data<D>>();
res[0] = h3; res[1 | 2] = h2; res[1 | 4] = h1; res[2 | 4] = h0;
return res;
}
template<class N> using sl2c = sl2<std::complex<N>>;
TD sl2c<typename D::Number> split_biquaternion_to_sl2c(const multivector<D>& h) {
using cn = std::complex<typename D::Number>;
return sl2(cn(h[0]-h[9], h[15]-h[6]), cn(h[3]+h[10], -h[5]-h[12]), cn(h[10]-h[3], h[12]-h[5]), cn(h[0]+h[9], h[6]+h[15]));
}
TD multivector<D> sl2c_to_split_biquaternion(const sl2c<typename D::Number>& e) {
auto res = zero_vector<multivector_data<D>>();
res[0] = +(real(e[0]) + real(e[3])) / 2;
res[3] = +(real(e[1]) - real(e[2])) / 2;
res[5] = -(imag(e[1]) + imag(e[2])) / 2;
res[6] = +(imag(e[3]) - imag(e[0])) / 2;
res[9] = +(real(e[3]) - real(e[0])) / 2;
res[10] = +(real(e[1]) + real(e[2])) / 2;
res[12] = +(imag(e[2]) - imag(e[1])) / 2;
res[15] = +(imag(e[0]) + imag(e[3])) / 2;
return res;
}
TD struct rep_halfplane {
using data = D;
using N = typename D::Number;
using point = std::complex<N>;
using isometry = sl2<N>;
static isometry cspin(int i, int j, N alpha) {
// return split_quaternion_to_sl2( rep_clifford<D>::cspin(i, j, alpha) );
if(i>j) std::swap(i, j), alpha = -alpha; alpha /= 2;
auto ca = cos(alpha), sa = sin(alpha);
return isometry(ca, -sa, sa, ca);
}
static isometry cspin90(int i, int j, N alpha) {
// return split_quaternion_to_sl2( rep_clifford<D>::cspin(i, j, alpha) );
auto ca = sqrt(N(2)), sa = sqrt(N(2));
if(i>j) std::swap(i, j), sa = -sa;
return isometry(ca, -sa, sa, ca);
}
static isometry lorentz(int i, int j, N alpha) {
// return split_quaternion_to_sl2( rep_clifford<D>::lorentz(i, j, alpha) );
if(i>j) std::swap(i, j); alpha /= 2;
if(i == 0) return isometry(exp(-alpha), N(0), N(0), exp(alpha));
if(i == 1) {
auto ca = cosh(alpha), sa = sinh(alpha);
return isometry(ca, sa, sa, ca);
}
throw hr::hr_exception("bad lorentz");
}
static isometry id() { return isometry(N(1),N(0),N(0),N(1)); };
static point center() { return point(N(0), N(1)); };
static point apply(const isometry& T, const point& x) {
return (T[0] * x + T[1] * 1) / (T[2] * x + T[3] * 1);
};
static isometry apply(const isometry& T, const isometry& U) { return T * U; };
static typename rep_clifford<D>::point to_poincare(const point& x) {
auto a = real(x), b = imag(x);
auto tmp = isometry(sqrt(b), a/sqrt(b), N(0), N(1)/sqrt(b));
auto sq = sl2_to_split_quaternion<D>(tmp);
// sq[0] = (sqrt(b) + 1/sqrt(b)) / 2;; sq[1 | 2] = a/sqrt(b)/2; sq[1 | 4] = (1/sqrt(b) - sqrt(b)) / 2; sq[2 | 4] = a/sqrt(b)/2;
sq = despin(sq);
return typename rep_clifford<D>::point({{sq}});
}
static isometry inverse(isometry T) { return isometry(T[3], -T[1], -T[2], T[0]); }
static isometry push(const point& p) { return split_quaternion_to_sl2<D>(to_poincare(p)[0]); }
static N dist0(const point& x) { return rep_clifford<D>::dist0(to_poincare(x)); }
static N angle(const point& x) { return rep_clifford<D>::angle(to_poincare(x)); }
static N get_coord(const point& x, int i) { return rep_clifford<D>::get_coord(to_poincare(x), i); }
// imag may be very small and still important, so do not use the default complex print
static std::string print(const point& x) { return hr::lalign(0, "{real:", real(x), " imag:", imag(x), "}"); }
static std::string print(const isometry& x) { return x.print(); }
};
TD struct rep_halfspace {
using data = D;
using N = typename D::Number;
struct point { std::complex<N> xy; N z; };
using isometry = sl2c<N>;
static isometry cspin(int i, int j, N alpha) {
return split_biquaternion_to_sl2c( rep_clifford<D>::cspin(i, j, alpha) );
}
static isometry cspin90(int i, int j) {
return split_biquaternion_to_sl2c( rep_clifford<D>::cspin90(i, j) );
}
static isometry lorentz(int i, int j, N alpha) {
return split_biquaternion_to_sl2c( rep_clifford<D>::lorentz(i, j, alpha) );
}
static isometry id() { return isometry(N(1),N(0),N(0),N(1)); }
static point center() { return point{ .xy = N(0), .z = N(1) }; }
static point apply(const isometry& T, const point& x) {
auto nom = T[0] * x.xy + T[1] * N(1);
auto nomz= T[0] * x.z;
auto den = T[2] * x.xy + T[3] * N(1);
auto denz= T[2] * x.z;
// D = den + denz * j
auto dnorm = std::norm(den) + std::norm(denz);
using std::conj;
// conj(D) = conj(den) - denz * j
// N / D = (nom + nomz * j) / (den + denz * j) =
// = (nom + nomz * j) * (conj(den) - denz * j) / dnorm
// auto rxy = (nom * conj(den) - nomz * j * denz * j);
// auto rz*j = (-nom * denz * j + nomz * j * conj(den))
// apply the formula: j * a = conj(a) * j
auto rxy = (nom * conj(den) + nomz * conj(denz));
auto rz = (nomz * den - nom * denz); // todo only real part
// println(hlog, "imag of rz = ", imag(rz));
return point { .xy = rxy / dnorm, .z = real(rz) / dnorm };
};
static isometry apply(const isometry& T, const isometry& U) { return T * U; };
static typename rep_clifford<D>::point to_poincare(const point& x) {
auto tmp = isometry(sqrt(x.z), x.xy/sqrt(x.z), N(0), N(1)/sqrt(x.z));
auto sq = sl2c_to_split_biquaternion<D>(tmp);
sq = despin(sq);
return typename rep_clifford<D>::point({{sq}});
}
static isometry inverse(isometry T) { return isometry(T[3], -T[1], -T[2], T[0]); }
static isometry push(const point& p) { return split_biquaternion_to_sl2c<D>(to_poincare(p)[0]); }
static N dist0(const point& x) { return rep_clifford<D>::dist0(to_poincare(x)); }
static N angle(const point& x) { return rep_clifford<D>::angle(to_poincare(x)); }
static N get_coord(const point& x, int i) { return rep_clifford<D>::get_coord(to_poincare(x), i); }
// imag may be very small and still important, so do not use the default complex print
static std::string print(const point& x) { return hr::lalign(0, "{x:", real(x.xy), " y:", imag(x.xy), " z:", x.z, "}"); }
static std::string print(const isometry& x) { return x.print(); }
};
template<class D> using rep_half = typename std::conditional<D::Dim==3, rep_halfplane<D>, rep_halfspace<D>>::type;
}

27
devmods/reps/rep-hr.cpp Normal file
View File

@ -0,0 +1,27 @@
namespace reps {
/* pull the HyperRogue representation; assumes HyperRogue geometry is set correctly, Number = ld, and Dim=3 or 4 */
TD struct rep_hr {
using data = D;
using N = typename D::Number;
using point = hr::hyperpoint;
using isometry = hr::transmatrix;
static constexpr isometry cspin(int i, int j, N alpha) { return hr::cspin(i, j, ld(alpha)); }
static constexpr isometry cspin90(int i, int j) { return hr::cspin90(i, j); }
static constexpr isometry lorentz(int i, int j, N alpha) { return hr::lorentz(i, j, ld(alpha)); }
static isometry id() { return hr::Id; };
static point center() { return D::Dim == 4 ? hr::C03 : hr::C02; };
static point apply(const isometry& T, const point& x) { return T * x; };
static isometry apply(const isometry& T, const isometry& U) { return T * U; };
static ld dist0(const point& x) { return hdist0(x); }
static ld angle(const point& x) { return atan2(x[1], x[0]); }
static ld get_coord(const point& x, int i) { return x[i]; }
static isometry inverse(const isometry& T) { return iso_inverse(T); }
static isometry push(const point& p) { return rgpushxto0(p); }
static std::string print(point p) { return hr::lalign(0, p); }
static std::string print(isometry p) { return hr::lalign(0, p); }
};
}

355
devmods/reps/rep-multi.cpp Normal file
View File

@ -0,0 +1,355 @@
namespace reps {
TD typename D::Number acos_auto(typename D::Number x) {
using N = typename D::Number;
if(hyperbolic) {
if(x < N(1)) return N(0);
return acosh(x);
}
if(sphere) {
if(x > N(1)) return N(0);
return acos(x);
}
throw hr::hr_exception("error");
}
/* use the linear representation, as in HyperRogue, but DO NOT apply nm, for comparison */
TD struct rep_linear_nn {
using data = D;
using point = mvector<data>;
using isometry = matrix<data>;
using N = typename D::Number;
static constexpr isometry id() {
matrix<D> result;
for(int i=0; i<D::Dim; i++)
for(int j=0; j<D::Dim; j++)
result[i][j] = N(i == j);
return result;
};
static constexpr isometry cspin(int i, int j, typename D::Number angle) {
auto res = id();
auto ca = cos(angle), sa = sin(angle);
res[i][i] = ca;
res[j][j] = ca;
res[i][j] = sa;
res[j][i] = -sa;
return res;
};
static constexpr isometry cspin90(int i, int j) {
auto res = id();
res[i][i] = 0;
res[j][j] = 0;
res[i][j] = 1;
res[j][i] = -1;
return res;
};
static constexpr isometry lorentz(int i, int j, typename D::Number angle) {
auto res = id();
auto ca = cosh(angle), sa = sinh(angle);
res[i][i] = ca;
res[j][j] = ca;
res[i][j] = sa;
res[j][i] = sa;
return res;
}
static constexpr point center() { return unit_vector<data>(D::Dim-1); }
static point apply(const isometry& T, const point& x) { return T * x; };
static isometry apply(const isometry& T, const isometry& U) { return T * U; };
static typename D::Number dist0(point x) {
return acos_auto<D> (x[D::Dim-1]);
}
static typename D::Number angle(const point& x) { return atan2(x[1], x[0]); }
static typename D::Number get_coord(point x, int i) { return x[i]; }
static isometry inverse(isometry T) {
for(int i=0; i<D::Dim; i++)
for(int j=0; j<i; j++) std::swap(T[i][j], T[j][i]);
if constexpr(D::Flipped != -1) {
for(int i=0; i<D::Dim-1; i++) T[i][D::Dim-1] = -T[i][D::Dim-1];
for(int i=0; i<D::Dim-1; i++) T[D::Dim-1][i] = -T[D::Dim-1][i];
}
return T;
}
static isometry push(const point& p) {
auto res = id();
// to do: for spherical!
N fac = N(1)/(p[D::Dim-1]+N(1));
for(int i=0; i<D::Dim-1; i++)
for(int j=0; j<D::Dim-1; j++)
res[i][j] += p[i] * p[j] * fac;
for(int d=0; d<D::Dim-1; d++)
res[d][D::Dim-1] = p[d],
res[D::Dim-1][d] = p[d];
res[D::Dim-1][D::Dim-1] = p[D::Dim-1];
return res;
}
static std::string print(point p) { return nzv(p); }
static std::string print(isometry p) { return nzv(p); }
};
TD mvector<D> get_column(matrix<D> a, int id) {
mvector<D> tmp;
for(int i=0; i<D::Dim; i++) tmp[i] = a[i][id];
return tmp;
}
TD typename D::Number inner(mvector<D> a, mvector<D> b) {
using N = typename D::Number;
N res(0);
for(int i=0; i<D::Dim; i++) res += a[i] * b[i] * (i==D::Flipped?-1:1);
if(isnan(res) || isinf(res)) return N(0);
return res;
}
TD void set_column(matrix<D>& a, int id, mvector<D> v) {
for(int i=0; i<D::Dim; i++) a[i][id] = v[i];
}
TD typename D::Number sqnorm(matrix<D> a) { return sqnorm<D>(get_column<D>(a, D::Dim-1)); }
bool fix_matrices;
TD matrix<D> apply_nm(matrix<D> a) {
using N = typename D::Number;
// normalize first
auto& lead = a[D::Dim-1][D::Dim-1];
if(nm == nmFlatten) a = a / lead, cbc[cbcDiv]--;
if(nm == nmForced || nm == nmWeak) a = a * pow(sqnorm<D>(a), -0.5);
if(nm == nmBinary) {
while(lead >= 2 && !isinf(lead)) { a = a / 2; } while(lead > 0 && lead < 0.5) { a = a * 2; }
}
// fixmatrix later
if(!fix_matrices) return a;
auto divby = (nm == nmBinary || nm == nmWeak || nm == nmCareless || nm == nmFlatten) ? sqnorm<D>(a) : N(1);
for(int i=D::Dim-2; i>=0; i--) {
auto ro = get_column(a, i);
auto last = get_column(a, D::Dim-1);
ro = ro + last * inner(ro, last) / divby;
for(int j=i+1; j<D::Dim-1; j++) {
auto next = get_column(a, j);
ro = ro - next * inner(ro, next) / divby;
}
auto in = inner(ro, ro);
if(in > N(0)) ro = ro * (pow(in*in, -.5) * divby);
set_column(a, i, ro);
}
return a;
}
/* use the linear representation, as in HyperRogue */
TD struct rep_linear {
using data = D;
using point = mvector<data>;
using isometry = matrix<data>;
using N = typename D::Number;
static constexpr isometry cspin(int i, int j, typename D::Number angle) {
return apply_nm<D>( rep_linear_nn<D>::cspin(i, j, angle) );
}
static constexpr isometry cspin90(int i, int j) {
return rep_linear_nn<D>::cspin90(i, j);
}
static constexpr isometry lorentz(int i, int j, typename D::Number angle) {
return apply_nm<D>( rep_linear_nn<D>::lorentz(i, j, angle) );
}
static isometry id() { return rep_linear_nn<D>::id(); };
static constexpr point center() { return unit_vector<data>(D::Dim-1); }
static point apply(const isometry& T, const point& x) { return apply_nm(T * x); };
static isometry apply(const isometry& T, const isometry& U) { return apply_nm(T * U); };
static typename D::Number dist0(point x) {
return acos_auto<D> (get_normalized(x, x[D::Dim-1]));
}
static typename D::Number angle(const point& x) { return atan2(x[1], x[0]); }
static typename D::Number get_coord(point x, int i) {
return get_normalized(x, x[i]); }
static isometry inverse(isometry T) {
return rep_linear_nn<D>::inverse(T);
}
static isometry push(const point& p) {
return apply_nm( rep_linear_nn<D>::push(get_normalized(p, p)) );
}
static std::string print(point p) { return nzv(p); }
static std::string print(isometry p) { return nzv(p); }
};
/* use the linear representation of points and the multivector representation of isometries */
TD struct rep_mixed {
using data = D;
using N = typename D::Number;
using point = mvector<data>;
using isometry = multivector<data>;
static isometry cspin(int i, int j, typename data::Number alpha, bool noflat = false) {
/* auto u = unit_vector<multivector_data<data>> (0);
auto ui = unit_vector<data> (i);
auto uj = unit_vector<data> (j);
return u * cos(alpha/2) + multimul(embed(ui), embed(uj)) * sin(alpha/2); */
auto res = zero_vector<multivector_data<data>> ();
if(nm == nmFlatten && !noflat) {
res[0] = N(1);
res[(1<<i) | (1<<j)] = tan(alpha/2) * (i > j ? 1 : -1);
return res;
}
res[0] = cos(alpha/2);
res[(1<<i) | (1<<j)] = sin(alpha/2) * (i > j ? 1 : -1);
return res;
}
static isometry cspin90(int i, int j, bool noflat = false) {
auto res = zero_vector<multivector_data<data>> ();
if(nm == nmFlatten && !noflat) {
res[0] = N(1);
res[(1<<i) | (1<<j)] = N(i > j ? 1 : -1);
return res;
}
res[0] = sqrt(N(.5));
res[(1<<i) | (1<<j)] = sqrt(N(.5)) * (i > j ? 1 : -1);
return res;
}
static isometry lorentz(int i, int j, typename data::Number alpha) {
/* // j must be time coordinate
auto u = unit_vector<multivector_data<data>> (0);
auto ui = unit_vector<data> (i);
auto uj = unit_vector<data> (j);
return u * cosh(alpha/2) + multimul(embed(uj), embed(ui)) * sinh(alpha/2); */
auto res = zero_vector<multivector_data<data>> ();
if(nm == nmFlatten) {
res[0] = N(1);
res[(1<<i) | (1<<j)] = tanh(alpha/2);
return res;
}
res[0] = cosh(alpha/2);
res[(1<<i) | (1<<j)] = sinh(alpha/2);
return res;
}
static isometry id() { return unit_vector<multivector_data<data>> (0); };
static constexpr point center() { return unit_vector<data>(D::Dim-1); }
static point apply(const isometry& T, const point& x) {
// return unembed(multimul(multimul(T, embed(x)), conjugate(T)));
return apply_nm(unembed(chkmul<odd<D>,flat_even<D>,underling<D>>(chkmul<flat_even<D>,flat_underling<D>,odd<D>>(T, embed(x)), conjugate(T))));
};
static isometry apply(const isometry& T, const isometry& U) {
auto res = apply_nm<even<D>, D>(chkmul<flat_even<D>,flat_even<D>,even<D>>(T, U));
return res;
}
static isometry inverse(isometry T) { return conjugate(T); }
static isometry push(const point& p) {
auto pm = get_normalized(p, p);
pm[D::Dim-1] = pm[D::Dim-1] + N(1);
// since p was normalized, sqnorm of pm is 2 * pm[D::Dim-1]
pm = pm * pow(2 * pm[D::Dim-1], -0.5);
multivector<data> v1 = embed(pm);
multivector<data> v2 = unit_vector<multivector_data<data>>(1<<(D::Dim-1));
multivector<data> v3 = chkmul<underling<D>,underling<D>,poincare<D>>(v1, v2);
v3 = apply_nm<poincare<D>, D>(v3);
return v3;
}
static typename D::Number dist0(point x) { return acos_auto<D> (get_normalized(x, x[D::Dim-1])); }
static typename D::Number angle(const point& x) { return atan2(x[1], x[0]); }
static typename D::Number get_coord(point x, int i) { return get_normalized(x, x[i]); }
static std::string print(point p) { return nzv(p); }
static std::string print(isometry p) { return nz(p); }
};
/* use the hyperboloid-Poincare representation of points and the multivector representation of isometries */
TD struct rep_clifford {
using data = D;
using N = typename D::Number;
using point = array< multivector<data>, 1>;
using isometry = multivector<data>;
static isometry cspin(int i, int j, typename data::Number alpha) { return rep_mixed<D>::cspin(i, j, alpha); }
static isometry cspin90(int i, int j) { return rep_mixed<D>::cspin90(i, j); }
// j must be the neg coordinate!
static isometry lorentz(int i, int j, N alpha) { return rep_mixed<D>::lorentz(i, j, alpha); }
static isometry id() { return rep_mixed<D>::id(); }
static constexpr point center() { return point{{ id() }}; }
static point apply(const isometry& T, const point& x) { return point{{ despin(chkmul<even<D>,poincare<D>,even<D>>(T, x[0])) }}; }
static isometry apply(const isometry& T, const isometry& U) { return apply_nm<even<D>,D>( chkmul<even<D>,even<D>,even<D>>(T, U) ); }
static isometry inverse(isometry T) { return conjugate(T); }
static isometry push(const point& p) { return p[0]; }
static typename D::Number dist0(const point& ax) {
return acos_auto<D>(get_normalized<poincare<D>, D, N>(ax[0], ax[0][0]))*2;
}
static constexpr int mvlast = 1<<(D::Dim-1);
static typename D::Number angle(const point& x) {
return atan2(x[0][2 | mvlast], x[0][1 | mvlast]);
}
static typename D::Number get_coord(const point& x, int i) {
auto x1 = multimul(multimul(x[0], unit_vector<multivector_data<data>> (mvlast)), conjugate(x[0]));
auto x2 = unembed(x1);
return get_normalized(x2, x2[i]);
}
static std::string print(point p) { return nz(p[0]); }
static std::string print(isometry p) { return nz(p); }
};
/* split isometries into the poincare and rotational part */
TD struct rep_gyro {
using data = D;
using N = typename D::Number;
using point = multivector<data>;
using isometry = poincare_rotation<data>;
static isometry cspin(int i, int j, typename data::Number alpha) { return { rep_mixed<D>::id(), rep_mixed<D>::cspin(i, j, alpha, true) }; }
static isometry cspin90(int i, int j, typename data::Number alpha) { return { rep_mixed<D>::id(), rep_mixed<D>::cspin90(i, j, alpha, true) }; }
static isometry lorentz(int i, int j, typename data::Number alpha) { return {rep_mixed<D>::lorentz(i, j, alpha), rep_mixed<D>::id() }; }
static isometry id() { return { rep_mixed<D>::id(), rep_mixed<D>::id() }; }
static constexpr point center() { return rep_mixed<D>::id(); }
static point apply(const isometry& T, const point& x) { return despin(chkmul<poincare<D>,poincare<D>,even<D>>(T.first, chkmul<rotational<D>,poincare<D>,poincare<D>>(T.second, x))); }
static isometry apply(const isometry& T, const isometry& U) {
auto R1 = apply_nm<rotational<D>, poincare<D>, poincare<D>> (T.second, U.first);
auto R2 = apply_nm<poincare<D>, poincare<D>, even<D>> (T.first, R1);
auto R3 = despin2(R2);
return { R3.first, apply_nm<rotational<D>, rotational<D>, rotational<D>> (R3.second, U.second) };
}
static isometry inverse(isometry T) { return { conjugate(T.first), conjugate(T.second) }; }
static isometry push(const point& p) { return { p, rep_mixed<D>::id() }; }
static typename D::Number dist0(const point& ax) {
return acos_auto<D>(get_normalized<poincare<D>, D, N>(ax, ax[0]))*2;
}
static constexpr int mvlast = 1<<(D::Dim-1);
static typename D::Number angle(const point& x) {
return atan2(x[0][2 | mvlast], x[0][1 | mvlast]);
}
static typename D::Number get_coord(const point& x, int i) {
auto x1 = multimul(multimul(x[0], unit_vector<multivector_data<data>> (mvlast)), conjugate(x[0]));
auto x2 = unembed(x1);
return get_normalized(x2, x2[i]);
}
static std::string print(point p) { return nz(p[0]); }
static std::string print(isometry p) { return "["+nz(p.first)+","+nz(p.second)+"]"; }
};
}

261
devmods/reps/rep-polar.cpp Normal file
View File

@ -0,0 +1,261 @@
bool polar_mod = true, polar_choose = true;
namespace reps {
template<class N> static void cyclefix(N& a) {
while(a > + get_deg<N>(180)) a -= get_deg<N>(360);
while(a < - get_deg<N>(180)) a += get_deg<N>(360);
}
template<class N> static N cyclefix_on(N a) { cyclefix(a); return a; }
/** the Taylor polynomial for 1-sqrt(1-y*y) */
template<class N> N ssqrt(N y) {
return y*y/2 + y*y*y*y/8 + y*y*y*y*y*y*y/16 + y*y*y*y*y*y*y*y*y/128;
}
TD struct rep_polar2 {
using data = D;
using N = typename D::Number;
struct point { N phi, r; };
struct isometry { N psi, phi, r; }; // spin by psi first
static isometry cspin(int i, int j, N alpha) {
if(i>j) std::swap(i, j), alpha = -alpha;
return isometry{.psi = -alpha, .phi = N(0), .r = N(0) };
}
static isometry cspin90(int i, int j) { return cspin(i, j, get_deg<N>(90)); }
static isometry lorentz(int i, int j, N alpha) {
if(i>j) std::swap(i, j);
if(i == 0) return isometry{.psi = N(0), .phi = N(0), .r = alpha};
if(i == 1) return isometry{.psi = N(0), .phi = get_deg<N>(90), .r = alpha};
throw hr::hr_exception("bad lorentz");
}
static isometry id() { return isometry{.psi = N(0), .phi = N(0), .r = N(0)}; };
static point center() { return point{.phi = N(0), .r = N(0)}; };
static std::string print(isometry T) {
return hr::lalign(0, "{phi=", T.phi, " r=", T.r, " psi=", T.psi, "}");
}
static std::string print(point T) {
return hr::lalign(0, "{phi=", T.phi, " r=", T.r, "}");
}
static isometry apply(isometry T, isometry U, bool need_psi = true) {
if(T.r == 0) return isometry {.psi = T.psi+U.psi, .phi = T.psi+U.phi, .r = U.r};
if(U.r == 0) return isometry {.psi = T.psi+U.psi, .phi = T.phi, .r = T.r};
N alpha = U.phi + T.psi - T.phi;
if(polar_mod) cyclefix(alpha);
isometry res;
N y1 = sinh(U.r) * sin(alpha);
auto ca = cos(alpha);
auto sa = sin(alpha);
N x1, x2;
// choose the appropriate method
if(polar_choose && ca >= N(0.5)) {
N u = ca >= N(.999999) ? ssqrt(sa) : N(1) - ca;
res.r = cosh(T.r + U.r) - u * sinh(T.r) * sinh(U.r);
x1 = sinh(T.r + U.r) - u * cosh(T.r) * sinh(U.r);
if(need_psi) x2 = sinh(T.r + U.r) - u * cosh(U.r) * sinh(T.r);
}
else if(polar_choose && ca <= N(-0.5)) {
N u = ca <= N(-.999999) ? ssqrt(-sa) : ca + N(1);
res.r = cosh(T.r - U.r) + u * sinh(T.r) * sinh(U.r);
x1 = sinh(T.r - U.r) + u * cosh(T.r) * sinh(U.r);
if(need_psi) x2 = sinh(U.r - T.r) + u * cosh(U.r) * sinh(T.r);
}
else {
res.r = sinh(T.r) * sinh(U.r) * ca + cosh(T.r) * cosh(U.r);
x1 = cosh(T.r) * sinh(U.r) * ca + cosh(U.r) * sinh(T.r);
if(need_psi) x2 = cosh(U.r) * sinh(T.r) * ca + cosh(T.r) * sinh(U.r);
}
if(res.r < N(1)) res.r = N(0); else res.r = acosh(res.r);
N beta = (y1 || x1) ? atan2(y1, x1) : N(0);
res.phi = T.phi + beta;
if(polar_mod) cyclefix(res.phi);
if(need_psi) {
N y2 = sinh(T.r) * sin(alpha);
N gamma = (y2 || x2) ? atan2(y2, x2) : N(0);
res.psi = T.psi + U.psi + beta + gamma - alpha;
if(polar_mod) cyclefix(res.psi);
}
return res;
};
static point apply(const isometry& T, const point& x) {
isometry x1 = apply(T, push(x), false);
return point { .phi = x1.phi, .r = x1.r};
};
static isometry inverse(isometry T) { return isometry{.psi = -T.psi, .phi = cyclefix_on<N>(get_deg<N>(180)+T.phi-T.psi), .r=T.r }; };
static isometry push(const point& p) { return isometry{.psi = N(0), .phi = p.phi, .r = p.r}; }
static N dist0(const point& x) { return x.r; }
static N angle(const point& x) { return x.phi; }
static N get_coord(const point& x, int i) {
if(i == 0) return cos(x.phi) * sinh(x.r);
if(i == 1) return sin(x.phi) * sinh(x.r);
if(i == 2) return cosh(x.r);
throw hr::hr_exception("bad get_coord");
}
};
TD struct rep_high_polar {
using data = D;
using N = typename D::Number;
struct sphere_data {
using Number = N;
static constexpr int Dim = D::Dim-1;
static constexpr int Flipped = -1;
};
using subsphere = rep_linear_nn<sphere_data>;
struct point { typename subsphere::point phi; N r; };
struct isometry { typename subsphere::isometry psi; typename subsphere::point phi; N r; };
static isometry cspin(int i, int j, N alpha) {
return isometry{.psi = subsphere::cspin(i, j, alpha), .phi = subsphere::center(), .r = N(0) };
}
static isometry cspin90(int i, int j) {
return isometry{.psi = subsphere::cspin90(i, j), .phi = subsphere::center(), .r = N(0) };
}
static isometry lorentz(int i, int j, N alpha) {
if(i>j) std::swap(i, j);
auto is = isometry{.psi = subsphere::id(), .phi = subsphere::center(), .r = alpha};
is.phi[D::Dim-2] = N(0);
is.phi[i] = N(1);
return is;
}
static isometry id() { return isometry{.psi = subsphere::id(), .phi = subsphere::center(), .r = N(0)}; }
static point center() { return point{.phi = subsphere::center(), .r = N(0)}; };
static std::string print(isometry T) {
return hr::lalign(0, "{phi=", subsphere::print(T.phi), " r=", T.r, " psi=", hr::kz(T.psi.values), "}");
}
static std::string print(point T) {
return hr::lalign(0, "{phi=", subsphere::print(T.phi), " r=", T.r, "}");
}
static isometry apply(isometry T, isometry U, bool need_psi = true) {
auto apsi = need_psi ? T.psi * U.psi : subsphere::id();
if(T.r == 0) return isometry {.psi = apsi, .phi = T.psi*U.phi, .r = U.r};
if(U.r == 0) return isometry {.psi = apsi, .phi = T.phi, .r = T.r};
auto aphi = T.psi * U.phi;
auto cos_alpha = inner<sphere_data>(aphi, T.phi);
auto& ca = cos_alpha;
isometry res;
N x1, x2;
auto orth = (aphi - T.phi * ca);
N sin_alpha;
if(ca > N(0.999999) || ca < N(0.999999))
sin_alpha = pow(sqnorm<sphere_data>(orth), .5);
else
sin_alpha = pow(N(1) - ca * ca, .5);
if(sin_alpha == N(0)) {
if(ca >= N(1)) {
return isometry{.psi = apsi, .phi = T.phi, .r = T.r + U.r };
}
if(ca <= N(-1)) {
if(T.r >= U.r) {
return isometry{.psi = apsi, .phi = T.phi, .r = T.r - U.r };
}
else {
return isometry{.psi = apsi, .phi = T.phi*-1, .r = U.r - T.r };
}
}
}
orth = orth / sin_alpha;
N y1 = sinh(U.r) * sin_alpha;
// choose the appropriate method
if(polar_choose && ca >= N(0.5)) {
N u = ca >= N(.999999) ? ssqrt(sin_alpha) : N(1) - ca;
res.r = cosh(T.r + U.r) - u * sinh(T.r) * sinh(U.r);
x1 = sinh(T.r + U.r) - u * cosh(T.r) * sinh(U.r);
if(need_psi) x2 = sinh(T.r + U.r) - u * cosh(U.r) * sinh(T.r);
}
else if(polar_choose && ca <= N(-0.5)) {
N u = ca <= N(-.999999) ? ssqrt(sin_alpha) : ca + N(1); // ca = u - 1
res.r = cosh(T.r - U.r) + u * sinh(T.r) * sinh(U.r);
x1 = sinh(T.r - U.r) + u * cosh(T.r) * sinh(U.r);
if(need_psi) x2 = sinh(U.r - T.r) + u * cosh(U.r) * sinh(T.r);
}
else {
res.r = sinh(T.r) * sinh(U.r) * ca + cosh(T.r) * cosh(U.r);
x1 = cosh(T.r) * sinh(U.r) * ca + cosh(U.r) * sinh(T.r);
if(need_psi) x2 = cosh(U.r) * sinh(T.r) * ca + cosh(T.r) * sinh(U.r);
}
if(res.r < N(1)) res.r = N(0); else res.r = acosh(res.r);
auto h1 = pow(x1*x1+y1*y1, -0.5);
N cos_beta = x1*h1, sin_beta = y1*h1;
res.phi = T.phi * cos_beta + orth * sin_beta;
if(need_psi) {
N y2 = sinh(T.r) * sin_alpha;
auto h2 = pow(x2*x2+y2*y2, -0.5);
N cos_gamma = x2*h2, sin_gamma = y2*h2;
// delta = beta + gamma - alpha
auto cos_beta_gamma = cos_beta * cos_gamma - sin_beta * sin_gamma;
auto sin_beta_gamma = cos_beta * sin_gamma + sin_beta * cos_gamma;
auto cos_delta = cos_beta_gamma * cos_alpha + sin_beta_gamma * sin_alpha;
auto sin_delta = sin_beta_gamma * cos_alpha - cos_beta_gamma * sin_alpha;
auto phi1 = T.phi * cos_delta + orth * sin_delta;
auto orth1 = orth * cos_delta - T.phi * sin_delta;
auto phi2 = phi1 - T.phi;
auto orth2 = orth1 - orth;
typename subsphere::isometry spinner = subsphere::id();
// Tv = v + <v, phi> * (phi'-phi) + <v, orth> * (orth'-orth)
for(int i=0; i<D::Dim-1; i++)
for(int j=0; j<D::Dim-1; j++)
spinner[i][j] += phi2[i] * T.phi[j] + orth2[i] * orth[j];
res.psi = spinner * apsi;
}
return res;
};
static point apply(const isometry& T, const point& x) {
isometry x1 = apply(T, push(x), false);
return point { .phi = x1.phi, .r = x1.r};
};
static isometry inverse(isometry T) { return isometry{.psi = subsphere::inverse(T.psi), .phi = subsphere::inverse(T.psi)*T.phi*-1, .r=T.r }; };
static isometry push(const point& p) { return isometry{.psi = subsphere::id(), .phi = p.phi, .r = p.r}; }
static N dist0(const point& x) { return x.r; }
static N angle(const point& x) { return subsphere::angle(x.phi); }
static N get_coord(const point& x, int i) { if(i == D::Dim-1) return cosh(x.r); else return x.phi[i] * sinh(x.r); }
};
template<class D> using rep_polar = typename std::conditional<D::Dim==3, rep_polar2<D>, rep_high_polar<D>>::type;
}

81
devmods/reps/reps.cpp Normal file
View File

@ -0,0 +1,81 @@
#include <boost/multiprecision/mpfr.hpp>
#include "../../hyper.h"
#define TD template<class D>
#undef sl2
namespace reps {
using namespace boost::multiprecision;
using big = mpfr_float_50;
}
namespace hr {
void print(hr::hstream& hs, ::reps::big b) {
std::stringstream ss;
ss << std::setprecision(10);
ss << b; string u; ss >> u; print(hs, u);
}
}
namespace reps {
using std::array;
using std::vector;
using hr::cell;
using hr::print;
using hr::hlog;
using hr::celldistance;
using hr::ld;
using hr::ginf;
using hr::geometry;
using hr::gcHyperbolic;
using hr::gcSphere;
using hr::C02;
using hr::C03;
using hr::qANYQ;
template <class N> N get_deg(int deg);
template<> ld get_deg<ld> (int deg) { return M_PI*deg/180; }
template<> big get_deg<big> (int deg) { return atan(big(1))*deg/45; }
enum eNormalizeMode {
nmInvariant, // if the input was normalized, the output will be normalized too
nmForced, // normalize the output
nmWeak, // weakly normalize the output
nmCareless, // do not try to keep the output normalized
nmFlatten, // flatten the representation
nmBinary // try to avoid overflow
};
eNormalizeMode nm;
}
#include "counter.cpp"
#include "multivector.cpp"
#include "rep-hr.cpp"
#include "rep-multi.cpp"
#include "rep-halfplane.cpp"
#include "rep-polar.cpp"
#include "tests.cpp"
namespace reps {
// -- tests ---
void test_systems() {
run_all_tests();
fflush(stdout);
exit(1);
}
void set_repgeo() {
if(test_dim == 3) { hr::set_geometry(hr::gNormal); hr::set_variation(hr::eVariation::pure); }
if(test_dim == 4) { hr::set_geometry(hr::gSpace435); }
}
int a = hr::arg::add1("-test-reps", test_systems) + hr::arg::add1("-repgeo", set_repgeo);
}

733
devmods/reps/results.Md Normal file
View File

@ -0,0 +1,733 @@
# What is it
This is a study of numerical precision errors in various representations of 2D hyperbolic geometry.
It is generally the best to combine a representation with tiling; the tests take this into
account.
# Representations studied
The following representations are studied:
* **linear**: points in the hyperboloid model; isometries as linear transformation matrices.
* **mixed**: points in the hyperboloid model; isometries using Clifford algebras. (Clifford algebras
are a generalization of 'quaternions' commonly used in 3D graphics.)
* **clifford**: points are also represented using Clifford algebras, that is, p is represented as
the isometry u such as u(C0) = p and u does not introduce extra rotations.
* **halfplane (2D)**: points are represented using the half-plane model; isometries are represented using
SL(2,R).
* **halfspace (3D)**: points are represented using the half-space model; isometries are represented using
SL(2,C).
* **polar 2D**: points are represented using polar coordinates; isometries need one extra angle.
* **general polar**: like polar 2D, but instead of angles, we use rotated unit vectors and rotation
matrices; this also makes it work in higher dimension.
## Variations
Both in linear and Clifford representations, there is the correct "normalized" representation;
if the normalized representation is multiplied by some factor x, most formulas still work,
and for those which do not, it is easy to compute x. This yields the following variations:
* **invariant**: keep the invariant that the points and isometries are normalized
(that is: output is normalized under the assumption that the input is normalized)
* **careless**: do not care about normalization
(advantages: some computations are avoided; possible to represent ultra-ideal points in
linear representations)
* **forced**: normalize the output after every computation
(might be a good idea for points/isometries close to the center, but generally a bad
idea if they are far away -- in that case, the norm generally cannot be computed, but
distances and angles still tend to be correct in the invariant computations)
* **weakly forced**: like forced, but do not normalize if the norm could not be computed
due to precision errors
* **flatten**: instead of normal normalization, make the leading coordinate equal to 1.
The leading coordinate is the 'timelike' coordinate of linear representations
of points, and the 'unit' coordinate of Clifford representations.
(advantage: save memory: H2 represented only 2 coordinates instead of 3;
disadvantage: might not represent ultra-ideal points if they would be infinite)
* **binary**: in careless, values may easily explode and cause underflow/overflow; avoid this
by making the leading coordinate in \[0.5, 2) range (by multiplying by powers of 2, which is
presumably fast)
Furthermore:
* in linear, matrices can be **fixed** by replacing them by a correct orthogonal matrix close
to the current computation
* in (non-general) polar, forcing angles into [-pi,pi] may be needed to prevent explosion
* in **improved** polar, one of three variants of the cosine rule can be used, depending on the angle,
to improve the numerical precision; also even more precise computation to avoid numerical
precision errors for angles very close to 0 or pi
* in the Clifford representation, the **gyro** variant splits the isometries into
the translational part (which is flattened, making it equivalent to the Poincare disk model)
and the rotational part (for which 'invariant' is used). This fixes the problem
with full flattening where rotations by 180° are flattened to infinity. (AFAIK
Hyperbolica uses roughly this)
## Observations
* except linear, all the methods of representing isometries can only represent
orientation-preserving ones
* Clifford isometries of H2 is essentially the same as SL(2,R) of halfplane -- it is
just the change of the basis
* linear/Clifford representations are not that good at representing points close to the
boundary of the disk (invariant can somewhat tell the distance but flattened cannot);
halfplane is better here
# Tests
## test_loop_iso
In this test, for each i, we construct a path in the tiling by always moving to a random
adjacent tile, until we get to a tile i afar; then, we return to the start (also randomly,
may stray further from the path). We compose all the relative tile isometries into T and see
if T(C0) = C0. The score is the first i for which it fails.
Discussion: This makes rep_mixed worse than rep_lorentz.
## test_loop_point
Same as test_loop_iso but we apply the consecutive isometries to point right away.
Discussion: This makes rep_mixed worse than rep_lorentz.
## test_angledist
For each i (skipping some), construct a path outwards in the tiling, compose isometries,
and see if the distance and angle to that tile have been computed correctly.
Discussion: Invariant representations have no problem with this, even if the points obtained are beyond the precision otherwise.
## test_similarity, test_dissimilarity, test_other
For each i, compute the distance between two points in distance i from the starting point.
The angle between them is very small (test_similarity), close to 180° (test_dissimilarity),
close to 1° (test_other).
Discussion: Similarity is obviously the most difficult. Halfplane is surprisingly powerful in all cases.
## test_walk
This is essentially walking in a straight line in HyperRogue. After some time, it can be often clearly observed that we
have 'deviated' from the original straight line. This test checks how long we can walk.
We construct an isometry T representing a random direction. In each step, we compose this isometry with a translation (T := T * translate(1/16)).
Whenever the point T * C0 is closer to the center of another tile, we rebase to that new tile.
For a test, we actually do this in parallel with two isometries T0 and T1, where T1 = T0 * translate(1/32). We count the number of steps
until the paths diverge. Numbers over 1000 are not actually that good, 1000+n means that, after n steps, the implementation no longer detects tile
changes. Numbers of 10000 signify that some even weirder problem happened.
Discussion: Since the isometry matrices are always small (constrained to tiles), fixing definitely helps here. Without fixing, T stops
being an isometry (an effect visible in HyperRogue when fixing is disabled).
## test_close
Here we see whether small errors accumulate when moving close to the center. In test i, we move randomly until we reach distance i+1,
after which we return to the start (always reducing the distance). After each return to the start, we check if the representation is
still fine (if not, we restart with the original representation). The number given is the number of errors in 10000 steps.
Discussion: Errors do not appear to accumulate when we simply move close to the start (or rather, they accumulate very slowly).
## test_count
This simply computes the number of numerical operations performed for every geometric operation. Numerical operations are categorized as:
* Addition/subtraction
* Multiplication (multiplication by constant not counted)
* Division (division by constant not counted)
* Functions: exp, log, (a)sin/cos/tan(h), sqrt, inverse sqrt
Geometric operations are:
* spin: return rotation by given angle in given axes
* L0: return translation by given value in axis 0
* L1: return translation by given value in axis 1
* ip: apply isometry to point
* ii: compose isometries
* d0: compute the distance of point from 0
* angle: compute the (2D) angle of point
* inverse: compute the inverse of an isometry
* push: convert a point into a translation
# Implementation notes
Note: the program currently assumes hyperbolic geometry (it was intended to support spherical
geometry but not everywhere the correct handling is implemented).
# Results
## Results on the {7,3} tiling
```
test_loop_iso
linear+F invariant: (17,16,17,16,17,17,17,17,16,17,17,17,17,16,16,17,17,16,17,17)
linear+F forced : (20,19,19,20,20,19,20,20,19,20,20,18,19,19,19,19,20,19,19,19)
linear+F weak : (21,19,20,20,20,19,24,20,19,25,24,18,19,19,19,19,20,19,19,19)
linear+F flatten : (19,19,21,20,20,20,20,20,19,19,19,21,19,20,19,19,19,19,19,20)
linear+F careless : (19,19,19,19,20,19,20,20,19,20,18,18,19,18,19,19,19,19,19,19)
linear+F binary : (19,19,19,19,20,19,20,20,19,20,18,18,19,18,19,19,19,19,19,19)
linear-F invariant: (17,17,17,18,18,18,21,17,16,17,19,18,17,18,23,17,18,17,19,17)
linear-F forced : (19,19,19,19,20,19,19,20,19,20,20,20,19,19,19,19,19,19,19,19)
linear-F weak : (19,19,20,19,20,19,19,20,19,21,20,20,21,19,19,19,20,19,19,19)
linear-F flatten : (20,19,20,20,21,19,20,18,19,19,20,21,19,21,20,19,19,19,19,20)
linear-F careless : (20,19,19,21,19,19,20,17,19,20,19,20,19,19,19,19,19,19,19,20)
linear-F binary : (20,19,19,21,19,19,20,17,19,20,19,20,19,19,19,19,19,19,19,20)
mixed invariant: (34,35,34,36,34,35,34,34,36,35,34,35,36,34,35,34,33,35,32,36)
mixed forced : (34,34,34,35,34,36,33,34,36,35,35,36,36,34,35,34,34,35,34,34)
mixed weak : (34,34,34,35,34,36,33,34,36,35,35,36,36,34,35,34,34,35,34,34)
mixed flatten : (20,5,18,13,13,13,4,13,9,29,25,9,36,22,19,30,5,35,14,2)
mixed careless : (34,34,34,35,34,34,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
mixed binary : (34,34,34,35,34,34,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
Clifford invariant: (32,35,34,36,34,35,34,34,36,33,34,35,36,34,35,34,33,34,32,36)
Clifford forced : (34,34,34,35,34,36,33,34,36,35,35,36,36,34,35,34,34,35,34,34)
Clifford weak : (34,34,34,35,34,36,33,34,36,35,35,36,36,34,35,34,34,35,34,34)
Clifford flatten : (34,34,34,35,34,36,35,34,36,35,35,36,37,34,35,34,36,35,34,34)
Clifford careless : (34,34,34,35,34,34,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
Clifford binary : (34,34,34,35,34,34,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
Clifford gyro : (34,34,34,35,34,36,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
halfplane invariant: (34,34,34,35,34,36,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
polar basic : (34,34,34,35,34,34,33,34,36,35,35,24,36,34,35,34,35,35,34,34)
polar improved : (34,34,34,34,33,36,35,33,36,35,35,36,35,34,35,34,34,35,34,35)
polar F/F : (34,36,35,35,33,34,33,33,36,35,35,36,36,34,35,34,35,35,34,34)
polar F/T : (34,34,34,34,33,36,35,33,36,35,35,36,35,34,35,34,34,35,34,35)
polar T/F : (34,34,35,36,34,36,35,34,35,35,35,36,35,34,35,34,35,35,34,36)
polar T/T : (34,36,35,34,34,36,35,34,36,35,35,36,35,34,35,34,34,35,34,35)
test_loop_point
linear+F invariant: (17,16,17,16,17,17,17,17,16,17,17,17,17,16,16,17,17,16,17,17)
linear+F forced : (20,19,19,20,20,19,20,20,19,20,20,18,19,19,19,19,20,19,19,19)
linear+F weak : (21,19,20,20,20,19,24,20,19,25,24,18,19,19,19,19,20,19,19,19)
linear+F flatten : (19,19,21,20,20,20,20,20,19,19,19,21,19,20,19,19,19,19,19,20)
linear+F careless : (19,19,19,19,20,19,20,20,19,20,18,18,19,18,19,19,19,19,19,19)
linear+F binary : (19,19,19,19,20,19,20,20,19,20,18,18,19,18,19,19,19,19,19,19)
linear-F invariant: (17,17,17,18,18,18,21,17,16,17,19,18,17,18,23,17,18,17,19,17)
linear-F forced : (19,19,19,19,20,19,19,20,19,20,20,20,19,19,19,19,19,19,19,19)
linear-F weak : (19,19,20,19,20,19,19,20,19,21,20,20,21,19,19,19,20,19,19,19)
linear-F flatten : (20,19,20,20,21,19,20,18,19,19,20,21,19,21,20,19,19,19,19,20)
linear-F careless : (20,19,19,21,19,19,20,17,19,20,19,20,19,19,19,19,19,19,19,20)
linear-F binary : (20,19,19,21,19,19,20,17,19,20,19,20,19,19,19,19,19,19,19,20)
mixed invariant: (18,17,17,19,20,18,19,19,17,17,18,17,17,16,16,18,25,17,17,19)
mixed forced : (19,19,19,19,19,19,19,17,19,20,19,20,19,19,19,20,19,19,20,20)
mixed weak : (19,23,19,19,19,19,21,17,19,23,19,20,24,20,19,20,22,19,23,20)
mixed flatten : (20,19,19,20,19,19,19,18,20,20,19,18,18,19,18,20,19,19,19,19)
mixed careless : (19,19,19,19,19,20,19,18,19,19,19,21,19,20,18,19,20,19,19,20)
mixed binary : (19,19,19,19,19,20,19,18,19,19,19,21,19,20,18,19,20,19,19,20)
Clifford invariant: (32,34,31,34,33,36,31,35,32,33,32,36,32,34,33,36,33,32,34,34)
Clifford forced : (34,34,34,35,34,36,35,34,35,35,35,36,35,34,35,34,35,35,34,34)
Clifford weak : (34,34,34,35,34,36,35,34,35,35,35,36,35,34,35,34,35,35,34,34)
Clifford flatten : (34,34,34,35,34,36,35,34,36,35,34,36,36,34,35,34,35,35,34,34)
Clifford careless : (3,1,3,2,2,2,2,2,2,3,2,2,3,2,2,3,2,2,1,3)
Clifford binary : (34,34,34,35,34,34,35,34,36,35,35,36,35,34,35,34,35,35,34,34)
Clifford gyro : (34,36,34,35,34,36,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
halfplane invariant: (34,36,34,35,34,36,35,34,36,35,35,36,36,34,35,34,35,35,34,34)
polar basic : (34,34,34,35,34,34,33,34,36,35,35,24,36,34,35,34,35,35,34,34)
polar improved : (34,34,34,34,33,36,35,33,36,35,35,36,35,34,35,34,34,35,34,35)
polar F/F : (34,36,35,35,33,34,33,33,36,35,35,36,36,34,35,34,35,35,34,34)
polar F/T : (34,34,34,34,33,36,35,33,36,35,35,36,35,34,35,34,34,35,34,35)
polar T/F : (34,34,35,36,34,36,35,34,35,35,35,36,35,34,35,34,35,35,34,36)
polar T/T : (34,36,35,34,34,36,35,34,36,35,35,36,35,34,35,34,34,35,34,35)
test_angledist
linear+F invariant: (767,767,767)
linear+F forced : (21,21,21)
linear+F weak : (21,21,21)
linear+F flatten : (21,21,21)
linear+F careless : (21,21,21)
linear+F binary : (21,21,21)
linear-F invariant: (767,767,767)
linear-F forced : (21,21,21)
linear-F weak : (21,21,21)
linear-F flatten : (21,21,21)
linear-F careless : (21,21,21)
linear-F binary : (21,21,21)
mixed invariant: (767,767,767)
mixed forced : (21,21,21)
mixed weak : (21,21,21)
mixed flatten : (21,21,21)
mixed careless : (21,21,21)
mixed binary : (21,21,21)
Clifford invariant: (767,767,767)
Clifford forced : (39,39,47)
Clifford weak : (39,39,39)
Clifford flatten : (39,39,39)
Clifford careless : (2,3,3)
Clifford binary : (39,47,39)
Clifford gyro : (39,47,39)
halfplane invariant: (767,767,767)
polar basic : (443,443,443)
polar improved : (443,443,443)
polar F/F : (767,767,767)
polar F/T : (767,767,767)
polar T/F : (767,767,767)
polar T/T : (767,767,767)
test_similarity
linear+F invariant: (18,17,17,18,17,18,18,17,18,17,18,18,17,17,17,18,17,17,17,17)
linear+F forced : (19,18,18,18,19,18,18,19,19,18,18,18,19,18,19,19,18,19,19,18)
linear+F weak : (19,18,18,18,19,18,18,19,19,18,18,18,19,18,19,19,18,19,19,18)
linear+F flatten : (18,19,18,18,18,19,19,19,19,18,18,18,19,18,19,19,19,19,18,19)
linear+F careless : (19,18,19,18,19,18,18,19,19,18,18,18,19,19,19,19,18,18,19,18)
linear+F binary : (19,18,19,18,19,18,18,19,19,18,18,18,19,19,19,19,18,18,19,18)
linear-F invariant: (18,18,19,18,18,18,18,18,18,18,18,19,19,19,18,18,19,18,18,18)
linear-F forced : (18,19,19,19,19,19,18,19,18,19,19,19,19,19,18,19,19,19,19,19)
linear-F weak : (18,19,19,19,19,19,18,19,18,19,19,19,19,19,18,19,19,19,19,19)
linear-F flatten : (19,18,19,19,19,19,19,19,18,19,19,19,19,19,18,19,19,19,19,19)
linear-F careless : (18,19,19,19,19,19,19,19,18,19,19,19,19,19,19,19,19,19,19,19)
linear-F binary : (18,19,19,19,19,19,19,19,18,19,19,19,19,19,19,19,19,19,19,19)
mixed invariant: (18,19,18,19,18,18,18,18,18,19,19,19,18,19,18,18,18,19,19,18)
mixed forced : (19,19,19,19,19,18,19,19,18,18,18,19,20,19,19,20,19,19,19,19)
mixed weak : (19,19,19,19,19,18,19,19,18,18,19,19,21,20,19,19,19,20,19,20)
mixed flatten : (19,19,19,19,19,19,19,19,20,18,19,19,19,19,20,19,19,19,19,19)
mixed careless : (19,20,19,19,19,18,19,19,19,19,19,20,20,19,19,19,19,19,19,19)
mixed binary : (19,20,19,19,19,18,19,19,19,19,19,20,20,19,19,19,19,19,19,19)
Clifford invariant: (33,33,33,32,32,34,34,33,32,34,33,33,34,33,33,33,33,34,33,33)
Clifford forced : (36,35,35,35,35,35,37,35,36,36,36,35,35,35,35,37,36,36,35,35)
Clifford weak : (36,35,35,35,35,35,37,35,36,36,36,35,35,35,35,37,36,36,35,35)
Clifford flatten : (35,37,36,35,36,35,35,38,36,37,36,35,37,35,37,38,36,38,35,36)
Clifford careless : (37,35,36,35,35,36,35,35,37,35,38,36,38,35,37,36,35,35,35,37)
Clifford binary : (37,35,36,35,35,36,35,35,37,35,38,36,38,35,37,36,35,35,35,37)
Clifford gyro : (37,35,37,37,37,36,35,36,36,36,37,36,35,36,37,37,36,37,37,35)
halfplane invariant: (35,36,36,36,36,35,35,37,37,37,37,36,35,36,38,37,36,36,37,35)
polar basic : (19,18,18,18,19,18,18,18,18,18,18,18,18,19,18,18,18,18,18,18)
polar improved : (37,37,37,37,37,38,38,37,37,36,37,37,38,39,38,37,37,39,37,38)
polar F/F : (19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19)
polar F/T : (35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35)
polar T/F : (19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19)
polar T/T : (35,35,35,35,35,36,35,35,35,36,36,35,35,35,35,35,35,35,35,36)
test_dissimilarity
linear+F invariant: (125,124,147,123,134,130,126,128,123,125,130,130,127,125,125,131,123,124,125,127)
linear+F forced : (7,6,7,7,7,7,8,7,6,7,7,7,7,7,7,7,7,7,7,7)
linear+F weak : (7,7,7,7,9,13,8,7,9,7,9,7,7,7,11,9,7,8,7,7)
linear+F flatten : (7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7)
linear+F careless : (7,7,7,7,7,7,7,7,6,7,8,7,7,7,7,7,7,7,7,7)
linear+F binary : (7,7,7,7,7,7,7,7,6,7,8,7,7,7,7,7,7,7,7,7)
linear-F invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
linear-F forced : (10,10,10,10,10,10,10,10,10,9,9,10,10,10,10,10,10,9,10,10)
linear-F weak : (9,15,13,12,11,11,10,9,16,9,10,9,13,10,12,11,10,9,10,9)
linear-F flatten : (9,10,10,10,10,10,9,9,10,10,10,10,10,10,9,10,10,10,10,10)
linear-F careless : (10,10,10,9,10,9,10,10,10,10,9,10,10,9,9,10,9,10,10,9)
linear-F binary : (10,10,10,9,10,9,10,10,10,10,9,10,10,9,9,10,9,10,10,9)
mixed invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
mixed forced : (10,9,10,9,10,10,10,9,10,10,10,10,10,10,10,10,10,9,10,10)
mixed weak : (10,9,12,9,9,10,10,11,10,9,12,11,10,9,11,11,11,9,11,10)
mixed flatten : (10,9,10,10,9,10,10,10,10,10,10,10,10,10,9,10,10,10,10,10)
mixed careless : (10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,10,10,10,10,9)
mixed binary : (10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,10,10,10,10,9)
Clifford invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
Clifford forced : (18,19,18,18,19,18,19,18,19,19,18,19,18,17,19,19,19,19,19,19)
Clifford weak : (18,18,18,18,19,18,18,18,19,18,18,19,18,18,18,18,19,18,18,19)
Clifford flatten : (18,19,18,19,19,18,18,18,19,19,18,18,19,19,18,18,18,19,19,18)
Clifford careless : (19,18,19,18,18,19,19,18,18,18,18,18,19,18,19,19,19,18,19,18)
Clifford binary : (19,18,19,18,18,19,19,18,18,18,18,18,19,18,19,19,19,18,19,18)
Clifford gyro : (18,18,18,19,19,18,19,20,18,18,18,18,18,19,19,19,18,19,18,18)
halfplane invariant: (35,35,35,35,35,35,35,35,34,36,37,34,35,36,35,35,35,35,36,35)
polar basic : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar improved : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar F/F : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar F/T : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar T/F : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar T/T : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
test_other
linear+F invariant: (97,97,101,107,97,97,126,107,101,101,112,112,99,101,112,131,107,97,97,94)
linear+F forced : (10,10,10,10,10,10,10,10,11,10,10,10,10,11,10,11,10,10,10,10)
linear+F weak : (10,11,10,11,12,13,11,11,13,14,10,10,10,11,11,11,12,10,13,10)
linear+F flatten : (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,10)
linear+F careless : (10,11,10,10,10,10,10,10,10,10,10,10,10,11,10,10,10,10,10,10)
linear+F binary : (10,11,10,10,10,10,10,10,10,10,10,10,10,11,10,10,10,10,10,10)
linear-F invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
linear-F forced : (12,12,12,13,13,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12)
linear-F weak : (12,12,12,18,13,12,12,14,14,14,12,12,12,12,13,12,12,12,12,12)
linear-F flatten : (12,12,12,12,12,12,12,12,12,12,13,12,12,12,12,12,12,12,12,12)
linear-F careless : (12,12,13,12,12,12,13,12,13,13,12,12,12,12,12,12,12,12,12,12)
linear-F binary : (12,12,13,12,12,12,13,12,13,13,12,12,12,12,12,12,12,12,12,12)
mixed invariant: (359,360,359,359,359,359,359,359,359,359,359,359,359,359,360,359,359,359,359,359)
mixed forced : (14,13,14,14,13,13,13,14,13,14,14,14,14,13,14,13,13,14,13,13)
mixed weak : (13,13,14,14,13,13,13,14,13,18,13,16,14,13,15,14,13,14,13,13)
mixed flatten : (13,14,14,14,14,14,13,14,14,14,13,14,13,14,14,13,13,14,14,13)
mixed careless : (14,13,14,14,13,14,14,14,14,14,14,14,13,14,13,14,13,14,13,13)
mixed binary : (14,13,14,14,13,14,14,14,14,14,14,14,13,14,13,14,13,14,13,13)
Clifford invariant: (361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361)
Clifford forced : (21,21,23,21,21,21,22,21,23,21,22,21,21,21,21,22,21,21,21,22)
Clifford weak : (21,21,23,21,21,21,22,21,23,21,21,21,21,21,21,22,21,21,21,22)
Clifford flatten : (21,21,22,21,22,22,21,23,21,21,22,22,22,22,22,21,21,22,22,22)
Clifford careless : (21,22,22,21,21,22,22,23,21,21,21,22,22,21,21,21,22,22,22,23)
Clifford binary : (21,22,22,21,21,22,22,23,21,21,21,22,22,21,21,21,22,22,22,23)
Clifford gyro : (23,23,23,23,24,23,23,24,23,24,23,23,23,23,23,23,23,23,23,23)
halfplane invariant: (35,35,35,35,36,38,37,35,36,36,37,36,35,36,35,36,36,38,38,35)
polar basic : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar improved : (360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360)
polar F/F : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar F/T : (360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360)
polar T/F : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar T/T : (360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360)
test_walk
linear+F invariant: (658,606,622,603,606,608,667,620,615,616,616,619,631,609,613,614,632,635,592,612)
linear+F forced : (632,617,606,617,608,607,607,628,627,632,626,627,596,652,623,639,615,617,615,616)
linear+F weak : (613,626,622,636,606,605,640,594,609,615,592,639,625,607,613,600,635,620,622,604)
linear+F flatten : (605,618,608,625,677,649,612,607,614,649,621,609,602,599,615,645,609,597,597,638)
linear+F careless : (617,615,620,608,603,606,654,597,612,598,626,624,601,613,616,609,602,627,601,619)
linear+F binary : (617,615,620,608,603,606,654,597,612,598,626,624,601,613,616,609,602,627,601,619)
linear-F invariant: (309,298,341,329,349,304,302,301,292,314,305,310,322,307,314,1315,1312,295,10000,10000)
linear-F forced : (1294,1290,1318,1308,1297,1287,1297,1295,1348,1304,1301,1309,1303,1318,292,1299,1294,1291,1288,1298)
linear-F weak : (298,295,301,289,299,289,287,301,297,294,305,297,316,286,292,291,301,293,303,299)
linear-F flatten : (297,1324,1299,1293,1315,1301,1313,1305,1305,306,1282,1310,1307,1309,1292,1306,1296,1315,1313,1289)
linear-F careless : (1305,1310,1299,1298,1308,307,1318,1296,1293,1300,302,1306,1298,1287,1299,1315,1312,290,1290,1298)
linear-F binary : (1305,1310,1299,1298,1308,307,1318,1296,1293,1300,302,1306,1298,1287,1299,1315,1312,290,1290,1298)
mixed invariant: (622,634,587,620,607,619,609,612,599,646,607,623,616,590,615,592,637,636,659,613)
mixed forced : (599,666,588,608,607,602,630,671,601,602,618,630,618,601,599,599,614,601,596,617)
mixed weak : (599,666,588,608,607,602,630,671,601,602,618,630,618,601,599,599,614,601,596,617)
mixed flatten : (611,616,607,605,610,603,595,605,593,614,617,593,602,642,610,616,625,593,636,617)
mixed careless : (622,634,587,620,607,619,609,612,599,646,607,623,616,590,615,592,637,636,659,613)
mixed binary : (622,634,587,620,607,619,609,612,599,646,607,623,616,590,615,592,637,636,659,613)
Clifford invariant: (622,634,587,620,607,619,609,612,599,646,607,623,616,590,615,592,637,636,659,613)
Clifford forced : (599,666,588,608,607,602,630,671,601,602,618,630,618,601,599,599,614,601,596,617)
Clifford weak : (599,666,588,608,607,602,630,671,601,602,618,630,618,601,599,599,614,601,596,617)
Clifford flatten : (611,616,607,605,610,603,595,605,593,614,617,593,602,642,610,616,625,593,636,617)
Clifford careless : (622,634,587,620,607,619,609,612,599,646,607,623,616,590,615,592,637,636,659,613)
Clifford binary : (622,634,587,620,607,619,609,612,599,646,607,623,616,590,615,592,637,636,659,613)
Clifford gyro : (600,586,602,621,625,621,625,603,593,630,634,600,586,597,600,609,601,592,617,615)
halfplane invariant: (600,586,602,621,625,621,625,603,593,630,634,600,586,597,600,609,601,592,617,615)
polar basic : (1055,67,1078,66,72,1050,66,1073,70,1052,66,1070,66,67,71,73,1064,1070,67,66)
polar improved : (71,1068,1073,1059,67,55,67,1071,65,1052,1067,1078,67,63,69,1067,57,66,69,1059)
polar F/F : (605,566,605,563,566,583,565,591,578,616,591,568,601,569,584,559,621,579,589,601)
polar F/T : (573,596,633,569,581,590,565,588,590,581,600,614,597,571,595,619,576,573,582,631)
polar T/F : (594,662,662,598,591,686,590,610,593,592,588,588,600,581,598,572,618,578,589,588)
polar T/T : (583,594,601,586,570,601,594,579,585,581,582,614,649,614,674,639,588,580,587,588)
test_close
linear+F invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,18,78,130,126,118)
linear+F forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,11,70,110,118)
linear+F weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,11,70,110,118)
linear+F flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,55,99,116)
linear+F careless : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,67,107,113)
linear+F binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,67,107,113)
linear-F invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,89,117,118)
linear-F forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,73,117,117)
linear-F weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,73,117,116)
linear-F flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,15,49,103,115)
linear-F careless : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,62,112,115)
linear-F binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,62,112,115)
mixed invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,36,101,117,115)
mixed forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,72,114,117)
mixed weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,72,114,115)
mixed flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,75,115,116)
mixed careless : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,73,113,112)
mixed binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,73,113,112)
Clifford invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford careless : (1666,1698,1241,859,666,545,447,378,339,298,262,245,244,207,196,175,170,168,157,144)
Clifford binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford gyro : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
halfplane invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar basic : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar improved : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar F/F : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar F/T : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar T/F : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar T/T : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
test_count
linear+F invariant: (spin(24A 34M 9D 4F) L0(24A 34M 9D 4F) L1(24A 34M 9D 4F) ip(9A 9M) ii(51A 51M 9D) d0(1F) angle(1F) inverse() push(29A 42M 10D 2F))
linear+F forced : (spin(27A 46M 9D 5F) L0(27A 46M 9D 5F) L1(27A 46M 9D 5F) ip(12A 15M 1F) ii(54A 73M 9D 3F) d0(1F) angle(1F) inverse() push(32A 54M 10D 3F))
linear+F weak : (spin(30A 49M 9D 5F) L0(30A 49M 9D 5F) L1(30A 49M 9D 5F) ip(12A 15M 1F) ii(57A 76M 9D 3F) d0(3A 4M 2F) angle(1F) inverse() push(38A 63M 10D 4F))
linear+F flatten : (spin(27A 37M 17D 4F) L0(27A 37M 17D 4F) L1(27A 37M 17D 4F) ip(9A 9M 2D) ii(54A 54M 17D) d0(3A 4M 2F) angle(1F) inverse() push(35A 51M 18D 3F))
linear+F careless : (spin(27A 37M 9D 4F) L0(27A 37M 9D 4F) L1(27A 37M 9D 4F) ip(9A 9M) ii(54A 64M 9D 2F) d0(3A 4M 2F) angle(1F) inverse() push(35A 51M 10D 3F))
linear+F binary : (spin(27A 37M 9D 4F) L0(27A 37M 9D 4F) L1(27A 37M 9D 4F) ip(9A 9M) ii(54A 64M 9D 2F) d0(3A 4M 2F) angle(1F) inverse() push(35A 51M 10D 3F))
linear-F invariant: (spin(2F) L0(2F) L1(2F) ip(9A 9M) ii(27A 27M) d0(1F) angle(1F) inverse() push(5A 8M 1D))
linear-F forced : (spin(3A 12M 3F) L0(3A 12M 3F) L1(3A 12M 3F) ip(12A 15M 1F) ii(30A 39M 1F) d0(1F) angle(1F) inverse() push(8A 20M 1D 1F))
linear-F weak : (spin(3A 12M 3F) L0(3A 12M 3F) L1(3A 12M 3F) ip(12A 15M 1F) ii(30A 39M 1F) d0(3A 4M 2F) angle(1F) inverse() push(11A 26M 1D 2F))
linear-F flatten : (spin(8D 2F) L0(8D 2F) L1(8D 2F) ip(9A 9M 2D) ii(27A 27M 8D) d0(3A 4M 2F) angle(1F) inverse() push(8A 14M 9D 1F))
linear-F careless : (spin(2F) L0(2F) L1(2F) ip(9A 9M) ii(27A 27M) d0(3A 4M 2F) angle(1F) inverse() push(8A 14M 1D 1F))
linear-F binary : (spin(2F) L0(2F) L1(2F) ip(9A 9M) ii(27A 27M) d0(3A 4M 2F) angle(1F) inverse() push(8A 14M 1D 1F))
mixed invariant: (spin(2F) L0(2F) L1(2F) ip(17A 24M) ii(12A 16M) d0(1F) angle(1F) inverse() push(5A 7M))
mixed forced : (spin(2F) L0(2F) L1(2F) ip(20A 30M 1F) ii(15A 28M 1F) d0(1F) angle(1F) inverse() push(7A 18M 1F))
mixed weak : (spin(2F) L0(2F) L1(2F) ip(20A 30M 1F) ii(15A 28M 1F) d0(3A 4M 2F) angle(1F) inverse() push(10A 24M 2F))
mixed flatten : (spin(1F) L0(1F) L1(1F) ip(17A 15M 2D) ii(12A 12M) d0(3A 4M 2F) angle(1F) inverse() push(8A 15M 1F))
mixed careless : (spin(2F) L0(2F) L1(2F) ip(17A 24M) ii(12A 16M) d0(3A 4M 2F) angle(1F) inverse() push(8A 13M 1F))
mixed binary : (spin(2F) L0(2F) L1(2F) ip(17A 24M) ii(12A 16M) d0(3A 4M 2F) angle(1F) inverse() push(8A 13M 1F))
Clifford invariant: (spin(2F) L0(2F) L1(2F) ip(12A 28M 1F) ii(12A 16M) d0(1F) angle(1F) inverse() push())
Clifford forced : (spin(2F) L0(2F) L1(2F) ip(13A 29M 1F) ii(15A 28M 1F) d0(1F) angle(1F) inverse() push())
Clifford weak : (spin(2F) L0(2F) L1(2F) ip(13A 29M 1F) ii(15A 28M 1F) d0(2A 4M 2F) angle(1F) inverse() push())
Clifford flatten : (spin(1F) L0(1F) L1(1F) ip(11A 20M) ii(12A 19M) d0(2A 4M 2F) angle(1F) inverse() push())
Clifford careless : (spin(2F) L0(2F) L1(2F) ip(11A 18M) ii(12A 16M) d0(2A 4M 2F) angle(1F) inverse() push())
Clifford binary : (spin(2F) L0(2F) L1(2F) ip(11A 18M) ii(12A 16M) d0(2A 4M 2F) angle(1F) inverse() push())
Clifford gyro : (spin(2F) L0(2F) L1(2F) ip(5A 10M 2D) ii(4A 8M) d0(9A 12M 2D 5F) angle(7A 8M 2D 4F) inverse() push(11A 8M 2D 3F))
halfplane invariant: (spin(2F) L0(2F) L1(2F) ip(5A 10M 2D) ii(4A 8M) d0(8A 16M 2D 5F) angle(8A 16M 2D 5F) inverse() push(12A 16M 2D 4F))
polar basic : (spin(2F) L0() L1() ip(15A 25M 2D 12F) ii(53A 73M 2D 17F) d0() angle(1F) inverse(4A 4M) push())
polar improved : (spin(2F) L0() L1() ip(20A 41M 2D 10F) ii(59A 88M 2D 15F) d0() angle(1F) inverse(4A 4M) push())
polar F/F : (spin() L0() L1() ip(5A 7M 14F) ii(10A 11M 21F) d0() angle() inverse(14A) push())
polar F/T : (spin() L0() L1() ip(5A 7M 14F) ii(14A 8M 18F) d0() angle() inverse(14A) push())
polar T/F : (spin() L0() L1() ip(5A 7M 14F) ii(11A 11M 21F) d0() angle() inverse(2A) push())
polar T/T : (spin() L0() L1() ip(5A 7M 14F) ii(15A 8M 18F) d0() angle() inverse(2A) push())
```
## Results on the {4,3,5} honeycomb
```
test_loop_iso
linear+F invariant: (32,32,34,34,41,39,60,43,32,31,38,36,36,36,41,50,33,37,33,53)
linear+F forced : (22,22,24,25,25,23,25,25,25,26,23,26,24,26,24,25,24,24,24,26)
linear+F weak : (24,25,26,25,28,26,25,25,27,25,23,27,27,27,27,26,24,24,27,26)
linear+F flatten : (22,22,24,25,25,23,27,26,25,26,25,26,24,26,26,26,24,24,24,26)
linear+F careless : (26,25,26,25,25,26,27,25,26,26,23,26,27,27,26,26,25,24,27,26)
linear+F binary : (26,25,26,25,25,26,27,25,26,26,23,26,27,27,26,26,25,24,27,26)
linear-F invariant: (35,72,27,37,38,43,27,25,29,44,24,47,26,27,28,29,42,35,29,29)
linear-F forced : (26,25,26,25,25,26,25,25,26,27,25,26,27,27,26,27,24,25,24,26)
linear-F weak : (31,25,30,25,26,29,25,25,26,27,25,26,29,27,27,27,24,31,24,26)
linear-F flatten : (22,22,26,25,25,23,25,26,25,26,23,24,24,26,24,27,24,24,24,26)
linear-F careless : (22,22,24,25,26,23,25,25,25,26,23,24,27,26,24,26,24,24,27,26)
linear-F binary : (22,22,24,25,26,23,25,25,25,26,23,24,27,26,24,26,24,24,27,26)
mixed invariant: (49,47,44,47,42,44,47,45,46,47,45,49,46,50,45,49,42,48,49,45)
mixed forced : (51,50,49,49,47,47,46,47,48,47,48,49,50,50,49,47,52,47,48,49)
mixed weak : (51,50,49,49,47,47,46,47,48,47,48,49,50,50,49,47,52,47,48,49)
mixed flatten : (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
mixed careless : (51,50,46,50,47,47,48,47,48,47,48,49,50,50,49,51,52,51,48,49)
mixed binary : (51,50,46,50,47,47,48,47,48,47,48,49,50,50,49,51,52,51,48,49)
Clifford invariant: (46,47,44,44,42,44,47,45,45,46,45,50,46,50,45,39,42,44,49,45)
Clifford forced : (51,50,49,49,47,47,46,47,48,47,48,49,50,50,49,47,52,47,48,49)
Clifford weak : (51,50,49,49,47,47,46,47,48,47,48,49,50,50,49,47,52,47,48,49)
Clifford flatten : (55,78,999,58,57,81,55,79,98,999,58,51,66,52,99,51,58,54,88,66)
Clifford careless : (51,50,46,50,47,47,48,47,48,47,48,49,50,50,49,51,52,51,48,49)
Clifford binary : (51,50,46,50,47,47,48,47,48,47,48,49,50,50,49,51,52,51,48,49)
Clifford gyro : (51,50,49,50,50,47,48,47,51,47,50,49,50,50,49,51,52,54,50,51)
halfplane invariant: (51,50,49,50,47,47,48,47,48,47,50,49,50,50,49,51,52,51,48,51)
polar basic : (12,50,46,49,47,47,48,47,48,3,46,49,50,50,47,7,52,3,48,49)
polar improved : (49,46,49,50,50,47,48,47,51,47,50,49,50,50,49,51,48,51,48,49)
test_loop_point
linear+F invariant: (999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999)
linear+F forced : (22,22,24,25,25,23,25,25,25,26,23,26,24,26,24,25,24,24,24,26)
linear+F weak : (24,25,26,25,28,26,25,25,27,25,23,27,27,27,27,26,24,24,27,26)
linear+F flatten : (22,22,24,25,25,23,27,26,25,26,25,27,24,26,26,26,24,24,24,26)
linear+F careless : (26,25,26,25,25,26,27,25,26,26,23,26,27,27,26,26,25,24,27,26)
linear+F binary : (26,25,26,25,25,26,27,25,26,26,23,26,27,27,26,26,25,24,27,26)
linear-F invariant: (35,72,27,37,38,43,27,25,29,44,24,47,26,27,28,29,42,35,29,29)
linear-F forced : (26,25,26,25,25,26,25,25,26,27,25,26,27,27,26,27,24,25,24,26)
linear-F weak : (31,25,30,25,26,29,25,25,26,27,25,26,29,27,27,27,24,31,24,26)
linear-F flatten : (22,22,26,25,25,23,25,26,25,26,23,24,24,26,24,27,24,24,24,26)
linear-F careless : (22,22,24,25,26,23,25,25,25,26,23,24,27,26,24,26,24,24,27,26)
linear-F binary : (22,22,24,25,26,23,25,25,25,26,23,24,27,26,24,26,24,24,27,26)
mixed invariant: (24,22,22,25,23,25,26,22,24,22,23,25,26,27,24,23,25,22,23,24)
mixed forced : (26,25,26,25,25,23,25,25,26,27,23,26,27,26,26,26,25,24,24,26)
mixed weak : (27,25,30,25,25,23,25,25,26,27,23,26,27,26,26,28,25,24,24,28)
mixed flatten : (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
mixed careless : (26,25,24,25,25,26,27,25,26,26,26,26,27,27,26,26,24,25,24,26)
mixed binary : (26,25,24,25,25,26,27,25,26,26,26,26,27,27,26,26,24,25,24,26)
Clifford invariant: (46,45,48,44,42,44,45,48,47,48,46,41,45,49,48,39,50,48,51,45)
Clifford forced : (49,50,46,49,47,47,46,45,48,47,45,49,50,50,49,51,52,47,48,49)
Clifford weak : (49,50,46,49,47,47,46,45,48,47,45,49,50,50,49,51,52,47,48,49)
Clifford flatten : (50,48,46,49,47,46,48,47,48,47,45,47,50,50,49,47,42,47,48,49)
Clifford careless : (3,3,1,2,2,2,2,2,3,3,3,2,3,2,1,2,3,3,1,3)
Clifford binary : (51,48,49,49,47,47,48,47,48,47,45,49,50,50,49,47,52,47,48,49)
Clifford gyro : (51,50,46,50,50,47,48,48,51,47,50,49,50,50,49,51,52,51,48,49)
halfplane invariant: (49,50,46,49,47,47,48,47,51,47,50,49,50,50,49,51,52,51,48,49)
polar basic : (12,50,46,49,47,47,48,47,48,3,46,49,50,50,47,7,52,3,48,49)
polar improved : (49,46,49,50,50,47,48,47,51,47,50,49,50,50,49,51,48,51,48,49)
test_angledist
linear+F invariant: (999,999,999)
linear+F forced : (26,26,32)
linear+F weak : (26,32,32)
linear+F flatten : (26,26,32)
linear+F careless : (26,26,32)
linear+F binary : (26,26,32)
linear-F invariant: (999,999,999)
linear-F forced : (26,26,32)
linear-F weak : (32,26,32)
linear-F flatten : (26,26,32)
linear-F careless : (26,32,32)
linear-F binary : (26,32,32)
mixed invariant: (999,999,999)
mixed forced : (26,26,32)
mixed weak : (26,26,32)
mixed flatten : (2,2,1)
mixed careless : (26,26,32)
mixed binary : (26,26,32)
Clifford invariant: (999,999,999)
Clifford forced : (57,57,47)
Clifford weak : (69,57,47)
Clifford flatten : (57,57,47)
Clifford careless : (5,4,4)
Clifford binary : (57,57,47)
Clifford gyro : (57,69,57)
halfplane invariant: (999,999,999)
polar basic : (532,532,5)
polar improved : (532,532,532)
test_similarity
linear+F invariant: (17,16,16,16,16,16,17,16,17,16,17,17,16,16,16,17,17,16,16,17)
linear+F forced : (17,17,17,18,19,18,18,18,18,17,18,18,17,18,17,18,18,17,17,17)
linear+F weak : (17,17,17,18,18,18,18,18,17,17,18,18,17,18,17,18,17,17,17,17)
linear+F flatten : (17,17,17,18,18,18,18,18,17,17,18,18,17,18,17,18,18,17,17,17)
linear+F careless : (17,17,17,18,19,18,17,18,17,17,18,18,17,18,17,17,18,17,17,17)
linear+F binary : (17,17,17,18,19,18,17,18,17,17,18,18,17,18,17,17,18,17,17,17)
linear-F invariant: (17,18,18,17,17,17,17,18,17,18,17,18,17,18,17,17,17,17,17,17)
linear-F forced : (18,19,18,18,18,18,18,18,18,18,18,19,19,18,19,19,18,19,18,18)
linear-F weak : (18,19,18,18,18,17,18,18,18,18,19,19,19,18,19,19,18,19,18,18)
linear-F flatten : (19,18,19,18,18,18,18,20,18,19,18,18,20,19,19,19,18,19,18,18)
linear-F careless : (19,18,18,18,19,18,18,20,19,18,18,19,19,19,18,18,19,18,18,18)
linear-F binary : (19,18,18,18,19,18,18,20,19,18,18,19,19,19,18,18,19,18,18,18)
mixed invariant: (18,19,19,19,19,19,18,19,19,18,18,19,19,19,19,19,19,18,19,18)
mixed forced : (19,19,19,18,18,19,19,18,19,19,19,19,19,19,19,20,19,19,19,19)
mixed weak : (19,19,19,18,18,19,19,18,18,19,19,19,19,20,19,18,19,18,18,19)
mixed flatten : (19,19,18,19,19,18,19,20,18,19,19,20,19,19,20,18,19,19,19,20)
mixed careless : (19,19,19,19,19,20,20,19,19,19,19,19,19,19,19,18,19,19,19,19)
mixed binary : (19,19,19,19,19,20,20,19,19,19,19,19,19,19,19,18,19,19,19,19)
Clifford invariant: (34,33,34,35,33,34,33,32,34,34,33,34,34,34,34,35,33,34,33,34)
Clifford forced : (35,36,35,37,36,35,35,36,36,36,35,37,35,36,36,36,36,36,36,35)
Clifford weak : (35,36,35,37,36,35,35,36,36,36,35,37,35,36,36,36,36,36,36,35)
Clifford flatten : (35,36,35,35,36,36,37,37,36,36,36,36,36,36,38,35,37,36,37,36)
Clifford careless : (36,36,38,36,37,35,35,37,36,36,37,35,37,35,35,35,35,37,36,38)
Clifford binary : (36,36,38,36,37,35,35,37,36,36,37,35,37,35,35,35,35,37,36,38)
Clifford gyro : (36,37,38,36,35,37,35,36,38,36,36,36,36,36,36,37,35,34,35,36)
halfplane invariant: (36,35,36,36,37,38,38,36,37,36,37,36,35,36,35,37,35,36,36,35)
polar basic : (17,18,18,17,17,17,17,18,18,18,17,17,17,18,17,17,17,17,17,17)
polar improved : (34,37,35,36,37,36,34,36,35,35,35,34,36,35,36,36,35,35,35,35)
test_dissimilarity
linear+F invariant: (63,63,64,75,63,63,64,64,64,64,63,63,73,66,63,63,76,74,64,64)
linear+F forced : (6,7,7,7,7,7,7,7,7,7,7,7,6,7,7,7,7,7,7,6)
linear+F weak : (7,9,8,8,7,8,8,7,13,8,7,8,6,7,7,8,8,7,8,7)
linear+F flatten : (8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,7,7,7)
linear+F careless : (7,7,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6)
linear+F binary : (7,7,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6)
linear-F invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
linear-F forced : (10,10,10,10,10,10,10,10,10,10,10,9,9,10,9,10,10,9,10,9)
linear-F weak : (12,9,9,14,10,9,9,11,11,11,11,13,9,12,10,13,9,10,15,10)
linear-F flatten : (10,10,10,9,9,9,10,10,10,10,10,10,10,9,9,10,10,10,10,10)
linear-F careless : (10,9,9,10,9,10,9,10,9,10,10,10,10,10,9,9,9,10,10,9)
linear-F binary : (10,9,9,10,9,10,9,10,9,10,10,10,10,10,9,9,9,10,10,9)
mixed invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
mixed forced : (10,10,10,10,10,10,10,10,9,10,10,10,10,10,9,9,9,10,9,10)
mixed weak : (10,16,11,15,9,12,10,9,10,14,10,10,10,11,11,11,11,10,11,11)
mixed flatten : (9,10,9,10,10,10,9,10,9,10,10,10,10,9,10,9,10,9,9,9)
mixed careless : (10,9,9,10,10,10,10,9,10,10,9,10,10,10,10,10,9,9,9,10)
mixed binary : (10,9,9,10,10,10,10,9,10,10,9,10,10,10,10,10,9,9,9,10)
Clifford invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
Clifford forced : (18,17,17,19,20,17,18,18,19,19,18,18,17,19,18,18,19,18,19,18)
Clifford weak : (19,17,17,18,19,17,18,18,17,18,18,18,17,18,18,17,18,18,19,19)
Clifford flatten : (19,18,18,18,19,18,18,18,18,18,18,19,19,18,18,19,18,19,18,18)
Clifford careless : (18,18,18,18,18,18,18,19,19,18,18,18,18,18,18,19,18,19,19,18)
Clifford binary : (18,18,18,18,18,18,18,19,19,18,18,18,18,18,18,19,18,19,19,18)
Clifford gyro : (18,17,18,19,19,19,18,19,18,19,18,18,19,19,19,19,18,18,19,17)
halfplane invariant: (34,35,36,35,35,35,35,34,35,35,36,35,35,37,36,37,35,35,34,35)
polar basic : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar improved : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
test_other
linear+F invariant: (73,50,65,68,65,50,68,50,64,67,65,63,50,66,63,50,68,50,64,67)
linear+F forced : (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10)
linear+F weak : (10,10,11,10,11,17,10,12,13,12,11,11,10,10,10,11,11,16,10,14)
linear+F flatten : (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10)
linear+F careless : (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10)
linear+F binary : (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10)
linear-F invariant: (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
linear-F forced : (12,12,13,12,12,12,12,12,12,12,12,13,12,12,12,12,12,12,12,12)
linear-F weak : (12,12,12,12,13,12,14,13,12,15,12,14,16,12,15,12,12,16,12,12)
linear-F flatten : (12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12)
linear-F careless : (13,12,13,12,12,12,12,12,12,12,12,12,12,12,12,12,13,12,12,12)
linear-F binary : (13,12,13,12,12,12,12,12,12,12,12,12,12,12,12,12,13,12,12,12)
mixed invariant: (359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359)
mixed forced : (14,14,14,13,14,13,14,13,14,14,13,14,14,13,13,14,13,14,14,13)
mixed weak : (15,13,14,13,14,14,16,13,16,14,14,14,13,13,13,14,13,13,14,15)
mixed flatten : (14,13,13,14,13,14,14,14,13,13,14,14,14,14,13,14,14,13,14,14)
mixed careless : (14,14,13,13,13,13,13,13,14,14,13,14,14,13,13,14,13,13,14,13)
mixed binary : (14,14,13,13,13,13,13,13,14,14,13,14,14,13,13,14,13,13,14,13)
Clifford invariant: (361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361)
Clifford forced : (22,21,21,21,22,21,22,22,22,22,22,21,21,22,22,22,22,21,21,22)
Clifford weak : (22,21,21,21,22,21,22,22,22,22,22,21,21,22,22,22,22,21,21,22)
Clifford flatten : (22,22,22,22,22,22,22,22,22,22,22,21,21,22,22,22,22,22,22,22)
Clifford careless : (22,21,22,22,22,23,21,21,21,22,22,21,22,21,22,22,22,22,22,22)
Clifford binary : (22,21,22,22,22,23,21,21,21,22,22,21,22,21,22,22,22,22,22,22)
Clifford gyro : (23,24,23,23,23,24,23,23,23,23,23,23,23,23,23,23,23,24,23,23)
halfplane invariant: (35,35,35,35,35,35,35,35,35,36,37,35,35,35,36,36,35,35,35,35)
polar basic : (356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356)
polar improved : (360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360)
test_walk
linear+F invariant: (614,576,600,601,581,579,609,600,596,565,596,610,583,588,595,606,591,592,579,614)
linear+F forced : (598,653,583,603,584,597,581,582,618,568,608,621,586,596,636,604,584,619,585,586)
linear+F weak : (606,604,616,593,604,592,583,611,598,576,597,579,603,584,575,591,584,587,600,591)
linear+F flatten : (619,599,580,615,608,615,600,593,601,577,615,603,579,590,635,589,589,586,560,589)
linear+F careless : (620,596,575,593,602,591,576,587,603,574,596,604,589,615,599,623,586,620,612,602)
linear+F binary : (620,596,575,593,602,591,576,587,603,574,596,604,589,615,599,623,586,620,612,602)
linear-F invariant: (293,291,289,304,1295,307,285,302,290,297,1311,289,320,292,305,289,285,2132,2137,284)
linear-F forced : (1292,288,1303,1298,301,1288,1285,1290,297,288,304,298,293,299,1300,1291,1294,1276,1281,1288)
linear-F weak : (288,288,284,300,301,291,286,294,297,288,304,288,293,299,300,286,291,10000,281,293)
linear-F flatten : (1292,1297,1303,1311,1292,1285,1296,1297,10000,1299,1321,298,1311,1288,293,1315,1287,1280,1283,1286)
linear-F careless : (1288,1292,1288,303,1295,1295,1285,1303,291,1290,1310,289,1321,1290,1298,1289,1284,1276,1282,1287)
linear-F binary : (1288,1292,1288,303,1295,1295,1285,1303,291,1290,1310,289,1321,1290,1298,1289,1284,1276,1282,1287)
mixed invariant: (592,582,592,572,580,598,589,597,594,567,595,600,605,591,602,611,596,580,589,587)
mixed forced : (592,587,597,579,582,627,592,603,603,565,596,576,589,591,596,606,592,594,591,592)
mixed weak : (592,587,597,579,582,627,592,603,603,565,596,576,589,591,596,606,592,594,591,592)
mixed flatten : (28,363,52,303,296,336,292,316,288,287,308,298,298,298,310,314,293,371,353,324)
mixed careless : (592,582,592,572,580,598,589,597,594,567,595,600,605,591,602,611,596,580,589,587)
mixed binary : (592,582,592,572,580,598,589,597,594,567,595,600,605,591,602,611,596,580,589,587)
Clifford invariant: (592,582,592,572,580,598,589,597,594,567,595,600,605,591,602,611,596,580,589,587)
Clifford forced : (592,587,597,579,582,627,592,603,603,565,596,576,589,591,596,606,592,594,591,592)
Clifford weak : (592,587,597,579,582,627,592,603,603,565,596,576,589,591,596,606,592,594,591,592)
Clifford flatten : (614,604,595,598,570,595,589,587,599,573,599,585,603,602,634,602,596,600,584,596)
Clifford careless : (592,582,592,572,580,598,589,597,594,567,595,600,605,591,602,611,596,580,589,587)
Clifford binary : (592,582,592,572,580,598,589,597,594,567,595,600,605,591,602,611,596,580,589,587)
Clifford gyro : (601,581,606,584,595,604,609,589,582,596,601,601,579,601,619,589,588,583,588,587)
halfplane invariant: (576,614,594,596,580,604,594,600,610,566,593,584,603,597,606,608,588,579,575,590)
polar basic : (25,1047,69,1045,1045,1033,59,1065,1041,67,1064,56,1044,1034,70,68,55,53,53,55)
polar improved : (55,58,70,1045,1045,1057,56,1065,59,68,1065,55,1044,1034,1070,66,1056,53,52,58)
test_close
linear+F invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,22)
linear+F forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear+F weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear+F flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear+F careless : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear+F binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear-F invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8)
linear-F forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear-F weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear-F flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
linear-F careless : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
linear-F binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
mixed invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
mixed forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
mixed weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
mixed flatten : (5000,2716,1760,1229,986,774,667,584,500,460,430,365,344,299,286,283,257,237,231,234)
mixed careless : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
mixed binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford forced : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford weak : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford flatten : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford careless : (1666,1539,1427,1047,817,653,547,483,418,381,350,308,283,260,247,230,212,202,188,183)
Clifford binary : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Clifford gyro : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
halfplane invariant: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar basic : (0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
polar improved : (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
test_count
linear+F invariant: (spin(60A 78M 24D 5F) L0(60A 78M 24D 5F) L1(60A 78M 24D 5F) ip(16A 16M) ii(124A 142M 24D 3F) d0(1F) angle(1F) inverse() push(70A 96M 25D 3F))
linear+F forced : (spin(64A 98M 24D 6F) L0(64A 98M 24D 6F) L1(64A 98M 24D 6F) ip(20A 24M 1F) ii(128A 162M 24D 4F) d0(1F) angle(1F) inverse() push(74A 116M 25D 4F))
linear+F weak : (spin(68A 102M 24D 6F) L0(68A 102M 24D 6F) L1(68A 102M 24D 6F) ip(20A 24M 1F) ii(132A 166M 24D 4F) d0(4A 5M 2F) angle(1F) inverse() push(82A 128M 25D 5F))
linear+F flatten : (spin(64A 82M 39D 5F) L0(64A 82M 39D 5F) L1(64A 82M 39D 5F) ip(16A 16M 3D) ii(128A 146M 39D 3F) d0(4A 5M 2F) angle(1F) inverse() push(78A 108M 40D 4F))
linear+F careless : (spin(64A 82M 24D 5F) L0(64A 82M 24D 5F) L1(64A 82M 24D 5F) ip(16A 16M) ii(128A 146M 24D 3F) d0(4A 5M 2F) angle(1F) inverse() push(78A 108M 25D 4F))
linear+F binary : (spin(64A 82M 24D 5F) L0(64A 82M 24D 5F) L1(64A 82M 24D 5F) ip(16A 16M) ii(128A 146M 24D 3F) d0(4A 5M 2F) angle(1F) inverse() push(78A 108M 25D 4F))
linear-F invariant: (spin(2F) L0(2F) L1(2F) ip(16A 16M) ii(64A 64M) d0(1F) angle(1F) inverse() push(10A 18M 1D))
linear-F forced : (spin(4A 20M 3F) L0(4A 20M 3F) L1(4A 20M 3F) ip(20A 24M 1F) ii(68A 84M 1F) d0(1F) angle(1F) inverse() push(14A 38M 1D 1F))
linear-F weak : (spin(4A 20M 3F) L0(4A 20M 3F) L1(4A 20M 3F) ip(20A 24M 1F) ii(68A 84M 1F) d0(4A 5M 2F) angle(1F) inverse() push(18A 46M 1D 2F))
linear-F flatten : (spin(15D 2F) L0(15D 2F) L1(15D 2F) ip(16A 16M 3D) ii(64A 64M 15D) d0(4A 5M 2F) angle(1F) inverse() push(14A 26M 16D 1F))
linear-F careless : (spin(2F) L0(2F) L1(2F) ip(16A 16M) ii(64A 64M) d0(4A 5M 2F) angle(1F) inverse() push(14A 26M 1D 1F))
linear-F binary : (spin(2F) L0(2F) L1(2F) ip(16A 16M) ii(64A 64M) d0(4A 5M 2F) angle(1F) inverse() push(14A 26M 1D 1F))
mixed invariant: (spin(2F) L0(2F) L1(2F) ip(52A 64M) ii(56A 64M) d0(1F) angle(1F) inverse() push(7A 10M))
mixed forced : (spin(2F) L0(2F) L1(2F) ip(56A 72M 1F) ii(63A 88M 1F) d0(1F) angle(1F) inverse() push(10A 30M 1F))
mixed weak : (spin(2F) L0(2F) L1(2F) ip(56A 72M 1F) ii(63A 88M 1F) d0(4A 5M 2F) angle(1F) inverse() push(14A 38M 2F))
mixed flatten : (spin(1F) L0(1F) L1(1F) ip(52A 49M 3D) ii(56A 56M) d0(4A 5M 2F) angle(1F) inverse() push(11A 21M 1F))
mixed careless : (spin(2F) L0(2F) L1(2F) ip(52A 64M) ii(56A 64M) d0(4A 5M 2F) angle(1F) inverse() push(11A 18M 1F))
mixed binary : (spin(2F) L0(2F) L1(2F) ip(52A 64M) ii(56A 64M) d0(4A 5M 2F) angle(1F) inverse() push(11A 18M 1F))
Clifford invariant: (spin(2F) L0(2F) L1(2F) ip(39A 68M 1F) ii(56A 64M) d0(1F) angle(1F) inverse() push())
Clifford forced : (spin(2F) L0(2F) L1(2F) ip(39A 68M 1F) ii(63A 88M 1F) d0(1F) angle(1F) inverse() push())
Clifford weak : (spin(2F) L0(2F) L1(2F) ip(39A 68M 1F) ii(63A 88M 1F) d0(3A 5M 2F) angle(1F) inverse() push())
Clifford flatten : (spin(1F) L0(1F) L1(1F) ip(36A 51M) ii(56A 71M) d0(3A 5M 2F) angle(1F) inverse() push())
Clifford careless : (spin(2F) L0(2F) L1(2F) ip(36A 48M) ii(56A 64M) d0(3A 5M 2F) angle(1F) inverse() push())
Clifford binary : (spin(2F) L0(2F) L1(2F) ip(36A 48M) ii(56A 64M) d0(3A 5M 2F) angle(1F) inverse() push())
Clifford gyro : (spin(8A 1F) L0(8A 1F) L1(8A 1F) ip(23A 38M 1D) ii(24A 32M) d0(23A 26M 1D 5F) angle(20A 21M 1D 4F) inverse() push(28A 21M 1D 3F))
halfplane invariant: (spin(8A 2F) L0(8A 2F) L1(8A 2F) ip(23A 38M 1D) ii(24A 32M) d0(23A 38M 1D 5F) angle(23A 38M 1D 5F) inverse() push(31A 38M 1D 4F))
polar basic : (spin(2F) L0() L1() ip(24A 35M 3D 12F) ii(114A 135M 3D 17F) d0() angle(1F) inverse(9A 9M) push())
polar improved : (spin(2F) L0() L1() ip(29A 51M 3D 10F) ii(120A 150M 3D 15F) d0() angle(1F) inverse(9A 9M) push())
```

538
devmods/reps/tests.cpp Normal file
View File

@ -0,0 +1,538 @@
namespace reps {
constexpr int test_dim = 3;
constexpr bool in_hyperbolic = true;
int edges, valence;
void prepare_tests() {
hr::start_game();
if(MDIM != test_dim) throw hr::hr_exception("fix your dimension");
if(!(in_hyperbolic ? hyperbolic : sphere)) throw hr::hr_exception("fix your geometry");
if(hr::variation != hr::eVariation::pure) throw hr::hr_exception("fix your variation");
if(quotient) throw hr::hr_exception("fix your quotient");
if(test_dim == 4) {
if(cginf.tiling_name != "{4,3,5}") throw hr::hr_exception("only {4,3,5} implemented in 3D");
edges = 4;
valence = 5;
}
else {
edges = hr::cwt.at->type;
bool ok;
valence = hr::get_valence(hr::cwt.at, 1, ok);
}
}
struct data {
using Number = hr::ld;
static constexpr int Dim = test_dim;
static constexpr int Flipped = in_hyperbolic ? test_dim-1 : -1;
};
struct countdata {
using Number = countfloat;
static constexpr int Dim = data::Dim;
static constexpr int Flipped = data::Flipped;
};
struct bigdata {
using Number = big;
static constexpr int Dim = data::Dim;
static constexpr int Flipped = data::Flipped;
};
using good = rep_linear_nn<bigdata>;
int debug; // 0 -- never, 1 -- only errors, 2 -- always
vector<cell*> randomwalk(std::mt19937& gen, cell *from, int dist) {
vector<cell*> res = { from };
while(celldistance(from, res.back()) < dist) {
int i = gen() % res.back()->type;
res.push_back(res.back()->cmove(i));
}
return res;
}
template<class N> N rand01(std::mt19937& gen) { return N(((gen() & HRANDMAX) | 1) / (HRANDMAX+1.)); }
vector<cell*> random_return(std::mt19937& gen, cell *from, cell *to, ld peq, ld pbad) {
vector<cell*> res = { from };
ld d = celldistance(to, from);
while(to != res.back()) {
int i = gen() % res.back()->type;
cell *r1 = res.back()->cmove(i);
ld d1 = celldistance(to, r1);
bool ok = d1 < d ? true : d1 == d ? rand01<ld>(gen) < peq : rand01<ld>(gen) < pbad;
if(ok) { res.push_back(r1); d = d1; }
}
return res;
}
vector<cell*> vrev(vector<cell*> a) { reverse(a.begin(), a.end()); return a; }
vector<cell*> vcon(vector<cell*> a, vector<cell*> b) { for(auto bi: b) a.push_back(bi); return a; }
template<class N> N edge_of_triangle_with_angles(N alpha, N beta, N gamma) {
N of = (cos(alpha) + cos(beta) * cos(gamma)) / (sin(beta) * sin(gamma));
if(hyperbolic) return acosh(of);
return acos(of);
}
template<class N> N get_edgelen() {
N beta = get_deg<N>(360)/valence;
return edge_of_triangle_with_angles<N> (beta, get_deg<N>(180)/edges, get_deg<N>(180)/edges);
}
template<class T> typename T::isometry cpush(int c, typename T::data::Number distance) {
return T::lorentz(c, T::data::Dim-1, distance);
}
template<class T> struct cube_rotation_data_t {
std::vector<std::pair<hr::transmatrix, typename T::isometry>> mapping;
};
template<class T> cube_rotation_data_t<T> cube_rotation_data;
template<class T> cube_rotation_data_t<T>& build_cube_rotation() {
auto& crd = cube_rotation_data<T>;
auto& crdm = crd.mapping;
// using N = typename T::data::Number;
if(crdm.empty()) {
crdm.emplace_back(hr::Id, T::id());
for(int i=0; i<isize(crdm); i++)
for(int j=0; j<3; j++) for(int k=0; k<3; k++) if(j != k) {
hr::transmatrix U = crdm[i].first * hr::cspin90(j, k);
bool is_new = true;
for(int i0=0; i0<isize(crdm); i0++) if(hr::eqmatrix(U, crdm[i0].first)) is_new = false;
// if(is_new) crdm.emplace_back(U, T::apply(crdm[i].second, T::cspin(j, k, get_deg<N>(90))));
if(is_new) crdm.emplace_back(U, T::apply(crdm[i].second, T::cspin90(j, k)));
}
if(isize(crdm) != 24) {
println(hlog, "the number of rotations found: ", isize(crdm));
throw hr::hr_exception("wrong number of rotations");
}
}
return crd;
}
template<class T, class U> U apply_move(cell *a, cell *b, U to) {
if(a == b) return to;
using N = typename T::data::Number;
if constexpr(test_dim == 4) {
auto& crdm = build_cube_rotation<T>().mapping;
int ida = neighborId(a, b);
auto M = hr::currentmap->adj(a, ida);
for(int i0=0; i0<isize(crdm); i0++)
for(int i1=0; i1<isize(crdm); i1++)
if(hr::eqmatrix(M, crdm[i0].first * hr::xpush(1.06128) * crdm[i1].first)) {
to = T::apply(crdm[i1].second, to);
to = T::apply(cpush<T>(0, get_edgelen<N>()), to);
to = T::apply(crdm[i0].second, to);
return to;
}
println(hlog, "tessf = ", hr::cgip->tessf);
println(hlog, "len = ", get_edgelen<N>());
throw hr::hr_exception("rotation not found");
}
int ida = neighborId(a, b);
int idb = neighborId(b, a);
auto P1 = T::cspin(0, 1, idb * get_deg<N>(360) / edges);
to = T::apply(P1, to);
auto P2 = cpush<T>(0, get_edgelen<N>());
to = T::apply(P2, to);
auto P3 = T::cspin(1, 0, get_deg<N>(180) + ida * get_deg<N>(360) / edges);
to = T::apply(P3, to);
return to;
}
template<class T, class U> U apply_path(vector<cell*> path, U to) {
for(int i=hr::isize(path)-2; i>=0; i--)
to = apply_move<T, U> (path[i], path[i+1], to);
return to;
}
template<class T> double test_sanity(int i) {
hr::indenter in(2);
ld d1 = 1.25, d2 = 1.5;
typename good::point gp = good::center();
gp = good::apply(cpush<good>(0, d1), gp);
gp = good::apply(cpush<good>(1, d2), gp);
gp = good::apply(good::cspin(0, 1, get_deg<big>(72)), gp);
typename T::point p = T::center();
p = T::apply(cpush<T>(0, d1), p);
p = T::apply(cpush<T>(1, d2), p);
p = T::apply(T::cspin(0, 1, get_deg<typename T::data::Number>(72)), p);
double res = 0;
#define ADD(x, y) if(debug) println(hlog, "VS ", x, ",", y); res += pow( double(x-y), 2);
#define ADDA(x, y) if(debug) println(hlog, "VS ", x, ",", y); res += pow( cyclefix_on(double(x-y)), 2);
if(debug) println(hlog, "p=", T::print(p));
ADD(T::get_coord(p, 0), good::get_coord(gp, 0));
ADD(T::get_coord(p, 1), good::get_coord(gp, 1));
ADD(T::get_coord(p, 2), good::get_coord(gp, 2));
ADD(T::dist0(p), good::dist0(gp));
ADDA(T::angle(p), good::angle(gp));
return res;
}
template<class T> double test_consistency(int i) {
double res = 0;
using D = typename T::data;
auto a = cpush<T>(0, 1);
auto b = cpush<T>(1, 1);
auto c = cpush<T>(0, 1);
auto s = T::apply(T::apply(a, b), c);
auto sp = T::apply(s, T::center());
auto s1 = T::apply(a, T::apply(b, c));
auto sp1 = T::apply(s1, T::center());
auto sp2 = T::apply(a, T::apply(b, T::apply(c, T::center())));
ADD(T::dist0(sp), T::dist0(sp1));
ADD(T::dist0(sp), T::dist0(sp2));
for(int i=0; i<D::Dim; i++) { ADD(T::get_coord(sp, i), T::get_coord(sp1, i)); }
for(int i=0; i<D::Dim; i++) { ADD(T::get_coord(sp, i), T::get_coord(sp2, i)); }
if(test_dim == 3) {
ADDA(T::angle(sp), T::angle(sp1));
ADDA(T::angle(sp), T::angle(sp2));
}
return res;
}
template<class T> double test_tba(int id) {
std::mt19937 testr; testr.seed(id);
for(int i=0; i<hr::cwt.at->type; i++) {
vector<cell*> p = {hr::cwt.at, hr::cwt.at->cmove(i), hr::cwt.at};
auto h = apply_path<T>(p, T::center());
if(debug == 2) println(hlog, "i=", hr::lalign(3, i), " h = ", T::print(h), " distance =", T::dist0(h));
if(T::dist0(h) >= 0 && T::dist0(h) < 0.1) continue;
exit(1);
}
return 999;
}
template<class T> double test_loop_point(int id) {
std::mt19937 testr; testr.seed(id);
for(int i=0; i<100; i++) {
auto p1 = randomwalk(testr, hr::cwt.at, i);
auto p2 = random_return(testr, p1.back(), hr::cwt.at, 1/16., 1/32.);
auto p = vcon(p1, p2);
if(debug == 2) println(hlog, "path = ", p);
auto h = apply_path<T>(vrev(p), T::center());
if(debug == 2) println(hlog, "i=", hr::lalign(3, i), " h = ", T::print(h), " distance =", T::dist0(h));
if(T::dist0(h) >= 0 && T::dist0(h) < 0.1) continue;
return i;
}
return 999;
}
template<class T> double test_loop_iso(int id) {
std::mt19937 testr; testr.seed(id);
for(int i=0; i<100; i++) {
auto p1 = randomwalk(testr, hr::cwt.at, i);
auto p2 = random_return(testr, p1.back(), hr::cwt.at, 1/16., 1/32.);
auto p = vcon(p1, p2);
if(debug == 2) println(hlog, "path = ", p);
auto h = apply_path<T>(vrev(p), T::id());
auto hr = T::apply(h, T::center());
// println(hlog, "i=", hr::lalign(3, i), " h=", hr);
if(debug == 2) println(hlog, "i=", hr::lalign(3, i), " hr = ", T::print(hr), " distance = ", T::dist0(hr));
if(T::dist0(hr) >= 0 && T::dist0(hr) < 0.1) continue;
if(debug == 1) println(hlog, "i=", hr::lalign(3, i), " hr = ", T::print(hr), " distance = ", T::dist0(hr));
return i;
}
return 999;
}
template<class T, class F> vector<T> repeat_test(const F& f, int qty) {
vector<T> res;
for(int i=0; i<qty; i++) res.push_back(f(i));
return res;
}
template<class T> typename T::isometry random_rotation(std::mt19937& testr) {
using D = typename T::data;
using N = typename D::Number;
if(D::Dim == 3) {
auto alpha = rand01<N>(testr) * get_deg<N>(360);
return T::cspin(0, 1, alpha);
}
auto x = T::id();
for(int i=0; i<100; i++) {
int c0 = testr() % (D::Dim-1);
int c1 = testr() % (D::Dim-1);
if(c0 == c1) continue;
auto len = rand01<N>(testr) * get_deg<N>(360);
x = T::apply(T::cspin(c0, c1, len), x);
}
return x;
}
template<class T> typename T::isometry random_iso(std::mt19937& testr) {
auto x = T::id();
using D = typename T::data;
using N = typename D::Number;
for(int i=0; i<100; i++) {
int c0 = testr() % D::Dim;
int c1 = testr() % D::Dim;
if(c0 == c1) continue;
if(c0 == D::Flipped) std::swap(c0, c1);
N len = c1 < D::Flipped ? rand01<N>(testr) * get_deg<N>(360) : (rand01<N>(testr)-N(0.5)) * N(0.25);
if(c1 == D::Flipped) x = T::apply(T::lorentz(c0, c1, len), x);
else x = T::apply(T::cspin(c0, c1, len), x);
}
return x;
}
template<class T> std::string test_count(int id) {
std::mt19937 testr; testr.seed(id);
hr::shstream out;
auto A = random_iso<T>(testr);
auto B = random_iso<T>(testr);
auto C = random_iso<T>(testr);
auto P = T::apply(C, T::center());
for(int i=0; i<9; i++) {
counts.clear();
for(auto& i: cbc) i = 0;
std::string s;
switch(i) {
case 0: s = "spin"; T::cspin(0, 1, countfloat(.5)); break;
case 1: s = "L0"; T::lorentz(0, T::data::Dim-1, countfloat(.5)); break;
case 2: s = "L1"; T::lorentz(1, T::data::Dim-1, countfloat(.5)); break;
case 3: s = "ip"; T::apply(A, P); break;
case 4: s = "ii"; T::apply(A, B); break;
case 5: s = "d0"; T::dist0(P); break;
case 6: s = "angle"; T::angle(P); break;
case 7: s = "inverse"; T::inverse(A); break;
case 8: s = "push"; T::push(P); break;
}
if(i) print(out, " ");
if(1) {
print(out, s, "(");
bool nsp = false;
for(int i=1; i<5; i++) if(cbc[i]) {
if(nsp) print(out, " ");
print(out, cbc[i], hr::s0+".AMDF"[i]);
nsp = true;
}
print(out, ")");
}
}
return out.s;
}
template<class A, class B> bool closeto(A a, B b) { return abs(a-b) < 0.1; }
template<class A, class B> bool closeto_angle(A a, B b) { return abs(cyclefix_on(double(a-b))) < 0.1; }
template<class T> double test_angledist(int id) {
std::mt19937 testr; testr.seed(id);
for(int i=1; i<1000; i += (1 + i/5)) {
auto p = randomwalk(testr, hr::cwt.at, i);
auto h = apply_path<T>(vrev(p), T::center());
auto gh = apply_path<good>(vrev(p), good::center());
if(debug == 2) {
println(hlog, "good: ", good::print(gh), " dist = ", good::dist0(gh), " angle = ", good::angle(gh));
println(hlog, "test: ", T::print(h), " dist = ", T::dist0(h), " angle = ", T::angle(h), " [i=", i, "]");
}
if(closeto(good::dist0(gh), T::dist0(h)) && closeto_angle(good::angle(gh), T::angle(h))) continue;
if(debug == 1) {
println(hlog, "good: ", good::print(gh), " dist = ", good::dist0(gh), " angle = ", good::angle(gh));
println(hlog, "test: ", T::print(h), " dist = ", T::dist0(h), " angle = ", T::angle(h), " [i=", i, "]");
}
return i;
}
return 999;
}
#define TEST_VARIANTS(x,D,q,t,rn, r) \
nm = nmInvariant; println(hlog, rn, "invariant: ", repeat_test<t>(x<r<D>>, q)); \
nm = nmForced; println(hlog, rn, "forced : ", repeat_test<t>(x<r<D>>, q)); \
nm = nmWeak; println(hlog, rn, "weak : ", repeat_test<t>(x<r<D>>, q)); \
nm = nmFlatten; println(hlog, rn, "flatten : ", repeat_test<t>(x<r<D>>, q)); \
nm = nmCareless; println(hlog, rn, "careless : ", repeat_test<t>(x<r<D>>, q)); \
nm = nmBinary; println(hlog, rn, "binary : ", repeat_test<t>(x<r<D>>, q));
/*
#define TEST_ALL(x,D,q,t) \
println(hlog, "HyperRogue: ", repeat_test<t>(x<rep_hr<D>>, q)); \
polar_mod = polar_choose = false; println(hlog, "high polar: ", repeat_test<t>(x<rep_high_polar<D>>, q)); \
if(test_dim == 3) { polar_mod = polar_choose = false; println(hlog, "low polar : ", repeat_test<t>(x<rep_polar2<D>>, q)); }
*/
// println(hlog, "HyperRogue : ", repeat_test<t>(x<rep_hr<D>>, q));
#define TEST_ALL(x,D,q,t) \
fix_matrices = true; TEST_VARIANTS(x,D,q,t,"linear+F ", rep_linear) \
fix_matrices = false; TEST_VARIANTS(x,D,q,t,"linear-F ", rep_linear) \
TEST_VARIANTS(x,D,q,t,"mixed ", rep_mixed) \
TEST_VARIANTS(x,D,q,t,"Clifford ", rep_clifford) \
nm = nmFlatten; println(hlog, "Clifford gyro : ", repeat_test<t>(x<rep_half<D>>, q)); \
nm = nmInvariant; println(hlog, "halfplane invariant: ", repeat_test<t>(x<rep_half<D>>, q)); \
polar_choose = false; println(hlog, "polar basic : ", repeat_test<t>(x<rep_high_polar<D>>, q)); \
polar_choose = true; println(hlog, "polar improved : ", repeat_test<t>(x<rep_high_polar<D>>, q)); \
if(test_dim == 3) { \
polar_mod = false; polar_choose = false; println(hlog, "polar F/F : ", repeat_test<t>(x<rep_polar2<D>>, q)); \
polar_mod = false; polar_choose = true; println(hlog, "polar F/T : ", repeat_test<t>(x<rep_polar2<D>>, q)); \
polar_mod = true; polar_choose = false; println(hlog, "polar T/F : ", repeat_test<t>(x<rep_polar2<D>>, q)); \
polar_mod = true; polar_choose = true; println(hlog, "polar T/T : ", repeat_test<t>(x<rep_polar2<D>>, q)); \
}
template<class T> double test_distances(int id, int a) {
std::mt19937 testr; testr.seed(id);
using N = typename T::data::Number;
for(int i=1; i<1000; i ++) {
auto R = random_rotation<T>(testr);
auto dif = exp(N(-1) * i) + get_deg<N>(a);
auto p1 = T::apply(T::apply(R, cpush<T>(0, N(i))), T::center());
auto p2 = T::apply(T::apply(R, T::apply(T::cspin(0, 1, dif), cpush<T>(0, N(i)))), T::center());
auto pd = T::apply(T::inverse(T::push(p1)), p2);
auto d = T::dist0(pd);
// for good we do not need R actually
auto gp1 = good::apply(cpush<good>(0, N(i)), good::center());
auto gp2 = good::apply(good::apply(good::cspin(0, 1, dif), cpush<good>(0, N(i))), good::center());
auto gd = good::dist0(good::apply(good::inverse(good::push(gp1)), gp2));
if(debug == 2) println(hlog, T::print(p1), " ... ", T::print(p2), " = ", T::print(pd), " d=", d, " [i=", i, " dif=", dif, "]");
if(closeto(d, gd)) continue;
return i;
}
return 999;
}
template<class T> double test_similarity(int id) { return test_distances<T>(id, 0); }
template<class T> double test_dissimilarity(int id) { return test_distances<T>(id, 180); }
template<class T> double test_other(int id) { return test_distances<T>(id, 1); }
template<class T> double test_walk(int id) {
std::mt19937 testr; testr.seed(id);
ld step = 1/16.;
// mover-relative to cell-relative
auto R0 = random_rotation<T>(testr);
cell *c0 = hr::cwt.at;
auto R1 = T::apply(R0, cpush<T>(0, step/2));
cell *c1 = hr::cwt.at;
int i = 0;
int lastchange = 0;
while(i< lastchange + 1000 && i < 10000 && celldistance(c0, c1) < 3) {
// println(hlog, "iteration ", i, " in ", c0, " vs ", c1);
auto rebase = [&] (typename T::isometry& R, cell*& c, int id) {
ld d = T::dist0(T::apply(R, T::center()));
for(int dir=0; dir<c->type; dir++) {
cell *altc = c->cmove(dir);
auto altR = apply_move<T>(altc, c, R);
ld altd = T::dist0(T::apply(altR, T::center()));
if(altd < d + 1/256.) {
R = altR; c = altc; lastchange = i; return;
}
}
};
R0 = T::apply(R0, cpush<T>(0, step)); rebase(R0, c0, 0);
R1 = T::apply(R1, cpush<T>(0, step)); rebase(R1, c1, 1);
i++;
}
return i;
}
template<class T> double test_close(int id) {
std::mt19937 testr; testr.seed(id);
cell *c = hr::cwt.at;
int phase = 0;
auto p0 = T::apply(cpush<T>(0, 1/8.), T::center());
auto p = p0;
int steps = 0;
const int maxdist = id + 1;
int errors = 0;
while(steps < 10000) {
int d = testr() % c->type;
cell *c1 = c->cmove(d);
bool do_move = false;
switch(phase) {
case 0:
/* always move */
do_move = true;
if(celldistance(c1, hr::cwt.at) == maxdist) phase = 1;
break;
case 1:
/* move only towards the center */
int d0 = celldistance(c, hr::cwt.at);
int d1 = celldistance(c1, hr::cwt.at);
do_move = d1 < d0;
if(d1 == 0) phase = 0;
break;
}
if(do_move) {
p = apply_move<T>(c1, c, p); c = c1; steps++;
if(debug == 2) println(hlog, "dist = ", celldistance(c, hr::cwt.at), " dist = ", T::dist0(p));
if(c == hr::cwt.at) {
auto d = T::dist0(p);
auto a = T::angle(p);
if(!closeto(d, 1/8.) || !closeto_angle(a, 0)) {
errors++; phase = 0; c = hr::cwt.at; p = p0;
}
}
}
}
return errors;
}
void run_all_tests() {
prepare_tests();
// println(hlog, "test_sanity"); TEST_ALL(test_sanity, data, 1, ld);
// println(hlog, "test_consistency"); TEST_ALL(test_consistency, data, 1, ld);
println(hlog, "test_loop_iso"); TEST_ALL(test_loop_iso, data, 20, int);
println(hlog, "test_loop_point"); TEST_ALL(test_loop_point, data, 20, int);
println(hlog, "test_angledist"); TEST_ALL(test_angledist, data, 3, int);
println(hlog, "test_similarity"); TEST_ALL(test_similarity, data, 20, int);
println(hlog, "test_dissimilarity"); TEST_ALL(test_dissimilarity, data, 20, int);
println(hlog, "test_other"); TEST_ALL(test_other, data, 20, int);
println(hlog, "test_walk"); TEST_ALL(test_walk, data, 20, int);
println(hlog, "test_close"); TEST_ALL(test_close, data, 20, int);
println(hlog, "test_count"); TEST_ALL(test_count, countdata, 1, std::string);
}
}

1806
devmods/rulegen-tests.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,241 @@
tessellations/multitile/4-7/1+3a/1a2+3af/4-7-1a2+3af-30.tes
tessellations/other/toimine/toimine884/112/toimine884-112-076.tes
tessellations/other/toimine/toimine884/211/051-100/toimine884-211-072.tes
tessellations/pseudo-Archimedean/Euclidean/4-uniform/eu\ 666\ 666\ 3366\ 333333\ AFAS6.tes
tessellations/multitile/6-3/1+3a/6-3-1r2+3af-3.tes
tessellations/other/heavpoot-a/hp-3a+6s3b+6a1.tes
tessellations/multitile/3-6/1+3/3-6-1a+3a-3.tes
tessellations/pseudo-Archimedean/Euclidean/4-uniform/eu 4444 33344 33344 33434 A1AFF.tes
tessellations/pseudo-Archimedean/Euclidean/4-uniform/eu 33344 33434 333333 333333 FAS6S3b.tes
tessellations/pseudo-Archimedean/Euclidean/4-uniform/eu 3cc 334c 33434 333333.tes
tessellations/pseudo-Archimedean/Euclidean/4-uniform/eu 46c 3366 3446 33344.tes
tessellations/multitile/4-6/2+2/2a1+2f/001-100/4-6-2a1+2f-083.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-58.tes
tessellations/other/toimine/toimine6612/121/101-150/toimine6612-121-116.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-18.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-34.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-04.tes
tessellations/multitile/3-7/1+2+3/3-7-1f+2r+3f-19.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-51.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-545.tes
tessellations/other/toimine/toimine6620/211/toimine6620-211-54.tes
tessellations/other/toimine/toimine886/111/toimine886-111-08.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-503.tes
tessellations/other/toimine/toimine6610/121/toimine6610-121-20.tes
tessellations/other/toimine/toimine6612/211/101-150/toimine6612-211-126.tes
tessellations/polyschwartz/245/2-2 + 6-39.tes
tessellations/other/toimine/toimine6615/121/toimine6615-121-02.tes
tessellations/other/toimine/toimine6612/211/101-150/toimine6612-211-131.tes
tessellations/multitile/polyforms/schwarz/245/1-1 + 4-8 s1.tes
tessellations/other/toimine/toimine6617/113/toimine6617-113-16.tes
tessellations/multitile/polyforms/schwarz/245/2-2 + 6-39.tes
tessellations/other/toimine/toimine6618/211/151-159/toimine6618-211-151.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-16.tes
tessellations/polyschwartz/237/1-1 + 7-08.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-59.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-146.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-568.tes
tessellations/other/toimine/toimine6618/111/toimine6618-111-17.tes
tessellations/other/toimine/toimine6612/211/201-243/toimine6612-211-243.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-52.tes
tessellations/other/toimine/toimine885/211/toimine885-211-23.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-64.tes
tessellations/other/toimine/toimine885/211/toimine885-211-44.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-58.tes
tessellations/other/toimine/toimine6612/112/151-200/toimine6612-112-188.tes
tessellations/multitile/polyforms/schwarz/245/45 + 410/12/45 + 410 + 410 s02.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-49.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-564.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-42.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-03.tes
tessellations/other/toimine/toimine6610/211/toimine6610-211-13.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-36.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-22.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-57.tes
tessellations/other/toimine/toimine6618/112/toimine6618-112-002.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-60.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-06.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-53.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-02.tes
tessellations/multitile/3-8/1+2+3/1f+2a1+3f/3-8-1f+2a1+3f-44.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-57.tes
tessellations/other/toimine/toimine885/112/toimine885-112-10.tes
tessellations/other/toimine/toimine6618/211/151-159/toimine6618-211-159.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-117.tes
tessellations/other/toimine/toimine6611/112/toimine6611-112-09.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-33.tes
tessellations/other/toimine/toimine6618/211/051-100/toimine6618-211-070.tes
tessellations/other/toimine/toimine6610/112/toimine6610-112-28.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-25.tes
tessellations/other/toimine/toimine6610/211/toimine6610-211-27.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/401-500/3-8-1f+2f+3f-425.tes
tessellations/other/toimine/toimine6617/113/toimine6617-113-13.tes
tessellations/other/toimine/toimine6612/112/051-100/toimine6612-112-082.tes
tessellations/other/toimine/toimine6620/111/toimine6620-111-09.tes
tessellations/other/toimine/toimine668/121/toimine668-121-12.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-40.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/401-500/3-8-1f+2f+3f-496.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/101-200/3-8-1f+2f+3f-101.tes
tessellations/other/toimine/toimine6612/112/151-200/toimine6612-112-164.tes
tessellations/other/toimine/toimine6612/211/051-100/toimine6612-211-080.tes
tessellations/other/toimine/toimine6611/121/toimine6611-121-11.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-11.tes
tessellations/other/toimine/toimine6612/211/051-100/toimine6612-211-078.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-24.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-62.tes
tessellations/other/toimine/toimine6612/121/001-050/toimine6612-121-012.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/401-500/3-8-1f+2f+3f-424.tes
tessellations/other/toimine/toimine6617/113/toimine6617-113-12.tes
tessellations/other/toimine/toimine6615/121/toimine6615-121-19.tes
tessellations/other/toimine/toimine6612/121/201-227/toimine6612-121-226.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-12.tes
tessellations/other/toimine/toimine6620/211/toimine6620-211-19.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-563.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-03.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-31.tes
tessellations/other/toimine/toimine6615/211/toimine6615-211-53.tes
tessellations/other/toimine/toimine2311/4+2/toimine2311-4+2-07.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-150.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-04.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-64.tes
tessellations/multitile/polyforms/schwarz/245/1-1 + 4-8 s2.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-54.tes
tessellations/multitile/polyforms/schwarz/237/1-1 + 7-08.tes
tessellations/other/toimine/toimine6620/121/toimine6620-121-29.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-09.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-45.tes
tessellations/other/toimine/toimine6612/211/101-150/toimine6612-211-122.tes
tessellations/other/toimine/toimine6612/121/151-200/toimine6612-121-172.tes
tessellations/other/toimine/toimine6612/121/201-227/toimine6612-121-211.tes
tessellations/other/toimine/toimine6615/211/toimine6615-211-61.tes
tessellations/other/toimine/toimine6612/112/151-200/toimine6612-112-155.tes
tessellations/other/toimine/toimine6618/211/051-100/toimine6618-211-088.tes
tessellations/other/toimine/toimine6612/211/051-100/toimine6612-211-086.tes
tessellations/other/toimine/toimine6618/111/toimine6618-111-14.tes
tessellations/polyschwartz/245/1-1 + 4-8 s2.tes
tessellations/other/toimine/toimine6612/112/101-150/toimine6612-112-142.tes
tessellations/other/toimine/toimine6612/211/001-050/toimine6612-211-045.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-36.tes
tessellations/multitile/4-6/2+2/2a1+2f/001-100/4-6-2a1+2f-033.tes
tessellations/other/toimine/toimine6612/121/151-200/toimine6612-121-177.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-20.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/401-500/3-8-1f+2f+3f-445.tes
tessellations/other/toimine/toimine6618/121/051-100/toimine6618-121-066.tes
tessellations/other/toimine/toimine6612/111/toimine6612-111-30.tes
tessellations/multitile/4-6/2+2/2f+2f/401-500/4-6-2f+2f-466.tes
tessellations/other/toimine/toimine6617/113/toimine6617-113-14.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-12.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-09.tes
tessellations/other/toimine/toimine6610/211/toimine6610-211-17.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-69.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-17.tes
tessellations/other/toimine/toimine6611/121/toimine6611-121-04.tes
tessellations/other/toimine/toimine6610/211/toimine6610-211-23.tes
tessellations/other/toimine/toimine668/211/toimine668-211-08.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-40.tes
tessellations/other/toimine/toimine6612/211/201-243/toimine6612-211-233.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-35.tes
tessellations/other/toimine/toimine6618/211/051-100/toimine6618-211-058.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/301-400/3-8-1f+2f+3f-396.tes
tessellations/other/toimine/toimine6612/112/101-150/toimine6612-112-124.tes
tessellations/other/toimine/toimine668/112/toimine668-112-04.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-53.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-50.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-47.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-05.tes
tessellations/other/toimine/toimine668/112/toimine668-112-02.tes
tessellations/other/toimine/toimine6612/112/101-150/toimine6612-112-136.tes
tessellations/polyschwartz/245/1-1 + 5-01.tes
tessellations/other/toimine/toimine6612/112/201-250/toimine6612-112-219.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-18.tes
tessellations/multitile/polyforms/schwarz/245/1-1 + 5-01.tes
tessellations/other/toimine/toimine6618/121/101-126/toimine6618-121-114.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-51.tes
tessellations/other/toimine/toimine6618/211/051-100/toimine6618-211-060.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-21.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-37.tes
tessellations/other/toimine/toimine6612/211/201-243/toimine6612-211-232.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-08.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-15.tes
tessellations/other/toimine/toimine6620/211/toimine6620-211-36.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-45.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-129.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-70.tes
tessellations/other/toimine/toimine6610/121/toimine6610-121-16.tes
tessellations/polyschwartz/245/45 + 410/12/45 + 410 + 410 s02.tes
tessellations/multitile/polyforms/schwarz/245/1-1 + 4-8 s3.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-76.tes
tessellations/other/toimine/toimine6620/112/toimine6620-112-47.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-14.tes
tessellations/multitile/3-7/1+1+3/3-7-1f+1f+3f-20.tes
tessellations/other/toimine/toimine6618/211/051-100/toimine6618-211-065.tes
tessellations/other/toimine/toimine6610/112/toimine6610-112-06.tes
tessellations/other/toimine/toimine885/121/toimine885-121-34.tes
tessellations/other/toimine/toimine6615/211/toimine6615-211-04.tes
tessellations/other/toimine/toimine6618/121/051-100/toimine6618-121-086.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/101-200/3-8-1f+2f+3f-169.tes
tessellations/other/toimine/toimine885/211/toimine885-211-37.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-55.tes
tessellations/other/toimine/toimine2311/4+2/toimine2311-4+2-60.tes
tessellations/multitile/4-6/2+2/2f+2f/401-500/4-6-2f+2f-447.tes
tessellations/other/toimine/toimine6612/211/051-100/toimine6612-211-059.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-61.tes
tessellations/other/toimine/toimine6620/111/toimine6620-111-07.tes
tessellations/other/toimine/toimine6618/121/051-100/toimine6618-121-056.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-48.tes
tessellations/other/toimine/toimine6612/211/101-150/toimine6612-211-125.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-47.tes
tessellations/polyschwartz/245/1-1 + 4-8 s3.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-13.tes
tessellations/other/toimine/toimine885/121/toimine885-121-25.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-59.tes
tessellations/other/toimine/toimine6615/211/toimine6615-211-44.tes
tessellations/other/toimine/toimine6612/111/toimine6612-111-26.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-26.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-596.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-49.tes
tessellations/other/toimine/toimine2311/4+2/toimine2311-4+2-42.tes
tessellations/other/toimine/toimine6618/211/151-159/toimine6618-211-156.tes
tessellations/other/toimine/toimine6618/121/051-100/toimine6618-121-096.tes
tessellations/other/toimine/toimine6618/121/101-126/toimine6618-121-125.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-11.tes
tessellations/other/toimine/toimine2311/3+3/toimine2311-3+3-46.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-34.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-54.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-56.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-128.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/001-100/3-8-1f+2f+3f-091.tes
tessellations/other/toimine/toimine668/211/toimine668-211-17.tes
tessellations/other/toimine/toimine6612/112/151-200/toimine6612-112-153.tes
tessellations/other/toimine/toimine6612/112/201-250/toimine6612-112-215.tes
tessellations/other/toimine/toimine668/112/toimine668-112-28.tes
tessellations/other/toimine/toimine668/112/toimine668-112-01.tes
tessellations/other/toimine/toimine6620/121/toimine6620-121-37.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-63.tes
tessellations/other/toimine/toimine6610/211/toimine6610-211-19.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-29.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-43.tes
tessellations/other/toimine/toimine6618/121/101-126/toimine6618-121-126.tes
tessellations/other/toimine/toimine668/211/toimine668-211-19.tes
tessellations/other/toimine/toimine6612/112/101-150/toimine6612-112-140.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-30.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-32.tes
tessellations/multitile/3-11/1+1+1/3-11-1a+1a+1f-2.tes
tessellations/polyschwartz/245/1-1 + 4-8 s1.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-110.tes
tessellations/other/toimine/toimine6612/112/151-200/toimine6612-112-176.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-149.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-50.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-62.tes
tessellations/other/toimine/toimine886/211/toimine886-211-011.tes
tessellations/other/toimine/toimine6615/111/toimine6615-111-28.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-44.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-10.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-38.tes
tessellations/other/toimine/toimine2311/2+4/toimine2311-2+4-46.tes
tessellations/other/toimine/toimine6618/211/101-150/toimine6618-211-125.tes
tessellations/other/toimine/toimine6620/211/toimine6620-211-18.tes
tessellations/other/toimine/toimine668/211/toimine668-211-21.tes
tessellations/other/toimine/toimine6610/121/toimine6610-121-04.tes
tessellations/other/toimine/toimine6611/112/toimine6611-112-02.tes
tessellations/multitile/3-8/1+2+3/1f+2f+3f/501-596/3-8-1f+2f+3f-565.tes

View File

@ -17,7 +17,7 @@
// Add e.g. '-dim 128 128 128' before -write to generate
// a more/less precise table.
// # ./hyper -geo Sol -iz-list -sn-unittest -build -write solv-geodesics-a.dat -visualize devmods/san1/solva-%04d.png -improve -write solv-geodesics.dat -visualize devmods/san1/solvb-%04d.png
// # ./hyper -rk-steps 100 -geo Sol -iz-list -sn-unittest -build -write solv-geodesics-a.dat -visualize devmods/san1/solva-%04d.png -improve -write solv-geodesics.dat -visualize devmods/san1/solvb-%04d.png
// # ./hyper -dim 32 32 32 -geo 3:1/2 -iz-list -sn-unittest -build -write ssol-geodesics-a.dat -visualize devmods/san1/ssola-%04d.png -improve -write ssol-geodesics.dat -visualize devmods/san1/ssolb-%04d.png
// # ./hyper -dim 32 32 32 -geo 3:2 -iz-list -sn-unittest -build -write shyp-geodesics.dat -visualize devmods/san1/shypa-%04d.png
@ -51,11 +51,11 @@ int max_iter = 999999;
hyperpoint fail(.1, .2, .3, .4);
hyperpoint iterative_solve(hyperpoint xp, hyperpoint candidate, int prec, ld minerr, bool debug = false) {
hyperpoint iterative_solve(hyperpoint xp, hyperpoint candidate, ld minerr, bool debug = false) {
transmatrix T = Id; T[0][1] = 8; T[2][2] = 5;
auto f = [&] (hyperpoint x) { return nisot::numerical_exp(x, prec); }; // T * x; };
auto f = [&] (hyperpoint x) { return nisot::numerical_exp(x); }; // T * x; };
auto ver = f(candidate);
ld err = solerror(xp, ver);
@ -136,6 +136,8 @@ hyperpoint iterative_solve(hyperpoint xp, hyperpoint candidate, int prec, ld min
nextiter: ;
}
// println(hlog, "#it = ", iter);
return at;
}
@ -201,10 +203,12 @@ void build_sols(int PRECX, int PRECY, int PRECZ) {
if((nih && iz == 0) || iz == PRECZ-1) return;
auto solve_at = [&] (int ix, int iy) {
// if(ix != 30 || iy <= 50 || iz) return;
ld x = ix_to_x(ix / (PRECX-1.));
ld y = ix_to_x(iy / (PRECY-1.));
ld z = iz_to_z(iz / (PRECZ-1.));
auto v = hyperpoint ({x,y,z,1});
vector<hyperpoint> candidates;
@ -212,8 +216,6 @@ void build_sols(int PRECX, int PRECY, int PRECZ) {
candidates.push_back(point3(0,0,0));
static constexpr int prec = 100;
// sort(candidates.begin(), candidates.end(), [&] (hyperpoint a, hyperpoint b) { return solerror(v, direct_exp(a, prec)) > solerror(v, direct_exp(b, prec)); });
// cand_best = candidates.back();
@ -221,25 +223,25 @@ void build_sols(int PRECX, int PRECY, int PRECZ) {
vector<hyperpoint> solved_candidates;
for(auto c: candidates) {
auto solt = iterative_solve(v, c, prec, 1e-6, false);
auto solt = iterative_solve(v, c, 1e-6, false);
solved_candidates.push_back(solt);
if(solerror(v, nisot::numerical_exp(solt, prec)) < 1e-9) break;
if(solerror(v, nisot::numerical_exp(solt)) < 1e-9) break;
}
sort(solved_candidates.begin(), solved_candidates.end(), [&] (hyperpoint a, hyperpoint b) { return solerror(v, nisot::numerical_exp(a, prec)) > solerror(v, nisot::numerical_exp(b, prec)); });
sort(solved_candidates.begin(), solved_candidates.end(), [&] (hyperpoint a, hyperpoint b) { return solerror(v, nisot::numerical_exp(a)) > solerror(v, nisot::numerical_exp(b)); });
cand = solved_candidates.back();
auto xerr = solerror(v, nisot::numerical_exp(cand, prec));
auto xerr = solerror(v, nisot::numerical_exp(cand));
if(cand == fail) {
println(hlog, format("[%2d %2d %2d] FAIL", iz, iy, ix));
println(hlog, hr::format("[%2d %2d %2d] FAIL", iz, iy, ix));
}
else if(xerr > 1e-3) {
println(hlog, format("[%2d %2d %2d] ", iz, iy, ix));
println(hlog, hr::format("[%2d %2d %2d] ", iz, iy, ix));
println(hlog, "f(?) = ", v);
println(hlog, "f(", cand, ") = ", nisot::numerical_exp(cand, prec));
println(hlog, "f(", cand, ") = ", nisot::numerical_exp(cand));
println(hlog, "error = ", xerr);
println(hlog, "canned = ", compress(azeq_to_table(cand)));
max_err = xerr;
@ -263,7 +265,7 @@ void build_sols(int PRECX, int PRECY, int PRECZ) {
}
if(it < last_x && it < last_y) solve_at(it, it);
std::lock_guard<std::mutex> fm(file_mutex);
if(0) println(hlog, format("%2d: %2d", iz, it));
if(0) println(hlog, hr::format("%2d: %2d", iz, it));
}
};
@ -418,7 +420,7 @@ hyperpoint find_optimal_geodesic(hyperpoint res) {
max_iter = 1000;
auto h1 = iterative_solve(res, p.first * quality(p) / hypot_d(3, p.first), 100, 1e-6);
if(deb) println(hlog, "h1 returns ", h1, " of length ", hypot_d(3, h1), " and error ", hypot_d(3, nisot::numerical_exp(h1, 100) - res));
if(deb) println(hlog, "h1 returns ", h1, " of length ", hypot_d(3, h1), " and error ", hypot_d(3, nisot::numerical_exp(h1) - res));
if(h1 == fail) return;
@ -467,7 +469,7 @@ void visualize_table(sn::tabled_inverses& tab, const string& s) {
for(int i=0; i<3; i++)
part(p, i) = 0x80 + 0x70 * tab.get_int(ix, iy, iz)[i];
}
SDL_SavePNG(rb.srf, format(s.c_str(), iz).c_str());
SDL_SavePNG(rb.srf, hr::format(s.c_str(), iz).c_str());
}
}

View File

@ -6,18 +6,24 @@ namespace hr {
namespace tests {
int errors = 0;
string test_eq(hyperpoint h1, hyperpoint h2, ld err = 1e-6) {
if(sqhypot_d(MDIM, h1 -h2) < err)
return "OK";
else
return "ERROR";
return lalign(0, "OK ", h1, " ", h2);
else {
errors++;
return lalign(0, "ERROR", " ", h1, " ", h2);
}
}
string test_eq(transmatrix T1, transmatrix T2, ld err = 1e-6) {
if(eqmatrix(T1, T2, err))
return "OK";
else
else {
errors++;
return "ERROR";
}
}
int readArgs() {
@ -28,7 +34,6 @@ int readArgs() {
start_game();
shift(); int d = argi();
vector<cell*> l = currentmap->allcells();
int errors = 0;
int unknown = 0;
for(cell *c1: l) if(c1->cpdist <= d)
for(cell *c2: l) if(c2->cpdist <= d) {
@ -94,8 +99,25 @@ int readArgs() {
println(hlog, "test rgpushxto0: ", test_eq(rgpushxto0(h) * C0, h));
println(hlog, "test gpushxto0: ", test_eq(gpushxto0(h) * h, C0));
println(hlog, "test inverses: ", test_eq(inverse(rgpushxto0(h)), gpushxto0(h)));
println(hlog, "test iso_inverse: ", test_eq(iso_inverse(rgpushxto0(h)), gpushxto0(h)));
}
if(errors) exit(1);
}
else if(argis("-partest", [] {
hyperpoint h = point31(.01, .05, 0);
if(LDIM == 3) h[2] = .015;
println(hlog, "h = ", h);
println(hlog, "good Ph = ", parabolic13(h));
println(hlog, "good DPh = ", test_eq(h, deparabolic13(parabolic13(h))));
// println(hlog, "bad Ph = ", parabolic10(h));
// println(hlog, "bad DPh = ", test_eq(h, deparabolic10(parabolic10(h))));
if(LDIM == 3) {
println(hlog, "min Ph = ", bt::bt_to_minkowski(h));
println(hlog, "min DPh = ", test_eq(h, bt::minkowski_to_bt(bt::bt_to_minkowski(h))));
}
});
else return 1;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -9,35 +9,37 @@
namespace hr {
#if HDR
static const int POLY_DRAWLINES = 1; // draw the lines
static const int POLY_DRAWAREA = 2; // draw the area
static const int POLY_INVERSE = 4; // draw the inverse -- useful in stereographic projection
static const int POLY_ISSIDE = 8; // never draw in inverse
static const int POLY_BEHIND = 16; // there are points behind the camera
static const int POLY_TOOLARGE = 32; // some coordinates are too large -- best not to draw to avoid glitches
static const int POLY_INFRONT = 64; // on the sphere (orthogonal projection), do not draw without any points in front
static const int POLY_HASWALLS = 128; // floor shapes which have their sidewalls
static const int POLY_PLAIN = 256; // plain floors
static const int POLY_FULL = 512; // full floors
static const int POLY_HASSHADOW = 1024; // floor shapes which have their shadows, or can use shFloorShadow
static const int POLY_GP = 2048; // Goldberg shapes
static const int POLY_VCONVEX = 4096; // Convex shape (vertex)
static const int POLY_CCONVEX = 8192; // Convex shape (central)
static const int POLY_CENTERIN = 16384; // new system of side checking
static const int POLY_FORCEWIDE = (1<<15); // force wide lines
static const int POLY_NOTINFRONT = (1<<16); // points not in front
static const int POLY_NIF_ERROR = (1<<17); // points moved to the outline cross the image, disable
static const int POLY_BADCENTERIN = (1<<18); // new system of side checking
static const int POLY_PRECISE_WIDE = (1<<19); // precise width calculation
static const int POLY_FORCE_INVERTED = (1<<20); // force inverted
static const int POLY_ALWAYS_IN = (1<<21); // always draw this
static const int POLY_TRIANGLES = (1<<22); // made of TRIANGLES, not TRIANGLE_FAN
static const int POLY_INTENSE = (1<<23); // extra intense colors
static const int POLY_DEBUG = (1<<24); // debug this shape
static const int POLY_PRINTABLE = (1<<25); // these walls are printable
static const int POLY_FAT = (1<<26); // fatten this model in WRL export (used for Rug)
static const int POLY_SHADE_TEXTURE = (1<<27); // texture has 'z' coordinate for shading
static const int POLY_ONE_LEVEL = (1<<28); // only one level of the universal cover in SL(2,R)
static constexpr int POLY_DRAWLINES = 1; // draw the lines
static constexpr int POLY_DRAWAREA = 2; // draw the area
static constexpr int POLY_INVERSE = 4; // draw the inverse -- useful in stereographic projection
static constexpr int POLY_ISSIDE = 8; // never draw in inverse
static constexpr int POLY_BEHIND = 16; // there are points behind the camera
static constexpr int POLY_TOOLARGE = 32; // some coordinates are too large -- best not to draw to avoid glitches
static constexpr int POLY_INFRONT = 64; // on the sphere (orthogonal projection), do not draw without any points in front
static constexpr int POLY_HASWALLS = 128; // floor shapes which have their sidewalls
static constexpr int POLY_PLAIN = 256; // plain floors
static constexpr int POLY_FULL = 512; // full floors
static constexpr int POLY_HASSHADOW = 1024; // floor shapes which have their shadows, or can use shFloorShadow
static constexpr int POLY_GP = 2048; // Goldberg shapes
static constexpr int POLY_VCONVEX = 4096; // Convex shape (vertex)
static constexpr int POLY_CCONVEX = 8192; // Convex shape (central)
static constexpr int POLY_CENTERIN = 16384; // new system of side checking
static constexpr int POLY_FORCEWIDE = (1<<15); // force wide lines
static constexpr int POLY_NOTINFRONT = (1<<16); // points not in front
static constexpr int POLY_NIF_ERROR = (1<<17); // points moved to the outline cross the image, disable
static constexpr int POLY_BADCENTERIN = (1<<18); // new system of side checking
static constexpr int POLY_PRECISE_WIDE = (1<<19); // precise width calculation
static constexpr int POLY_FORCE_INVERTED = (1<<20); // force inverted
static constexpr int POLY_ALWAYS_IN = (1<<21); // always draw this
static constexpr int POLY_TRIANGLES = (1<<22); // made of TRIANGLES, not TRIANGLE_FAN
static constexpr int POLY_INTENSE = (1<<23); // extra intense colors
static constexpr int POLY_DEBUG = (1<<24); // debug this shape
static constexpr int POLY_PRINTABLE = (1<<25); // these walls are printable
static constexpr int POLY_FAT = (1<<26); // fatten this model in WRL export (used for Rug)
static constexpr int POLY_SHADE_TEXTURE = (1<<27); // texture has 'z' coordinate for shading
static constexpr int POLY_ONE_LEVEL = (1<<28); // only one level of the universal cover in SL(2,R)
static constexpr int POLY_APEIROGONAL = (1<<29); // only vertices indexed up to she are drawn as the boundary
static constexpr int POLY_NO_FOG = (1<<30); // disable fog for this
/** \brief A graphical element that can be drawn. Objects are not drawn immediately but rather queued.
*
@ -71,6 +73,8 @@ struct dqi_poly : drawqueueitem {
int offset;
/** \brief how many vertices in the model */
int cnt;
/** cnt for POLY_APEIROGONAL */
int apeiro_cnt;
/** \brief the offset in the texture vertices */
int offset_texture;
/** \brief outline color */
@ -164,35 +168,40 @@ EX int texts_merged;
EX int shapes_merged;
#if MINIMIZE_GL_CALLS
color_t triangle_color, line_color;
PPR lprio;
ld m_shift;
vector<glvertex> triangle_vertices;
vector<glvertex> line_vertices;
vector<glhr::colored_vertex> triangle_vertices;
vector<glhr::colored_vertex> line_vertices;
#endif
EX void glflush() {
DEBBI(DF_GRAPH, ("glflush"));
#if MINIMIZE_GL_CALLS
current_display->set_all(0, m_shift);
if(isize(triangle_vertices)) {
// printf("%08X %08X | %d shapes, %d/%d vertices\n", triangle_color, line_color, shapes_merged, isize(triangle_vertices), isize(line_vertices));
if(triangle_color) {
// printf("%3d | %d shapes, %d/%d vertices\n", lprio, shapes_merged, isize(triangle_vertices), isize(line_vertices));
current_display->next_shader_flags = GF_VARCOLOR;
current_display->set_all(0, m_shift);
if(true) {
glhr::be_nontextured();
glapplymatrix(Id);
glhr::current_vertices = NULL;
glhr::vertices(triangle_vertices);
glhr::color2(triangle_color);
glhr::prepare(triangle_vertices);
glhr::color2(0xFFFFFFFF);
glDrawArrays(GL_TRIANGLES, 0, isize(triangle_vertices));
}
triangle_vertices.clear();
if(isize(line_vertices)) goto jump;
}
if(isize(line_vertices)) {
if(line_color) {
current_display->next_shader_flags = GF_VARCOLOR;
current_display->set_all(0, m_shift);
jump:
if(true) {
glhr::be_nontextured();
glapplymatrix(Id);
glhr::current_vertices = NULL;
glhr::vertices(line_vertices);
glhr::color2(line_color);
glhr::prepare(line_vertices);
glhr::color2(0xFFFFFFFF);
glDrawArrays(GL_LINES, 0, isize(line_vertices));
}
line_vertices.clear();
@ -220,7 +229,7 @@ EX void glflush() {
else
#endif
for(int ed = (current_display->stereo_active() && text_shift)?-1:0; ed<2; ed+=2) {
for(int ed = (current_display->separate_eyes() && text_shift)?-1:0; ed<2; ed+=2) {
glhr::set_modelview(glhr::translate(-ed*text_shift-current_display->xcenter,-current_display->ycenter, 0));
current_display->set_mask(ed);
drawer();
@ -228,7 +237,7 @@ EX void glflush() {
GLERR("print");
}
if(current_display->stereo_active() && text_shift && !svg::in) current_display->set_mask(0);
if(current_display->separate_eyes() && text_shift && !svg::in) current_display->set_mask(0);
texts_merged = 0;
text_vertices.clear();
@ -304,12 +313,11 @@ EX bool two_sided_model() {
#endif
if(GDIM == 3) return false;
if(in_vr_sphere) return true;
if(pmodel == mdHyperboloid) return !euclid && !in_vr;
if(pmodel == mdHemisphere || pmodel == mdHyperboloid) return !in_vr;
// if(pmodel == mdHemisphere) return true;
if(pmodel == mdDisk) return sphere;
if(pmodel == mdDisk) return sphere || (hyperbolic && pconf.alpha < 0 && pconf.alpha > -1);
if(pmodel == mdRetroLittrow) return sphere;
if(pmodel == mdRetroHammer) return sphere;
if(pmodel == mdHemisphere) return !in_vr;
if(pmodel == mdRotatedHyperboles) return true;
if(pmodel == mdSpiral && pconf.spiral_cone < 360) return true;
return false;
@ -333,6 +341,9 @@ EX int get_side(const hyperpoint& H) {
double horizon = curnorm / pconf.alpha;
return (H[2] <= -horizon) ? -1 : 1;
}
if(pmodel == mdDisk && hyperbolic && pconf.alpha < 0 && pconf.alpha > -1) {
return (H[2] * (H[2] + pconf.alpha) < sqhypot_d(2, H)) ? -1 : 1;
}
if(pmodel == mdRetroLittrow && sphere) {
return H[2] >= 0 ? 1 : -1;
}
@ -341,15 +352,25 @@ EX int get_side(const hyperpoint& H) {
}
if(pmodel == mdRotatedHyperboles)
return H[1] > 0 ? -1 : 1;
if(pmodel == mdHyperboloid && hyperbolic)
return (models::sin_ball * H[2] > -models::cos_ball * H[1]) ? -1 : 1;
if(pmodel == mdHyperboloid && sphere)
return (models::sin_ball * H[2] > models::cos_ball * H[1]) ? -1 : 1;
if(pmodel == mdHemisphere) {
if(pmodel == mdHyperboloid) {
return det2(pconf.ball() * cspin90(2, 1) * rgpushxto0(H)) > 0 ? 1 : -1;
}
if(pmodel == mdHyperboloidFlat && sphere)
return H[2] >= 0 ? 1 : -1;
if(pmodel == mdHemisphere && !sphere) {
hyperpoint res;
applymodel(shiftless(H), res);
return res[2] < 0 ? -1 : 1;
}
if(pmodel == mdHemisphere && sphere) {
auto H1 = H;
int s = H1[2] > 0 ? 1 : -1;
if(hemi_side && s != hemi_side) return -spherespecial;
H1[0] /= H1[2]; H1[1] /= H1[2];
H1[2] = -s * sqrt(1 + H1[0]*H1[0] + H1[1] * H1[1]);
dynamicval<geometryinfo1> g(cginf.g, giHyperb2);
return det2(pconf.ball() * cspin90(2, 1) * rgpushxto0(H1)) > 0 ? 1 : -1;
}
if(pmodel == mdSpiral && pconf.spiral_cone < 360) {
return cone_side(shiftless(H));
}
@ -422,10 +443,10 @@ void addpoint(const shiftpoint& H) {
if(sphere && pmodel == mdSpiral) {
if(isize(glcoords)) {
hyperpoint Hscr1;
shiftpoint H1 = H; H1.shift += 2 * M_PI;
shiftpoint H1 = H; H1.shift += TAU;
applymodel(H1, Hscr1);
if(hypot_d(2, Hlast-Hscr1) < hypot_d(2, Hlast-Hscr)) { Hscr = Hscr1; }
H1.shift -= 4 * M_PI;
H1.shift -= 2 * TAU;
applymodel(H1, Hscr1);
if(hypot_d(2, Hlast-Hscr1) < hypot_d(2, Hlast-Hscr)) { Hscr = Hscr1; }
}
@ -453,7 +474,7 @@ void addpoint(const shiftpoint& H) {
void coords_to_poly() {
polyi = isize(glcoords);
for(int i=0; i<polyi; i++) {
if(!current_display->stereo_active()) glcoords[i][2] = 0;
if(!current_display->separate_eyes()) glcoords[i][2] = 0;
polyx[i] = current_display->xcenter + glcoords[i][0] - glcoords[i][2];
polyxr[i] = current_display->xcenter + glcoords[i][0] + glcoords[i][2];
@ -464,6 +485,12 @@ void coords_to_poly() {
bool behind3(shiftpoint h) {
if(pmodel == mdGeodesic)
return lp_apply(inverse_exp(h))[2] < 0;
if(pmodel == mdLiePerspective)
return lp_apply(lie_log(h))[2] < 0;
#if MAXMDIM >= 4
if(pmodel == mdRelPerspective)
return lp_apply(rel_log(h, false))[2] < 0;
#endif
return h[2] < 0;
}
@ -480,8 +507,16 @@ void addpoly(const shiftmatrix& V, const vector<glvertex> &tab, int ofs, int cnt
return;
}
tofix.clear(); knowgood = false;
if(among(pmodel, mdPerspective, mdGeodesic)) {
if(poly_flags & POLY_TRIANGLES) {
if(in_perspective()) {
if(get_shader_flags() & SF_SEMIDIRECT) {
dynamicval<bool> d(computing_semidirect, true);
for(int i=ofs; i<ofs+cnt; i++) {
hyperpoint Hscr;
applymodel(V * glhr::gltopoint(tab[i]), Hscr);
add1(Hscr);
}
}
else if(poly_flags & POLY_TRIANGLES) {
for(int i=ofs; i<ofs+cnt; i+=3) {
shiftpoint h0 = V * glhr::gltopoint(tab[i]);
shiftpoint h1 = V * glhr::gltopoint(tab[i+1]);
@ -628,26 +663,31 @@ void dqi_poly::gldraw() {
int ioffset = offset;
#if MINIMIZE_GL_CALLS
if(current_display->stereo_active() == 0 && !tinf && (color == 0 || ((flags & (POLY_VCONVEX | POLY_CCONVEX)) && !(flags & (POLY_INVERSE | POLY_FORCE_INVERTED))))) {
if(color != triangle_color || outline != line_color || texts_merged || m_shift != V.shift) {
if(current_display->separate_eyes() == 0 && !tinf && (color == 0 || ((flags & (POLY_VCONVEX | POLY_CCONVEX)) && !(flags & (POLY_INVERSE | POLY_FORCE_INVERTED))))) {
if(lprio != prio || texts_merged || m_shift != V.shift) {
glflush();
triangle_color = color;
line_color = outline;
lprio = prio;
m_shift = V.shift;
}
shapes_merged++;
if((flags & POLY_CCONVEX) && !(flags & POLY_VCONVEX)) {
vector<glvertex> v2(cnt+1);
for(int i=0; i<cnt+1; i++) v2[i] = glhr::pointtogl( V.T * glhr::gltopoint( v[offset+i-1] ) );
vector<glhr::colored_vertex> v2(cnt+1);
for(int i=0; i<cnt+1; i++) v2[i] = glhr::colored_vertex( V.T * glhr::gltopoint( v[offset+i-1] ), color);
if(color) for(int i=0; i<cnt; i++) triangle_vertices.push_back(v2[0]), triangle_vertices.push_back(v2[i]), triangle_vertices.push_back(v2[i+1]);
for(int i=1; i<cnt; i++) line_vertices.push_back(v2[i]), line_vertices.push_back(v2[i+1]);
if(outline) {
for(auto& v: v2) v.set_color(outline);
for(int i=1; i<cnt; i++) line_vertices.push_back(v2[i]), line_vertices.push_back(v2[i+1]);
}
}
else {
vector<glvertex> v2(cnt);
for(int i=0; i<cnt; i++) v2[i] = glhr::pointtogl( V.T * glhr::gltopoint( v[offset+i] ) );
vector<glhr::colored_vertex> v2(cnt);
for(int i=0; i<cnt; i++) v2[i] = glhr::colored_vertex( V.T * glhr::gltopoint( v[offset+i] ), color);
if(color) for(int i=2; i<cnt-1; i++) triangle_vertices.push_back(v2[0]), triangle_vertices.push_back(v2[i-1]), triangle_vertices.push_back(v2[i]);
for(int i=1; i<cnt; i++) line_vertices.push_back(v2[i-1]), line_vertices.push_back(v2[i]);
if(outline) {
for(auto& v: v2) v.set_color(outline);
for(int i=1; i<cnt; i++) line_vertices.push_back(v2[i-1]), line_vertices.push_back(v2[i]);
}
}
return;
}
@ -661,6 +701,7 @@ void dqi_poly::gldraw() {
else
glhr::be_textured();
if(flags & POLY_SHADE_TEXTURE) current_display->next_shader_flags |= GF_TEXTURE_SHADED;
if(flags & POLY_NO_FOG) current_display->next_shader_flags |= GF_NO_FOG;
glBindTexture(GL_TEXTURE_2D, tinf->texture_id);
if(isize(tinf->colors))
glhr::vertices_texture_color(v, tinf->tvertices, tinf->colors, offset, offset_texture);
@ -670,20 +711,26 @@ void dqi_poly::gldraw() {
}
else {
glhr::be_nontextured();
if(flags & POLY_NO_FOG) current_display->next_shader_flags |= GF_NO_FOG;
glhr::vertices(v);
}
next_slr:
for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) {
for(int ed = current_display->separate_eyes() ? -1 : 0; ed<2; ed+=2) {
if(global_projection && global_projection != ed) continue;
if(min_slr < max_slr) {
current_display->set_all(ed, sl2 ? 0 : V.shift);
glhr::set_index_sl(V.shift + M_PI * min_slr * hybrid::csteps / cgi.psl_steps);
}
else if(sl2) {
current_display->set_all(ed, 0);
glhr::set_index_sl(V.shift);
}
else {
current_display->set_all(ed, V.shift);
current_display->set_all(ed, sl2 ? 0 : V.shift);
glhr::set_index_sl(V.shift + M_PI * min_slr * hybrid::csteps / cgi.psl_steps);
}
bool draw = color;
@ -699,7 +746,7 @@ void dqi_poly::gldraw() {
glhr::color2(color, (flags & POLY_INTENSE) ? 2 : 1);
glhr::set_depthtest(model_needs_depth() && prio < PPR::SUPERLINE);
glhr::set_depthwrite(model_needs_depth() && prio != PPR::TRANSPARENT_SHADOW && prio != PPR::EUCLIDEAN_SKY);
glhr::set_fogbase(prio == PPR::SKY ? 1.0 + (euclid ? 20 : 5 / sightranges[geometry]) : 1.0);
glhr::set_fogbase(prio == PPR::SKY ? 1.0 + ((abs(cgi.SKY - cgi.LOWSKY)) / sightranges[geometry]) : 1.0);
glDrawArrays(GL_TRIANGLES, ioffset, cnt);
}
else {
@ -710,7 +757,7 @@ void dqi_poly::gldraw() {
glStencilOp( GL_INVERT, GL_INVERT, GL_INVERT);
glStencilFunc( GL_ALWAYS, 0x1, 0x1 );
glhr::color2(0xFFFFFFFF);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, offset, cnt);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ioffset, cnt);
current_display->set_mask(ed);
glhr::color2(color);
@ -738,7 +785,7 @@ void dqi_poly::gldraw() {
else {
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc( GL_EQUAL, 1, 1);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, offset, cnt);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ioffset, cnt);
}
glDisable(GL_STENCIL_TEST);
@ -746,6 +793,7 @@ void dqi_poly::gldraw() {
}
if(outline && !tinf) {
if(flags & POLY_APEIROGONAL) cnt = apeiro_cnt;
glhr::color2(outline);
glhr::set_depthtest(model_needs_depth() && prio < PPR::SUPERLINE);
glhr::set_depthwrite(model_needs_depth() && prio != PPR::TRANSPARENT_SHADOW && prio != PPR::EUCLIDEAN_SKY);
@ -780,12 +828,27 @@ void dqi_poly::gldraw() {
#endif
EX ld scale_at(const shiftmatrix& T) {
if(GDIM == 3 && pmodel == mdPerspective) return 1 / abs((tC0(unshift(T)))[2]);
if(GDIM == 3 && pmodel == mdPerspective) {
ld z = (tC0(unshift(T)))[2];
if(z == 0) return 1;
z = 1 / abs(z);
if(z > 10) return 10;
return z;
}
if(sol) return 1;
hyperpoint h1, h2, h3;
applymodel(tC0(T), h1);
applymodel(T * xpush0(.01), h2);
applymodel(T * ypush(.01) * C0, h3);
if(mdBandAny()) {
ld x2 = 2;
if(pmodel == mdBandEquiarea) x2 /= 2;
ld x4 = 2 * x2;
if(h2[0] > h1[0] + x2) h2[0] -= x4;
if(h2[0] < h1[0] - x2) h2[0] += x4;
if(h3[0] > h1[0] + x2) h3[0] -= x4;
if(h3[0] < h1[0] - x2) h3[0] += x4;
}
return sqrt(hypot_d(2, h2-h1) * hypot_d(2, h3-h1) / .0001);
}
@ -803,6 +866,17 @@ EX ld linewidthat(const shiftpoint& h) {
return dfc;
}
}
else if(hyperbolic && pmodel == mdRelPerspective) {
if(abs(h[3]) < 1e-6) return 1;
return 1 / (1 + abs(h[3]));
}
else if(sl2 && pmodel == mdRelPerspective) {
if(abs(h[2]) < 1e-6) return 1;
return 1 / (1 + abs(h[2]));
}
else if(hyperbolic && GDIM == 3 && pmodel == mdPerspective && pconf.alpha == 0 && h[3] < 0.99) {
return 1;
}
else if(perfect_linewidth >= (inHighQual ? 1 : 2)) {
hyperpoint h0 = h.h / zlevel(h.h);
shiftmatrix T = shiftless(rgpushxto0(h0), h.shift);
@ -850,13 +924,30 @@ ld period_at(ld y) {
}
}
void ori_to_scr(glvertex& g) {
auto& Ori = pconf.mori().v2;
tie(g[0], g[1]) = make_pair(
Ori[0][0] * g[0] + Ori[0][1] * g[1],
Ori[1][0] * g[0] + Ori[1][1] * g[1]
);
}
void scr_to_ori(glvertex& g) {
auto& Ori = pconf.mori().v2;
/* we invert it, so transposition is applied in the formula */
tie(g[0], g[1]) = make_pair(
Ori[0][0] * g[0] + Ori[1][0] * g[1],
Ori[0][1] * g[0] + Ori[1][1] * g[1]
);
}
void adjust(bool tinf) {
periods.resize(isize(glcoords));
if(!models::model_straight)
for(auto& g: glcoords)
models::apply_orientation(g[0], g[1]);
scr_to_ori(g);
for(int i = 0; i<isize(glcoords); i++) periods[i] = period_at(glcoords[i][1]);
@ -914,7 +1005,7 @@ void adjust(bool tinf) {
if(abs(first - last) < 1e-6) {
if(!models::model_straight)
for(auto& g: glcoords)
models::apply_orientation(g[1], g[0]);
ori_to_scr(g);
}
else {
if(tinf) {
@ -945,7 +1036,7 @@ void adjust(bool tinf) {
}
if(!models::model_straight)
for(auto& g: glcoords)
models::apply_orientation(g[1], g[0]);
ori_to_scr(g);
// we have already looped
loop_min = loop_max = 0;
}
@ -1053,7 +1144,7 @@ EX namespace s2xe {
}
void add2(pt h, int gen) {
glcoords.push_back(glhr::pointtogl(point31(sin(h[0]) * (h[1] + 2 * M_PI * gen), cos(h[0]) * (h[1] + 2 * M_PI * gen), h[2])));
glcoords.push_back(glhr::pointtogl(point31(sin(h[0]) * (h[1] + TAU * gen), cos(h[0]) * (h[1] + TAU * gen), h[2])));
stinf.tvertices.push_back(glhr::makevertex(h[3], h[4], 0));
}
@ -1070,13 +1161,13 @@ EX namespace s2xe {
bool to_right(const pt& h2, const pt& h1) {
ld x2 = h2[0];
ld x1 = h1[0];
if(x2 < x1) x2 += 2 * M_PI;
if(x2 < x1) x2 += TAU;
return x2 >= x2 && x2 <= x1 + M_PI;
}
EX int qrings = 32;
ld seg() { return 2 * M_PI / qrings; }
ld seg() { return TAU / qrings; }
void add_ortho_triangle(pt bl, pt tl, pt br, pt tr) {
@ -1109,12 +1200,12 @@ EX namespace s2xe {
}
void add_ordered_triangle(array<pt, 3> v) {
if(v[1][0] < v[0][0]) v[1][0] += 2 * M_PI;
if(v[2][0] < v[1][0]) v[2][0] += 2 * M_PI;
if(v[1][0] < v[0][0]) v[1][0] += TAU;
if(v[2][0] < v[1][0]) v[2][0] += TAU;
if(v[2][0] - v[0][0] < 1e-6) return;
ld x = (v[1][0] - v[0][0]) / (v[2][0] - v[0][0]);
if(v[2][0] < v[0][0] + M_PI / 4 && maxy < M_PI - M_PI/4 && sightranges[geometry] <= 5) {
if(v[2][0] < v[0][0] + 45._deg && maxy < 135._deg && sightranges[geometry] <= 5) {
addall(v[0], v[1], v[2]);
return;
}
@ -1140,16 +1231,16 @@ EX namespace s2xe {
}
void add_triangle_around(array<pt, 3> v) {
ld baseheight = (v[0][1] > M_PI/2) ? M_PI : 0;
ld baseheight = (v[0][1] > 90._deg) ? M_PI : 0;
ld tu = (v[0][3] + v[1][3] + v[2][3]) / 3;
ld tv = (v[0][4] + v[1][4] + v[2][4]) / 3;
array<pt, 3> vhigh;
for(int i=0; i<3; i++) { vhigh[i] = v[i]; vhigh[i][1] = baseheight; vhigh[i][3] = tu; vhigh[i][4] = tv; }
if(v[1][0] < v[0][0]) v[1][0] = v[1][0] + 2 * M_PI, vhigh[1][0] = vhigh[1][0] + 2 * M_PI;
if(v[1][0] < v[0][0]) v[1][0] = v[1][0] + TAU, vhigh[1][0] = vhigh[1][0] + TAU;
add_ortho_triangle(v[0], vhigh[0], v[1], vhigh[1]);
if(v[2][0] < v[1][0]) v[2][0] = v[2][0] + 2 * M_PI, vhigh[2][0] = vhigh[2][0] + 2 * M_PI;
if(v[2][0] < v[1][0]) v[2][0] = v[2][0] + TAU, vhigh[2][0] = vhigh[2][0] + TAU;
add_ortho_triangle(v[1], vhigh[1], v[2], vhigh[2]);
if(v[0][0] < v[2][0]) v[0][0] = v[0][0] + 2 * M_PI, vhigh[0][0] = vhigh[0][0] + 2 * M_PI;
if(v[0][0] < v[2][0]) v[0][0] = v[0][0] + TAU, vhigh[0][0] = vhigh[0][0] + TAU;
add_ortho_triangle(v[2], vhigh[2], v[0], vhigh[0]);
}
@ -1160,12 +1251,12 @@ EX namespace s2xe {
minz = min(abs(v[0][2]), max(abs(v[1][2]), abs(v[2][2])));
auto& s = sightranges[geometry];
maxgen = sqrt(s * s - minz * minz) / (2 * M_PI) + 1;
maxgen = sqrt(s * s - minz * minz) / TAU + 1;
maxy = max(v[0][1], max(v[1][1], v[2][1]));
miny = min(v[0][1], min(v[1][1], v[2][1]));
with_zero = true;
if(maxy < M_PI / 4) {
if(maxy < 45._deg) {
add2(v[0], 0);
add2(v[1], 0);
add2(v[2], 0);
@ -1255,7 +1346,7 @@ void draw_s2xe0(dqi_poly *p) {
set_width(1);
glcoords.clear();
int maxgen = sightranges[geometry] / (2 * M_PI) + 1;
int maxgen = sightranges[geometry] / TAU + 1;
auto crossdot = [&] (const hyperpoint h1, const hyperpoint h2) { return make_pair(h1[0] * h2[1] - h1[1] * h2[0], h1[0] * h2[0] + h1[1] * h2[1]); };
vector<point_data> pd;
@ -1287,7 +1378,7 @@ void draw_s2xe0(dqi_poly *p) {
for(int i=0; i<p->cnt; i++) {
auto &c1 = pd[i];
auto &c0 = pd[i==0?p->cnt-1 : i-1];
if(c1.distance > M_PI/2 && c0.distance > M_PI/2 && crossdot(c0.direction, c1.direction).second < 0) return;
if(c1.distance > 90._deg && c0.distance > 90._deg && crossdot(c0.direction, c1.direction).second < 0) return;
if(c1.bad == 2) return;
if(c1.bad == 1) no_gens = true;
}
@ -1299,12 +1390,12 @@ void draw_s2xe0(dqi_poly *p) {
angles[i] = atan2(pd[i].direction[1], pd[i].direction[0]);
}
sort(angles.begin(), angles.end());
angles.push_back(angles[0] + 2 * M_PI);
angles.push_back(angles[0] + TAU);
bool ok = false;
for(int i=1; i<isize(angles); i++)
if(angles[i] >= angles[i-1] + M_PI) ok = true;
if(!ok) {
for(auto &c: pd) if(c.distance > M_PI/2) return;
for(auto &c: pd) if(c.distance > 90._deg) return;
no_gens = true;
}
}
@ -1314,7 +1405,7 @@ void draw_s2xe0(dqi_poly *p) {
for(int gen=-g; gen<=g; gen++) {
for(int i=0; i<p->cnt; i++) {
auto& cur = pd[i];
ld d = cur.distance + 2 * M_PI * gen;
ld d = cur.distance + TAU * gen;
hyperpoint h;
h[0] = cur.direction[0] * d;
h[1] = cur.direction[1] * d;
@ -1381,8 +1472,6 @@ void draw_stretch(dqi_poly *p) {
auto &lb = results[i+1];
auto &lc = results[i+2];
int ia = 0, ib = 0, ic = 0;
for(auto& ha: la) for(auto& hb: lb) if(test(ha, hb))
for(auto& hc: lc) if(test(ha, hc) && test(hb, hc)) {
@ -1392,7 +1481,6 @@ void draw_stretch(dqi_poly *p) {
if(p->tinf)
for(int j=0; j<3; j++)
stinf.tvertices.push_back(p->tinf->tvertices[p->offset_texture+i+j]);
ia++; ib++; ic++;
}
}
npoly.cnt = isize(glcoords);
@ -1478,21 +1566,21 @@ EX namespace ods {
dqi_poly npoly = *p;
npoly.offset = 0;
npoly.tab = &glcoords;
npoly.V = Id;
npoly.V = shiftless(Id);
npoly.tinf = p->tinf ? &stinf : NULL;
if(npoly.tinf) {
npoly.offset_texture = 0;
stinf.texture_id = p->tinf->texture_id;
stinf.tvertices.clear();
}
npoly.V = Id;
npoly.V = shiftless(Id);
glcoords.clear();
array<hyperpoint, 6> h;
if(0) for(int i=0; i<p->cnt; i+=3) {
for(int j=0; j<3; j++)
h[j] = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]);
h[j] = unshift(p->V) * glhr::gltopoint((*p->tab)[p->offset+i+j]);
for(int j=0; j<3; j++) {
glcoords.push_back(glhr::makevertex(h[j][0], h[j][1], h[j][2]));
@ -1503,23 +1591,23 @@ EX namespace ods {
if(1) for(int i=0; i<p->cnt; i+=3) {
for(int j=0; j<3; j++) {
hyperpoint o = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]);
if(nonisotropic || prod) {
o = lp_apply(inverse_exp(o, iTable, false));
o[3] = 1;
shiftpoint o = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]);
if(nonisotropic || gproduct) {
auto o1 = lp_apply(inverse_exp(o, pNORMAL));
o1[3] = 1;
dynamicval<eGeometry> g(geometry, gEuclid);
if(!project(o, h[j], h[j+3], global_projection == -1))
if(!project(o1, h[j], h[j+3], global_projection == -1))
goto next_i;
}
else if(!project(o, h[j], h[j+3], global_projection == -1))
else if(!project(unshift(o), h[j], h[j+3], global_projection == -1))
goto next_i;
}
for(int j=0; j<6; j++) {
// let Delta be from 0 to 2PI
if(h[j][2]<0) h[j][2] += 2 * M_PI;
if(h[j][2]<0) h[j][2] += TAU;
// Theta is from -PI/2 to PI/2. Let it be from 0 to PI
h[j][1] += global_projection * M_PI/2;
h[j][1] += global_projection * 90._deg;
h[j][3] = 1;
}
@ -1536,8 +1624,8 @@ EX namespace ods {
cyclefix(h[4][0], h[3][0]);
cyclefix(h[5][0], h[3][0]);
if(abs(h[1][1] - h[0][1]) > M_PI/2) goto next_i;
if(abs(h[2][1] - h[0][1]) > M_PI/2) goto next_i;
if(abs(h[1][1] - h[0][1]) > 90._deg) goto next_i;
if(abs(h[2][1] - h[0][1]) > 90._deg) goto next_i;
if(h[0][0] < -M_PI || h[0][0] > M_PI) println(hlog, h[0][0]);
@ -1546,7 +1634,7 @@ EX namespace ods {
if(h[1][0] < -M_PI || h[2][0] < -M_PI) lst++;
if(h[1][0] > +M_PI || h[2][0] > +M_PI) fst--;
for(int x=fst; x<=lst; x++) for(int j=0; j<3; j++) {
glcoords.push_back(glhr::makevertex(h[j][0] + 2 * M_PI * x, h[j][1], h[j][2]));
glcoords.push_back(glhr::makevertex(h[j][0] + TAU * x, h[j][1], h[j][2]));
if(npoly.tinf) stinf.tvertices.push_back(p->tinf->tvertices[p->offset_texture+i+j]);
}
}
@ -1567,21 +1655,46 @@ EX namespace ods {
bool broken_projection(dqi_poly& p0) {
int broken_coord = models::get_broken_coord(pmodel);
static bool in_broken = false;
bool both_broken = pmodel == mdConformalSquare;
transmatrix T = p0.V.T, IT = Id, FT = Id;
if(both_broken) FT = cspin(0, 1, 45._deg), T = FT * T, IT = cspin(0, 1, -45._deg);
ld zlow = 0;
if(both_broken) {
ld t = pconf.model_transition;
zlow = (1-t*t) / (1+t*t);
}
// x * mt / (1-z) <= 1
// sqrt(1-z*z) * mt / (1-z) <= 1
// sqrt(1-z*z) <= (1-z) / mt
if(broken_coord && !in_broken) {
int zcoord = broken_coord;
int ycoord = 3 - zcoord;
int xcoord = 0;
zcoord = 2;
vector<hyperpoint> all;
for(int i=0; i<p0.cnt; i++)
all.push_back(p0.V.T * glhr::gltopoint((*p0.tab)[p0.offset+i]));
all.push_back(T * glhr::gltopoint((*p0.tab)[p0.offset+i]));
int fail = 0;
int last_fail;
for(auto& h: all) models::apply_orientation(h[0], h[1]);
for(auto& h: all) models::scr_to_ori(h);
auto break_in_xz = [&] (hyperpoint a, hyperpoint b, int xcoord, int zcoord) {
return a[xcoord] * b[xcoord] <= 0 && (a[xcoord] * (b[zcoord]+zlow) - b[xcoord] * (a[zcoord]+zlow)) * (a[xcoord] - b[xcoord]) < 0;
};
auto break_in = [&] (hyperpoint a, hyperpoint b) {
return a[0] * b[0] <= 0 && (a[0] * b[zcoord] - b[0] * a[zcoord]) * (a[0] - b[0]) < 0;
if(both_broken) {
for(int xc=0; xc<2; xc++) {if(break_in_xz(a, b, xc, zcoord)) { xcoord = xc; ycoord = 1-xc; return true; } }
return false;
}
return break_in_xz(a, b, xcoord, zcoord);
};
for(int i=0; i<p0.cnt-1; i++)
@ -1591,16 +1704,21 @@ bool broken_projection(dqi_poly& p0) {
dqi_poly p = p0;
p.tab = &v;
p.offset = 0;
p.V.T = Id;
p.V.T = IT;
/* we don't rotate h's back, just change p.V */
for(int i=0; i<3; i++)
models::apply_orientation(p.V.T[i][0], p.V.T[i][1]);
models::scr_to_ori(p.V.T[i]);
if(fail) {
if(p0.tinf) return true;
dynamicval<bool> ib(in_broken, true);
ld part = ilerp(all[last_fail][0], all[last_fail+1][0], 0);
ld part = ilerp(all[last_fail][xcoord], all[last_fail+1][xcoord], 0);
if(both_broken && all[last_fail][ycoord] * all[last_fail+1][ycoord] < 0) {
ld part2 = ilerp(all[last_fail][ycoord], all[last_fail+1][ycoord], 0);
if(part2 > part) part = part2, swap(xcoord, ycoord);
}
hyperpoint initial = normalize(lerp(all[last_fail], all[last_fail+1], 1 - (1-part) * .99));
bool have_initial = true;
v.push_back(glhr::pointtogl(initial));
@ -1608,19 +1726,48 @@ bool broken_projection(dqi_poly& p0) {
int at = last_fail;
do {
v.push_back(glhr::pointtogl(all[at]));
if(at == p0.cnt-1 && all[at] != all[0]) {
if(at == p0.cnt-1 && sqhypot_d(2, all[at] - all[0]) > 1e-6) {
p.cnt = isize(v); p.draw(); v.clear(); at = 0;
have_initial = false;
}
int next = at+1;
if(next == p0.cnt) next = 0;
if(break_in(all[at], all[next])) {
ld part = ilerp(all[at][0], all[next][0], 0);
ld part = ilerp(all[at][xcoord], all[next][xcoord], 0);
if(both_broken && all[at][ycoord] * all[next][ycoord] < 0) {
ld part2 = ilerp(all[at][ycoord], all[next][ycoord], 0);
if(part2 < part) part = part2, swap(xcoord, ycoord);
}
hyperpoint final = normalize(lerp(all[at], all[next], part * .99));
v.push_back(glhr::pointtogl(final));
if(have_initial) {
int max = 4 << vid.linequality;
if(final[0] * initial[0] > 0) {
if(both_broken) {
auto square_close_corner = [&] (hyperpoint h) {
hyperpoint end = -C0;
end[0] = 0.01 * signum(h[0]);
end[1] = 0.01 * signum(h[1]);
/* if(abs(h1[0]) > abs(h1[1]))
end[0] = 0.01 * signum(h1[0]), end[1] = 0.001 * signum(h1[1]);
else
end[1] = 0.01 * signum(h1[1]), end[0] = 0.001 * signum(h1[0]); */
return normalize(end);
};
hyperpoint endf = square_close_corner(final);
hyperpoint endi = square_close_corner(initial);
if(endf != endi) {
for(int i=1; i<=max; i++)
v.push_back(glhr::pointtogl(lerp(final, endf, i * 1. / max)));
for(int i=0; i<=max; i++)
v.push_back(glhr::pointtogl(lerp(endi, initial, i * 1. / max)));
}
else {
for(int i=1; i<=max; i++)
v.push_back(glhr::pointtogl(lerp(final, initial, i * 1. / max)));
}
}
else if(final[xcoord] * initial[xcoord] > 0) {
for(int i=1; i<=max; i++)
v.push_back(glhr::pointtogl(lerp(final, initial, i * 1. / max)));
}
@ -1744,8 +1891,8 @@ void dqi_poly::draw() {
shiftpoint h2 = V * glhr::gltopoint((*tab)[offset+(i+1)%cnt]);
hyperpoint ah1 = h1.h, ah2 = h2.h;
models::apply_orientation(ah1[0], ah1[1]);
models::apply_orientation(ah2[0], ah2[1]);
models::scr_to_ori(ah1);
models::scr_to_ori(ah2);
if(ah1[1] * ah2[1] > 0) continue;
ld c1 = ah1[1], c2 = -ah2[1];
if(c1 < 0) c1 = -c1, c2 = -c2;
@ -1828,7 +1975,7 @@ void dqi_poly::draw() {
if(isize(glcoords) <= 1) return;
cyl::loop_min = cyl::loop_max = 0;
if(sphere && mdBandAny())
if((sphere && mdBandAny()) || pmodel == mdPolar)
cyl::adjust(tinf);
int poly_limit = max(vid.xres, vid.yres) * 2;
@ -1899,8 +2046,8 @@ void dqi_poly::draw() {
if(l || lastl) {
for(int i=0; i<isize(glcoords); i++) {
glcoords[i][0] += models::ocos * cyl::periods[i] * (l - lastl);
glcoords[i][1] += models::osin * cyl::periods[i] * (l - lastl);
glcoords[i][0] += pconf.mori().get()[0][0] * cyl::periods[i] * (l - lastl);
glcoords[i][1] += pconf.mori().get()[1][0] * cyl::periods[i] * (l - lastl);
}
lastl = l;
}
@ -1989,10 +2136,10 @@ void dqi_poly::draw() {
else
filledPolygonColorI(srend, polyx, polyy, polyi, color);
if(current_display->stereo_active()) filledPolygonColorI(auxrend, polyxr, polyy, polyi, color);
if(current_display->separate_eyes()) filledPolygonColorI(auxrend, polyxr, polyy, polyi, color);
((vid.antialias & AA_NOGL) ?aapolylineColor:polylineColor)(srend, polyx, polyy, polyi, outline);
if(current_display->stereo_active()) aapolylineColor(auxrend, polyxr, polyy, polyi, outline);
if(current_display->separate_eyes()) aapolylineColor(auxrend, polyxr, polyy, polyi, outline);
if(vid.xres >= 2000 || fatborder) {
int xmi = 3000, xma = -3000;
@ -2060,10 +2207,10 @@ EX void prettypoly(const vector<hyperpoint>& t, color_t fillcol, color_t linecol
ptd.intester = C0;
ptd.draw();
}
vector<glvertex> curvedata;
int curvestart = 0;
bool keep_curvedata = false;
EX vector<glvertex> curvedata;
EX int curvestart = 0;
EX bool keep_curvedata = false;
EX void queuereset(eModel m, PPR prio) {
queueaction(prio, [m] () { glflush(); pmodel = m; });
@ -2129,7 +2276,7 @@ EX void quickqueue() {
/* todo */
ld xintval(const shiftpoint& h) {
if(sphereflipped()) return -h.h[2];
if(sphere_flipped) return -h.h[2];
if(hyperbolic) return -h.h[2];
return -intval(h.h, C0);
}
@ -2143,7 +2290,7 @@ int qp[PMAX], qp0[PMAX];
color_t darken_color(color_t& color, bool outline) {
int alpha = color & 255;
if(sphere && pmodel == mdDisk && pconf.alpha <= 1)
if(sphere && pmodel == mdDisk && pconf.alpha <= 0.99)
return 0;
else {
if(outline && alpha < 255)
@ -2173,13 +2320,13 @@ EX void sort_drawqueue() {
#if MINIMIZE_GL_CALLS
map<color_t, vector<unique_ptr<drawqueueitem>>> subqueue;
for(auto& p: ptds) subqueue[(p->prio == PPR::CIRCLE || p->prio == PPR::OUTCIRCLE) ? 0 : p->outline_group()].push_back(move(p));
for(auto& p: ptds) subqueue[(p->prio == PPR::CIRCLE || p->prio == PPR::OUTCIRCLE) ? 0 : p->outline_group()].push_back(std::move(p));
ptds.clear();
for(auto& p: subqueue) for(auto& r: p.second) ptds.push_back(move(r));
for(auto& p: subqueue) for(auto& r: p.second) ptds.push_back(std::move(r));
subqueue.clear();
for(auto& p: ptds) subqueue[(p->prio == PPR::CIRCLE || p->prio == PPR::OUTCIRCLE) ? 0 : p->color].push_back(move(p));
for(auto& p: ptds) subqueue[(p->prio == PPR::CIRCLE || p->prio == PPR::OUTCIRCLE) ? 0 : p->color].push_back(std::move(p));
ptds.clear();
for(auto& p: subqueue) for(auto& r: p.second) ptds.push_back(move(r));
for(auto& p: subqueue) for(auto& r: p.second) ptds.push_back(std::move(r));
#endif
for(auto& p: ptds) {
@ -2200,7 +2347,7 @@ EX void sort_drawqueue() {
vector<unique_ptr<drawqueueitem>> ptds2;
ptds2.resize(siz);
for(int i = 0; i<siz; i++) ptds2[qp[int(ptds[i]->prio)]++] = move(ptds[i]);
for(int i = 0; i<siz; i++) ptds2[qp[int(ptds[i]->prio)]++] = std::move(ptds[i]);
swap(ptds, ptds2);
}
@ -2224,7 +2371,7 @@ EX void draw_backside() {
ptd->draw();
}
spherespecial = sphereflipped() ? 1 : -1;
spherespecial = sphere_flipped ? 1 : -1;
reset_projection();
if(pmodel == mdRotatedHyperboles) {
@ -2271,9 +2418,44 @@ EX void set_vr_sphere() {
#endif
}
EX int hemi_side = 0;
EX void draw_main() {
DEBBI(DF_GRAPH, ("draw_main"));
if(pconf.back_and_front == 1 && vid.consider_shader_projection) {
dynamicval<int> pa(pconf.back_and_front);
pconf.back_and_front = 0;
draw_main();
pconf.back_and_front = 2;
reset_projection();
draw_main();
return;
}
if(pmodel == mdHemisphere && sphere && hemi_side == 0 && !vrhr::rendering()) {
hemi_side = (pconf.ball() * hyperpoint(0,1,0,1)) [2] < 0 ? 1 : -1;
draw_main();
if(pconf.show_hyperboloid_flat) {
dynamicval<eModel> dv (pmodel, mdHyperboloidFlat);
dynamicval<int> ds (spherespecial, 1);
for(auto& ptd: ptds)
if(!among(ptd->prio, PPR::MOBILE_ARROW, PPR::OUTCIRCLE, PPR::CIRCLE))
ptd->draw();
}
for(auto& ptd: ptds) if(ptd->prio == PPR::OUTCIRCLE) {
auto c = dynamic_cast<dqi_poly*> (&*ptd);
if(c) { c->color = 0; c->outline = 0; }
}
hemi_side *= -1;
draw_main();
hemi_side = 0;
return;
}
set_vr_sphere();
if(sphere && GDIM == 3 && pmodel == mdPerspective && !stretch::in() && !ray::in_use) {
@ -2371,7 +2553,7 @@ EX void drawqueue() {
#endif
#if MAXMDIM >= 4 && CAP_GL
if(WDIM == 2 && GDIM == 3 && hyperbolic && !vrhr::rendering()) make_air();
make_air();
#endif
#if CAP_VR
@ -2421,8 +2603,27 @@ EX void drawqueue() {
});
}
if(draw_plain_floors && (default_flooralpha < 255 || svg::in)) for(PPR p: {PPR::FLOOR}) {
int pp = int(p);
if(qp0[pp] == qp[pp]) continue;
auto get_z = [&] (const unique_ptr<drawqueueitem>& p) -> ld {
auto d = dynamic_cast<dqi_poly*> (&*p);
if(!d) return 0;
hyperpoint h = Hypc;
for(int i=0; i<d->cnt; i++) h += glhr::gltopoint( (*d->tab)[d->offset + i] );
h /= d->cnt; normalize(h);
h = unshift(d->V) * h;
return h[2];
};
sort(&ptds[qp0[int(p)]], &ptds[qp[int(p)]],
[&] (const unique_ptr<drawqueueitem>& p1, const unique_ptr<drawqueueitem>& p2) {
return get_z(p1) > get_z(p2);
});
}
#if CAP_SDL
if(current_display->stereo_active() && !vid.usingGL) {
if(current_display->separate_eyes() && !vid.usingGL) {
if(aux && (aux->w != s->w || aux->h != s->h)) {
SDL_FreeSurface(aux);
@ -2450,7 +2651,7 @@ EX void drawqueue() {
reset_projection();
#if CAP_GL
if(model_needs_depth() && current_display->stereo_active()) {
if(model_needs_depth() && current_display->separate_eyes()) {
global_projection = -1;
draw_main();
#if CAP_GL
@ -2523,6 +2724,7 @@ EX dqi_poly& queuepolyat(const shiftmatrix& V, const hpcshape& h, color_t col, P
ptd.tinf = h.tinf;
if(neon_mode != eNeon::none && (h.flags & POLY_TRIANGLES))
ptd.tinf = nullptr;
ptd.apeiro_cnt = h.she - h.s;
ptd.offset_texture = h.texture_offset;
ptd.intester = h.intester;
return ptd;
@ -2560,9 +2762,18 @@ EX void curvepoint(const hyperpoint& H1) {
curvedata.push_back(glhr::pointtogl(H1));
}
EX dqi_poly& queuecurve(const shiftmatrix& V, color_t linecol, color_t fillcol, PPR prio) {
EX void curvepoint_first() {
curvedata.push_back(curvedata[curvestart]);
}
EX dqi_poly& queuecurve_reuse(const shiftmatrix& V, color_t linecol, color_t fillcol, PPR prio) {
auto &res = queuetable(V, curvedata, isize(curvedata)-curvestart, linecol, fillcol, prio);
res.offset = curvestart;
return res;
}
EX dqi_poly& queuecurve(const shiftmatrix& V, color_t linecol, color_t fillcol, PPR prio) {
auto &res = queuecurve_reuse(V, linecol, fillcol, prio);
curvestart = isize(curvedata);
return res;
}
@ -2681,7 +2892,7 @@ EX void write_in_space(const shiftmatrix& V, int fsize, double size, const strin
}
if(frame) for(int i=0; i<360; i+=45) {
auto &res = queuetable(V * xspinpush(i*degree, frame*scale), curvedata, isize(curvedata)-curvestart, col & 0xFF, col & 0xFF, prio);
auto &res = queuetable(V * xspinpush(i*degree, frame*scale), curvedata, isize(curvedata)-curvestart, poly_outline, poly_outline, prio);
res.offset = curvestart;
res.offset_texture = fstart;
res.tinf = &finf;

1397
embeddings.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -54,20 +54,14 @@ EX vector<cell*> worms, ivies, ghosts, golems, hexsnakes;
/** temporary changes during bfs */
vector<pair<cell*, eMonster>> tempmonsters;
/** additional direction information for BFS algorithms.
* It remembers from where we have got to this location
* the opposite cell will be added to the queue first,
* which helps the AI.
**/
EX vector<int> reachedfrom;
/** The position of the first cell in dcal in distance 7. New wandering monsters can be generated in dcal[first7..]. */
EX int first7;
/** the list of all nearby cells, according to cpdist */
EX vector<cell*> dcal;
/** the list of all nearby cells, according to current pathdist */
EX vector<cell*> pathq;
EX vector<cellwalker> pathq;
/** the number of big statues -- they increase monster generation */
EX int statuecount;
@ -88,26 +82,61 @@ EX int gamerange() { return getDistLimit() + gamerange_bonus; }
EX cell *pd_from;
EX int pd_range;
EX void onpath(cell *c, int d) {
c->pathdist = d;
pathq.push_back(c);
#if HDR
/** The pathdata is used to keep a list of visited cells. It is used as follows:
* 1) create pathdata object: pathdata pd(identifier)
* 2) use one of the following methods to mark cells as visited:
* 2a) onpath_with_dir or onpath_random_dir, to mark a cell together with its distance and the direction we came from (used by computePathdist to make pathfinding not sensitive to direction indexing)
* 2b) onpath, to mark a cell at its distance (used when ordering is irrelevant: compute_graphical_distance and in shmup)
* 2c) onpatk_mark, to just mark a cell (used in groupmove2)
* 3) All the visited cells are listed in pathq, and they have 'pathdist' set to their recorded distance (0 in case of onpath_mark).
* 4) When the pathdata object is deleted, all the pathdist values are cleared back to PINFD.
* The variable 'pathlock' ensures that we do not use two pathdata objects at once.
**/
struct pathdata {
void checklock();
~pathdata();
pathdata(eMonster m, bool include_allies IS(true));
pathdata(int i);
};
#endif
/** using pathdata, record a cell (together with direction) as visited */
EX void onpath_with_dir(cellwalker cw, int d) {
if(!pathlock) {
println(hlog, "onpath(", cw, ", ", d, ") without pathlock");
}
cw.at->pathdist = d;
pathq.push_back(cw);
}
EX void onpath(cell *c, int d, int sp) {
c->pathdist = d;
pathq.push_back(c);
reachedfrom.push_back(sp);
/** using pathdata, record a cell as visited, with random direction */
EX void onpath_random_dir(cell *c, int d) {
onpath_with_dir(cellwalker(c, hrand(c->type), hrand(2)), d);
}
EX void onpath(cell *c, int d) {
onpath_with_dir(cellwalker(c, 0, 0), d);
}
EX void onpath_mark(cell *c) {
onpath_with_dir(cellwalker(c, 0, 0), 0);
}
EX void clear_pathdata() {
for(auto c: pathq) c->pathdist = PINFD;
for(auto c: pathq) c.at->pathdist = PINFD;
pathq.clear();
pathqm.clear();
reachedfrom.clear();
}
/** This ensures that we do not use two pathdata objects at once */
EX int pathlock = 0;
/** compute_graphical_distance determines the distance of every cell
* from the current FOV center. It uses the pathq structures but
* does not lock them */
EX void compute_graphical_distance() {
if(pathlock) { printf("path error: compute_graphical_distance\n"); }
cell *c1 = centerover ? centerover : pd_from ? pd_from : cwt.at;
@ -115,19 +144,21 @@ EX void compute_graphical_distance() {
if(pd_from == c1 && pd_range == sr) return;
clear_pathdata();
pathlock++;
pd_from = c1;
pd_range = sr;
c1->pathdist = 0;
pathq.push_back(pd_from);
onpath(c1, 0);
for(int qb=0; qb<isize(pathq); qb++) {
cell *c = pathq[qb];
cell *c = pathq[qb].at;
if(c->pathdist == pd_range) break;
if(qb == 0) forCellCM(c1, c) ;
forCellEx(c1, c)
if(c1->pathdist == PINFD)
onpath(c1, c->pathdist + 1);
}
pathlock--;
}
const int max_radius = 16;
@ -151,7 +182,7 @@ struct princess_ai {
void princess_ai::run() {
int radius = toggle_radius(waOpenPlate);
if(pathq.empty()) return;
int d = pathq.back()->pathdist;
int d = pathq.back().at->pathdist;
if(d == PINFD - 1) return;
d++;
if(d < 5) d = 5; /* the Princess AI avoids plates when too close to the player */
@ -166,7 +197,7 @@ void princess_ai::run() {
info[0].visit(c1);
}
if(k == radius && c->wall == waOpenPlate && c->pathdist == PINFD)
onpath(c, d, hrand(c->type));
onpath_random_dir(c, d);
}
}
@ -174,7 +205,7 @@ EX void computePathdist(eMonster param, bool include_allies IS(true)) {
for(cell *c: targets)
if(include_allies || isPlayerOn(c))
onpath(c, isPlayerOn(c) ? 0 : 1, hrand(c->type));
onpath_random_dir(c, isPlayerOn(c) ? 0 : 1);
int qtarg = isize(targets);
@ -187,8 +218,10 @@ EX void computePathdist(eMonster param, bool include_allies IS(true)) {
princess_retry:
for(; qb < isize(pathq); qb++) {
cell *c = pathq[qb];
int fd = reachedfrom[qb] + c->type/2;
cellwalker cw = pathq[qb];
/* The opposite cell will be added to the queue first, which helps the AI. */
cw += cw.at->type/2;
cell*& c = cw.at;
if(c->monst && !isBug(c) && !(isFriendly(c) && !c->stuntime)) {
pathqm.push_back(c);
continue; // no paths going through monsters
@ -202,15 +235,19 @@ EX void computePathdist(eMonster param, bool include_allies IS(true)) {
int d = c->pathdist;
if(d == PINFD - 1) continue;
for(int j=0; j<c->type; j++) {
int i = (fd+j) % c->type;
cellwalker cw1 = cw + j;
// printf("i=%d cd=%d\n", i, c->move(i)->cpdist);
cell *c2 = c->move(i);
cell *c2 = cw1.peek();
flagtype f = P_MONSTER | P_REVDIR;
if(param == moTameBomberbird) f |= P_FLYING;
flagtype f = P_MONSTER;
if(param == moTameBomberbird) f |= P_FLYING | P_ISFRIEND;
if(isPrincess(param)) f |= P_ISFRIEND | P_USEBOAT | P_CHAIN;
if(param == moGolem) f |= P_ISFRIEND;
bool pass = c2 && c2->pathdist == PINFD;
if(pass && qb < qtarg && !nonAdjacent(c, c2) && !thruVine(c,c2)) pass = passable(c2, NULL, f);
else pass = pass && passable(c, c2, f);
if(c2 && c2->pathdist == PINFD &&
passable(c2, (qb<qtarg) && !nonAdjacent(c,c2) && !thruVine(c,c2) ?NULL:c, f)) {
if(pass) {
if(qb >= qtarg) {
if(param == moTortoise && nogoSlow(c, c2)) continue;
@ -220,7 +257,7 @@ EX void computePathdist(eMonster param, bool include_allies IS(true)) {
continue;
}
onpath(c2, d+1, c->c.spin(i));
onpath_with_dir(cw1 + wstep, d+1);
}
else if(c2 && c2->wall == waClosedGate && princess)
@ -234,33 +271,39 @@ EX void computePathdist(eMonster param, bool include_allies IS(true)) {
}
}
#if HDR
struct pathdata {
void checklock() {
if(pd_from) pd_from = NULL, clear_pathdata();
if(pathlock) printf("path error\n");
pathlock++;
}
~pathdata() {
pathlock--;
clear_pathdata();
}
pathdata(eMonster m, bool include_allies IS(true)) {
checklock();
computePathdist(m, include_allies);
}
pathdata(int i) {
checklock();
}
};
#endif
pathdata::~pathdata() {
pathlock--;
clear_pathdata();
}
void pathdata::checklock() {
if(pd_from) pd_from = NULL, clear_pathdata();
if(pathlock) printf("path error\n");
pathlock++;
}
pathdata::pathdata(int i) { checklock(); }
pathdata::pathdata(eMonster m, bool include_allies IS(true)) {
checklock();
if(isize(pathq))
println(hlog, "! we got tiles on pathq: ", isize(pathq));
computePathdist(m, include_allies);
}
// pathdist end
/** additional direction information for BFS algorithms.
* It remembers from where we have got to this location
* the opposite cell will be added to the queue first,
* which helps the AI. Used in bfs().
**/
EX vector<int> bfs_reachedfrom;
/** calculate cpdist, 'have' flags, and do general fixings */
EX void bfs() {
calcTidalPhase();
yendor::onpath();
int dcs = isize(dcal);
@ -283,16 +326,13 @@ EX void bfs() {
airmap.clear();
if(!(hadwhat & HF_ROSE)) rosemap.clear();
dcal.clear(); reachedfrom.clear();
dcal.clear(); bfs_reachedfrom.clear();
recalcTide = false;
for(cell *c: player_positions()) {
if(c->cpdist == 0) continue;
c->cpdist = 0;
checkTide(c);
dcal.push_back(c);
reachedfrom.push_back(hrand(c->type));
bfs_reachedfrom.push_back(hrand(c->type));
if(!invismove) targets.push_back(c);
}
@ -308,7 +348,7 @@ EX void bfs() {
first7 = 0;
while(true) {
if(qb == isize(dcal)) break;
int i, fd = reachedfrom[qb] + 3;
int i, fd = bfs_reachedfrom[qb] + dcal[qb]->type/2;
cell *c = dcal[qb++];
int d = c->cpdist;
@ -328,7 +368,7 @@ EX void bfs() {
c2->wall = waSea;
if(c2 && signed(c2->cpdist) > d+1) {
if(WDIM == 3 && !gmatrix.count(c2)) {
if(WDIM == 3 && (d > 2 && !gmatrix.count(c2))) {
if(!first7) first7 = qb;
continue;
}
@ -336,7 +376,7 @@ EX void bfs() {
// remove treasures
if(!peace::on && c2->item && c2->cpdist == distlimit && itemclass(c2->item) == IC_TREASURE &&
c2->item != itBabyTortoise &&
!among(c2->item, itBrownian, itBabyTortoise) && WDIM != 3 &&
(items[c2->item] >= (ls::any_chaos()?10:20) + currentLocalTreasure || getGhostcount() >= 2)) {
c2->item = itNone;
if(c2->land == laMinefield) { c2->landparam &= ~3; }
@ -346,7 +386,7 @@ EX void bfs() {
c2->item = itNone;
c2->landparam |= 2;
c2->landparam &= ~1;
if(!c2->monst) c2->monst = moBomberbird;
if(!c2->monst) c2->monst = moBomberbird, c2->stuntime = 0;
}
if(c2->item == itBarrow && c2->cpdist == distlimit && c2->wall != waBarrowDig) {
@ -389,10 +429,8 @@ EX void bfs() {
if(!keepLightning) c2->ligon = 0;
dcal.push_back(c2);
reachedfrom.push_back(c->c.spin(i));
bfs_reachedfrom.push_back(c->c.spin(i));
checkTide(c2);
if(c2->wall == waBigStatue && c2->land != laTemple)
statuecount++;
@ -503,11 +541,6 @@ EX void bfs() {
if(c2->wall == waThumperOn) {
targets.push_back(c2);
}
while(recalcTide) {
recalcTide = false;
for(int i=0; i<isize(dcal); i++) checkTide(dcal[i]);
}
for(auto& t: tempmonsters) t.first->monst = t.second;
@ -786,8 +819,18 @@ EX void findWormIvy(cell *c) {
else break;
}
}
EX void advance_tides() {
calcTidalPhase();
recalcTide = true;
while(recalcTide) {
recalcTide = false;
for(int i=0; i<isize(dcal); i++) checkTide(dcal[i]);
}
}
EX void monstersTurn() {
reset_spill();
checkSwitch();
mirror::breakAll();
DEBB(DF_TURN, ("bfs"));
@ -799,7 +842,7 @@ EX void monstersTurn() {
if(!phase2) movemonsters();
for(cell *pc: player_positions()) if(pc->item == itOrbSafety) {
collectItem(pc, true);
collectItem(pc, pc, true);
return;
}
@ -823,6 +866,8 @@ EX void monstersTurn() {
if(!phase1) livecaves();
if(!phase1) ca::simulate();
if(!phase1) heat::processfires();
// this depends on turncount, so we do it always
advance_tides();
for(cell *c: crush_now) {
changes.ccell(c);
@ -837,7 +882,7 @@ EX void monstersTurn() {
changes.value_keep(crush_now);
changes.value_keep(crush_next);
crush_now = move(crush_next);
crush_now = std::move(crush_next);
crush_next.clear();
DEBB(DF_TURN, ("heat"));
@ -865,4 +910,25 @@ EX void monstersTurn() {
#endif
}
/** check if whirlline is looped, if yes, remove the repeat; may not detect loops immediately */
EX bool looped(vector<cell*>& whirlline) {
if(isize(whirlline) == 1)
return false;
if(whirlline.back() == whirlline.front()) {
whirlline.pop_back();
return true;
}
int pos = isize(whirlline)/2;
if(isize(whirlline) > 2 && whirlline.back() == whirlline[pos]) {
while(pos && whirlline.back() == whirlline[pos])
whirlline.pop_back();
/* something weird must have happened... */
static bool once = true;
if(once) addMessage("warning: a looped line");
once = false;
return true;
}
return false;
}
}

View File

@ -12,8 +12,8 @@ EX namespace euc {
#if HDR
struct coord : array<int, 3> {
coord() {}
coord(int x, int y, int z) { self[0] = x; self[1] = y; self[2] = z; }
explicit coord() = default;
constexpr explicit coord(int x, int y, int z) : array<int,3> {{x,y,z}} {}
coord& operator += (coord b) { for(int i: {0,1,2}) self[i] += b[i]; return self; }
coord& operator -= (coord b) { for(int i: {0,1,2}) self[i] -= b[i]; return self; }
coord operator + (coord b) const { coord a = self; return a += b; }
@ -32,7 +32,7 @@ EX namespace euc {
EX const coord eutester = coord(3,7,0);
EX intmatrix euzeroall = make_array<coord>(euzero, euzero, euzero);
static const intmatrix main_axes = make_array<coord>(coord(1,0,0), coord(0,1,0), coord(0,0,1));
static constexpr intmatrix main_axes = make_array<coord>(coord(1,0,0), coord(0,1,0), coord(0,0,1));
EX vector<coord> get_shifttable() {
static const coord D0 = main_axes[0];
@ -46,10 +46,12 @@ EX namespace euc {
switch(g) {
case gCubeTiling:
case gMengerSponge:
shifttable = { +D0, +D1, +D2 };
break;
case gRhombic3:
case gSierpinskiTet:
shifttable = { D0+D1, D0+D2, D1+D2, D1-D2, D0-D2, D0-D1 };
break;
@ -58,10 +60,13 @@ EX namespace euc {
break;
case gEuclid:
case gSierpinski3:
case gSixFlake:
shifttable = { D0, D1, D1-D0, -D0, -D1, D0-D1 };
break;
case gEuclidSquare:
case gSierpinski4:
shifttable = { D0, D1, -D0, -D1 };
break;
@ -137,10 +142,10 @@ EX namespace euc {
map<gp::loc, struct cdata> eucdata;
void compute_tmatrix() {
cgi.require_basics();
shifttable = get_shifttable();
tmatrix.resize(S7);
for(int i=0; i<S7; i++)
tmatrix[i] = eumove(shifttable[i]);
for(int i=0; i<S7; i++) tmatrix[i] = eumove(shifttable[i]);
}
void on_dim_change() override {
@ -149,7 +154,7 @@ EX namespace euc {
vector<cell*> toruscells;
vector<cell*>& allcells() override {
if(bounded) {
if(closed_manifold && !disksize) {
if(isize(toruscells) == 0) {
celllister cl(getOrigin()->c7, 1000, 1000000, NULL);
toruscells = cl.lst;
@ -236,6 +241,7 @@ EX namespace euc {
}
transmatrix adj(cell *c, int i) override {
if(dont_inverse()) return adj(c->master, i);
if(WDIM == 3) return adj(c->master, i);
else return hrmap_standard::adj(c, i);
}
@ -255,8 +261,11 @@ EX namespace euc {
bool draw = drawcell_subs(c, V * spin(master_to_c7_angle()));
if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000 && !hybrid::pmap) continue;
if(draw) for(int i=0; i<S7; i++)
dq::enqueue_by_matrix(h->move(i), optimized_shift(V * adj(h, i)));
if(draw) for(int i=0; i<S7; i++) {
auto V1 = V * adj(h, i);
if(geom3::apply_break_cylinder && cgi.emb->break_cylinder(V, V1)) continue;
dq::enqueue_by_matrix(h->move(i), optimized_shift(V1));
}
}
}
@ -634,7 +643,7 @@ EX namespace euc {
}
set_flag(ginf[g].flags, qANYQ, eu.infinite_dims < dim);
set_flag(ginf[g].flags, qBOUNDED, eu.infinite_dims == 0);
set_flag(ginf[g].flags, qCLOSED, eu.infinite_dims == 0);
set_flag(ginf[g].flags, qSMALL, eu.infinite_dims == 0 && eu.det <= 4096);
bool nonori = false;
if(eu.twisted&1) nonori = !nonori;
@ -882,7 +891,7 @@ EX namespace euc {
auto& T_edit = eu_edit.user_axes;
auto& twisted_edit = eu_edit.twisted;
cmode = sm::SIDE | sm::MAYDARK | sm::TORUSCONFIG;
gamescreen(1);
gamescreen();
dialog::init(XLAT("Euclidean quotient spaces"));
for(int y=0; y<dim+1; y++)
@ -954,7 +963,7 @@ EX namespace euc {
dialog::addItem("special manifolds", 'S');
dialog::add_action([] {
dialog::editNumber(quotient_size, 1, 12, 1, 2, "special manifold size", "");
dialog::extra_options = [] {
dialog::get_di().extra_options = [] {
auto q = quotient_size;
torus_config_option(XLAT("third-turn space"), 'A', make_third_turn(q,0,q));
torus_config_option(XLAT("quarter-turn space"), 'B', make_quarter_turn(q,0,q));
@ -1037,7 +1046,7 @@ EX namespace euc {
"not implemented.)"
)
);
dialog::extra_options = show_fundamental;
dialog::get_di().extra_options = show_fundamental;
});
}
}
@ -1200,13 +1209,14 @@ EX transmatrix eumove(coord co) {
}
transmatrix Mat = Id;
if(a4) {
Mat[0][LDIM] += co[0] * cgi.tessf;
Mat[1][LDIM] += co[1] * cgi.tessf;
Mat[0][2] += co[0] * cgi.tessf;
Mat[1][2] += co[1] * cgi.tessf;
}
else {
Mat[0][LDIM] += (co[0] + co[1] * .5) * cgi.tessf;
Mat[1][LDIM] += co[1] * q3 /2 * cgi.tessf;
Mat[0][2] += (co[0] + co[1] * .5) * cgi.tessf;
Mat[1][2] += co[1] * q3 /2 * cgi.tessf;
}
if(embedded_plane) Mat = cgi.emb->base_to_actual(Mat);
return Mat;
}
@ -1356,7 +1366,9 @@ EX void generate() {
*/
EX bool in() {
if(fake::in()) return FPIU(in());
return euclid && standard_tiling();
if(geometry == gCubeTiling && (reg3::cubes_reg3 || !PURE)) return false;
if(cgflags & qEXPERIMENTAL) return false;
return meuclid && standard_tiling();
}
EX bool in(int dim) { return in() && WDIM == dim; }

View File

@ -23,6 +23,7 @@ void canonicize(vector<int>& t) {
#if HDR
struct expansion_analyzer {
int sibling_limit;
vector<int> gettype(cell *c);
int N;
vector<cell*> samples;
@ -99,27 +100,36 @@ template<class T, class U> vector<int> get_children_codes(cell *c, const T& dist
}
return res;
}
void expansion_analyzer::preliminary_grouping() {
samples.clear();
codeid.clear();
children.clear();
if(reg3::in_rule()) {
children.clear();
if(currentmap->strict_tree_rules()) {
N = isize(rulegen::treestates);
children.resize(N);
rootid = rulegen::rule_root;
for(int i=0; i<N; i++)
for(int v: rulegen::treestates[i].rules)
if(v >= 0) children[i].push_back(v);
}
#if MAXMDIM >= 4
else if(reg3::exact_rules()) {
rootid = reg3::rule_get_root(0);
auto& chi = reg3::rule_get_children();
N = isize(chi) / S7;
auto& chpos = reg3::rule_get_childpos();
N = isize(chpos) - 1;
children.resize(N);
int k = 0;
for(int i=0; i<N; i++) for(int j=0; j<S7; j++) {
for(int i=0; i<N; i++) for(int j=0; j<chpos[i+1]-chpos[i]; j++) {
int ck = chi[k];
if(ck < -1) ck += (1<<16);
if(ck >= 0)
children[i].push_back(ck);
k++;
}
#endif
}
#endif
else {
sample_id(currentmap->gamestart());
// queue for, do not change to range-based for
@ -135,7 +145,10 @@ void expansion_analyzer::preliminary_grouping() {
}
void expansion_analyzer::reduce_grouping() {
if(reg3::in_rule()) return;
#if MAXMDIM >= 4
if(reg3::exact_rules()) return;
#endif
if(currentmap->strict_tree_rules()) return;
int old_N = N;
vector<int> grouping;
grouping.resize(N);
@ -180,7 +193,7 @@ void expansion_analyzer::reduce_grouping() {
for(int i=0; i<nogroups; i++)
for(int j: children[groupsample[i]])
newchildren[i].push_back(grouping[j]);
children = move(newchildren);
children = std::move(newchildren);
for(auto& p: codeid) p.second = grouping[p.second];
N = nogroups;
rootid = grouping[rootid];
@ -200,6 +213,7 @@ bignum& expansion_analyzer::get_descendants(int level) {
}
bignum& expansion_analyzer::get_descendants(int level, int type) {
if(!N) preliminary_grouping(), reduce_grouping();
auto& pd = descendants;
size_upto(pd, level+1);
for(int d=0; d<=level; d++)
@ -227,7 +241,11 @@ bool expansion_analyzer::verify(int id) {
int expansion_analyzer::valid(int v, int step) {
if(step < 0) return 0;
int more = reg3::in_rule() ? 1 : 5;
#if MAXMDIM >= 4
int more = 5;
#else
int more = reg3::exact_rules() ? 1 : 5;
#endif
#if CAP_GMP == 0
if(get_descendants(step+v+v+more).approx_int() >= bignum::BASE) return 0;
typedef ld val;
@ -380,14 +398,19 @@ int type_in_quick(expansion_analyzer& ea, cell *c, const cellfunction& f) {
}
EX bool sizes_known() {
if(reg3::in_rule()) return true;
if(bounded) return false;
#if MAXMDIM >= 4
if(reg3::exact_rules()) return true;
#endif
if(closed_manifold) return false;
// Castle Anthrax is infinite
if(bt::in()) return false;
// not implemented
if(arcm::in()) return false;
if(kite::in()) return false;
return true;
if(aperiodic) return false;
if(currentmap->strict_tree_rules()) return true;
if(arb::in()) return false;
if(INVERSE) return false;
return true;
}
EX bool trees_known() {
@ -408,29 +431,48 @@ string expansion_analyzer::approximate_descendants(int d, int max_length) {
return XLAT("about ") + fts(pow(10, log_10 - more_digits)) + "E" + its(more_digits);
}
#if HDR
enum eDistanceFrom { dfPlayer, dfStart, dfWorld };
#endif
EX string dfnames[3] = { "player", "start", "land" };
eDistanceFrom distance_from = dfPlayer;
EX eDistanceFrom distance_from = dfPlayer;
enum eNumberCoding { ncNone, ncDistance, ncType, ncDebug };
EX string ncnames[4] = { "NO", "distance", "type", "debug" };
eNumberCoding number_coding = ncDistance;
#if HDR
enum eNumberCoding { ncNone, ncDistance, ncType, ncDebug, ncError };
#endif
EX string ncnames[5] = { "NO", "distance", "type", "debug", "error" };
EX eNumberCoding number_coding = ncDistance;
bool mod_allowed() {
return cheater || autocheat || arcm::in() || tour::on;
EX bool mod_allowed() {
return cheater || autocheat || arcm::in() || arb::in() || tour::on;
}
EX bool distances_legal(cell *c) {
if(mod_allowed()) return true;
switch(distance_from) {
case dfPlayer:
return true;
case dfStart:
return bt::in();
case dfWorld:
return c && among(c->land, laOcean, laIvoryTower, laEndorian, laDungeon, laTemple, laWhirlpool, laCanvas);
}
return false;
}
EX int curr_dist(cell *c) {
if(!distances_legal(c)) return 0;
switch(distance_from) {
case dfPlayer:
return c->cpdist < INFD ? c->cpdist : celldistance(cwt.at, c);
case dfStart:
return celldist(c);
case dfWorld:
if(!mod_allowed() && !among(c->land, laOcean, laIvoryTower, laEndorian, laDungeon, laTemple, laWhirlpool, laCanvas))
return 0;
if((isCyclic(c->land) || c->land == laCanvas) && (eubinary || c->master->alt)) return celldistAlt(c);
if((isCyclic(c->land) || among(c->land, laCanvas, laCaribbean, laStorms, laRlyeh))) {
if(eubinary || c->master->alt) return celldistAlt(c);
return UNKNOWN;
}
return inmirror(c) ? (c->landparam & 255) : c->landparam;
}
return 0;
@ -441,6 +483,7 @@ int position;
EX int type_in_reduced(expansion_analyzer& ea, cell *c, const cellfunction& f) {
int a = ea.N;
int t = type_in(ea, c, f);
auto& expansion = get_expansion();
if(expansion.N != a) {
expansion.reduce_grouping();
t = type_in(ea, c, f);
@ -512,6 +555,15 @@ EX namespace ts {
return c->cmodmove(pid + (valence() == 3 ? 2 : 1) + id);
}
EX cell *get_child(cell *c, const cellfunction& cf, int v) {
for(int i=0; i<c->type; i++) if(cf(c->cmodmove(i+v)) <= cf(c) && cf(c->cmodmove(i)) > cf(c))
return c->cmodmove(i);
return nullptr;
}
EX cell *right_child(cell *c, const cellfunction& cf) { return get_child(c, cf, -1); }
EX cell *left_child(cell *c, const cellfunction& cf) { return get_child(c, cf, 1); }
#if HDR
inline cell *left_parent(cell *c, const cellfunction& cf) { return verified_add(c, 1, 0, cf); }
inline cell *right_parent(cell *c, const cellfunction& cf) { return verified_add(c, -1, 0, cf); }
@ -524,7 +576,7 @@ EX bool use_color_codes = true;
EX bool use_analyzer = true;
EX bool show_distance_lists = true;
int first_distance = 0, scrolltime = 0;
int last_distance = 16;
bool scrolling_distances = false;
EX map<int, color_t> expcolors;
@ -555,13 +607,13 @@ void celldrawer::do_viewdist() {
switch(number_coding) {
case ncDistance: {
label = its(cd);
label = cd == UNKNOWN ? "?" : its(cd);
dc = distcolors[cd];
break;
}
case ncType: {
int t = -1;
if(reg3::in_rule()) switch(distance_from) {
if(reg3::exact_rules()) switch(distance_from) {
case dfPlayer:
t = -1;
break;
@ -572,7 +624,18 @@ void celldrawer::do_viewdist() {
if(c->master->alt) t = c->master->alt->fiftyval;
break;
}
else t = type_in_reduced(expansion, c, curr_dist);
else if(currentmap->strict_tree_rules()) switch(distance_from) {
case dfPlayer:
t = -1;
break;
case dfStart:
t = c->master->fieldval;
break;
case dfWorld:
if(c->master->alt) t = c->master->alt->fieldval;
break;
}
else t = type_in_reduced(get_expansion(), c, curr_dist);
if(t >= 0) label = its(t), dc = distribute_color(t);
break;
}
@ -583,22 +646,22 @@ void celldrawer::do_viewdist() {
dc = (d != cd) ? 0xFF0000 : 0x00FF00;
label = its(d);
}
case ncError: {
if(pointer_indices.count(c)) label = index_pointer(c);
}
case ncNone: ;
}
if(!dist_label_colored) dc = dist_label_color;
// string label = its(fieldpattern::getriverdistleft(c)) + its(fieldpattern::getriverdistright(c));
/* queuepolyat(V, shFloor[ct6], darkena(gradient(0, distcolors[cd&7], 0, .25, 1), fd, 0xC0),
PPR::TEXT); */
if(label != "")
queuestr(V, (isize(label) > 1 ? .6 : 1), label, 0xFF000000 + dc, 1);
queuestr(V, (isize(label) > 1 ? .6 : 1) * mapfontscale / 100, label, 0xFF000000 + dc, 1);
}
EX void viewdist_configure_dialog() {
dialog::init("");
cmode |= sm::SIDE | sm::MAYDARK | sm::EXPANSION;
gamescreen(0);
gamescreen();
dialog::addSelItem(XLAT("which distance"), XLAT(dfnames[distance_from]), 'c');
dialog::add_action([] () { distance_from = mod_allowed() ? eDistanceFrom((distance_from + 1) % 3) : eDistanceFrom(2 - distance_from); });
@ -608,22 +671,11 @@ EX void viewdist_configure_dialog() {
dialog::addBoolItem_action(XLAT("color codes"), use_color_codes, 'u');
dialog::addSelItem(XLAT("display distances from"), its(first_distance), 'd');
dialog::add_action([] () {
scrolling_distances = false;
dialog::editNumber(first_distance, 0, 3000, 1, 0, XLAT("display distances from"), "");
dialog::bound_low(0);
});
dialog::addBoolItem(XLAT("strict tree maps"), currentmap->strict_tree_rules(), 's');
dialog::add_action_push(rulegen::show);
int id = 0;
using namespace linepatterns;
for(auto& lp: {&patTriTree, &patTriRings, &patTriOther}) {
dialog::addColorItem(XLAT(lp->lpname), lp->color, '1'+(id++));
dialog::add_action([&lp] () {
dialog::openColorDialog(lp->color, NULL);
dialog::dialogflags |= sm::MAYDARK | sm::SIDE | sm::EXPANSION;
});
}
dialog::addItem(XLAT("line patterns"), 'L');
dialog::add_action_push(linepatterns::showMenu);
if(!mod_allowed()) {
dialog::addItem(XLAT("enable the cheat mode for additional options"), 'C');
@ -679,28 +731,28 @@ string produce_coef_formula(vector<int> coef) {
return fmt;
}
EX bool auto_extend = true;
void expansion_analyzer::view_distances_dialog() {
static int lastticks;
if(scrolling_distances && !bounded) {
scrolltime += SDL_GetTicks() - lastticks;
first_distance += scrolltime / scrollspeed;
scrolltime %= scrollspeed;
if(scrolling_distances && !closed_manifold) {
dialog::list_skip += (SDL_GetTicks() - lastticks) * dialog::dfspace / scrollspeed;
}
lastticks = SDL_GetTicks();
if(first_distance < 0) first_distance = 0;
dynamicval<color_t> dv(distcolors[0], forecolor);
dialog::init("");
cmode |= sm::DIALOG_STRICT_X | sm::EXPANSION;
cmode |= sm::DIALOG_STRICT_X | sm::EXPANSION | sm::AUTO_VALUES | sm::NARROW_LINES;
int maxlen = bounded ? 128 : 16 + first_distance;
int maxlen = last_distance;
vector<bignum> qty(maxlen);
auto& expansion = get_expansion();
bool really_use_analyzer = use_analyzer && sizes_known();
if(really_use_analyzer) {
int t;
if(reg3::in_rule()) {
if(reg3::exact_rules() || currentmap->strict_tree_rules()) {
if(!N) preliminary_grouping();
t = rootid;
}
@ -711,12 +763,12 @@ void expansion_analyzer::view_distances_dialog() {
}
else {
if(distance_from == dfPlayer) {
celllister cl(cwt.at, bounded ? maxlen-1 : gamerange(), 100000, NULL);
celllister cl(cwt.at, closed_manifold ? maxlen-1 : gamerange(), 100000, NULL);
for(int d: cl.dists)
if(d >= 0 && d < maxlen) qty[d]++;
}
else {
celllister cl(cwt.at, bounded ? maxlen-1 : gamerange(), 100000, NULL);
celllister cl(cwt.at, closed_manifold ? maxlen-1 : gamerange(), 100000, NULL);
for(cell *c: cl.lst) if((not_only_descendants || is_descendant(c)) && curr_dist(c) < maxlen) qty[curr_dist(c)]++;
}
#if !CAP_GMP
@ -731,16 +783,17 @@ void expansion_analyzer::view_distances_dialog() {
}
#endif
}
dialog::addBreak(100 - 100 * scrolltime / scrollspeed);
for(int i=first_distance; i<maxlen; i++) if(!qty[i].digits.empty())
dialog::addInfo(its(i) + ": " + qty[i].get_str(100), distcolors[i]);
dialog::addBreak(100 * scrolltime / scrollspeed);
dialog::start_list(1600, 1600, 'a');
for(int i=0; i<maxlen; i++) if(!qty[i].digits.empty()) {
dialog::addSelItem(qty[i].get_str(100), " " + its(i), dialog::list_fake_key);
auto& last = dialog::lastItem();
last.color = last.colorv = distcolors[i];
}
dialog::end_list();
if(sizes_known() || bt::in()) {
if(euclid) {
if(euclid && !arb::in()) {
dialog::addBreak(200);
dialog::addInfo("a(d) = " + its(get_descendants(10).approx_int() - get_descendants(9).approx_int()) + "d", forecolor);
}
@ -761,12 +814,24 @@ void expansion_analyzer::view_distances_dialog() {
dialog::addItem(XLAT("scroll"), 'S');
dialog::addItem(XLAT("configure"), 'C');
dialog::addSelItem(XLAT("display distances up to"), its(last_distance), 'D');
dialog::add_action([] () {
scrolling_distances = false;
dialog::editNumber(last_distance, 0, 3000, 1, 0, XLAT("display distances up to"), "");
dialog::bound_low(0);
dialog::get_di().extra_options = [] {
add_edit(auto_extend);
};
});
dialog::display();
if(auto_extend && dialog::list_skip + dialog::list_actual_size == dialog::list_full_size) last_distance++;
}
EX void enable_viewdists() {
first_distance = 0;
scrolltime = 0;
last_distance = closed_manifold ? 128 : 16;
dialog::list_skip = 0;
scrolling_distances = false;
viewdists = true;
if(!mod_allowed()) {
number_coding = ncDistance;
@ -777,10 +842,11 @@ EX void enable_viewdists() {
bool expansion_handleKey(int sym, int uni) {
if((cmode & sm::NORMAL) && viewdists) {
dialog::handleNavigation(sym, uni);
if(uni == 'S' && (cmode & sm::EXPANSION)) scrolling_distances = !scrolling_distances;
else if(uni == 'C') pushScreen(viewdist_configure_dialog);
else if(uni == 'A' && (cmode & sm::EXPANSION)) use_analyzer = !use_analyzer;
else if(sym == SDLK_ESCAPE) first_distance = 0, viewdists = false;
else if(sym == SDLK_ESCAPE) dialog::list_skip = 0, viewdists = false;
else return false;
return true;
}
@ -794,6 +860,7 @@ void compute_coefficients() {
println(hlog, gp::operation_name(), " ", ginf[geometry].tiling_name);
start_game();
auto& expansion = get_expansion();
printf(" sizes:");
for(int i=0; i<expansion.valid_from+10; i++) printf(" %d", expansion.get_descendants(i).approx_int());
@ -815,6 +882,7 @@ int expansion_readArgs() {
else if(argis("-vap")) {
PHASEFROM(2);
start_game();
auto& expansion = get_expansion();
shift(); int radius = argi();
while(true) {
string s = expansion.approximate_descendants(radius, 100);
@ -825,6 +893,7 @@ int expansion_readArgs() {
else if(argis("-csizes")) {
PHASEFROM(2);
start_game();
auto& expansion = get_expansion();
expansion.get_growth();
shift(); for(int i=0; i<argi(); i++)
printf("%s / %s\n", expansion.get_descendants(i).get_str(1000).c_str(), expansion.get_descendants(i, expansion.diskid).get_str(1000).c_str());
@ -832,6 +901,7 @@ int expansion_readArgs() {
else if(argis("-csolve")) {
PHASEFROM(2);
start_game();
auto& expansion = get_expansion();
printf("preliminary_grouping...\n");
expansion.preliminary_grouping();
printf("N = %d\n", expansion.N);
@ -902,7 +972,7 @@ int expansion_readArgs() {
else if(argis("-expansion-labelcolor")) {
dist_label_colored = false;
shift(); dist_label_color = arghex();
shift(); dist_label_color = argcolor(24);
}
else if(argis("-expansion-off")) {
@ -917,11 +987,13 @@ auto ea_hook = addHook(hooks_args, 100, expansion_readArgs);
#endif
#endif
EX expansion_analyzer expansion;
EX int sibling_limit = 0;
EX expansion_analyzer& get_expansion() {
if(!cgi.expansion) cgi.expansion = make_shared<expansion_analyzer> ();
return *cgi.expansion;
}
EX void set_sibling_limit() {
auto& sibling_limit = get_expansion().sibling_limit;
if(0) ;
#if CAP_IRR
else if(IRREGULAR) sibling_limit = 3;
@ -974,6 +1046,7 @@ EX int hyperbolic_celldistance(cell *c1, cell *c2) {
int found_distance = INF;
int d = 0, d1 = celldist0(c1), d2 = celldist0(c2), sl_used = 0;
auto& sibling_limit = get_expansion().sibling_limit;
cell *cl1=c1, *cr1=c1, *cl2=c2, *cr2=c2;
while(true) {
@ -1016,7 +1089,7 @@ EX int hyperbolic_celldistance(cell *c1, cell *c2) {
else {
if(cl1 == cr2 || cr1 == cl2) found_distance = d;
}
}
}
if(d >= found_distance) {
if(sl_used == sibling_limit && IRREGULAR) {
@ -1038,4 +1111,4 @@ EX int hyperbolic_celldistance(cell *c1, cell *c2) {
}
}
}
}

View File

@ -1,5 +1,7 @@
// Hyperbolic Rogue -- fake mobile target
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
//
// Compile with: g++ fake-mobile.cpp -o fake-mobile -I/usr/include/SDL -lSDL -lSDL_gfx -lGL -lSDL_ttf -lz -Wno-invalid-offsetof
#define ISFAKEMOBILE 1
#define MOBPAR_FORMAL int
@ -9,7 +11,7 @@
#include <string>
namespace hr {
const char *scorefile = "fakemobile_score.txt";
std::string scorefile = "fakemobile_score.txt";
}
#include <SDL/SDL.h>
@ -55,6 +57,17 @@ int gdpop() { return graphdata[gdpos++]; }
TTF_Font *font[256];
const char* fontname = "DejaVuSans-Bold.ttf";
void load_font() {
if(!font[size])
font[size] = TTF_OpenFont(fontname, size);
if(!font[size]) {
fprintf(stderr, "failed to open font: %s", fontname);
exit(1);
}
}
bool rawdisplaystr(int x, int y, int shift, int size, const char *str, int color, int align) {
if(strlen(str) == 0) return false;
@ -69,8 +82,7 @@ bool rawdisplaystr(int x, int y, int shift, int size, const char *str, int color
col.r >>= darken; col.g >>= darken; col.b >>= darken;
if(!font[size])
font[size] = TTF_OpenFont("VeraBd.ttf", size);
load_font();
SDL_Surface *txt = TTF_RenderText_Solid(font[size], str, col);
@ -95,7 +107,7 @@ bool rawdisplaystr(int x, int y, int shift, int size, const char *str, int color
int textwidth(int siz, const string &str) {
if(isize(str) == 0) return 0;
if(!font[siz]) font[siz] = TTF_OpenFont("VeraBd.ttf", siz);
load_font();
int w, h;
TTF_SizeUTF8(font[siz], str.c_str(), &w, &h);

View File

@ -32,10 +32,15 @@ EX namespace fake {
if(in()) return true;
if(WDIM == 2 && standard_tiling() && (PURE || BITRUNCATED)) return true;
if(arcm::in() && PURE) return true;
if(hat::in()) return true;
if(WDIM == 2) return false;
if(among(geometry, gBitrunc3)) return false;
#if MAXMDIM >= 4
if(reg3::in() && !among(variation, eVariation::pure, eVariation::subcubes, eVariation::coxeter, eVariation::bch_oct)) return false;
return euc::in() || reg3::in();
#else
return euc::in();
#endif
}
map<cell*, ld> random_order;
@ -49,6 +54,7 @@ EX namespace fake {
dynamicval<hrmap*> gpm(pmap, this);
dynamicval<eGeometry> gag(actual_geometry, geometry);
dynamicval<eGeometry> g(geometry, underlying);
dynamicval<int> uc(cgip->use_count, cgip->use_count+1);
dynamicval<geometry_information*> gc(cgip, underlying_cgip);
dynamicval<hrmap*> gu(currentmap, underlying_map);
return t();
@ -69,6 +75,7 @@ EX namespace fake {
}
hrmap_fake() {
underlying_map = nullptr;
in_underlying([this] { initcells(); underlying_map = currentmap; });
for(hrmap*& m: allmaps) if(m == underlying_map) m = NULL;
}
@ -80,11 +87,35 @@ EX namespace fake {
}
heptagon *create_step(heptagon *parent, int d) override {
parent->c.connect(d, parent, d, false);
return parent;
return FPIU(currentmap->create_step(parent, d));
}
hyperpoint get_corner(cell *c, int cid, ld cf=3) override {
if(embedded_plane) {
geom3::light_flip(true);
hyperpoint h = get_corner(c, cid, cf);
geom3::light_flip(false);
return cgi.emb->base_to_actual(h);
}
if(arcm::in() || hat::in()) {
return underlying_map->get_corner(c, cid, cf);
}
hyperpoint h;
h = FPIU(currentmap->get_corner(c, cid, cf));
return befake(h);
}
transmatrix adj(cell *c, int d) override {
if(embedded_plane) {
geom3::light_flip(true);
transmatrix T = adj(c, d);
geom3::light_flip(false);
return cgi.emb->base_to_actual(T);
}
if(hat::in()) return underlying_map->adj(c, d);
if(variation == eVariation::coxeter) {
array<int, 3> which;
in_underlying([&which, c, d] {
@ -123,7 +154,11 @@ EX namespace fake {
}
transmatrix S1, S2;
ld dist;
#if MAXMDIM >= 4
bool impure = reg3::in() && !PURE;
#else
bool impure = !PURE;
#endif
vector<int> mseq;
if(impure) {
mseq = FPIU ( currentmap->get_move_seq(c, d) );
@ -219,19 +254,17 @@ EX namespace fake {
auto h1 = V * befake(FPIU(get_corner_position(c, (i+1) % c->type)));
ld b0 = atan2(unshift(h0));
ld b1 = atan2(unshift(h1));
while(b1 < b0) b1 += 2 * M_PI;
while(b1 < b0) b1 += TAU;
if(a0 == -1) {
draw_recursive(c->move(i), optimized_shift(V * adj(c, i)), b0, b1, c, depth+1);
}
else {
if(b1 - b0 > M_PI) continue;
if(b0 < a0 - M_PI) b0 += 2 * M_PI;
if(b0 > a0 + M_PI) b0 -= 2 * M_PI;
cyclefix(b0, a0);
if(b0 < a0) b0 = a0;
if(b1 > a1 + M_PI) b1 -= 2 * M_PI;
if(b1 < a1 - M_PI) b1 += 2 * M_PI;
cyclefix(b1, a1);
if(b1 > a1) b1 = a1;
if(b0 > b1) continue;
@ -361,12 +394,18 @@ EX namespace fake {
}
transmatrix ray_iadj(cell *c, int i) override {
if(WDIM == 2)
return to_other_side(get_corner(c, i), get_corner(c, i+1));
#if MAXMDIM >= 4
if(PURE) return iadj(c, i);
auto& v = get_cellshape(c).faces_local[i];
hyperpoint h =
project_on_triangle(v[0], v[1], v[2]);
transmatrix T = rspintox(h);
return T * xpush(-2*hdist0(h)) * spintox(h);
#else
return Id;
#endif
}
};
@ -390,8 +429,8 @@ EX namespace fake {
#endif
EX hyperpoint befake(hyperpoint h) {
auto h1 = h / h[WDIM] * scale;
h1[WDIM] = 1;
auto h1 = h / h[LDIM] * scale;
h1[LDIM] = 1;
if(material(h1) > 1e-3)
h1 = normalize(h1);
return h1;
@ -513,8 +552,10 @@ EX ld compute_euclidean() {
#if CAP_ARCM
if(arcm::in()) return arcm::current.N * 2 / arcm::current.euclidean_angle_sum;
#endif
if(underlying == gAperiodicHat) return 6;
if(WDIM == 2) return 4 / (S7-2.) + 2;
if(underlying == gRhombic3) return 3;
if(underlying == gBitrunc3) return 2.55208;
int middle = get_middle();
@ -529,6 +570,7 @@ EX ld around_orig() {
if(arcm::in())
return arcm::current.N;
#endif
if(hat::in()) return 6;
if(WDIM == 2)
return S3;
if(underlying == gRhombic3)
@ -565,12 +607,16 @@ EX void compute_scale() {
ginf[gFake].g = geometry_of_curvature(good - around, WDIM);
geom3::apply_always3();
ld around_ideal = 1/(1/2. - 1./get_middle());
bool have_ideal = abs(around_ideal - around) < 1e-6;
if(underlying == gRhombic3 || underlying == gBitrunc3) have_ideal = false;
finalizer f([&] {if(vid.always3 && WDIM == 2) {
geom3::ginf_backup[gFake] = ginf[gFake];
geom3::apply_always3_to(ginf[gFake]);
}});
if(arcm::in()) {
ginf[gFake].tiling_name = "(" + ginf[gArchimedean].tiling_name + ")^" + fts(around / around_orig());
return;
@ -633,8 +679,9 @@ void set_gfake(ld _around) {
compute_scale();
check_cgi();
cgi.require_basics();
if(currentmap) new hrmap_fake(currentmap);
if(hat::in()) hat::reshape();
}
EX void change_around() {
@ -658,7 +705,7 @@ EX void change_around() {
/* to compute scale */
if(WDIM == 2)
cgi.prepare_basics();
cgi.require_basics();
}
t = scale / t;
@ -678,45 +725,46 @@ EX void configure() {
underlying_cgip = cgip;
around = around_orig();
}
dialog::editNumber(around, 2.01, 10, 1, around, "fake curvature",
dialog::editNumber(around, 2.01, 10, 1, around, XLAT("fake curvature"),
XLAT(
"This feature lets you construct the same tiling, but "
"from shapes of different curvature.\n\n"
"The number you give here is (2D) vertex degree or (3D) "
"the number of cells around an edge.\n\n"
"the number of cells around an edge.\n\n")
);
if(fake::in())
dialog::reaction = change_around;
dialog::get_di().reaction = change_around;
else
dialog::reaction_final = change_around;
dialog::extra_options = [] {
dialog::get_di().reaction_final = change_around;
dialog::get_di().extra_options = [] {
ld e = compute_euclidean();
dialog::addSelItem("Euclidean", fts(e), 'E');
dialog::addSelItem(XLAT("Euclidean"), fts(e), 'E');
dialog::add_action([e] {
around = e;
popScreen();
change_around();
});
dialog::addSelItem("original", fts(around_orig()), 'O');
dialog::addSelItem(XLAT("original"), fts(around_orig()), 'O');
dialog::add_action([] {
around = around_orig();
popScreen();
change_around();
});
dialog::addSelItem("double original", fts(2 * around_orig()), 'D');
dialog::addSelItem(XLAT("double original"), fts(2 * around_orig()), 'D');
dialog::add_action([] {
around = 2 * around_orig();
popScreen();
change_around();
});
dialog::addBoolItem_action("draw all if multiple of original", multiple_special_draw, 'M');
dialog::addBoolItem_action("draw copies (2D only)", recursive_draw, 'C');
dialog::addBoolItem_action(XLAT("draw all if multiple of original"), multiple_special_draw, 'M');
dialog::addBoolItem_action(XLAT("draw copies (2D only)"), recursive_draw, 'C');
dialog::addBoolItem_choice("unordered", ordered_mode, 0, 'U');
dialog::addBoolItem_choice("pre-ordered", ordered_mode, 1, 'P');
dialog::addBoolItem_choice("post-ordered", ordered_mode, 2, 'Q');
dialog::addBoolItem_choice(XLAT("unordered"), ordered_mode, 0, 'U');
dialog::addBoolItem_choice(XLAT("pre-ordered"), ordered_mode, 1, 'P');
dialog::addBoolItem_choice(XLAT("post-ordered"), ordered_mode, 2, 'Q');
};
}

View File

@ -43,7 +43,7 @@ EX bool isprime(int n) {
}
#if HDR
#define MWDIM (prod ? 3 : WDIM+1)
#define MWDIM (mproduct ? 3 : WDIM+1)
struct matrix : array<array<int, MAXMDIM>, MAXMDIM> {
bool operator == (const matrix& B) const {
@ -77,7 +77,7 @@ EX int btspin(int id, int d) {
#if HDR
static const int ERR = -99;
static constexpr int ERR = -99;
struct triplet_info {
int i, j, size;
@ -142,14 +142,23 @@ struct fpattern {
}
int sqr(int x) { return mul(x,x); }
int err;
matrix mmul(const matrix& A, const matrix& B) {
matrix res;
for(int i=0; i<MWDIM; i++) for(int k=0; k<MWDIM; k++) {
int t = 0;
#ifdef EASY
for(int j=0; j<MWDIM; j++) t += mul(A[i][j], B[j][k]);
t %= Prime;
int tp = 0, tn = 0;
for(int j=0; j<MWDIM; j++) {
int val = mul(A[i][j], B[j][k]);
if(val > 0) tp += val;
else tn += val;
}
tp %= Prime; tn %= Prime;
if(tp && tn) err++;
t = tp + tn;
#else
for(int j=0; j<MWDIM; j++) t = add(t, mul(A[i][j], B[j][k]));
#endif
@ -263,7 +272,7 @@ struct fpattern {
void build();
static const int MAXDIST = 120;
static constexpr int MAXDIST = 120;
vector<char> disthep;
vector<char> disthex;
@ -295,6 +304,7 @@ struct fpattern {
exit(1);
}
build();
analyze();
}
fpattern(int p) {
@ -361,12 +371,13 @@ struct discovery {
#endif
bool fpattern::check_order(matrix M, int req) {
int err = 0;
matrix P = M;
for(int i=1; i<req; i++) {
if(P == Id) return false;
P = mmul(P, M);
}
return P == Id;
return P == Id && !err;
}
vector<matrix> fpattern::generate_isometries() {
@ -496,6 +507,7 @@ unsigned fpattern::compute_hash() {
bool fpattern::generate_all3() {
reg3::generate_fulls();
err = 0;
matrices.clear();
matcode.clear();
@ -504,19 +516,23 @@ bool fpattern::generate_all3() {
for(int i=0; i<isize(matrices); i++) {
add1(mmul(matrices[i], R), fullv[i] * cgi.full_R);
add1(mmul(matrices[i], X), fullv[i] * cgi.full_X);
if(err) return false;
}
local_group = isize(matrices);
if(local_group != isize(cgi.cellrotations)) return false;
for(int i=0; i<(int)matrices.size(); i++) {
matrix E = mmul(matrices[i], P);
if(!matcode.count(E))
for(int j=0; j<local_group; j++) add1(mmul(E, matrices[j]));
if(err) return false;
if(isize(matrices) >= limitv) { println(hlog, "limitv exceeded"); return false; }
}
hashv = compute_hash();
DEBB(DF_FIELD, ("all = ", isize(matrices), "/", local_group, " = ", isize(matrices) / local_group, " hash = ", hashv, " count = ", ++hash_found[hashv]));
if(use_quotient_fp)
generate_quotientgroup();
generate_quotientgroup();
return true;
}
@ -584,8 +600,11 @@ void fpattern::generate_quotientgroup() {
}
EX purehookset hooks_solve3;
int fpattern::solve3() {
reg3::construct_relations();
reg3::generate_fulls();
DEBB(DF_FIELD, ("generating isometries for ", Field));
@ -594,10 +613,6 @@ int fpattern::solve3() {
int cmb = 0;
int N = isize(cgi.rels);
vector<int> fails(N);
vector<matrix> possible_P, possible_X, possible_R;
for(auto& M: iso3) {
@ -613,35 +628,32 @@ int fpattern::solve3() {
DEBB(DF_FIELD, ("field = ", Field, " #P = ", isize(possible_P), " #X = ", isize(possible_X), " #R = ", isize(possible_R), " r_order = ", cgi.r_order, " xp_order = ", cgi.xp_order));
for(auto& xX: possible_X)
for(auto& xP: possible_P) if(check_order(mmul(xP, xX), cgi.xp_order))
for(auto& xR: possible_R) if(check_order(mmul(xR, xX), cgi.rx_order)) { // if(xR[0][0] == 1 && xR[0][1] == 0)
#if CAP_THREAD && MAXMDIM >+ 4
for(auto& xP: possible_P) if(check_order(mmul(xP, xX), cgi.xp_order))
for(auto& xR: possible_R) if(check_order(mmul(xR, xX), cgi.rx_order)) {
err = 0;
if(mmul(xX, xP) != mmul(xR, mmul(mmul(xP, xX), xR))) continue;
if(err) continue;
#if CAP_THREAD && MAXMDIM >= 4
if(dis) dis->check_suspend();
if(dis && dis->stop_it) return 0;
#endif
auto by = [&] (char ch) -> matrix& { return ch == 'X' ? xX : ch == 'R' ? xR : xP; };
for(int i=0; i<N; i++) {
matrix ml = Id;
for(char c: cgi.rels[i].first) { ml = mmul(ml, by(c)); if(ml == Id) { fails[i]++; goto bad; }}
matrix mr = Id;
for(char c: cgi.rels[i].second) { mr = mmul(mr, by(c)); if(mr == Id) { fails[i]++; goto bad; }}
if(ml != mr) { fails[i]++; goto bad;}
}
P = xP; R = xR; X = xX;
if(!generate_all3()) continue;
callhooks(hooks_solve3);
#if CAP_THREAD && MAXMDIM >= 4
if(dis) { dis->discovered(); continue; }
#endif
if(force_hash && hashv != force_hash) continue;
cmb++;
goto ok;
bad: ;
}
ok:
DEBB(DF_FIELD, ("cmb = ", cmb, " for field = ", Field));
for(int i=0; i<N; i++) if(fails[i]) DEBB(DF_FIELD, (cgi.rels[i], " fails = ", fails[i]));
return cmb;
}
@ -1121,9 +1133,9 @@ void fpattern::analyze() {
int riverdist = dijkstra(PURE ? distflower : distriver, indist);
DEBB(DF_FIELD, ("river dist = %d\n", riverdist));
for(int i=0; i<isize(currfp.matrices); i++)
if(currfp.distflower[i] == 0) {
distflower0 = currfp.inverses[i]+1;
for(int i=0; i<isize(matrices); i++)
if(distflower[i] == 0) {
distflower0 = inverses[i]+1;
break;
}
@ -1269,7 +1281,13 @@ EX struct fpattern& getcurrfp() {
return current_quotient_field;
if(geometry == gSpace535) {
// 120 cells, hash = 9EF7A9C4
static fpattern fp(5);
static fpattern fp(0);
if(use_rule_fp) {
fp.Prime = 5; fp.force_hash = 0xDCC3CACEu; fp.solve();
}
else {
fp.Prime = 5; fp.force_hash = 0x9EF7A9C4u; fp.solve();
}
return fp;
}
if(geometry == gSpace534) {
@ -1279,7 +1297,7 @@ EX struct fpattern& getcurrfp() {
// fp.Prime = 5; fp.force_hash = 0x72414D0C; fp.solve();
if(use_rule_fp) {
fp.Prime = 11; fp.force_hash = 0x5FC4CFF0; fp.solve();
fp.Prime = 11; fp.force_hash = 0x5FC4CFF0u; fp.solve();
}
else {
shstream ins(STR("\x05\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\xfc\xff\xff\xff\x01\x00\x00\x00\x04\x00\x00\x00\xfc\xff\xff\xff\x04\x00\x00\x00\xfe\xff\xff\xff\x00\x00\x00\x00\x01\x00\x00\x00\xfe\xff\xff\xff\x04\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\x01\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x00\x00\x02\x00\x00\x00\xfd\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"));
@ -1295,7 +1313,7 @@ EX struct fpattern& getcurrfp() {
// what is 0x72414D0C??
if(use_rule_fp) {
fp.Prime = 11; fp.force_hash = 0x65CE0C00; fp.solve();
fp.Prime = 11; fp.force_hash = 0x65CE0C00u; fp.solve();
}
else {
shstream ins(STR("\x05\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfc\xff\xff\xff\x04\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\xff\xff\xff\xff\x02\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\xfd\xff\xff\xff\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xfd\xff\xff\xff\x00\x00\x00\x00\xfd\xff\xff\xff\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"));
@ -1305,20 +1323,28 @@ EX struct fpattern& getcurrfp() {
}
if(geometry == gSpace436) {
static fpattern fp(0);
// FF82A214
shstream ins(STR("\x05\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x00\x00\xfe\xff\xff\xff\xfd\xff\xff\xff\x01\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\xfd\xff\xff\xff\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\xfc\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xfd\xff\xff\xff\x00\x00\x00\x00\xfd\xff\xff\xff\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"));
hread_fpattern(ins, fp);
if(fp.Prime) return fp;
if(use_rule_fp) {
fp.Prime = 2; fp.force_hash = 0x235F7508u; fp.solve();
}
else {
// FF82A214
shstream ins(STR("\x05\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x00\x00\xfe\xff\xff\xff\xfd\xff\xff\xff\x01\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\xfd\xff\xff\xff\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\xfc\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xfd\xff\xff\xff\x00\x00\x00\x00\xfd\xff\xff\xff\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"));
hread_fpattern(ins, fp);
}
return fp;
}
if(geometry == gSpace336) {
// 672 cells in E3F6B7BC
// 672 cells in 885F1184
// 9408 cells in C4089F34
static fpattern fp(0);
if(fp.Prime) return fp;
// fp.Prime = 7; fp.force_hash = 0xE3F6B7BCu; fp.solve();
shstream ins(STR("\x07\x00\x00\x00\x03\x00\x00\x00\xfa\xff\xff\xff\x02\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\xfe\xff\xff\xff\xfb\xff\xff\xff\xfc\xff\xff\xff\x03\x00\x00\x00\xfb\xff\xff\xff\xfd\xff\xff\xff\xfb\xff\xff\xff\x01\x00\x00\x00\xfd\xff\xff\xff\xfe\xff\xff\xff\xfd\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfa\xff\xff\xff\xfb\xff\xff\xff\x00\x00\x00\x00\xfa\xff\xff\xff\x02\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\xfb\xff\xff\xff\x06\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"));
hread_fpattern(ins, fp);
if(use_rule_fp) {
fp.Prime = 3; fp.force_hash = 0xD29C2418u; fp.solve();
}
else {
// fp.Prime = 7; fp.force_hash = 0xE3F6B7BCu; fp.solve();
shstream ins(STR("\x07\x00\x00\x00\x03\x00\x00\x00\xfa\xff\xff\xff\x02\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\xfe\xff\xff\xff\xfb\xff\xff\xff\xfc\xff\xff\xff\x03\x00\x00\x00\xfb\xff\xff\xff\xfd\xff\xff\xff\xfb\xff\xff\xff\x01\x00\x00\x00\xfd\xff\xff\xff\xfe\xff\xff\xff\xfd\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\xff\xff\xff\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfa\xff\xff\xff\xfb\xff\xff\xff\x00\x00\x00\x00\xfa\xff\xff\xff\x02\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\xfb\xff\xff\xff\x06\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"));
hread_fpattern(ins, fp);
}
return fp;
}
if(geometry == gSpace344) {
@ -1328,7 +1354,12 @@ EX struct fpattern& getcurrfp() {
// 2600 cells in EC29DCEC
static fpattern fp(0);
if(fp.Prime) return fp;
fp.Prime = 5; fp.force_hash = 0x558C8ED0u; fp.solve();
if(use_rule_fp) {
fp.Prime = 3; fp.force_hash = 0xB23AF1F4u; fp.solve();
}
else {
fp.Prime = 5; fp.force_hash = 0x558C8ED0u; fp.solve();
}
return fp;
// 4900 cells in CDCC7860 (7)
}
@ -1337,7 +1368,12 @@ EX struct fpattern& getcurrfp() {
if(fp.Prime) return fp;
// 130 cells in 3BA5C5A4
// 260 cells in 9FDE7B38
fp.Prime = 5; fp.force_hash = 0x9FDE7B38u; fp.solve();
if(use_rule_fp) {
fp.Prime = 5; fp.force_hash = 0x61385498u; fp.solve();
}
else {
fp.Prime = 5; fp.force_hash = 0x9FDE7B38u; fp.solve();
}
return fp;
}
if(geometry == gSpace345) {
@ -1346,7 +1382,12 @@ EX struct fpattern& getcurrfp() {
// 30 cells in 02ADCAA4 (3^2)
// 650 cells in 7EFE8D98 (5^2)
// 55 cells in F447F75C (11)
fp.Prime = 11; fp.force_hash = 0xF447F75Cu; fp.solve();
if(use_rule_fp) {
fp.Prime = 3; fp.force_hash = 0xF978E264u; fp.solve();
}
else {
fp.Prime = 11; fp.force_hash = 0xF447F75Cu; fp.solve();
}
return fp;
}
if(geometry == gSpace353) {
@ -1359,12 +1400,16 @@ EX struct fpattern& getcurrfp() {
}
if(geometry == gSpace354) {
static fpattern fp(0);
if(fp.Prime) return fp;
fp.Prime = 11; fp.force_hash = 0x363D8DA4u; fp.solve();
// fp.Prime = 11; fp.force_hash = 0x363D8DA4u; fp.solve();
fp.Prime = 5; fp.force_hash = 0x58A8E850u; fp.solve();
return fp;
}
if(geometry == gCubeTiling) {
static fpattern fp(2);
return fp;
}
if(!hyperbolic) return fp_invalid;
if(WDIM == 3 && !quotient && !hybri && !bt::in()) {
if(WDIM == 3 && !quotient && !mhybrid && !bt::in()) {
static fpattern fp(0);
if(fp.Prime) return fp;
for(int p=2; p<20; p++) { fp.Prime = p; if(!fp.solve()) break; }
@ -1457,19 +1502,22 @@ EX void enableFieldChange() {
ginf[geometry].distlimit = ginf[gxcur.base].distlimit;
ginf[geometry].tiling_name = ginf[gxcur.base].tiling_name;
ginf[geometry].default_variation = ginf[gxcur.base].default_variation;
ginf[geometry].flags = qFIELD | qANYQ | qBOUNDED;
ginf[geometry].flags = qFIELD | qANYQ | qCLOSED;
fieldpattern::current_quotient_field.init(gxcur.primes[gxcur.current_prime_id].p);
}
EX eGeometry underlying_geometry;
EX void field_from_current() {
auto& go = ginf[geometry];
underlying_geometry = geometry;
dynamicval<eGeometry> g(geometry, gFieldQuotient);
auto& gg = ginf[geometry];
gg.sides = go.sides;
gg.vertex = go.vertex;
gg.distlimit = go.distlimit;
gg.tiling_name = go.tiling_name;
gg.flags = go.flags | qANYQ | qFIELD | qBOUNDED;
gg.flags = go.flags | qANYQ | qFIELD | qCLOSED;
gg.g = go.g;
gg.default_variation = go.default_variation;
fieldpattern::quotient_field_changed = true;

View File

@ -37,6 +37,7 @@ WALLFLAGCHECK(isAlch, flag & WF_ALCHEMY)
WALLFLAGCHECK(isAlchAny, flag & WF_ALCHEMY)
WALLFLAGCHECK(realred, flag & WF_RED)
WALLFLAGCHECK(isWall, flag & WF_WALL)
WALLFLAGCHECK(isNonblock, flag & WF_NONBLOCK)
WALLFLAGCHECK(isPushable, flag & WF_PUSHABLE)
WALLFLAGCHECK(conegraphtype, flag & WF_CONE)
WALLFLAGCHECK(isStandardTree, flag & WF_STDTREE)

View File

@ -26,7 +26,18 @@ EX vector<basic_textureinfo> floor_texture_vertices;
EX vector<glvertex> floor_texture_map;
EX struct renderbuffer *floor_textures;
EX basic_textureinfo* get_floor_texture_vertices(int index) {
if(noGUI || !vid.usingGL) return nullptr;
return &floor_texture_vertices[index];
}
/* 0: generate no floorshapes; 1: generate only plain floorshapes; 2: generate all */
EX int floorshapes_level = 2;
EX ld global_boundary_ratio = 1;
void geometry_information::init_floorshapes() {
if(floorshapes_level == 0) return;
all_escher_floorshapes.clear();
all_plain_floorshapes = {
&shFloor, &shMFloor, &shMFloor2, &shMFloor3, &shMFloor4,
@ -36,6 +47,7 @@ void geometry_information::init_floorshapes() {
for(auto s: all_plain_floorshapes) s->is_plain = true;
auto init_escher = [this] (escher_floorshape& sh, int s0, int s1, int noft, int s2) {
if(floorshapes_level == 1) return;
sh.shapeid0 = s0;
sh.shapeid1 = s1;
sh.noftype = noft;
@ -79,6 +91,9 @@ void geometry_information::init_floorshapes() {
for(auto sh: all_escher_floorshapes) sh->id = ids++;
}
/** matrixitem::second[2][2] == APEIROGONAL_INVALID is used to denote a matrix that uses fake apeirogon vertices and thus should not be used */
const ld APEIROGONAL_INVALID = -2;
typedef pair<transmatrix, vector<transmatrix>> matrixitem;
struct mesher {
@ -96,17 +111,17 @@ mesher msh(eGeometry g, int sym, ld main, ld v0, ld v1, ld bspi, ld scale) {
dynamicval<eGeometry> dg(geometry, g);
hyperpoint rot = xpush(v0) * xspinpush0(M_PI - M_PI/sym, main);
hyperpoint bnlfar = xpush(v0) * spin(M_PI) * rspintox(rot) * rspintox(rot) * rspintox(rot) * xpush0(hdist0(rot));
hyperpoint bnrfar = xpush(v0) * spin(M_PI) * spintox(rot) * spintox(rot) * spintox(rot) * xpush0(hdist0(rot));
hyperpoint bnlfar = xpush(v0) * spin180() * rspintox(rot) * rspintox(rot) * rspintox(rot) * xpush0(hdist0(rot));
hyperpoint bnrfar = xpush(v0) * spin180() * spintox(rot) * spintox(rot) * spintox(rot) * xpush0(hdist0(rot));
m.lcorner = xspinpush0 (bspi-M_PI/sym, main);
m.rcorner = xspinpush0 (bspi+M_PI/sym, main);
m.lcorner = xspinpush0 (bspi - M_PI/sym, main);
m.rcorner = xspinpush0 (bspi + M_PI/sym, main);
m.mfar[0] = xspinpush0 (bspi, v0);
m.mfar[1] = xspinpush0 (bspi, v1);
m.vfar[0] = spin(bspi) * bnlfar;
m.vfar[2] = spin(bspi) * bnrfar;
m.vfar[1] = spin(-2*M_PI/sym) * m.vfar[2];
m.vfar[3] = spin(+2*M_PI/sym) * m.vfar[0];
m.vfar[1] = spin(-TAU/sym) * m.vfar[2];
m.vfar[3] = spin(+TAU/sym) * m.vfar[0];
return m;
}
@ -121,16 +136,11 @@ matrixitem genitem(const transmatrix& m1, const transmatrix& m2, int nsym) {
mi.first = m1;
mi.second.resize(nsym);
for(int i=0; i<nsym; i++)
mi.second[i] = spin(2*M_PI*i/nsym) * m2;
mi.second[i] = spin(TAU*i/nsym) * m2;
return mi;
}
bool do_kleinize() { return S3 >= OINF; }
EX hyperpoint kleinize(hyperpoint h) {
if(GDIM == 2) return point3(h[0]/h[2], h[1]/h[2], 1);
else return point31(h[0]/h[3], h[1]/h[3], h[2]/h[3]);
}
bool do_kleinize() { return S3 >= OINF || (cgflags & qIDEAL); }
EX hyperpoint may_kleinize(hyperpoint h) {
if(do_kleinize()) return kleinize(h);
@ -139,7 +149,7 @@ EX hyperpoint may_kleinize(hyperpoint h) {
void addmatrix(matrixlist& matrices, hyperpoint o0, hyperpoint o1, hyperpoint o2, hyperpoint n0, hyperpoint n1, hyperpoint n2, int d, int osym, int nsym) {
if(do_kleinize()) o0 = kleinize(o0), o1 = kleinize(o1), o2 = kleinize(o2), n0 = kleinize(n0), n1 = kleinize(n1), n2 = kleinize(n2);
matrices.v.push_back(genitem(inverse(spin(2*M_PI*d/osym)*build_matrix(o0, o1, o2,C02)), spin(2*M_PI*d/nsym)*build_matrix(n0, n1, n2,C02), nsym));
matrices.v.push_back(genitem(inverse(spin(TAU*d/osym)*build_matrix(o0, o1, o2,C02)), spin(TAU*d/nsym)*build_matrix(n0, n1, n2,C02), nsym));
}
matrixlist hex_matrices, hept_matrices;
@ -215,47 +225,64 @@ void geometry_information::bshape2(hpcshape& sh, PPR prio, int shapeid, matrixli
hyperpoint lstmid = hpxyz(0,0,0);
for(auto pp: lst) lstmid += pp;
transmatrix T = spin(-m.o.bspi);
while((spin(2*M_PI / rots) * T* lstmid)[0] < (T*lstmid)[0])
T = spin(2*M_PI / rots) * T;
while((spin(-2*M_PI / rots) * T* lstmid)[0] < (T*lstmid)[0])
T = spin(-2*M_PI / rots) * T;
while((spin(TAU / rots) * T* lstmid)[0] < (T*lstmid)[0])
T = spin(TAU / rots) * T;
while((spin(-TAU / rots) * T* lstmid)[0] < (T*lstmid)[0])
T = spin(-TAU / rots) * T;
T = spin(m.o.bspi) * T;
for(auto &pp: lst) pp = T * pp;
if(osym % rots && rots % osym) printf("warning: rotation oddity (shapeid %d, osym=%d rots=%d)\n", shapeid, osym, rots);
if(osym % rots && rots % osym && (debugflags & DF_GEOM)) printf("warning: rotation oddity (shapeid %d, osym=%d rots=%d)\n", shapeid, osym, rots);
if(rots > osym && rots % osym == 0) {
int rep = rots / osym;
int s = lst.size();
for(int i=0; i<s*(rep-1); i++)
lst.push_back(spin(2*M_PI/rots) * lst[i]);
lst.push_back(spin(TAU/rots) * lst[i]);
rots /= rep;
}
bshape(sh, prio);
/* in case of apeirogonal shapes, we may need to cyclically rotate */
bool apeirogonal = false;
vector<hyperpoint> tail, head;
for(int r=0; r<nsym; r+=osym/rots) {
for(hyperpoint h: lst) {
hyperpoint nh = may_kleinize(h);
int mapped = 0;
int invalid = 0;
for(auto& m: matrices) {
hyperpoint z = m.first * h;
if(z[0] > -1e-5 && z[1] > -1e-5 && z[2] > -1e-5) {
if(m.second[r][2][2] == APEIROGONAL_INVALID) invalid++;
nh = m.second[r] * z, mapped++;
}
}
if(mapped == 0) printf("warning: not mapped (shapeid %d)\n", shapeid);
hpcpush(mid(nh, nh));
if(mapped == 0 && (debugflags & DF_GEOM)) printf("warning: not mapped (shapeid %d)\n", shapeid);
if(invalid) {
apeirogonal = true;
for(auto h: head) tail.push_back(h);
head.clear();
}
if(!invalid) head.push_back(nh);
}
}
hpcpush(hpc[last->s]);
for(auto& h: head) hpcpush(h);
for(auto& h: tail) hpcpush(h);
if(!apeirogonal) hpcpush(starting_point);
}
template<class T> void sizeto(T& t, int n) {
if(isize(t) <= n) t.resize(n+1);
}
template<class T, class U> void sizeto(T& t, int n, const U& val) {
if(isize(t) <= n) t.resize(n+1, val);
}
void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld shift, ld size, cell *c) {
sizeto(fsh.b, id);
@ -265,20 +292,23 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld
if(bt::in()) {
const int STEP = vid.texture_step;
for(int t=0; t<2; t++) {
if(t == 0)
bshape(fsh.b[id], fsh.prio);
if(t == 1)
bshape(fsh.shadow[id], fsh.prio);
int STEP1 = STEP;
if((embedded_plane || geom3::flipped) && t == 0) STEP1 = 1;
for(int i=0; i<sides; i++) {
hyperpoint h0 = bt::get_corner_horo_coordinates(c, i) * size;
hyperpoint h1 = bt::get_corner_horo_coordinates(c, i+1) * size;
if(t) h0 *= SHADMUL, h1 *= SHADMUL;
hyperpoint hd = (h1 - h0) / STEP;
for(int j=0; j<STEP; j++) {
hyperpoint hd = (h1 - h0) / STEP1;
for(int j=0; j<STEP1; j++) {
hpcpush(bt::get_horopoint(h0 + hd * j));
if(geometry == gBinary4 && among(i, 2, 4)) break;
if(geometry == gBinaryTiling && among(i, 0, 4)) break;
@ -299,7 +329,7 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld
hyperpoint h1 = bt::get_corner_horo_coordinates(c, i+1) * size;
hyperpoint hd = (h1 - h0) / STEP;
for(int j=0; j<=STEP; j++)
hpcpush(iddspin(c, i) * bt::get_horopoint(h0 + hd * j));
hpcpush(iddspin_side(c, i) * bt::get_horopoint(h0 + hd * j));
chasmifyPoly(dlow_table[k], dhi_table[k], k);
}
}
@ -310,11 +340,11 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld
bshape(fsh.b[id], fsh.prio);
for(int t=0; t<=sides; t++)
hpcpush(xspinpush0(t*2 * M_PI / sides + shift * M_PI / S42, size));
hpcpush(xspinpush0(t * TAU / sides + shift * S_step, size));
bshape(fsh.shadow[id], fsh.prio);
for(int t=0; t<=sides; t++)
hpcpush(xspinpush0(t*2 * M_PI / sides + shift * M_PI / S42, size * SHADMUL));
hpcpush(xspinpush0(t * TAU / sides + shift * S_step, size * SHADMUL));
for(int k=0; k<SIDEPARS; k++) {
fsh.side[k].resize(2);
@ -322,6 +352,17 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld
hpcpush(xspinpush0(+M_PI/sides, size));
hpcpush(xspinpush0(-M_PI/sides, size));
chasmifyPoly(dlow_table[k], dhi_table[k], k);
if(cgi.emb->is_euc_in_noniso()) {
fsh.gpside[k].resize(c->type);
for(int i=0; i<c->type; i++) {
sizeto(fsh.gpside[k][i], id);
bshape(fsh.gpside[k][i][id], PPR::LAKEWALL);
hpcpush(xspinpush0(M_PI - i * TAU / sides + shift * S_step, size));
hpcpush(xspinpush0(M_PI - (i + 1) * TAU / sides + shift * S_step, size));
chasmifyPoly(dlow_table[k], dhi_table[k], k);
}
}
}
}
@ -329,6 +370,40 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld
namespace irr { void generate_floorshapes(); }
#endif
void geometry_information::finish_apeirogon(hyperpoint center) {
last->flags |= POLY_APEIROGONAL;
last->she = isize(hpc);
if(arb::apeirogon_simplified_display) {
hyperpoint p = towards_inf(last_point, center, ideal_limit);
hyperpoint q = towards_inf(starting_point, center, ideal_limit);
hpc.push_back(p);
hpc_connect_ideal(p, q);
hpc.push_back(q);
}
else {
hpcpush(center);
hpcpush(starting_point);
}
}
hyperpoint get_circumscribed_corner(cell *c, int t, hyperpoint h) {
hyperpoint h0 = currentmap->adjmod(c, t) * h;
hyperpoint h1 = currentmap->adjmod(c, t-1) * h;
transmatrix T;
array<hyperpoint, 3> hs = {h, h0, h1};
set_column(T, 3, C03);
hyperpoint res = C03;
for(int i=0; i<3; i++) {
hyperpoint ahs = hs[i];
if(hyperbolic) ahs[3] *= -1;
set_column(T, i, ahs);
res[i] = dot_d(4, hs[i], ahs);
}
T = transpose(T);
return inverse(T) * res;
}
// !siid equals pseudohept(c)
void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, int sidir) {
@ -379,30 +454,33 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
vector<hyperpoint> cornerlist;
int cor = c->type;
bool apeirogonal = false;
if(&fsh == &shTriheptaFloor) {
if(!siid) {
for(int i=0; i<cor; i++)
cornerlist.push_back(midcorner(c, i, .49));
cornerlist.push_back(midcorner(c, i, .5 - .01 * global_boundary_ratio));
}
else {
for(int i=0; i<cor; i++) {
int ri = i;
if((i&1) == ((sidir+siid)&1)) ri--;
ri = c->c.fix(ri);
cornerlist.push_back(mid(get_corner_position(c, ri, 3.1), get_corner_position(c, c->c.fix(ri+1), 3.1)));
ld val = 3 + 0.1 * global_boundary_ratio;
cornerlist.push_back(mid(get_corner_position(c, ri, val), get_corner_position(c, c->c.fix(ri+1), val)));
}
}
}
else if(&fsh == &shBigTriangle) {
ld val = 1 - 0.06 * global_boundary_ratio;
if(!siid) {
for(int i=0; i<cor; i++) cornerlist.push_back(hpxy(0,0));
}
else if(geosupport_chessboard()) {
for(int i=0; i<cor; i++) {
hyperpoint nc = nearcorner(c, i);
cornerlist.push_back(mid_at(hpxy(0,0), nc, .94));
cornerlist.push_back(mid_at(hpxy(0,0), nc, val));
}
}
else {
@ -411,16 +489,17 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
if((i&1) != ((sidir+siid)&1)) ri--;
ri = c->c.fix(ri);
hyperpoint nc = nearcorner(c, ri);
cornerlist.push_back(mid_at(hpxy(0,0), nc, .94));
cornerlist.push_back(mid_at(hpxy(0,0), nc, val));
}
}
}
else if(&fsh == &shBigHepta) {
ld val = 1 - 0.06 * global_boundary_ratio;
if(!siid) {
for(int i=0; i<cor; i++) {
hyperpoint nc = nearcorner(c, i);
cornerlist.push_back(mid_at(hpxy(0,0), nc, .94));
cornerlist.push_back(mid_at(hpxy(0,0), nc, val));
}
}
else {
@ -428,7 +507,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
}
}
else if(arb::in()) {
else if(arb::in() || aperiodic || arcm::in() || IRREGULAR) {
vector<hyperpoint> actual;
for(int j=0; j<cor; j++)
actual.push_back(get_corner_position(c, j));
@ -441,20 +520,37 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
min_dist = dist;
}
ld dist = min_dist * (1 - 3 / sca);
auto &ac = arb::current_or_slided();
ld dist = min_dist * (1 - 3 / sca) * (arb::in() ? ac.boundary_ratio : 1);
ld area = 0;
for(int j=0; j<cor; j++) {
hyperpoint current = kleinize(actual[j]);
hyperpoint last = kleinize(actual[j?j-1:cor-1]);
hyperpoint last = kleinize(atmod(actual, j-1));
area += current[0] * last[1] - last[0] * current[1];
}
if(area < 0) dist = -dist;
if(area < 0) dist = -dist;
apeirogonal = false;
int id = 0;
arb::shape *sh = nullptr;
if(arb::in()) {
id = arb::id_of(c->master);
sh = &ac.shapes[id];
apeirogonal = sh->apeirogonal;
}
for(int j=0; j<cor; j++) {
hyperpoint last = actual[j?j-1:cor-1];
hyperpoint current = ypush(1e-6 * randd()) * xpush(1e-6) * actual[j];
hyperpoint next = actual[j<cor-1?j+1:0];
hyperpoint last = atmod(actual, j-1);
hyperpoint current = ypush(1e-7) * xpush(1e-6) * actual[j];
hyperpoint next = atmod(actual, j+1);
if(apeirogonal) {
if(j == 0) last = arb::get_adj(ac, id, cor-1, id, cor-2, false) * actual[cor-3];
if(j == cor-2) next = arb::get_adj(ac, id, cor-2, id, cor-1, false) * actual[1];
if(j == cor-1) { cornerlist.push_back(sh->vertices.back()); continue; }
}
auto T = gpushxto0(current);
last = T * last;
next = T * next;
@ -486,6 +582,10 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
else if(&fsh == &shTriheptaFloor && cor == 4 && siid)
/* trihepta floors generate digons too */
for(int i=0; i<=cor; i++) hpcpush(spin((i&1) ? .1 : -.1) * cornerlist[i%cor]);
else if(apeirogonal) {
for(int i=0; i<=cor-2; i++) hpcpush(cornerlist[i]);
finish_apeirogon(cornerlist.back());
}
else
for(int i=0; i<=cor; i++) hpcpush(cornerlist[i%cor]);
@ -539,7 +639,8 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
auto& m = (siid && geosupport_football() == 2) ? hex_matrices : hept_matrices;
int cor = c->type;
bool apeirogonal = arb::is_apeirogonal(c);
m.n.sym = cor;
int v = sidir+siid;
@ -551,13 +652,24 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
hyperpoint center = hpxy(0,0);
for(int cid=0; cid<cor; cid++) {
hyperpoint nlcorner = get_corner_position(c, (d+cid+v+1) % cor, 3 / fsh.scale * (ii ? 1/SHADMUL : 1));
hyperpoint nrcorner = get_corner_position(c, (d+cid+v+2) % cor, 3 / fsh.scale * (ii ? 1/SHADMUL : 1));
hyperpoint nfar = nearcorner(c, (d+cid+v+1) % cor);
hyperpoint nlfar = farcorner(c, (d+cid+v+1) % cor, 0);
hyperpoint nrfar = farcorner(c, (d+cid+v+1) % cor, 1);
int dcidv = d + cid + v;
if(apeirogonal) dcidv--;
int dcidv1 = gmod(dcidv + 1, cor);
int dcidv2 = gmod(dcidv + 2, cor);
if(apeirogonal && dcidv1 >= cor-2) {
for(int j: {0,1,2,3})
m.v[i+j].second[cid][2][2] = APEIROGONAL_INVALID;
continue;
}
hyperpoint nlcorner = get_corner_position(c, dcidv1, 3 / fsh.scale * (ii ? 1/SHADMUL : 1));
hyperpoint nrcorner = get_corner_position(c, dcidv2, 3 / fsh.scale * (ii ? 1/SHADMUL : 1));
hyperpoint nfar = nearcorner(c, dcidv1);
hyperpoint nlfar = farcorner(c, dcidv1, 0);
hyperpoint nrfar = farcorner(c, dcidv1, 1);
m.v[i].second[cid] = build_matrix(center, nlcorner, nrcorner,C02);
m.v[i+1].second[cid] = build_matrix(nfar, nlcorner, nrcorner,C02);
m.v[i+2].second[cid] = build_matrix(nfar, nlcorner, nlfar,C02);
@ -567,14 +679,22 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
i += 4;
}
if(i != isize(m.v)) printf("warning: i=%d sm=%d\n", i, isize(m.v));
if(i != isize(m.v)) printf("warning: i=%d sm=%d\n", i, isize(m.v));
bshape2((ii?fsh.shadow:fsh.b)[id], fsh.prio, (fsh.shapeid2 && geosupport_football() < 2) ? fsh.shapeid2 : siid?fsh.shapeid0:fsh.shapeid1, m);
if(apeirogonal && !first) {
int id = arb::id_of(c->master);
auto &ac = arb::current_or_slided();
auto& sh = ac.shapes[id];
hpcpush(arb::get_adj(arb::current_or_slided(), id, cor-2, id, cor-1, false) * starting_point);
finish_apeirogon(sh.vertices.back());
}
}
}
}
#if MAXMDIM >= 4
if(WDIM == 2 && GDIM == 3) {
if(embedded_plane) {
finishshape();
for(auto pfsh: all_plain_floorshapes) {
auto& fsh = *pfsh;
@ -586,31 +706,57 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
sizeto(fsh.levels[k], id);
bshape(fsh.levels[k][id], fsh.prio);
last->flags |= POLY_TRIANGLES;
last->tinf = &floor_texture_vertices[fsh.id];
last->tinf = get_floor_texture_vertices(fsh.id);
last->texture_offset = 0;
#if CAP_BT
if(bt::in())
for(int t=0; t<c->type; t++)
texture_order([&] (ld x, ld y) {
hyperpoint left = bt::get_corner_horo_coordinates(c, t);
hyperpoint right = bt::get_corner_horo_coordinates(c, t+1);
hpcpush(orthogonal_move(bt::get_horopoint(left * x + right * y), dfloor_table[k]));
});
else
#endif
if(1) {
int s = fsh.b[id].s;
int e = fsh.b[id].e-1;
for(int t=0; t<e-s; t++) {
hyperpoint v1 = may_kleinize(hpc[s+t]) - C0;
hyperpoint v2 = may_kleinize(hpc[s+t+1]) - C0;
int e = fsh.b[id].e-1;
if(vid.pseudohedral == phInscribed) {
hyperpoint ctr = Hypc;
for(int t=0; t<e-s; t++)
ctr += kleinize(cgi.emb->orthogonal_move(hpc[s+t], dfloor_table[k]));
ctr = normalize(ctr);
for(int t=0; t<e-s; t++) {
hyperpoint v1 = kleinize(cgi.emb->orthogonal_move(hpc[s+t], dfloor_table[k])) - ctr;
hyperpoint v2 = kleinize(cgi.emb->orthogonal_move(hpc[s+t+1], dfloor_table[k])) - ctr;
texture_order([&] (ld x, ld y) {
hpcpush(normalize(ctr + v1 * x + v2 * y));
});
}
}
if(vid.pseudohedral == phCircumscribed) {
vector<hyperpoint> hs(c->type);
hyperpoint z = Hypc; z[2] = dfloor_table[k];
hyperpoint ctr = cgi.emb->logical_to_actual(z);
for(int t=0; t<c->type; t++) hs[t] = get_circumscribed_corner(c, t, ctr);
// for(int t=0; t<c->type; t++) hs[t] = xspinpush0(t * TAU / c->type, 0.2); // kleinize(get_circumscribed_corner(c, t, ctr));
for(int t=0; t<c->type; t++) {
hyperpoint v1 = hs[t] - ctr;
hyperpoint v2 = atmod(hs, t+1) - ctr;
texture_order([&] (ld x, ld y) {
hpcpush(normalize(ctr + v1 * x + v2 * y));
});
}
/* also affect the plain floor */
bshape(fsh.b[id], PPR::FLOOR);
for(hyperpoint& h: hs) hpcpush(h);
hpcpush(hs[0]);
}
if(vid.pseudohedral == phOFF) for(int t=0; t<e-s; t++) {
hyperpoint v1 = cgi.emb->actual_to_logical(hpc[s+t]);
hyperpoint v2 = cgi.emb->actual_to_logical(hpc[s+t+1]);
texture_order([&] (ld x, ld y) {
hpcpush(
orthogonal_move(
normalize(C0 + v1 * x + v2 * y)
, dfloor_table[k])
);
hyperpoint a = v1 * x + v2 * y;
a[2] = dfloor_table[k];
auto c = cgi.emb->logical_to_actual(a);
cgi.hpcpush(c);
});
}
}
@ -623,27 +769,20 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
sizeto(fsh.cone[co], id);
bshape(fsh.cone[co][id], fsh.prio);
last->flags |= POLY_TRIANGLES;
last->tinf = &floor_texture_vertices[fsh.id];
last->tinf = get_floor_texture_vertices(fsh.id);
last->texture_offset = 0;
ld h = (FLOOR - WALL) / (co+1);
ld top = co ? (FLOOR + WALL) / 2 : WALL;
#if CAP_BT
if(bt::in())
for(int t=0; t<c->type; t++)
texture_order([&] (ld x, ld y) {
hyperpoint left = bt::get_corner_horo_coordinates(c, t);
hyperpoint right = bt::get_corner_horo_coordinates(c, t+1);
hpcpush(orthogonal_move(bt::get_horopoint(left * x + right * y), top + h * (x+y)));
});
else
#endif
if(1) {
int s = fsh.b[id].s;
int e = fsh.b[id].e-1;
for(int t=0; t<e-s; t++) {
hyperpoint v1 = may_kleinize(hpc[s+t]) - C0;
hyperpoint v2 = may_kleinize(hpc[s+t+1]) - C0;
texture_order([&] (ld x, ld y) { hpcpush(orthogonal_move(normalize(C0 + v1 * x + v2 * y), top + h * (x+y))); });
hyperpoint v1 = cgi.emb->actual_to_logical(hpc[s+t]);
hyperpoint v2 = cgi.emb->actual_to_logical(hpc[s+t+1]);
texture_order([&] (ld x, ld y) {
hyperpoint a = v1 * x + v2 * y; a[2] = top + h * (x+y);
hpcpush(cgi.emb->logical_to_actual(a));
});
}
}
@ -691,6 +830,8 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
#endif
}
EX hookset<bool(cell*)> hooks_floorshapes;
void geometry_information::generate_floorshapes() {
DEBBI(DF_POLY, ("generate_floorshapes"));
@ -699,19 +840,23 @@ void geometry_information::generate_floorshapes() {
cell model;
model.master = &modelh;
modelh.c7 = &model;
model.type = modelh.type = S7;
model.type = modelh.type = FULL_EDGE;
auto mmerge1 = [&] (int i, int j) { model.c.setspin(i, j, false); modelh.c.setspin(i, j, false); };
auto mmerge = [&] (int i, int j) { mmerge1(i, j); mmerge1(j, i); };
for(int i=0; i<S7; i++) {
for(int i=0; i<FULL_EDGE; i++) {
model.move(i) = &model;
modelh.move(i) = &modelh;
model.c.setspin(i, i, false);
modelh.c.setspin(i, i, false);
}
if(WDIM == 3) ;
model.type = modelh.type = S7;
if(callhandlers(false, hooks_floorshapes, &model)) ;
else if(WDIM == 3) ;
#if CAP_IRR
else if(IRREGULAR) {
@ -737,6 +882,14 @@ void geometry_information::generate_floorshapes() {
else if(inforder::mixed()) { /* will be generated on the fly */ }
else if(hat::in()) {
dynamicval<bool> ncor(approx_nearcorner, true);
for(int i=0; i<2; i++) {
modelh.c7 = i == 1 ? &model : nullptr;
generate_floorshapes_for(i, &model, 0, 0);
}
}
#if CAP_BT
else if(kite::in()) {
dynamicval<bool> ncor(approx_nearcorner, true);
@ -751,21 +904,7 @@ void geometry_information::generate_floorshapes() {
#if CAP_ARCM
else if(arcm::in()) {
arcm::parent_index_of(&modelh) = 0;
auto &ac = arcm::current;
for(int i=0; i<2*ac.N + 2; i++) {
if(ac.regular && i>=2 && i < 2*ac.N) continue;
arcm::id_of(&modelh) = i;
model.type = isize(ac.triangles[i]);
if(DUAL) model.type /= 2, arcm::parent_index_of(&modelh) = !(i&1);
if(BITRUNCATED)
generate_floorshapes_for(i, &model, !arcm::pseudohept(&model), arcm::pseudohept(&model) ? 0 : 1^(i&1));
else if(geosupport_football() == 2)
generate_floorshapes_for(i, &model, !arcm::pseudohept(&model), i >= 4 ? 1 : 0);
else
generate_floorshapes_for(i, &model, 0, 0);
}
/* will be generated on the fly */
}
#endif
@ -777,6 +916,7 @@ void geometry_information::generate_floorshapes() {
for(int i=0; i<n; i++) {
auto &ms = models[i];
auto &mh = modelh[i];
mh.fieldval = -1;
for(auto& t: ms.c.move_table) t = nullptr;
for(auto& t: mh.c.move_table) t = nullptr;
}
@ -795,11 +935,11 @@ void geometry_information::generate_floorshapes() {
auto& sh = c.shapes[i];
for(int j=0; j<sh.size(); j++) {
auto& co = sh.connections[j];
mh.c.connect(j, &modelh[get<0>(co)], get<1>(co), get<2>(co));
ms.c.connect(j, &models[get<0>(co)], get<1>(co), get<2>(co));
mh.c.connect(j, &modelh[co.sid], co.eid, co.mirror);
ms.c.connect(j, &models[co.sid], co.eid, co.mirror);
}
}
for(int i=0; i<n; i++) generate_floorshapes_for(i, &models[i], 0, 0);
for(int i=0; i<n; i++) generate_floorshapes_for(i, &models[i], c.shapes[i].football_type < 2, c.shapes[i].football_type == 0);
}
else if(geometry == gBinary4) {
@ -822,12 +962,21 @@ void geometry_information::generate_floorshapes() {
generate_floorshapes_for(0, &model, 1, 0);
}
#if CAP_BT
else if(bt::in()) {
dynamicval<hrmap*> c(currentmap, bt::new_alt_map(nullptr));
model.type = S6; generate_floorshapes_for(0, &model, 0, 0);
model.type = S7; generate_floorshapes_for(1, &model, 1, 0);
delete currentmap;
}
#endif
else {
static hrmap_standard stdmap;
dynamicval<hrmap*> c(currentmap, &stdmap);
// cell model;
model.type = S6; generate_floorshapes_for(0, &model, 0, 0);
model.type = S7; generate_floorshapes_for(1, &model, bt::in() ? 0 : 1, 0);
model.type = S7; generate_floorshapes_for(1, &model, 0, 0);
}
}
@ -837,20 +986,21 @@ EX namespace gp {
EX void clear_plainshapes() {
for(int m=0; m<3; m++)
for(int sd=0; sd<8; sd++)
for(int i=0; i<32; i++)
for(int j=0; j<32; j++)
for(int i=0; i<GOLDBERG_LIMIT; i++)
for(int j=0; j<GOLDBERG_LIMIT; j++)
for(int k=0; k<8; k++)
cgi.gpdata->pshid[m][sd][i][j][k] = -1;
cgi.gpdata->nextid = 0;
}
void build_plainshape(int& id, gp::local_info& li, cell *c0, int siid, int sidir) {
cgi.require_shapes();
id = cgi.gpdata->nextid++;
bool master = !(li.relative.first||li.relative.second);
int cor = master ? S7 : SG6;
if(master) li.last_dir = -1;
DEBB(DF_GP, (format("last=%d at=%d,%d tot=%d siid=%d sidir=%d cor=%d id=%d\n", li.last_dir, li.relative.first, li.relative.second, li.total_dir, siid, sidir, cor, id)));
DEBB(DF_GP, (hr::format("last=%d at=%d,%d tot=%d siid=%d sidir=%d cor=%d id=%d\n", li.last_dir, li.relative.first, li.relative.second, li.total_dir, siid, sidir, cor, id)));
cgi.generate_floorshapes_for(id, c0, siid, sidir);
@ -859,6 +1009,10 @@ EX namespace gp {
}
EX int get_plainshape_id(cell *c) {
if(li_for != c) {
li_for = c;
current_li = get_local_info(c);
}
int siid, sidir;
cell *c1 = c;
auto f = [&] {
@ -892,11 +1046,11 @@ EX namespace gp {
sidir = 0;
}
else f();
auto& id = cgi.gpdata->pshid[siid][sidir][draw_li.relative.first&31][draw_li.relative.second&31][gmod(draw_li.total_dir, S6)];
auto& id = cgi.gpdata->pshid[siid][sidir][current_li.relative.first&GOLDBERG_MASK][current_li.relative.second&GOLDBERG_MASK][gmod(current_li.total_dir, S6)];
if(id == -1 && sphere && isize(cgi.shFloor.b) > 0) {
forCellEx(c1, c) if(!gmatrix0.count(c1)) return 0;
}
if(id == -1) build_plainshape(id, draw_li, c, siid, sidir);
if(id == -1) build_plainshape(id, current_li, c, siid, sidir);
return id;
}
EX }
@ -933,6 +1087,23 @@ EX void set_floor(const transmatrix& spin, hpcshape& sh) {
qfi.usershape = -1;
}
/** currently only for arcm */
EX void ensure_floorshape_generated(int id, cell *c) {
hpcshape nul; nul.s = -1;
sizeto(cgi.shFloor.b, id, nul);
if(cgi.shFloor.b[id].s == -1) {
cgi.require_shapes();
if(BITRUNCATED)
cgi.generate_floorshapes_for(id, c, !arcm::pseudohept(c), arcm::pseudohept(c) ? 0 : 1^(id&1));
else if(geosupport_football() == 2)
cgi.generate_floorshapes_for(id, c, !arcm::pseudohept(c), id >= 4 ? 1 : 0);
else
cgi.generate_floorshapes_for(id, c, 0, 0);
cgi.finishshape();
cgi.extra_vertices();
}
}
EX int shvid(cell *c) {
return currentmap->shvid(c);
}
@ -967,7 +1138,7 @@ int hrmap_standard::shvid(cell *c) {
cgi.tessf = edge_of_triangle_with_angles(0, M_PI/t, M_PI/t);
cgi.crossf = cgi.tessf;
println(hlog, "generating floorshapes for ", t);
cgi.require_shapes();
cgi.generate_floorshapes_for(t, &model, 0, 0);
cgi.finishshape();
cgi.extra_vertices();
@ -1004,12 +1175,14 @@ EX struct dqi_poly *draw_shapevec(cell *c, const shiftmatrix& V, const vector<hp
#endif
#if CAP_ARCM
else if(arcm::in()) {
return &queuepolyat(V, shv[shvid(c)], col, prio);
int id = shvid(c);
ensure_floorshape_generated(id, c);
return &queuepolyat(V, shv[id], col, prio);
}
#endif
else if(GOLDBERG && ishex1(c))
return &queuepolyat(V * pispin, shv[0], col, prio);
else if(!(S7&1) && PURE && !kite::in() && !a4) {
else if(!(S7&1) && PURE && !aperiodic && !a4) {
auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, 0);
if(si.id == 8) si.dir++;
transmatrix D = applyPatterndir(c, si);
@ -1112,7 +1285,7 @@ void draw_shape_for_texture(floorshape* sh) {
queuepoly(shiftless(eupush(gx+a, gy+b)), sh->b[0], 0xFFFFFFFF);
if(sh == &cgi.shCrossFloor) {
queuepoly(shiftless(eupush(gx, gy) * spin(M_PI/4)), cgi.shCross, 0x808080FF);
queuepoly(shiftless(eupush(gx, gy) * spin(45._deg)), cgi.shCross, 0x808080FF);
}
if(1) {
@ -1131,15 +1304,17 @@ void draw_shape_for_texture(floorshape* sh) {
ld d = hdist(h1, h2);
hyperpoint h3 = h1 + (h2-h1) /d * min(d, .1);
for(int a=0; a<4; a++) {
curvepoint(eupush(gx,gy) * eupush(spin(90*degree*a) * h1) * C0);
curvepoint(eupush(gx,gy) * eupush(spin(90*degree*a) * h3) * C0);
curvepoint(eupush(gx,gy) * eupush(spin(90._deg*a) * h1) * C0);
curvepoint(eupush(gx,gy) * eupush(spin(90._deg*a) * h3) * C0);
queuecurve(shiftless(Id), 0x10101010, 0, PPR::LINE);
}
}
auto& ftv = floor_texture_vertices[sh->id];
ftv.tvertices.clear();
ftv.texture_id = floor_textures->renderedTexture;
auto ftv = get_floor_texture_vertices(sh->id);
if(ftv) {
ftv->tvertices.clear();
ftv->texture_id = floor_textures->renderedTexture;
}
hyperpoint center = eupush(gx, gy) * C0;
hyperpoint v1 = hpxyz3(sd, sd, 0, 0);
@ -1167,9 +1342,9 @@ void draw_shape_for_texture(floorshape* sh) {
};
// SL2 needs 6 times more
texture_order([&] (ld x, ld y) {
if(ftv) texture_order([&] (ld x, ld y) {
auto v = tvec_at(x, y);
ftv.tvertices.push_back(glhr::makevertex(v[0], v[1], 0));
ftv->tvertices.push_back(glhr::makevertex(v[0], v[1], 0));
});
floor_texture_square_size = 2 * (tvec_at(1, 0)[0] - tvec_at(0, 0)[0]);
@ -1186,11 +1361,12 @@ EX void ensure_vertex_number(basic_textureinfo& bti, int qty) {
/** ensure_vertex_number for a hpcshape */
EX void ensure_vertex_number(hpcshape& sh) {
if(!sh.tinf) return;
ensure_vertex_number(*sh.tinf, sh.e - sh.s);
}
EX void bind_floor_texture(hpcshape& li, int id) {
li.tinf = &floor_texture_vertices[id];
li.tinf = get_floor_texture_vertices(id);
ensure_vertex_number(li);
}
@ -1205,7 +1381,7 @@ void geometry_information::make_floor_textures_here() {
vid.xres = FLOORTEXTURESIZE;
vid.yres = FLOORTEXTURESIZE;
pconf.scale = 0.125;
pconf.camera_angle = 0;
dynamicval<transmatrix> vm(pconf.cam(), Id);
pconf.alpha = 1;
dynamicval<ld> lw(vid.linewidth, 2);
@ -1290,7 +1466,9 @@ EX void make_floor_textures() {
dynamicval<eModel> gm(pmodel, mdDisk);
dynamicval<eVariation> va(variation, eVariation::pure);
dynamicval<geometryinfo1> gie(ginf[geometry].g, giEuclid2);
dynamicval<flagtype> gief(ginf[geometry].flags, qOPTQ);
dynamicval<geometryinfo1> gih(ginf[gNormal].g, giHyperb2);
dynamicval<flagtype> gihf(ginf[gNormal].flags, 0);
dynamicval<bool> a3(vid.always3, false);
dynamicval<bool> hq(inHighQual, true);
dynamicval<int> hd(darken, 0);

View File

@ -266,6 +266,10 @@ EX void activateSafety(eLand l) {
save_turns = turncount;
}
#endif
if(items[itOrbChoice]) {
items[itOrbChoice] = 0;
cwt.at->item = itOrbSafety;
}
}
EX void placeGolem(cell *on, cell *moveto, eMonster m) {
@ -343,6 +347,8 @@ EX void pushThumper(const movei& mi) {
if(w == waThumperOn)
explode = 2;
}
if(w == waExplosiveBarrel && cto->wall == waMineMine)
explode = 2;
destroyTrapsOn(cto);
if(cto->wall == waOpenPlate || cto->wall == waClosePlate) {
toggleGates(cto, cto->wall);
@ -389,7 +395,11 @@ EX void pushThumper(const movei& mi) {
if(w == waRichDie && dice::data[cto].happy() > 0) {
cto->wall = waHappyDie;
if(cto->land == laDice && th->land == laDice) {
int q = items[itDice];
gainItem(itDice);
if(vid.bubbles_all || (threshold_met(items[itDice]) > threshold_met(q) && vid.bubbles_threshold)) {
drawBubble(cto, iinf[itDice].color, its(items[itDice]), 0.5);
}
addMessage(XLAT("The die is now happy, and you are rewarded!"));
}
else {

View File

@ -40,7 +40,8 @@ string euchelp =
#if CAP_FIELD
void showQuotientConfig() {
using namespace fieldpattern;
gamescreen(2);
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("field quotient"));
fgeomextra& gxcur = fgeomextras[current_extra];
for(int i=0; i<isize(fgeomextras); i++) {
@ -102,7 +103,8 @@ void showQuotientConfig() {
auto& cfp = currfp;
auto triplets = cfp.find_triplets();
pushScreen([triplets] {
gamescreen(2);
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("alternate manifolds"));
int id = 0;
for(auto t: triplets) {
@ -150,11 +152,8 @@ void validity_info() {
EX bool showquotients;
string validclasses[4] = {" (X)", " (½)", "", " (!)"};
EX void ge_land_selection() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
EX void gen_landvisited() {
if(cheater) for(int i=0; i<landtypes; i++) landvisited[i] = true;
for(int i=0; i<landtypes; i++)
@ -175,6 +174,13 @@ EX void ge_land_selection() {
landvisited[laCamelot] |= hiitemsMax(treasureType(laCamelot)) >= 1;
landvisited[laCA] = true;
landvisited[laAsteroids] = true;
}
EX void ge_land_selection() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
gen_landvisited();
dialog::init(XLAT("select the starting land"));
if(dialog::infix != "") mouseovers = dialog::infix;
@ -185,17 +191,17 @@ EX void ge_land_selection() {
});
stable_sort(landlist.begin(), landlist.end(), [] (eLand l1, eLand l2) { return land_validity(l1).quality_level > land_validity(l2).quality_level; });
for(int i=0; i<euperpage; i++) {
if(euperpage * eupage + i >= isize(landlist)) { dialog::addBreak(100); break; }
eLand l = landlist[euperpage * eupage + i];
char ch = '1'+i;
dialog::start_list(900, 900, '1');
for(auto& l: landlist) {
string s = XLAT1(linf[l].name);
if(landvisited[l]) {
dialog::addBoolItem(s, l == specialland, ch);
dialog::addBoolItem(s, l == specialland, dialog::list_fake_key++);
}
else {
dialog::addSelItem(s, XLAT("(locked)"), ch);
dialog::addSelItem(s, XLAT("(locked)"), dialog::list_fake_key++);
}
dialog::lastItem().color = linf[l].color;
@ -204,7 +210,7 @@ EX void ge_land_selection() {
if(landvisited[l]) dialog::do_if_confirmed(dual::mayboth([l] {
stop_game_and_switch_mode(tactic::on ? rg::tactic : rg::nothing);
firstland = specialland = l;
if(l == laCanvas || l == laAsteroids)
if(l == laCanvas || l == laAsteroids || (land_validity(l).flags & lv::switch_to_single))
land_structure = lsSingle;
else if(among(l, laCrossroads, laCrossroads2))
land_structure = lsNiceWalls;
@ -215,13 +221,13 @@ EX void ge_land_selection() {
}));
});
}
dialog::addItem(XLAT("next page"), '-');
dialog::addInfo(XLAT("press letters to search"));
dialog::end_list();
dialog::addBreak(25);
validity_info();
dialog::addBreak(25);
dialog::addInfo(XLAT("press letters to search"));
dual::add_choice();
dialog::addBack();
dialog::display();
@ -229,11 +235,7 @@ EX void ge_land_selection() {
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni == '-' || uni == PSEUDOKEY_WHEELUP || uni == PSEUDOKEY_WHEELDOWN) {
eupage++;
if(eupage * euperpage >= isize(landlist)) eupage = 0;
}
else if(dialog::editInfix(uni)) eupage = 0;
if(dialog::editInfix(uni)) dialog::list_skip = 0;
else if(doexiton(sym, uni)) popScreen();
};
}
@ -247,6 +249,7 @@ EX void activate_ge_land_selection() {
#if HDR
struct geometry_filter {
string name;
int hotkey;
/** test if the current geometry matches the filter */
function<bool()> test;
};
@ -256,35 +259,36 @@ EX geometry_filter *current_filter;
bool forced_quotient() { return quotient && !(cgflags & qOPTQ); }
EX geometry_filter gf_hyperbolic = {"hyperbolic", [] { return (arcm::in() || arb::in() || hyperbolic) && !forced_quotient(); }};
EX geometry_filter gf_spherical = {"spherical", [] { return (arcm::in() || arb::in() || sphere) && !forced_quotient(); }};
EX geometry_filter gf_euclidean = {"Euclidean", [] { return (arcm::in() || arb::in() || euclid) && !forced_quotient(); }};
EX geometry_filter gf_other = {"non-isotropic", [] { return prod || nonisotropic; }};
EX geometry_filter gf_regular_2d = {"regular 2D tesselations", [] {
EX geometry_filter gf_hyperbolic = {"hyperbolic", 'h', [] { return (arcm::in() || arb::in() || hyperbolic) && !forced_quotient(); }};
EX geometry_filter gf_spherical = {"spherical", 's', [] { return (arcm::in() || arb::in() || sphere) && !forced_quotient(); }};
EX geometry_filter gf_euclidean = {"Euclidean", 'e', [] { return (arcm::in() || arb::in() || euclid) && !forced_quotient(); }};
EX geometry_filter gf_other = {"non-isotropic", 'n', [] { return mproduct || nonisotropic; }};
EX geometry_filter gf_regular_2d = {"regular 2D tesselations", 'r', [] {
return standard_tiling() && WDIM == 2 && !forced_quotient();
}};
EX geometry_filter gf_regular_3d = {"regular 3D honeycombs", [] {
EX geometry_filter gf_regular_3d = {"regular 3D honeycombs", '3', [] {
if(euclid) return geometry == gCubeTiling;
return !bt::in() && !kite::in() && WDIM == 3 && !forced_quotient() && !nonisotropic && !prod;
return !bt::in() && !kite::in() && WDIM == 3 && !forced_quotient() && !nonisotropic && !mproduct;
}};
EX geometry_filter gf_quotient = {"interesting quotient spaces", [] {
EX geometry_filter gf_quotient = {"interesting quotient spaces", 'q', [] {
return forced_quotient() && !elliptic;
}};
EX geometry_filter gf_tes_file = {"load from file", 'f', [] { return arb::in(); }};
EX geometry_filter gf_no_filters = {"no filters", '-', [] { return true; }};
EX vector<geometry_filter*> available_filters = { &gf_hyperbolic, &gf_spherical, &gf_euclidean, &gf_other, &gf_regular_2d, &gf_regular_3d, &gf_quotient };
EX vector<geometry_filter*> available_filters = { &gf_hyperbolic, &gf_spherical, &gf_euclidean, &gf_other, &gf_regular_2d, &gf_regular_3d, &gf_quotient, &gf_tes_file, &gf_no_filters };
void ge_select_filter() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(2);
gamescreen();
dialog::init(XLAT("geometries"));
char x = 'a';
for(auto f: available_filters) {
if(current_filter)
dialog::addBoolItem(XLAT(f->name), f == current_filter, x++);
dialog::addBoolItem(XLAT(f->name), f == current_filter, f->hotkey);
else
dialog::addItem(XLAT(f->name), x++);
dialog::addItem(XLAT(f->name), f->hotkey);
dialog::add_action([f] { current_filter = f; popScreen(); });
}
@ -322,7 +326,7 @@ void set_or_configure_geometry(eGeometry g) {
if(g == gRotSpace) {
bool ok = true;
if(arcm::in()) ok = PURE;
else if(bt::in() || kite::in()) ok = false;
else if(bt::in() || aperiodic) ok = false;
else ok = PURE || BITRUNCATED;
if(!ok) {
addMessage(XLAT("Only works with (semi-)regular tilings"));
@ -346,9 +350,11 @@ void set_or_configure_geometry(eGeometry g) {
/** is g2 the same tiling as the current geometry (geometry)? */
bool same_tiling(eGeometry g2) {
/* no quotients for fractals */
if(cgflags & qFRACTAL) return g2 == geometry;
if(g2 == gCrystal)
return S3 == 4;
if(g2 == gFieldQuotient && hyperbolic && standard_tiling())
if(g2 == gFieldQuotient && (hyperbolic || (geometry == gCubeTiling && reg3::cubes_reg3)) && standard_tiling())
return true;
if(g2 == gFieldQuotient && geometry != gFieldQuotient) {
int ce = 0;
@ -364,8 +370,9 @@ bool same_tiling(eGeometry g2) {
}
void ge_select_tiling() {
if(current_filter == &gf_tes_file) { popScreen(); set_or_configure_geometry(gArbitrary); }
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
if(!current_filter) { popScreen(); return; }
dialog::init();
@ -376,7 +383,8 @@ void ge_select_tiling() {
dialog::addBreak(100);
char letter = 'a';
dialog::start_list(500, 1500, 'a');
for(int i=0; i<isize(ginf); i++) {
eGeometry g = eGeometry(i);
if(among(g, gProduct, gRotSpace)) hybrid::configure(g);
@ -404,11 +412,12 @@ void ge_select_tiling() {
dialog::addBoolItem(
is_product ? XLAT("current geometry x E") :
is_rotspace ? XLAT("space of rotations in current geometry") :
XLAT(ginf[g].menu_displayed_name), on, letter++);
XLAT(ginf[g].menu_displayed_name), on, dialog::list_fake_key++);
dialog::lastItem().value += validclasses[land_validity(specialland).quality_level];
dialog::add_action([g] { set_or_configure_geometry(g); });
}
dialog::end_list();
dialog::addBreak(100);
dual::add_choice();
dialog::addBack();
@ -447,7 +456,8 @@ EX string dim_name() {
EX void showQuotientConfig3() {
using namespace fieldpattern;
gamescreen(2);
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("field quotient"));
auto& ds = discoveries[cginf.tiling_name];
@ -503,34 +513,27 @@ EX void showQuotientConfig3() {
}
#endif
EX string geometry_name() {
switch(ginf[geometry].cclass) {
EX string geometry_name(eGeometryClass gc) {
switch(gc) {
case gcHyperbolic:
return XLAT("hyperbolic") + dim_name();
return XLAT("hyperbolic");
case gcEuclid:
if(cgflags & qAFFINE)
return XLAT("affine") + dim_name();
return XLAT("flat") + dim_name();
return XLAT("affine");
return XLAT("flat");
case gcSphere:
return XLAT("spherical") + dim_name();
return XLAT("spherical");
case gcSolNIH:
#if CAP_SOLV
switch(sn::geom()) {
case gSol:
return XLAT("Sol");
case gNIH:
return XLAT("hyperbolic (3:2)");
case gSolN:
return XLAT("Sol (3:2)");
default:
return "unknown";
}
#else
case gcSol:
return XLAT("Sol");
#endif
case gcNIH:
return XLAT("hyperbolic (3:2)");
case gcSolN:
return XLAT("Sol (3:2)");
case gcNil:
return XLAT("Nil");
@ -544,9 +547,22 @@ EX string geometry_name() {
return "?";
}
EX string geometry_name() {
if(cgi.emb && cgi.emb->is_same_in_same())
return geometry_name(geom3::mgclass());
else if(embedded_plane && gproduct)
return geometry_name(geom3::mgclass()) + " (x E)";
else if(embedded_plane)
return geometry_name(geom3::mgclass()) + " @ " + geometry_name(geom3::ggclass());
else if(among(ginf[geometry].cclass, gcHyperbolic, gcEuclid, gcSphere))
return geometry_name(ginf[geometry].cclass) + dim_name();
else
return geometry_name(ginf[geometry].cclass);
}
EX void select_quotient_screen() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
dialog::init(XLAT("quotient spaces in ") + ginf[geometry].tiling_name);
char key = 'a';
@ -592,7 +608,7 @@ EX void select_quotient_screen() {
}
EX void select_quotient() {
if(euclid && !kite::in() && !arcm::in()) {
if(meuclid && !aperiodic && !arcm::in() && !reg3::cubes_reg3 && !(cgflags & qFRACTAL)) {
euc::prepare_torus3();
pushScreen(euc::show_torus3);
}
@ -606,7 +622,7 @@ EX void select_quotient() {
pushScreen(asonov::show_config);
}
#endif
else if(prod)
else if(mproduct)
pushScreen(product::show_config);
else if(rotspace)
hybrid::configure_period();
@ -630,11 +646,13 @@ EX void select_quotient() {
EX string full_geometry_name() {
string qstring = ginf[geometry].quotient_name;
bool variable =
!(prod || hybri || bt::in() || (WDIM == 3 && !reg3::in()) || kite::in() || arb::in());
!(mproduct || mhybrid || bt::in() || (WDIM == 3 && !reg3::in()) || aperiodic || arb::in());
string fgname = XLAT(ginf[geometry].tiling_name);
if(qstring != "none") fgname += " " + XLAT(qstring);
#if CAP_ARCM
if(arcm::in()) fgname = arcm::current.symbol;
#endif
if(variable) fgname = gp::operation_name() + " " + fgname;
return fgname;
}
@ -645,7 +663,7 @@ void action_change_variation() {
else if(arcm::in()) arcm::next_variation();
#endif
#if MAXMDIM >= 4
else if(reg3::in()) reg3::configure_variation();
else if(reg3::in() || geometry == gCubeTiling) reg3::configure_variation();
#endif
else if(euc::in(2,4) || !CAP_GP) dialog::do_if_confirmed([] {
set_variation(PURE ? eVariation::bitruncated : eVariation::pure);
@ -676,7 +694,7 @@ EX void menuitem_binary_width(char key) {
dialog::addSelItem(XLAT("binary tiling width"), fts(vid.binary_width), key);
dialog::add_action([] {
dialog::editNumber(vid.binary_width, 0, 2, 0.1, 1, XLAT("binary tiling width"), "");
dialog::reaction = [] () {
dialog::get_ne().reaction = [] () {
#if CAP_TEXTURE
texture::config.remap();
#endif
@ -691,7 +709,7 @@ EX void menuitem_nilwidth(char key) {
dialog::addSelItem(XLAT("Nil width"), fts(nilv::nilwidth), key);
dialog::add_action([] {
dialog::editNumber(nilv::nilwidth, 0.01, 2, 0.1, 1, XLAT("Nil width"), "");
dialog::reaction = ray::reset_raycaster;
dialog::get_ne().reaction = ray::reset_raycaster;
dialog::bound_low(0.01);
});
}
@ -705,126 +723,122 @@ EX void edit_stretch() {
"Value of 0 means not stretched, -1 means S2xE or H2xE (works only in the limit). (Must be > -1)"
)
);
dialog::reaction = [] { if(abs(stretch::factor+1) < 1e-3) stretch::factor = -.9; ray::reset_raycaster(); };
dialog::get_ne().reaction = [] { if(abs(stretch::factor+1) < 1e-3) stretch::factor = -.9; ray::reset_raycaster(); };
}
EX void showEuclideanMenu() {
// for(int i=2; i<lt; i++) landvisited[i] = true;
#if HDR
struct geometry_data {
int ts, tv, nom, denom, euler, demigenus, worldsize;
int area;
string spf;
string size_str;
};
#endif
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
dialog::init(XLAT("experiment with geometry"));
dialog::addSelItem(XLAT("geometry"), geometry_name(), 'd');
dialog::add_action([] { pushScreen(ge_select_tiling); pushScreen(ge_select_filter); });
dialog::addSelItem(XLAT("basic tiling"), XLAT(ginf[geometry].tiling_name), 't');
dialog::add_action([] {
if(!current_filter || !current_filter->test()) set_default_filter();
pushScreen(ge_select_tiling);
});
int ts = ginf[geometry].sides;
int tv = ginf[geometry].vertex;
int nom = (BITRUNCATED ? tv+ts : tv) * 4;
int denom = (2*ts + 2*tv - ts * tv);
EX geometry_data compute_geometry_data() {
geometry_data gd;
auto& ts = gd.ts;
auto& tv = gd.tv;
ts = ginf[geometry].sides;
tv = ginf[geometry].vertex;
gd.nom = (BITRUNCATED ? tv+ts : tv) * 4;
gd.denom = (2*ts + 2*tv - ts * tv);
#if CAP_GP
if(GOLDBERG || INVERSE) {
ld area = PIU(cgi.gpdata->area);
gd.area = PIU(cgi.gpdata->area);
if(GOLDBERG || WARPED) {
nom = 2 * (2*tv + (S3-2) * ts * (area-1));
gd.nom = 2 * (2*tv + (S3-2) * ts * (gd.area-1));
}
else if(UNRECTIFIED) {
if((gp::param.first + gp::param.second) % 2 == 0)
nom = ts * 2 * area;
gd.nom = ts * 2 * gd.area;
else
nom = (2*tv + (S3-2) * ts * (area-1));
gd.nom = (2*tv + (S3-2) * ts * (gd.area-1));
}
else if(UNTRUNCATED) {
if((gp::param.first - gp::param.second) % 3 == 0) {
nom = ts * 4 * area;
denom *= 3;
gd.nom = ts * 4 * gd.area;
gd.denom *= 3;
}
else {
nom = 2 * (2*tv + (S3-2) * ts * (area-1));
denom *= 3;
gd.nom = 2 * (2*tv + (S3-2) * ts * (gd.area-1));
gd.denom *= 3;
}
}
}
else
#endif
gd.area = PURE ? 1 : 3;
int worldsize;
int euler = 0;
if(euclid) euler = 0;
else if(sphere && nonorientable) euler = 1;
else if(sphere) euler = 2;
else if(!bounded) euler = -2;
else if(WDIM == 3) euler = 0;
gd.euler = 0;
if(meuclid) gd.euler = 0;
else if(msphere && nonorientable) gd.euler = 1;
else if(msphere) gd.euler = 2;
else if(!closed_manifold) gd.euler = -2;
else if(WDIM == 3) gd.euler = 0;
else switch(geometry) {
case gFieldQuotient:
worldsize = isize(currentmap->allcells());
euler = 2 * worldsize * denom / nom;
gd.worldsize = isize(currentmap->allcells());
gd.euler = 2 * gd.worldsize * gd.denom / gd.nom;
break;
case gMinimal:
euler = -1;
gd.euler = -1;
break;
case gZebraQuotient:
case gBolza:
euler = -2;
gd.euler = -2;
break;
case gKleinQuartic:
case gSchmutzM2:
case gBolza2:
euler = -4;
gd.euler = -4;
break;
case gSchmutzM3:
case gBring:
euler = -6;
gd.euler = -6;
break;
case gMacbeath:
euler = -12;
gd.euler = -12;
break;
default:
worldsize = isize(currentmap->allcells());
println(hlog, "warning: Euler characteristics unknown, worldsize = ", worldsize);
euler = 2 * worldsize * denom / nom;
gd.worldsize = isize(currentmap->allcells());
println(hlog, "warning: Euler characteristics unknown, worldsize = ", gd.worldsize);
gd.euler = 2 * gd.worldsize * gd.denom / gd.nom;
break;
}
nom *= euler;
denom *= 2;
gd.nom *= gd.euler;
gd.denom *= 2;
if(hybri) nom *= hybrid::csteps, denom *= cgi.single_step;
if(mhybrid) gd.nom *= hybrid::csteps, gd.denom *= cgi.single_step;
int g = gcd(nom, denom);
int g = gcd(gd.nom, gd.denom);
if(g) {
nom /= g;
denom /= g;
gd.nom /= g;
gd.denom /= g;
}
if(euclid && bounded) {
worldsize = euc::eu.det;
if(BITRUNCATED) worldsize *= (a4 ? 2 : 3);
if(GOLDBERG) worldsize *= cgi.gpdata->area;
if(euclid && closed_manifold) {
gd.worldsize = euc::eu.det;
if(BITRUNCATED) gd.worldsize *= (a4 ? 2 : 3);
if(GOLDBERG) gd.worldsize *= cgi.gpdata->area;
#if CAP_IRR
if(IRREGULAR) worldsize *= isize(irr::cells) / isize(irr::cells_of_heptagon);
if(IRREGULAR) gd.worldsize *= isize(irr::cells) / isize(irr::cells_of_heptagon);
#endif
}
else
worldsize = denom ? nom / denom : 0;
gd.worldsize = gd.denom ? gd.nom / gd.denom : 0;
if(euler < 0 && !bounded)
worldsize = -worldsize;
if(gd.euler < 0 && !closed_manifold)
gd.worldsize = -gd.worldsize;
string spf = its(ts);
if(0) ;
@ -896,7 +910,66 @@ EX void showEuclideanMenu() {
for(int z=1; z<S3; z++) spf = spf + "," + spf0;
}
gd.size_str =
disksize ? its(isize(currentmap->allcells())) :
#if CAP_BT
bt::in() ? fts(1440._deg * sqrt(2) * log(2) / pow(vid.binary_width, WDIM-1), 4) + " exp(∞)" :
#endif
#if CAP_ARCM
arcm::in() && (WDIM == 2) ? arcm::current.world_size() :
(arcm::in() && sphere) ? its(isize(currentmap->allcells())) :
#endif
#if CAP_CRYSTAL
cryst ? "∞^" + its(ts/2) :
#endif
WDIM == 3 && closed_manifold ? its(isize(currentmap->allcells())) :
WDIM == 3 && euclid ? "" :
gd.worldsize < 0 ? (gd.nom%gd.denom ? its(gd.nom)+"/"+its(gd.denom) : its(-gd.worldsize)) + " exp(∞)":
(euclid && quotient && !closed_manifold) ? "" :
gd.worldsize == 0 ? "∞²" :
its(gd.worldsize);
#if CAP_IRR
if(hyperbolic && IRREGULAR) {
gd.nom = isize(irr::cells);
// both Klein Quartic and Bolza2 are double the Zebra quotiennt
gd.denom = -2;
if(!quotient) gd.worldsize = gd.nom / gd.denom;
}
#endif
if(WDIM == 3) gd.euler = 0;
gd.demigenus = 2 - gd.euler;
return gd;
}
EX void add_size_action() {
if(WDIM == 2 || reg3::exact_rules()) dialog::add_action([] {
if(!viewdists) { enable_viewdists(); pushScreen(viewdist_configure_dialog); }
else if(viewdists) viewdists = false;
});
}
EX void showEuclideanMenu() {
// for(int i=2; i<lt; i++) landvisited[i] = true;
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("experiment with geometry"));
dialog::addSelItem(XLAT("geometry"), geometry_name(), 'd');
dialog::add_action([] { pushScreen(ge_select_tiling); pushScreen(ge_select_filter); });
dialog::addSelItem(XLAT("basic tiling"), XLAT(ginf[geometry].tiling_name), 't');
dialog::add_action([] {
if(!current_filter || !current_filter->test()) set_default_filter();
pushScreen(ge_select_tiling);
});
string qstring = ginf[geometry].quotient_name;
if(meuclid && quotient) qstring = ONOFF(true);
if(qstring == "none")
dialog::addBoolItem(XLAT("quotient space"), false, 'q');
@ -930,19 +1003,12 @@ EX void showEuclideanMenu() {
});
}
if(arb::in() && !arb::current.sliders.empty()) {
if(arb::in() && !(arb::current.sliders.empty() && arb::current.intsliders.empty())) {
dialog::addItem(XLAT("tessellation sliders"), '4');
dialog::add_action_push(arb::set_sliders);
}
#if CAP_IRR
if(hyperbolic && IRREGULAR) {
nom = isize(irr::cells);
// both Klein Quartic and Bolza2 are double the Zebra quotiennt
denom = -2;
if(!quotient) worldsize = nom / denom;
}
#endif
if(arb::is_apeirogonal()) add_edit(arb::apeirogon_simplified_display);
if(arb::in()) add_edit(debug_tiles);
#if MAXMDIM >= 4
if(cgflags & qULTRA) {
@ -954,13 +1020,14 @@ EX void showEuclideanMenu() {
}
#endif
if(prod) {
if(mproduct) {
dialog::addSelItem(XLAT("Z-level height factor"), fts(vid.plevel_factor), 'Z');
dialog::add_action([] {
dialog::editNumber(vid.plevel_factor, 0, 2, 0.1, 0.7, XLAT("Z-level height factor"), "");
dialog::get_ne().reaction = ray::reset_raycaster;
});
}
else if(hybri) {
else if(mhybrid) {
dialog::addSelItem(XLAT("number of levels"), its(hybrid::csteps / cgi.single_step), 'L');
dialog::add_action(hybrid::configure_period);
}
@ -968,10 +1035,16 @@ EX void showEuclideanMenu() {
menuitem_binary_width('v');
add_edit_wall_quality('W');
}
else if(hat::in()) {
add_edit(hat::hat_param);
add_edit(hat::hat_param_imag);
}
else if(nil) {
menuitem_nilwidth('v');
}
else if((WDIM == 3 || kite::in() || arb::in()) && !reg3::in()) dialog::addBreak(100);
else if((WDIM == 3 || aperiodic || arb::in()) && !reg3::in() && geometry != gCubeTiling) dialog::addBreak(100);
else if(cgclass & qFRACTAL)
dialog::addBreak(100);
else
menuitem_change_variation('v');
@ -990,7 +1063,7 @@ EX void showEuclideanMenu() {
}
#if MAXMDIM >= 4
if(hybri) {
if(mhybrid) {
auto r = rots::underlying_scale;
dialog::addSelItem(XLAT("view the underlying geometry"), r > 0 ? fts(r)+"x" : ONOFF(false), '6');
dialog::add_action([] {
@ -1005,7 +1078,7 @@ EX void showEuclideanMenu() {
);
dialog::bound_low(0);
dialog::bound_up(1);
dialog::extra_options = [] () { rots::draw_underlying(true); };
dialog::get_di().extra_options = [] () { rots::draw_underlying(true); };
});
}
#endif
@ -1017,17 +1090,18 @@ EX void showEuclideanMenu() {
dialog::addBreak(100);
menuitem_land_structure('l');
add_edit(req_disksize);
if(specialland == laMinefield && bounded) {
if(specialland == laMinefield && closed_or_bounded) {
dialog::addSelItem(XLAT("number of mines"), its(bounded_mine_quantity), 'm');
dialog::add_action([] {
dialog::editNumber(bounded_mine_quantity, 0, bounded_mine_max, 1, (bounded_mine_max+5)/10,
XLAT("number of mines"), "");
dialog::reaction = [] {
dialog::get_ne().reaction = [] {
if(bounded_mine_quantity < 0) bounded_mine_quantity = 0;
if(bounded_mine_quantity > bounded_mine_max) bounded_mine_quantity = bounded_mine_max;
};
dialog::reaction_final = [] {
dialog::get_ne().reaction_final = [] {
bounded_mine_percentage = bounded_mine_quantity * 1. / bounded_mine_max;
stop_game();
start_game();
@ -1046,7 +1120,7 @@ EX void showEuclideanMenu() {
}
dialog::addBoolItem(XLAT("pattern"), specialland == laCanvas, 'p');
if(specialland == laCanvas) dialog::lastItem().value = patterns::whichCanvas;
if(specialland == laCanvas) dialog::lastItem().value = ccolor::which->name;
dialog::add_action_push(patterns::showPrePattern);
validity_info();
if(WDIM == 3) {
@ -1054,8 +1128,9 @@ EX void showEuclideanMenu() {
dialog::add_action_push(show3D);
}
menuitem_projection('1');
if(nonisotropic && !sl2)
dialog::addBoolItem_action(XLAT("geodesic movement in Sol/Nil"), nisot::geodesic_movement, 'G');
if(lie_movement_available()) {
add_edit(nisot::geodesic_movement);
}
#if CAP_CRYSTAL && MAXMDIM >= 4
crystal::add_crystal_transform('x');
#endif
@ -1074,45 +1149,24 @@ EX void showEuclideanMenu() {
dialog::addTitle(XLAT("info about: %1", full_geometry_name()), 0xFFFFFF, 150);
if(WDIM == 2 && !arb::in() && !kite::in()) dialog::addSelItem(XLAT("faces per vertex"), spf, 0);
auto gd = compute_geometry_data();
if(WDIM == 2 && !arb::in() && !aperiodic) dialog::addSelItem(XLAT("faces per vertex"), gd.spf, 0);
if(arb::in() && arb::current.comment != "") {
dialog::addBreak(100);
dialog::addHelp(arb::current.comment);
}
dialog::addSelItem(XLAT("size of the world"),
#if CAP_BT
bt::in() ? fts(8 * M_PI * sqrt(2) * log(2) / pow(vid.binary_width, WDIM-1), 4) + " exp(∞)" :
#endif
#if CAP_ARCM
arcm::in() && (WDIM == 2) ? arcm::current.world_size() :
(arcm::in() && sphere) ? its(isize(currentmap->allcells())) :
#endif
#if CAP_CRYSTAL
cryst ? "∞^" + its(ts/2) :
#endif
WDIM == 3 && bounded ? its(isize(currentmap->allcells())) :
WDIM == 3 && euclid ? "" :
worldsize < 0 ? (nom%denom ? its(nom)+"/"+its(denom) : its(-worldsize)) + " exp(∞)":
(euclid && quotient && !bounded) ? "" :
worldsize == 0 ? "∞²" :
its(worldsize),
'3');
if(WDIM == 2 || reg3::in_rule()) dialog::add_action([] {
if(!viewdists) { enable_viewdists(); pushScreen(viewdist_configure_dialog); }
else if(viewdists) viewdists = false;
});
dialog::addSelItem(XLAT("size of the world"), gd.size_str, '3');
add_size_action();
if(bounded) {
if(WDIM == 3) euler = 0;
dialog::addSelItem(XLAT("Euler characteristics"), its(euler), 0);
if(closed_manifold) {
dialog::addSelItem(XLAT("Euler characteristics"), its(gd.euler), 0);
if(WDIM == 3) ;
else if(nonorientable)
dialog::addSelItem(XLAT("demigenus"), its(2-euler), 0);
dialog::addSelItem(XLAT("demigenus"), its(gd.demigenus), 0);
else
dialog::addSelItem(XLAT("genus"), its((2-euler)/2), 0);
dialog::addSelItem(XLAT("genus"), its(gd.demigenus/2), 0);
}
else dialog::addBreak(200);
@ -1232,6 +1286,12 @@ int read_geom_args() {
shift(); gp::param.second = argi();
set_variation(eVariation::goldberg);
}
else if(argis("-gph")) {
PHASEFROM(2);
shift(); int x = argi();
shift(); int y = argi();
gp::whirl_set({x, y});
}
else if(argis("-unrectified")) {
PHASEFROM(2);
set_variation(eVariation::unrectified);
@ -1244,32 +1304,39 @@ int read_geom_args() {
PHASEFROM(2);
set_variation(eVariation::warped);
}
#if MAXMDIM >= 4
else if(argis("-subcubes")) {
PHASEFROM(2);
stop_game();
set_variation(eVariation::subcubes);
shift(); reg3::subcube_count = argi();
}
else if(argis("-dual-subcubes")) {
PHASEFROM(2);
stop_game();
set_variation(eVariation::dual_subcubes);
shift(); reg3::subcube_count = argi();
}
else if(argis("-bch-subcubes")) {
PHASEFROM(2);
stop_game();
set_variation(eVariation::bch);
shift(); reg3::subcube_count = argi();
}
else if(argis("-bch-oct")) {
PHASEFROM(2);
stop_game();
set_variation(eVariation::bch_oct);
shift(); reg3::subcube_count = argi();
}
else if(argis("-coxeter")) {
PHASEFROM(2);
stop_game();
set_variation(eVariation::coxeter);
shift(); reg3::coxeter_param = argi();
}
#endif
#endif
#if CAP_FIELD
else if(argis("-fi")) {
fieldpattern::info();

View File

@ -22,7 +22,7 @@ struct usershapelayer {
extern int usershape_changes;
static const int USERLAYERS = 32;
static constexpr int USERLAYERS = 32;
struct usershape { usershapelayer d[USERLAYERS]; };
@ -35,6 +35,7 @@ struct hpcshape {
int texture_offset;
int shs, she;
void clear() { s = e = shs = she = texture_offset = 0; prio = PPR::ZERO; tinf = NULL; flags = 0; }
hpcshape() { clear(); }
};
#define SIDE_SLEV 0
@ -50,12 +51,21 @@ struct hpcshape {
#define SIDE_BSHA 12
#define SIDEPARS 13
/** GOLDBERG_BITS controls the size of tables for Goldberg. see gp::check_limits */
#ifndef GOLDBERG_BITS
#define GOLDBERG_BITS 5
#endif
static constexpr int GOLDBERG_LIMIT = (1<<GOLDBERG_BITS);
static constexpr int GOLDBERG_MASK = (GOLDBERG_LIMIT-1);
#ifndef BADMODEL
#define BADMODEL 0
#endif
#ifndef WINGS
static const int WINGS = (BADMODEL ? 1 : 4);
static constexpr int WINGS = (BADMODEL ? 1 : 4);
#endif
typedef array<hpcshape, WINGS+1> hpcshape_animated;
@ -98,6 +108,8 @@ struct gi_extension {
virtual ~gi_extension() {}
};
struct expansion_analyzer;
/** both for 'heptagon' 3D cells and subdivided 3D cells */
struct subcellshape {
/** \brief raw coordinates of vertices of all faces */
@ -131,6 +143,10 @@ struct subcellshape {
void compute_common();
};
enum class ePipeEnd {sharp, ball};
struct embedding_method;
/** basic geometry parameters */
struct geometry_information {
@ -158,6 +174,9 @@ struct geometry_information {
/** distance from heptagon center to heptagon vertex (either hexf or hcrossf) */
ld rhexf;
/** edge length */
ld edgelen;
/** basic parameters for 3D geometries */
map<int, int> close_distances;
@ -175,7 +194,6 @@ struct geometry_information {
vector<transmatrix> ultra_mirrors;
vector<pair<string, string> > rels;
int xp_order, r_order, rx_order;
transmatrix full_X, full_R, full_P;
@ -184,6 +202,8 @@ struct geometry_information {
vector<transmatrix> heptmove, hexmove, invhexmove;
int base_distlimit;
unique_ptr<embedding_method> emb;
/** size of the Sword (from Orb of the Sword), used in the shmup mode */
ld sword_size;
@ -216,7 +236,7 @@ struct geometry_information {
BODY, BODY1, BODY2, BODY3,
NECK1, NECK, NECK3, HEAD, HEAD1, HEAD2, HEAD3,
ALEG0, ALEG, ABODY, AHEAD, BIRD, LOWSKY, SKY, HIGH, HIGH2,
SHALLOW;
HELL, STAR, SHALLOW;
ld human_height, slev;
ld eyelevel_familiar, eyelevel_human, eyelevel_dog;
@ -239,16 +259,17 @@ hpcshape
shTriheptaSpecial[14],
shCross, shGiantStar[2], shLake, shMirror,
shHalfFloor[6], shHalfMirror[3],
shGem[2], shStar, shDisk, shDiskT, shDiskS, shDiskM, shDiskSq, shRing,
shGem[2], shStar, shFlash, shDisk, shHalfDisk, shDiskT, shDiskS, shDiskM, shDiskSq, shEccentricDisk, shDiskSegment,
shHeptagon, shHeptagram,
shTinyBird, shTinyShark,
shEgg,
shSpikedRing, shTargetRing, shSawRing, shGearRing, shPeaceRing, shHeptaRing,
shSpearRing, shLoveRing,
shFrogRing,
shPowerGearRing, shProtectiveRing, shTerraRing, shMoveRing, shReserved4, shMoonDisk,
shDaisy, shTriangle, shNecro, shStatue, shKey, shWindArrow,
shEgg, shSmallEgg,
shRing, shSpikedRing, shTargetRing, shSawRing, shGearRing, shPeaceRing,
shHeptaRing, shSpearRing, shLoveRing, shFrogRing,
shPowerGearRing, shProtectiveRing, shTerraRing, shMoveRing,
shReserved4, shMoonDisk,
shDaisy, shSnowflake, shTriangle, shNecro, shStatue, shKey, shWindArrow,
shGun,
shFigurine, shTreat,
shFigurine, shTreat, shSmallTreat,
shElementalShard,
// shBranch,
shIBranch, shTentacle, shTentacleX, shILeaf[3],
@ -262,43 +283,43 @@ hpcshape
shWolf1, shWolf2, shWolf3,
shRatEye1, shRatEye2, shRatEye3,
shDogStripes,
shPBody, shPSword, shPKnife,
shPBody, shSmallPBody, shPSword, shSmallPSword, shPKnife,
shFerocityM, shFerocityF,
shHumanFoot, shHumanLeg, shHumanGroin, shHumanNeck, shSkeletalFoot, shYetiFoot,
shMagicSword, shMagicShovel, shSeaTentacle, shKrakenHead, shKrakenEye, shKrakenEye2,
shMagicSword, shSmallSword, shMagicShovel, shSeaTentacle, shKrakenHead, shKrakenEye, shKrakenEye2,
shArrow,
shPHead, shPFace, shGolemhead, shHood, shArmor,
shAztecHead, shAztecCap,
shSabre, shTurban1, shTurban2, shVikingHelmet, shRaiderHelmet, shRaiderArmor, shRaiderBody, shRaiderShirt,
shWestHat1, shWestHat2, shGunInHand,
shKnightArmor, shKnightCloak, shWightCloak,
shGhost, shEyes, shSlime, shJelly, shJoint, shWormHead, shTentHead, shShark, shWormSegment, shSmallWormSegment, shWormTail, shSmallWormTail,
shSlimeEyes, shDragonEyes, shWormEyes, shGhostEyes,
shMiniGhost, shMiniEyes,
shHedgehogBlade, shHedgehogBladePlayer,
shGhost, shEyes, shSlime, shJelly, shJoint, shWormHead, shSmallWormHead, shTentHead, shShark, shWormSegment, shSmallWormSegment, shWormTail, shSmallWormTail,
shSlimeEyes, shDragonEyes, shSmallDragonEyes, shWormEyes, shSmallWormEyes, shGhostEyes,
shMiniGhost, shSmallEyes, shMiniEyes,
shHedgehogBlade, shSmallHedgehogBlade, shHedgehogBladePlayer,
shWolfBody, shWolfHead, shWolfLegs, shWolfEyes,
shWolfFrontLeg, shWolfRearLeg, shWolfFrontPaw, shWolfRearPaw,
shFemaleBody, shFemaleHair, shFemaleDress, shWitchDress,
shWitchHair, shBeautyHair, shFlowerHair, shFlowerHand, shSuspenders, shTrophy,
shBugBody, shBugArmor, shBugLeg, shBugAntenna,
shPickAxe, shPike, shFlailBall, shFlailTrunk, shFlailChain, shHammerHead,
shPickAxe, shSmallPickAxe, shPike, shFlailBall, shSmallFlailBall, shFlailTrunk, shSmallFlailTrunk, shFlailChain, shHammerHead, shSmallHammerHead,
shBook, shBookCover, shGrail,
shBoatOuter, shBoatInner, shCompass1, shCompass2, shCompass3,
shKnife, shTongue, shFlailMissile, shTrapArrow,
shPirateHook, shPirateHood, shEyepatch, shPirateX,
shPirateHook, shSmallPirateHook, shPirateHood, shEyepatch, shPirateX,
// shScratch,
shHeptaMarker, shSnowball, shHugeDisk, shSun, shNightStar, shEuclideanSky,
shHeptaMarker, shSnowball, shHugeDisk, shSkyboxSun, shSun, shNightStar, shEuclideanSky,
shSkeletonBody, shSkull, shSkullEyes, shFatBody, shWaterElemental,
shPalaceGate, shFishTail,
shMouse, shMouseLegs, shMouseEyes,
shPrincessDress, shPrinceDress,
shWizardCape1, shWizardCape2,
shBigCarpet1, shBigCarpet2, shBigCarpet3,
shGoatHead, shRose, shRoseItem, shThorns,
shGoatHead, shRose, shRoseItem, shSmallRose, shThorns,
shRatHead, shRatTail, shRatEyes, shRatCape1, shRatCape2,
shWizardHat1, shWizardHat2,
shTortoise[13][6],
shDragonLegs, shDragonTail, shDragonHead, shDragonSegment, shDragonNostril,
shDragonLegs, shDragonTail, shDragonHead, shSmallDragonHead, shDragonSegment, shDragonNostril, shSmallDragonNostril,
shDragonWings,
shSolidBranch, shWeakBranch, shBead0, shBead1,
shBatWings, shBatBody, shBatMouth, shBatFang, shBatEye,
@ -311,6 +332,8 @@ hpcshape
shTrylobiteFrontLeg, shTrylobiteRearLeg, shTrylobiteFrontClaw, shTrylobiteRearClaw,
shBullBody, shBullHead, shBullHorn, shBullRearHoof, shBullFrontHoof,
shSmallBullHead, shSmallBullHorn,
shTinyBullHead, shTinyBullHorn, shTinyBullBody,
shButterflyBody, shButterflyWing, shGadflyBody, shGadflyWing, shGadflyEye,
@ -323,9 +346,12 @@ hpcshape
shPBodyOnly, shPBodyArm, shPBodyHand, shPHeadOnly,
shDodeca;
shDodeca, shSmallerDodeca,
shLightningBolt, shHumanoid, shHalfHumanoid, shHourglass,
shShield, shSmallFan, shTreeIcon, shLeafIcon;
hpcshape shFrogRearFoot, shFrogFrontFoot, shFrogRearLeg, shFrogFrontLeg, shFrogRearLeg2, shFrogBody, shFrogEye, shFrogStripe, shFrogJumpFoot, shFrogJumpLeg;
hpcshape shFrogRearFoot, shFrogFrontFoot, shFrogRearLeg, shFrogFrontLeg, shFrogRearLeg2, shFrogBody, shFrogEye, shFrogStripe, shFrogJumpFoot, shFrogJumpLeg, shSmallFrogRearFoot, shSmallFrogFrontFoot, shSmallFrogRearLeg, shSmallFrogFrontLeg, shSmallFrogRearLeg2, shSmallFrogBody;
hpcshape_animated
shAnimatedEagle, shAnimatedTinyEagle, shAnimatedGadfly, shAnimatedHawk, shAnimatedButterfly,
@ -333,6 +359,8 @@ hpcshape
hpcshape shTinyArrow;
hpcshape shCrossbow, shCrossbowBolt, shCrossbowstringLoaded, shCrossbowstringUnloaded, shCrossbowstringSemiloaded, shCrossbowIcon, shCrossbowstringIcon;
hpcshape shReserved[16];
int orb_inner_ring; //< for shDisk* shapes, the number of vertices in the inner ring
@ -366,8 +394,20 @@ hpcshape
ld dlow_table[SIDEPARS], dhi_table[SIDEPARS], dfloor_table[SIDEPARS];
int prehpc;
/** list of points in all shapes */
vector<hyperpoint> hpc;
/** what shape are we currently creating */
hpcshape *last;
/** is the current shape already started? first = not yet */
bool first;
/** starting point of the current shape, can be ultraideal */
hyperpoint starting_point;
/** first ideal point of the current shape */
hyperpoint starting_ideal;
/** last added point of the current shape, can be ultraideal */
hyperpoint last_point;
/** last ideal point of the current shape */
hyperpoint last_ideal;
bool validsidepar[SIDEPARS];
@ -375,9 +415,9 @@ hpcshape
#endif
hpcshape shFullCross[2];
hpcshape *last;
int SD3, SD6, SD7, S12, S14, S21, S28, S42, S36, S84;
ld S_step;
vector<pair<int, cell*>> walloffsets;
@ -408,6 +448,7 @@ hpcshape
void prepare_usershapes();
void hpcpush(hyperpoint h);
void hpc_connect_ideal(hyperpoint a, hyperpoint b);
void hpcsquare(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint h4);
void chasmifyPoly(double fac, double fac2, int k);
void shift(hpcshape& sh, double dx, double dy, double dz);
@ -440,6 +481,7 @@ hpcshape
void generate_floorshapes_for(int id, cell *c, int siid, int sidir);
void generate_floorshapes();
void make_floor_textures_here();
void finish_apeirogon(hyperpoint center);
vector<hyperpoint> get_shape(hpcshape sh);
void add_cone(ld z0, const vector<hyperpoint>& vh, ld z1);
@ -478,32 +520,39 @@ hpcshape
/* Goldberg parameters */
#if CAP_GP
struct gpdata_t {
vector<array<array<array<transmatrix, 6>, 32>, 32>> Tf;
vector<array<array<array<transmatrix, 6>, GOLDBERG_LIMIT>, GOLDBERG_LIMIT>> Tf;
transmatrix corners;
ld alpha;
int area;
int pshid[3][8][32][32][8];
int pshid[3][8][GOLDBERG_LIMIT][GOLDBERG_LIMIT][8];
int nextid;
};
shared_ptr<gpdata_t> gpdata = nullptr;
#endif
shared_ptr<expansion_analyzer> expansion = nullptr;
int state = 0;
int usershape_state = 0;
/** contains the texture point coordinates for 3D models */
basic_textureinfo models_texture;
geometry_information() { last = NULL; }
geometry_information() { last = NULL; use_count = 0; }
void require_basics() { if(state & 1) return; state |= 1; prepare_basics(); }
void require_shapes() { if(state & 2) return; state |= 2; prepare_shapes(); }
void require_usershapes() { if(usershape_state == usershape_changes) return; usershape_state = usershape_changes; prepare_usershapes(); }
int timestamp;
hpcshape& generate_pipe(ld length, ld width);
hpcshape& gen_pipe(hpcshape& pipe, ePipeEnd endtype, ld ratio, const hr::function<hyperpoint(ld,ld,ld)>& f);
hpcshape& get_pipe_iso(ld length, ld width, ePipeEnd endtype = ePipeEnd::sharp);
hpcshape& get_pipe_noniso(hyperpoint target, ld width, ePipeEnd endtype = ePipeEnd::sharp);
map<string, unique_ptr<gi_extension>> ext;
/** prevent from being destroyed */
int use_count;
};
#endif
@ -524,11 +573,9 @@ EX void add_wall(int i, const vector<hyperpoint>& h) {
*/
#if HDR
static const ld hcrossf7 = 0.620672, hexf7 = 0.378077, tessf7 = 1.090550, hexhexdist7 = 0.566256;
static constexpr ld hcrossf7 = 0.620672, hexf7 = 0.378077, tessf7 = 1.090550, hexhexdist7 = 0.566256;
#endif
EX bool scale_used() { return (shmup::on && geometry == gNormal && BITRUNCATED) ? (cheater || autocheat) : true; }
EX bool is_subcube_based(eVariation var) {
return among(var, eVariation::subcubes, eVariation::dual_subcubes, eVariation::bch, eVariation::bch_oct);
}
@ -543,7 +590,7 @@ void geometry_information::prepare_basics() {
hexshift = 0;
ld ALPHA = 2 * M_PI / S7;
ld ALPHA = TAU / S7;
ld fmin, fmax;
@ -551,7 +598,13 @@ void geometry_information::prepare_basics() {
heptshape = nullptr;
if(arcm::in() && !prod)
xp_order = 0;
emb = make_embed();
bool geuclid = euclid;
bool ghyperbolic = hyperbolic;
if(arcm::in() && !mproduct)
ginf[gArchimedean].cclass = gcHyperbolic;
dynamicval<eVariation> gv(variation, variation);
@ -561,9 +614,9 @@ void geometry_information::prepare_basics() {
println(hlog, "bitruncated = ", BITRUNCATED);
}
if(hybri) {
if(mhybrid) {
auto t = this;
ld d = prod ? 1 : 2;
ld d = mproduct ? 1 : 2;
hybrid::in_underlying_geometry([&] {
t->rhexf = cgi.rhexf / d;
t->hexf = cgi.hexf / d;
@ -571,12 +624,14 @@ void geometry_information::prepare_basics() {
t->hcrossf = cgi.crossf / d;
t->tessf = cgi.tessf / d;
t->hexvdist = cgi.hexvdist / d;
t->hexhexdist = hdist(xpush0(cgi.hcrossf), xspinpush0(M_PI*2/S7, cgi.hcrossf)) / d;
t->hexhexdist = hdist(xpush0(cgi.hcrossf), xspinpush0(TAU/S7, cgi.hcrossf)) / d;
t->base_distlimit = cgi.base_distlimit-1;
});
goto hybrid_finish;
}
if(embedded_plane) geom3::light_flip(true);
if((sphere || hyperbolic) && WDIM == 3 && !bt::in()) {
rhexf = hexf = 0.378077;
crossf = hcrossf = 0.620672;
@ -588,13 +643,13 @@ void geometry_information::prepare_basics() {
s3 = S3;
if(fake::in() && !arcm::in()) s3 = fake::around;
beta = (S3 >= OINF && !fake::in()) ? 0 : 2*M_PI/s3;
beta = (S3 >= OINF && !fake::in()) ? 0 : TAU/s3;
tessf = euclid ? 1 : edge_of_triangle_with_angles(beta, M_PI/S7, M_PI/S7);
if(elliptic && S7 == 4 && !fake::in()) tessf = M_PI/2;
if(elliptic && S7 == 4 && !fake::in()) tessf = 90._deg;
hcrossf = euclid ? tessf / 2 / sin(M_PI/s3) : edge_of_triangle_with_angles(M_PI/2, M_PI/S7, beta/2);
hcrossf = euclid ? tessf / 2 / sin(M_PI/s3) : edge_of_triangle_with_angles(90._deg, M_PI/S7, beta/2);
if(S3 >= OINF) hcrossf = 10;
@ -604,15 +659,15 @@ void geometry_information::prepare_basics() {
for(int p=0; p<100; p++) {
ld f = (fmin+fmax) / 2;
hyperpoint H = xpush0(f);
hyperpoint H1 = spin(2*M_PI/S7) * H;
hyperpoint H1 = spin(TAU/S7) * H;
hyperpoint H2 = xpush0(tessf-f);
ld v1 = intval(H, H1), v2 = intval(H, H2);
if(fake::in() && WDIM == 2) {
hexvdist = hdist(xpush0(f), xspinpush0(ALPHA/2, hcrossf));
v2 = hdist(
spin(M_PI/2/S3) * xpush0(hexvdist),
spin(-M_PI/2/S3) * xpush0(hexvdist)
spin(90._deg/S3) * xpush0(hexvdist),
spin(-90._deg/S3) * xpush0(hexvdist)
);
v1 = hdist(
@ -626,36 +681,27 @@ void geometry_information::prepare_basics() {
hexf = fmin;
rhexf = BITRUNCATED ? hexf : hcrossf;
edgelen = hdist(xpush0(rhexf), xspinpush0(TAU/S7, rhexf));
if(BITRUNCATED && !(S7&1))
hexshift = ALPHA/2 + ALPHA * ((S7-1)/2) + M_PI;
finish:
heptmove.resize(S7);
hexmove.resize(S7);
invhexmove.resize(S7);
for(int d=0; d<S7; d++)
heptmove[d] = spin(-d * ALPHA) * xpush(tessf) * spin(M_PI);
for(int d=0; d<S7; d++)
hexmove[d] = spin(hexshift-d * ALPHA) * xpush(-crossf)* spin(M_PI);
for(int d=0; d<S7; d++) invhexmove[d] = iso_inverse(hexmove[d]);
hexvdist = hdist(xpush0(hexf), xspinpush0(ALPHA/2, hcrossf));
hexhexdist = fake::in() ?
2 * hdist0(mid(xspinpush0(M_PI/S6, hexvdist), xspinpush0(-M_PI/S6, hexvdist)))
: hdist(xpush0(crossf), xspinpush0(M_PI*2/S7, crossf));
: hdist(xpush0(crossf), xspinpush0(TAU/S7, crossf));
DEBB(DF_GEOM | DF_POLY,
(format("S7=%d S6=%d hexf = " LDF" hcross = " LDF" tessf = " LDF" hexshift = " LDF " hexhex = " LDF " hexv = " LDF "\n", S7, S6, hexf, hcrossf, tessf, hexshift,
(hr::format("S7=%d S6=%d hexf = " LDF" hcross = " LDF" tessf = " LDF" hexshift = " LDF " hexhex = " LDF " hexv = " LDF "\n", S7, S6, hexf, hcrossf, tessf, hexshift,
hexhexdist, hexvdist)));
base_distlimit = ginf[geometry].distlimit[!BITRUNCATED];
hybrid_finish:
#if CAP_GP
gp::compute_geometry(inv);
#endif
@ -670,6 +716,7 @@ void geometry_information::prepare_basics() {
crossf = hcrossf7 * ac.scale();
hexvdist = ac.scale() * .5;
rhexf = ac.scale() * .5;
edgelen = ac.edgelength;
}
#endif
#if CAP_BT
@ -677,9 +724,6 @@ void geometry_information::prepare_basics() {
if(geometry == gHoroRec || kite::in() || sol || nil || nih) hexvdist = rhexf = .5, tessf = .5, scalefactor = .5, crossf = hcrossf7/2;
if(bt::in()) scalefactor *= min<ld>(vid.binary_width, 1), crossf *= min<ld>(vid.binary_width, 1);
#endif
#if CAP_BT && MAXMDIM >= 4
if(bt::in()) bt::build_tmatrix();
#endif
#if MAXMDIM >= 4
if(reg3::in()) reg3::generate();
if(euc::in(3)) euc::generate();
@ -692,8 +736,6 @@ void geometry_information::prepare_basics() {
else if(nil) nilv::create_faces();
#endif
hybrid_finish:
scalefactor = crossf / hcrossf7;
orbsize = crossf;
@ -722,25 +764,40 @@ void geometry_information::prepare_basics() {
auto csc = arb::current_or_slided().cscale;
scalefactor = csc;
hcrossf = crossf = orbsize = hcrossf7 * csc;
hexf = rhexf = hexvdist = csc * .5;
hexf = rhexf = hexvdist = csc * arb::current_or_slided().floor_scale;
base_distlimit = arb::current.range;
}
#if MAXMDIM >= 4
if(is_subcube_based(variation)) {
scalefactor /= reg3::subcube_count;
orbsize /= reg3::subcube_count;
}
#endif
if(scale_used()) {
if(meuclid && ghyperbolic) {
scalefactor *= exp(-vid.depth);
}
if(msphere && geuclid) scalefactor *= (1 + vid.depth);
if(msphere && ghyperbolic) scalefactor *= sinh(1 + vid.depth);
if(true) {
scalefactor *= vid.creature_scale;
orbsize *= vid.creature_scale;
}
zhexf = BITRUNCATED ? hexf : crossf* .55;
if(scale_used()) zhexf *= vid.creature_scale;
zhexf *= vid.creature_scale;
if(WDIM == 2 && GDIM == 3) zhexf *= 1.5, orbsize *= 1.2;
floorrad0 = hexvdist* (GDIM == 3 ? 1 : 0.92);
floorrad1 = rhexf * (GDIM == 3 ? 1 : 0.94);
if(cgi.emb->is_euc_in_hyp()) {
zhexf *= exp(-vid.depth);
orbsize *= exp(-vid.depth);
}
floorrad0 = hexvdist* (GDIM == 3 ? 1 : 1 - 0.08 * global_boundary_ratio);
floorrad1 = rhexf * (GDIM == 3 ? 1 : 1 - 0.06 * global_boundary_ratio);
if(euc::in(2,4)) {
if(!BITRUNCATED)
@ -752,7 +809,7 @@ void geometry_information::prepare_basics() {
plevel = vid.plevel_factor * scalefactor;
single_step = 1;
if(hybri && !prod) {
if(mhybrid && !mproduct) {
#if CAP_ARCM
if(hybrid::underlying == gArchimedean)
arcm::current.get_step_values(psl_steps, single_step);
@ -770,17 +827,32 @@ void geometry_information::prepare_basics() {
plevel = M_PI * single_step / psl_steps;
}
if(hybri) {
/* we do not want too short creatures, better make the scale factor smaller */
scalefactor = min(scalefactor, cgi.plevel * 1.8 / vid.height_width);
}
set_sibling_limit();
geom3::light_flip(false);
#if CAP_BT && MAXMDIM >= 4
if(bt::in()) bt::build_tmatrix();
#endif
prepare_compute3();
if(hyperbolic && &currfp != &fieldpattern::fp_invalid)
currfp.analyze();
heptmove.resize(S7);
hexmove.resize(S7);
invhexmove.resize(S7);
for(int d=0; d<S7; d++)
heptmove[d] = spin(-d * ALPHA) * lxpush(tessf) * spin(M_PI);
for(int d=0; d<S7; d++)
hexmove[d] = spin(hexshift-d * ALPHA) * lxpush(-crossf)* spin(M_PI);
for(int d=0; d<S7; d++) invhexmove[d] = iso_inverse(hexmove[d]);
gp::prepare_matrices(inv);
#if CAP_SOLV
if(asonov::in()) {
asonov::prepare();
@ -789,13 +861,6 @@ void geometry_information::prepare_basics() {
#endif
}
EX transmatrix xspinpush(ld dir, ld dist) {
if(euclid)
return eupush(cos(dir) * dist, -sin(dir) * dist);
else
return spin(dir) * xpush(dist) * spin(-dir);
}
EX purehookset hooks_swapdim;
EX namespace geom3 {
@ -831,16 +896,21 @@ EX namespace geom3 {
}
EX ld lev_to_factor(ld lev) {
if(prod) return -lev;
if(mproduct) return -lev;
if(WDIM == 3) return lev;
if(GDIM == 3) return vid.depth - lev;
return projection_to_factor(lev_to_projection(lev));
}
EX ld factor_to_lev(ld fac) {
if(prod) return -fac;
if(GDIM == 3) return fac;
if(mproduct) return -fac;
if(WDIM == 3) return fac;
if(GDIM == 3) return vid.depth - fac;
return vid.depth - projection_to_abslev(factor_to_projection(fac));
}
EX ld to_wh(ld val) {
return factor_to_lev(val / actual_wall_height());
}
EX void do_auto_eye() {
if(!vid.auto_eye) return;
@ -860,9 +930,10 @@ EX namespace geom3 {
}
EX string invalid;
EX bool changing_embedded_settings;
EX ld actual_wall_height() {
if(hybri) return cgi.plevel;
if(mhybrid) return cgi.plevel;
#if CAP_GP
if(GOLDBERG && vid.gp_autoscale_heights)
return vid.wall_height * min<ld>(4 / hypot_d(2, gp::next), 1);
@ -877,7 +948,7 @@ EX namespace geom3 {
// tanh(depth) / tanh(camera) == pconf.alpha
invalid = "";
if(GDIM == 3) ;
if(GDIM == 3 || flipped || changing_embedded_settings);
else if(vid.tc_alpha < vid.tc_depth && vid.tc_alpha < vid.tc_camera)
pconf.alpha = tan_auto(vid.depth) / tan_auto(vid.camera);
else if(vid.tc_depth < vid.tc_alpha && vid.tc_depth < vid.tc_camera) {
@ -925,16 +996,18 @@ EX namespace geom3 {
ABODY = 1.08;
AHEAD = 1.12;
BIRD = 1.20;
SHALLOW = .95;
STUFF = 1;
LOWSKY = SKY = HIGH = HIGH2 = STAR = 1;
}
else {
INFDEEP = GDIM == 3 ? (sphere ? M_PI/2 : +5) : (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(vid.camera);
ld wh = actual_wall_height();
WALL = lev_to_factor(wh);
FLOOR = lev_to_factor(0);
human_height = vid.human_wall_ratio * wh;
if(WDIM == 3) human_height = scalefactor * vid.height_width / 2;
if(hybri) human_height = min(human_height, cgi.plevel * .9);
if(mhybrid) human_height = min(human_height, cgi.plevel * .9);
ld reduce = (WDIM == 3 ? human_height / 2 : 0);
@ -958,7 +1031,10 @@ EX namespace geom3 {
reduce = (GDIM == 3 ? human_height * .3 : 0);
STUFF = lev_to_factor(0) - max(orbsize * 0.3, zhexf * .6);
int sgn = vid.wall_height > 0 ? 1 : -1;
ld ees = cgi.emb->is_euc_in_noniso() ? geom3::euclid_embed_scale_mean() : 1;
STUFF = lev_to_factor(0) - sgn * max(orbsize * ees * 0.3, zhexf * ees * .6);
ABODY = lev_to_factor(human_height * .4 - reduce);
ALEG0 = lev_to_factor(human_height * .0 - reduce);
@ -971,55 +1047,78 @@ EX namespace geom3 {
slev = vid.rock_wall_ratio * wh / 3;
for(int s=0; s<=3; s++)
SLEV[s] = lev_to_factor(vid.rock_wall_ratio * wh * s/3);
LAKE = lev_to_factor(-vid.lake_top);
SHALLOW = lev_to_factor(-.4);
HELLSPIKE = lev_to_factor(-(vid.lake_top+vid.lake_bottom)/2);
BOTTOM = lev_to_factor(-vid.lake_bottom);
LOWSKY = lev_to_factor(2 * wh);
HIGH = LOWSKY;
HIGH2 = lev_to_factor(3 * wh);
SKY = LOWSKY - 5;
LAKE = lev_to_factor(wh * -vid.lake_top);
SHALLOW = lev_to_factor(wh * -vid.lake_shallow);
HELLSPIKE = lev_to_factor(wh * -(vid.lake_top+vid.lake_bottom)/2);
BOTTOM = lev_to_factor(wh * -vid.lake_bottom);
LOWSKY = lev_to_factor(vid.lowsky_height * wh);
HIGH = lev_to_factor(vid.wall_height2 * wh);
HIGH2 = lev_to_factor(vid.wall_height3 * wh);
SKY = vid.sky_height == use_the_default_value ? cgi.emb->height_limit(-sgn) : lev_to_factor(vid.sky_height * wh);
STAR = vid.star_height == use_the_default_value ? lerp(FLOOR, SKY, 0.95) : lev_to_factor(vid.star_height * wh);
HELL = -SKY;
if(embedded_plane)
INFDEEP = vid.infdeep_height == use_the_default_value ? cgi.emb->height_limit(sgn) : lev_to_factor(vid.infdeep_height * wh);
else
INFDEEP = (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(vid.camera);
/* in spherical/cylindrical case, make sure that the high stuff does not go through the center */
if(vid.height_limits) {
auto hp = cgi.emb->height_limit(1);
auto hn = cgi.emb->height_limit(-1);
auto adjust = [&] (ld& val, ld& guide, ld lerpval) {
if(val > hp)
val = lerp(guide, hp, lerpval);
else if(val < hn)
val = lerp(guide, hn, lerpval);
};
adjust(HIGH, FLOOR, 0.8);
adjust(HIGH2, HIGH, 0.5);
adjust(SKY, FLOOR, 1);
adjust(STAR, FLOOR, 0.9);
adjust(LAKE, FLOOR, 0.8);
adjust(SHALLOW, LAKE, 0.9);
adjust(BOTTOM, SHALLOW, 0.5);
adjust(INFDEEP, FLOOR, 1);
}
}
}
EX namespace geom3 {
EX void apply_always3() {
for(geometryinfo& gi: ginf) {
auto &g = gi.g;
if(vid.always3 && g.gameplay_dimension == 2 && g.graphical_dimension == 2) {
g.graphical_dimension++;
g.homogeneous_dimension++;
g.sig[3] = g.sig[2];
g.sig[2] = g.sig[1];
}
if(!vid.always3 && g.gameplay_dimension == 2 && g.graphical_dimension == 3) {
g.graphical_dimension--;
g.homogeneous_dimension--;
g.sig[1] = g.sig[2];
g.sig[2] = g.sig[3];
}
}
/** direction of swapping: +1 => from 2D to 3D; -1 => from 3D to 2D; 0 => make everything right */
EX int swap_direction;
EX void swapdim(int dir) {
swap_direction = dir;
decide_lpu();
swapmatrix_view(NLP, View);
swapmatrix_view(NLP, current_display->which_copy);
callhooks(hooks_swapdim);
for(auto m: allmaps) m->on_dim_change();
}
#if MAXMDIM >= 4
EX void switch_always3() {
EX void switch_always3() {
if(dual::split(switch_always3)) return;
#if CAP_GL && CAP_RUG
if(rug::rugged) rug::close();
#endif
if(vid.always3) swapdim(-1);
vid.always3 = !vid.always3;
apply_always3();
swapmatrix(View);
callhooks(hooks_swapdim);
check_cgi(); cgi.require_basics();
if(vid.always3) swapdim(+1);
}
#endif
#endif
EX void switch_tpp() {
if(dual::split(switch_fpp)) return;
if(pmodel == mdDisk && pconf.camera_angle) {
if(rug::rugged) rug::close();
if(pmodel == mdDisk && !models::camera_straight) {
vid.yshift = 0;
pconf.camera_angle = 0;
pconf.cam() = Id;
pconf.xposition = 0;
pconf.yposition = 0;
pconf.scale = 1;
@ -1027,7 +1126,7 @@ EX void switch_always3() {
}
else {
vid.yshift = -0.3;
pconf.camera_angle = -45;
pconf.cam() = cspin(1, 2, -45._deg);
pconf.scale = 18/16. * vid.xres / vid.yres / multi::players;
pconf.xposition = 0;
pconf.yposition = -0.9;
@ -1035,58 +1134,73 @@ EX void switch_always3() {
vid.fixed_facing_dir = 90;
}
}
EX void switch_fpp() {
#if MAXMDIM >= 4
#if CAP_GL && CAP_RUG
if(rug::rugged) rug::close();
#endif
if(dual::split(switch_fpp)) return;
check_cgi(); cgi.require_basics();
View = iso_inverse(models::rotmatrix()) * View;
check_cgi();
cgi.require_basics();
if(!changing_embedded_settings)
View = inverse(models::rotmatrix()) * View;
if(!vid.always3) {
vid.always3 = true;
apply_always3();
ld ms = min<ld>(cgi.scalefactor, 1);
vid.wall_height = 1.5 * ms;
if(sphere) {
vid.depth = M_PI / 6;
vid.wall_height = M_PI / 3;
}
vid.human_wall_ratio = 0.8;
if(euclid && allowIncreasedSight() && vid.use_smart_range == 0) {
genrange_bonus = gamerange_bonus = sightrange_bonus = cgi.base_distlimit * 3/2;
}
vid.camera = 0;
vid.depth = ms;
if(pmodel == mdDisk) pmodel = mdPerspective;
swapmatrix(View);
swapmatrix(current_display->which_copy);
callhooks(hooks_swapdim);
for(auto m: allmaps) m->on_dim_change();
if(cgflags & qIDEAL && vid.texture_step < 32)
vid.texture_step = 32;
#if CAP_RACING
racing::player_relative = true;
#endif
auto emb = make_embed();
emb->auto_configure();
check_cgi();
cgi.require_basics();
swapdim(+1);
}
else {
swapdim(-1);
vid.always3 = false;
apply_always3();
vid.wall_height = .3;
vid.human_wall_ratio = .7;
vid.camera = 1;
vid.depth = 1;
if(pmodel == mdPerspective) pmodel = mdDisk;
swapmatrix(View);
swapmatrix(current_display->which_copy);
callhooks(hooks_swapdim);
for(auto m: allmaps) m->on_dim_change();
if(!changing_embedded_settings) {
vid.wall_height = .3;
vid.human_wall_ratio = .7;
vid.camera = 1;
vid.depth = 1;
}
if(among(pmodel, mdPerspective, mdGeodesic)) pmodel = mdDisk;
swapdim(0);
}
View = models::rotmatrix() * View;
if(!changing_embedded_settings)
View = models::rotmatrix() * View;
#endif
}
EX void apply_settings_full() {
if(cgip && vid.always3) {
changing_embedded_settings = true;
geom3::switch_fpp();
#if MAXMDIM >= 4
delete_sky();
#endif
// not sure why this is needed...
resetGL();
geom3::switch_fpp();
changing_embedded_settings = false;
}
}
EX void apply_settings_light() {
#if MAXMDIM >= 4
if(cgip && vid.always3) {
changing_embedded_settings = true;
geom3::switch_always3();
geom3::switch_always3();
changing_embedded_settings = false;
}
#endif
}
EX }
EX geometry_information *cgip;
@ -1108,9 +1222,11 @@ EX string cgi_string() {
V("GEO", its(int(geometry)));
V("VAR", its(int(variation)));
if(arb::in() && arb::using_slided) {
if(arb::in()) {
for(auto& sl: arb::current.sliders)
V("AS", fts(sl.current));
for(auto& sl: arb::current.intsliders)
V("AS", its(sl.current));
}
if(fake::in()) {
@ -1123,30 +1239,39 @@ EX string cgi_string() {
if(GOLDBERG_INV) V("GP", its(gp::param.first) + "," + its(gp::param.second));
if(IRREGULAR) V("IRR", its(irr::irrid));
#if MAXMDIM >= 4
if(is_subcube_based(variation)) V("SC", its(reg3::subcube_count));
if(variation == eVariation::coxeter) V("COX", its(reg3::coxeter_param));
#endif
#if CAP_ARCM
if(arcm::in()) V("ARCM", arcm::current.symbol);
#endif
if(arb::in()) V("ARB", its(arb::current.order));
if(arb::in()) V("AP", its(arb::apeirogon_simplified_display));
if(arb::in()) V("F", its(arb::extended_football));
V("BR", fts(global_boundary_ratio));
if(cryst) V("CRYSTAL", its(ginf[gCrystal].sides) + its(ginf[gCrystal].vertex));
if(bt::in() || GDIM == 3) V("WQ", its(vid.texture_step));
if(hybri) {
if(mhybrid) {
V("U", PIU(cgi_string()));
// its(int(hybrid::underlying)));
}
if(prod) V("PL", fts(vid.plevel_factor));
if(mproduct) V("PL", fts(vid.plevel_factor));
if(geometry == gFieldQuotient) { V("S3=", its(S3)); V("S7=", its(S7)); }
if(nil) V("NIL", its(S7));
if(bt::in()) V("BT", fts(vid.binary_width));
if(hat::in()) V("H", fts(hat::hat_param));
if(hat::in() && hat::hat_param_imag) V("HI", fts(hat::hat_param_imag));
if(nil) V("NILW", fts(nilv::nilwidth));
@ -1162,11 +1287,32 @@ EX string cgi_string() {
V("ASH", ONOFF(vid.gp_autoscale_heights));
V("LT", fts(vid.lake_top));
V("LB", fts(vid.lake_bottom));
if(GDIM == 3 && vid.pseudohedral) {
V("PSH", fts(vid.pseudohedral));
V("PSD", fts(vid.depth_bonus));
}
V("LS", fts(vid.lake_shallow));
V("SSu", fts(vid.sun_size));
V("SSt", fts(vid.star_size));
V("WH2", fts(vid.wall_height2));
V("WH3", fts(vid.wall_height3));
V("WHL", fts(vid.lowsky_height));
if(vid.sky_height != use_the_default_value) V("SHe", fts(vid.sky_height));
if(vid.star_height != use_the_default_value) V("StH", fts(vid.star_height));
if(vid.infdeep_height != use_the_default_value) V("ID", fts(vid.infdeep_height));
}
V("3D", ONOFF(vid.always3));
if(scale_used()) V("CS", fts(vid.creature_scale));
if(embedded_plane) V("X:", its(geom3::ggclass()));
if(embedded_plane && meuclid) {
V("XS:", fts(geom3::euclid_embed_scale));
V("YS:", fts(geom3::euclid_embed_scale_y));
V("RS:", fts(geom3::euclid_embed_rotate));
}
if(vid.creature_scale != 1) V("CS", fts(vid.creature_scale));
if(WDIM == 3) V("HTW", fts(vid.height_width));
@ -1177,17 +1323,29 @@ EX string cgi_string() {
return s;
}
#if CAP_PORTALS
#define IFINTRA(x,y) x
#else
#define IFINTRA(x,y) y
#endif
EX void check_cgi() {
string s = cgi_string();
cgip = &cgis[s];
cgi.timestamp = ++ntimestamp;
if(hybri) hybrid::underlying_cgip->timestamp = ntimestamp;
if(mhybrid) hybrid::underlying_cgip->timestamp = ntimestamp;
if(fake::in()) fake::underlying_cgip->timestamp = ntimestamp;
#if CAP_ARCM
if(arcm::alt_cgip[0]) arcm::alt_cgip[0]->timestamp = ntimestamp;
if(arcm::alt_cgip[1]) arcm::alt_cgip[1]->timestamp = ntimestamp;
#endif
if(isize(cgis) > 4) {
int limit = 4;
for(auto& t: cgis) if(t.second.use_count) limit++;
if(isize(cgis) > limit) {
vector<pair<int, string>> timestamps;
for(auto& t: cgis) timestamps.emplace_back(-t.second.timestamp, t.first);
for(auto& t: cgis) if(!t.second.use_count) timestamps.emplace_back(-t.second.timestamp, t.first);
sort(timestamps.begin(), timestamps.end());
while(isize(timestamps) > 4) {
DEBB(DF_GEOM, ("erasing geometry ", timestamps.back().second));

View File

@ -42,7 +42,7 @@ EX transmatrix relative_matrix_recursive(heptagon *h2, heptagon *h1) {
}
else {
for(int i=0; i<h2->type; i++) if(h2->move(i) && h2->move(i)->distance < h2->distance) {
where = currentmap->iadj(h2, 0) * where;
where = currentmap->iadj(h2, i) * where;
h2 = h2->move(i);
goto again;
}
@ -57,7 +57,7 @@ transmatrix hrmap_standard::master_relative(cell *c, bool get_inverse) {
#if CAP_IRR
else if(IRREGULAR) {
int id = irr::cellindex[c];
ld alpha = 2 * M_PI / S7 * irr::periodmap[c->master].base.spin;
ld alpha = TAU / S7 * irr::periodmap[c->master].base.spin;
return get_inverse ? irr::cells[id].rpusher * spin(-alpha-master_to_c7_angle()): spin(alpha + master_to_c7_angle()) * irr::cells[id].pusher;
}
#endif
@ -68,7 +68,7 @@ transmatrix hrmap_standard::master_relative(cell *c, bool get_inverse) {
}
else {
auto li = gp::get_local_info(c);
transmatrix T = spin(master_to_c7_angle()) * cgi.gpdata->Tf[li.last_dir][li.relative.first&31][li.relative.second&31][gp::fixg6(li.total_dir)];
transmatrix T = spin(master_to_c7_angle()) * cgi.gpdata->Tf[li.last_dir][li.relative.first&GOLDBERG_MASK][li.relative.second&GOLDBERG_MASK][gp::fixg6(li.total_dir)];
if(get_inverse) T = iso_inverse(T);
return T;
}
@ -81,6 +81,8 @@ transmatrix hrmap_standard::master_relative(cell *c, bool get_inverse) {
}
else if(WDIM == 3)
return Id;
else if(dont_inverse())
return Id;
else
return pispin * Id;
}
@ -100,12 +102,12 @@ transmatrix hrmap_standard::adj(heptagon *h, int d) {
int t0 = h->type;
int t1 = h->cmove(d)->type;
int sp = h->c.spin(d);
return spin(-d * 2 * M_PI / t0) * xpush(spacedist(h->c7, d)) * spin(M_PI + 2*M_PI*sp/t1);
return spin(-d * TAU / t0) * lxpush(spacedist(h->c7, d)) * spin(M_PI + TAU * sp / t1);
}
transmatrix T = cgi.heptmove[d];
if(h->c.mirror(d)) T = T * Mirror;
int sp = h->c.spin(d);
if(sp) T = T * spin(2*M_PI*sp/S7);
if(sp) T = T * spin(TAU*sp/S7);
return T;
}
@ -139,7 +141,7 @@ transmatrix hrmap_standard::relative_matrixh(heptagon *h2, heptagon *h1, const h
steps++; if(steps > 10000) {
println(hlog, "not found"); return Id;
}
if(bounded) {
if(closed_manifold) {
transmatrix T;
ld bestdist = 1e9;
for(int d=0; d<S7; d++) {
@ -235,10 +237,14 @@ void horo_distance::become(hyperpoint h1) {
a = abs(bt::horo_level(h1));
}
#endif
else if(hybri)
else if(mhybrid || sl2)
a = 0, b = hdist(h1, C0);
else if(cgi.emb->is_euc_in_product())
a = 0, b = hdist(h1, C0);
else if(cgi.emb->is_cylinder())
a = 0, b = hdist(h1, tile_center());
else
a = 0, b = intval(h1, C0);
a = 0, b = intval(h1, tile_center());
}
horo_distance::horo_distance(shiftpoint h1, const shiftmatrix& T) {
@ -246,9 +252,13 @@ horo_distance::horo_distance(shiftpoint h1, const shiftmatrix& T) {
if(bt::in()) become(inverse_shift(T, h1));
else
#endif
if(sn::in() || hybri || nil) become(inverse_shift(T, h1));
if(sn::in() || mhybrid || nil || sl2) become(inverse_shift(T, h1));
else if(cgi.emb->is_euc_in_product())
a = 0, b = hdist(h1.h, unshift(T * tile_center(), h1.shift));
else if(cgi.emb->is_cylinder())
a = 0, b = hdist(h1.h, unshift(T * tile_center(), h1.shift));
else
a = 0, b = intval(h1.h, unshift(tC0(T), h1.shift));
a = 0, b = intval(h1.h, unshift(T * tile_center(), h1.shift));
}
bool horo_distance::operator < (const horo_distance z) const {
@ -268,6 +278,7 @@ void virtualRebase_cell(cell*& base, T& at, const U& check) {
while(true) {
cell *newbase = NULL;
forCellIdCM(c2, i, base) {
if(c2 == &out_of_bounds) continue;
transmatrix V2 = currentmap->iadj(base, i);
T cand_at = V2 * at;
horo_distance newz(check(cand_at));
@ -310,10 +321,10 @@ void virtualRebase_cell(cell*& base, T& at, const U& check) {
template<class T, class U>
void virtualRebase(cell*& base, T& at, const U& check) {
if(nil) {
if(nil && WDIM == 3) {
hyperpoint h = check(at);
auto step = [&] (int i) {
at = currentmap->iadj(base, i) * at;
at = currentmap->adj(base, (i+S7/2) % S7) * at;
base = base->cmove(i);
h = check(at);
};
@ -331,7 +342,44 @@ void virtualRebase(cell*& base, T& at, const U& check) {
return;
}
if(prod) {
if(geometry == gSol) {
/** the general algorithm sometimes makes much more iterations than needed... try to approximate the geodesic */
hyperpoint h = check(at);
auto step = [&] (int i) {
at = currentmap->iadj(base, i) * at;
base = base->cmove(i);
h = check(at);
};
auto nw = vid.binary_width * log(2);
while(abs(h[0]) > 2) step(6);
while(h[0] < -0.5 * nw) step(4);
while(h[0] > +0.5 * nw) step(0);
while(abs(h[1]) > 2) {
step(2);
while(h[0] < -0.5 * nw) step(4);
while(h[0] > +0.5 * nw) step(0);
}
while(h[1] < -0.5 * nw) step(5);
while(h[1] > +0.5 * nw) step(1);
while(h[2] > 1) {
step(2);
while(h[0] < -0.5 * nw) step(4);
while(h[0] > +0.5 * nw) step(0);
while(h[1] < -0.5 * nw) step(5);
while(h[1] > +0.5 * nw) step(1);
}
while(h[2] < -1) {
step(6);
while(h[0] < -0.5 * nw) step(4);
while(h[0] > +0.5 * nw) step(0);
while(h[1] < -0.5 * nw) step(5);
while(h[1] > +0.5 * nw) step(1);
}
}
/* todo variants of sol */
if(mproduct) {
auto d = product_decompose(check(at)).first;
while(d > cgi.plevel / 2) {
at = currentmap->iadj(base, base->type-1) * at;
@ -342,9 +390,9 @@ void virtualRebase(cell*& base, T& at, const U& check) {
base = base->cmove(base->type-2); d += cgi.plevel;
}
auto w = hybrid::get_where(base);
at = mscale(at, -d);
at = orthogonal_move(at, -d);
PIU( virtualRebase(w.first, at, check) );
at = mscale(at, +d);
at = orthogonal_move(at, +d);
base = hybrid::get_at(w.first, w.second);
return;
}
@ -400,13 +448,17 @@ void hrmap_hyperbolic::virtualRebase(heptagon*& base, transmatrix& at) {
}
EX bool no_easy_spin() {
return NONSTDVAR || arcm::in() || WDIM == 3 || bt::in() || kite::in();
return NONSTDVAR || arcm::in() || WDIM == 3 || bt::in() || aperiodic;
}
EX bool never_invert;
EX bool dont_inverse() { return never_invert || (PURE && cgi.emb->is_euc_in_noniso()); }
ld hrmap_standard::spin_angle(cell *c, int d) {
if(WDIM == 3) return SPIN_NOT_AVAILABLE;
ld hexshift = 0;
if(c == c->master->c7 && (S7 % 2 == 0) && BITRUNCATED) hexshift = cgi.hexshift + 2*M_PI/c->type;
if(c == c->master->c7 && (S7 % 2 == 0) && BITRUNCATED) hexshift = cgi.hexshift + TAU/c->type;
else if(cgi.hexshift && c == c->master->c7) hexshift = cgi.hexshift;
#if CAP_IRR
if(IRREGULAR) {
@ -417,7 +469,8 @@ ld hrmap_standard::spin_angle(cell *c, int d) {
return -atan2(p[1], p[0]) - hexshift;
}
#endif
return M_PI - d * 2 * M_PI / c->type - hexshift;
if(dont_inverse()) return - d * TAU / c->type;
return M_PI - d * TAU / c->type - hexshift;
}
EX transmatrix ddspin(cell *c, int d, ld bonus IS(0)) { return currentmap->spin_to(c, d, bonus); }
@ -425,7 +478,10 @@ EX transmatrix iddspin(cell *c, int d, ld bonus IS(0)) { return currentmap->spin
EX ld cellgfxdist(cell *c, int d) { return currentmap->spacedist(c, d); }
EX transmatrix ddspin_side(cell *c, int d, ld bonus IS(0)) {
if(kite::in()) {
if(cgi.emb->is_in_noniso())
return spin(bonus);
if(aperiodic) {
if(embedded_plane) return spin(bonus);
hyperpoint h1 = get_corner_position(c, gmod(d, c->type), 3);
hyperpoint h2 = get_corner_position(c, gmod(d+1, c->type) , 3);
hyperpoint hm = mid(h1, h2);
@ -435,7 +491,10 @@ EX transmatrix ddspin_side(cell *c, int d, ld bonus IS(0)) {
}
EX transmatrix iddspin_side(cell *c, int d, ld bonus IS(0)) {
if(kite::in()) {
if(cgi.emb->is_in_noniso())
return spin(bonus);
if(aperiodic) {
if(embedded_plane) return spin(bonus);
hyperpoint h1 = get_corner_position(c, gmod(d, c->type), 3);
hyperpoint h2 = get_corner_position(c, gmod(d+1, c->type) , 3);
hyperpoint hm = mid(h1, h2);
@ -493,7 +552,7 @@ transmatrix hrmap_standard::adj(cell *c, int i) {
return calc_relative_matrix(c->cmove(i), c, C0);
}
double d = cellgfxdist(c, i);
transmatrix T = ddspin(c, i) * xpush(d);
transmatrix T = ddspin(c, i) * lxpush(d);
if(c->c.mirror(i)) T = T * Mirror;
cell *c1 = c->cmove(i);
T = T * iddspin(c1, c->c.spin(i), M_PI);
@ -503,17 +562,17 @@ transmatrix hrmap_standard::adj(cell *c, int i) {
EX double randd() { return (rand() + .5) / (RAND_MAX + 1.); }
EX hyperpoint randomPointIn(int t) {
if(NONSTDVAR || arcm::in() || kite::in()) {
if(NONSTDVAR || arcm::in() || aperiodic) {
// Let these geometries be less confusing.
// Also easier to implement ;)
return xspinpush0(2 * M_PI * randd(), asinh(randd() / 20));
return xspinpush0(TAU * randd(), asinh(randd() / 20));
}
while(true) {
hyperpoint h = xspinpush0(2*M_PI*(randd()-.5)/t, asinh(randd()));
hyperpoint h = xspinpush0(TAU * (randd()-.5)/t, asinh(randd()));
double d =
PURE ? cgi.tessf : t == 6 ? cgi.hexhexdist : cgi.crossf;
if(hdist0(h) < hdist0(xpush(-d) * h))
return spin(2*M_PI/t * (rand() % t)) * h;
return spin(TAU / t * (rand() % t)) * h;
}
}
@ -537,15 +596,18 @@ hyperpoint hrmap_standard::get_corner(cell *c, int cid, ld cf) {
}
#endif
if(PURE) {
return ddspin(c,cid,M_PI/S7) * xpush0(cgi.hcrossf * 3 / cf);
if(cgi.emb->is_euc_in_noniso()) {
return lspinpush0(spin_angle(c, cid) + M_PI/S7, cgi.hcrossf * 3 / cf);
}
return ddspin(c,cid,M_PI/S7) * lxpush0(cgi.hcrossf * 3 / cf);
}
if(BITRUNCATED) {
if(!ishept(c))
return ddspin(c,cid,M_PI/S6) * xpush0(cgi.hexvdist * 3 / cf);
return ddspin(c,cid,M_PI/S6) * lxpush0(cgi.hexvdist * 3 / cf);
else
return ddspin(c,cid,M_PI/S7) * xpush0(cgi.rhexf * 3 / cf);
return ddspin(c,cid,M_PI/S7) * lxpush0(cgi.rhexf * 3 / cf);
}
return C0;
return tile_center();
}
EX bool approx_nearcorner = false;
@ -575,7 +637,7 @@ EX hyperpoint nearcorner(cell *c, int i) {
auto& t = ac.get_triangle(c->master, i-1);
int id = arcm::id_of(c->master);
int id1 = ac.get_adj(ac.get_adj(c->master, i-1), -2).first;
return xspinpush0(-t.first - M_PI / c->type, ac.inradius[id/2] + ac.inradius[id1/2] + (ac.real_faces == 0 ? 2 * M_PI / (ac.N == 2 ? 2.1 : ac.N) : 0));
return xspinpush0(-t.first - M_PI / c->type, ac.inradius[id/2] + ac.inradius[id1/2] + (ac.real_faces == 0 ? TAU / (ac.N == 2 ? 2.1 : ac.N) : 0));
}
if(BITRUNCATED) {
auto &ac = arcm::current;
@ -594,10 +656,10 @@ EX hyperpoint nearcorner(cell *c, int i) {
ld yx = log(2) / 2;
ld yy = yx;
hyperpoint neis[5];
neis[0] = bt::get_horopoint(2*yy, -0.5);
neis[1] = bt::get_horopoint(2*yy, +0.5);
neis[0] = bt::get_horopoint(2*yy, -0.25);
neis[1] = bt::get_horopoint(2*yy, +0.25);
neis[2] = bt::get_horopoint(0, 1);
neis[3] = bt::get_horopoint(-2*yy, c->master->zebraval ? -0.25 : +0.25);
neis[3] = bt::get_horopoint(-2*yy, c->master->zebraval ? -0.5 : +0.5);
neis[4] = bt::get_horopoint(0, -1);
return neis[i];
}
@ -605,15 +667,15 @@ EX hyperpoint nearcorner(cell *c, int i) {
ld yx = log(3) / 2;
ld yy = yx;
hyperpoint neis[6];
neis[0] = bt::get_horopoint(2*yy, -1);
neis[0] = bt::get_horopoint(2*yy, -1/3.);
neis[1] = bt::get_horopoint(2*yy, +0);
neis[2] = bt::get_horopoint(2*yy, +1);
neis[2] = bt::get_horopoint(2*yy, +1/3.);
neis[3] = bt::get_horopoint(0, 1);
neis[4] = bt::get_horopoint(-2*yy, c->master->zebraval / 3.);
neis[4] = bt::get_horopoint(-2*yy, c->master->zebraval);
neis[5] = bt::get_horopoint(0, -1);
return neis[i];
}
if(kite::in()) {
if(aperiodic) {
if(approx_nearcorner)
return currentmap->get_corner(c, i, 3) + currentmap->get_corner(c, i+1, 3) - C0;
else
@ -629,20 +691,20 @@ EX hyperpoint nearcorner(cell *c, int i) {
// ld xx = 1 / sqrt(2)/2;
hyperpoint neis[7];
neis[0] = bt::get_horopoint(0, 1);
neis[1] = bt::get_horopoint(yy*2, 1);
neis[1] = bt::get_horopoint(yy*2, 0.5);
neis[2] = bt::get_horopoint(yy*2, 0);
neis[3] = bt::get_horopoint(yy*2, -1);
neis[3] = bt::get_horopoint(yy*2, -0.5);
neis[4] = bt::get_horopoint(0, -1);
if(c->type == 7)
neis[5] = bt::get_horopoint(-yy*2, -.5),
neis[6] = bt::get_horopoint(-yy*2, +.5);
neis[5] = bt::get_horopoint(-yy*2, -1),
neis[6] = bt::get_horopoint(-yy*2, +1);
else
neis[5] = bt::get_horopoint(-yy*2, 0);
return neis[i];
}
#endif
double d = cellgfxdist(c, i);
return ddspin(c, i) * xpush0(d);
return ddspin(c, i) * lxpush0(d);
}
/** /brief get the coordinates of the another vertex of c->move(i)
@ -680,7 +742,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) {
}
#endif
#if CAP_BT
if(bt::in() || kite::in())
if(bt::in() || aperiodic)
return nearcorner(c, (i+which) % c->type); // lazy
#endif
#if CAP_ARCM
@ -691,7 +753,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) {
int id = arcm::id_of(c->master);
auto id1 = ac.get_adj(ac.get_adj(c->master, i-1), -2).first;
int n1 = isize(ac.adjacent[id1]);
return spin(-t.first - M_PI / c->type) * xpush(ac.inradius[id/2] + ac.inradius[id1/2]) * xspinpush0(M_PI + M_PI/n1*(which?3:-3), ac.circumradius[id1/2]);
return spin(-t.first - M_PI / c->type) * lxpush(ac.inradius[id/2] + ac.inradius[id1/2]) * xspinpush0(M_PI + M_PI/n1*(which?3:-3), ac.circumradius[id1/2]);
}
if(BITRUNCATED || DUAL) {
int mul = DUALMUL;
@ -705,7 +767,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) {
auto& t2 = arcm::current.get_triangle(adj);
return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -mul : 2*mul);
return spin(-t1.first) * lxpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -mul : 2*mul);
}
}
#endif
@ -731,7 +793,7 @@ EX hyperpoint get_warp_corner(cell *c, int cid) {
#if CAP_IRR || CAP_ARCM
if(IRREGULAR || arcm::in()) return midcorner(c, cid, .5);
#endif
return ddspin(c,cid,M_PI/S7) * xpush0(cgi.tessf/2);
return ddspin(c,cid,M_PI/S7) * lxpush0(cgi.tessf/2);
}
EX map<cell*, map<cell*, vector<transmatrix>>> brm_structure;
@ -757,13 +819,26 @@ EX void generate_brm(cell *c1) {
q.pop();
ld mindist = HUGE_VAL, maxdist = 0;
for(int i=0; i<c1->type; i++)
for(int j=0; j<c2->type; j++) {
ld d = hdist(get_corner_position(c1, i), T * get_corner_position(c2, j));
if(d < mindist) mindist = d;
if(d > maxdist) maxdist = d;
}
if(WDIM == 2) {
for(int i=0; i<c1->type; i++)
for(int j=0; j<c2->type; j++) {
ld d = hdist(get_corner_position(c1, i), T * get_corner_position(c2, j));
if(d < mindist) mindist = d;
if(d > maxdist) maxdist = d;
}
}
else {
auto& ss1 = currentmap->get_cellshape(c1);
auto& ss2 = currentmap->get_cellshape(c2);
for(auto v: ss1.vertices_only)
for(auto w: ss2.vertices_only) {
ld d = hdist(v, T*w);
if(d < mindist) mindist = d;
if(d > maxdist) maxdist = d;
}
}
auto& cu = cutoff[c2];
if(cu == 0 || cu > maxdist)
cu = maxdist;
@ -795,5 +870,211 @@ int brm_hook = addHook(hooks_clearmemory, 0, []() {
brm_structure.clear();
});
EX bool exhaustive_distance_appropriate() {
if(euclid && (aperiodic || arcm::in() || arb::in() || quotient)) return true;
#if MAXMDIM >= 4
if(nil && quotient) return true;
#endif
#if CAP_SOLV
if(asonov::in() && asonov::period_xy && asonov::period_xy <= 256) return true;
#endif
if(closed_manifold) return true;
return false;
}
#if HDR
struct pathgen {
cellwalker start;
cellwalker last;
vector<cell*> path;
bignum full_id_0;
int last_id;
};
#endif
EX pathgen generate_random_path_randomdir(cellwalker start, int length, bool for_yendor) {
start.spin = hrand(start.at->type);
return generate_random_path(start, length, for_yendor, false);
}
EX pathgen generate_random_path(cellwalker start, int length, bool for_yendor, bool randomdir) {
pathgen p;
p.start = start;
p.path.resize(length+1);
p.path[0] = start.at;
p.last_id = 0;
int turns = 0;
if(exhaustive_distance_appropriate()) {
permanent_long_distances(start.at);
int dist = max_saved_distance(start.at);
dist = min(dist, length);
auto at = random_in_distance(start.at, dist);
permanent_long_distances(at);
for(int a=length-1; a>=0; a--) {
p.path[a+1] = at;
vector<cell*> prev;
forCellCM(c2, at) if(celldistance(start.at, c2) == a) prev.push_back(c2);
if(isize(prev)) at = prev[hrand(isize(prev))];
}
p.path[0] = start.at;
p.last = p.path.back();
}
else if(mhybrid) {
/* I am lazy */
for(int i=1; i<=length; i++) p.path[i] = p.path[i-1]->cmove(p.path[i-1]->type-1);
p.last = p.path.back();
}
else {
int t = -1;
bignum full_id;
bool onlychild = true;
bool launched = false;
cellwalker ycw = start;
if(for_yendor) setdist(p.path[0], 7, NULL);
auto& expansion = get_expansion();
for(int i=0; i<length; i++) {
if(for_yendor && yendor::control(p, i, ycw)) { }
else if(bt::in()) {
// make it challenging
vector<int> ds;
for(int d=0; d<ycw.at->type; d++) {
bool increase;
if(sol)
increase = i < YDIST / 4 || i > 3 * YDIST / 4;
else
increase = i < YDIST/2;
if(increase) {
if(celldistAlt((ycw+d).cpeek()) < celldistAlt(ycw.at))
ds.push_back(d);
}
else {
if(celldistAlt((ycw+d).cpeek()) > celldistAlt(ycw.at) && (ycw+d).cpeek() != p.path[i-1])
ds.push_back(d);
}
}
if(isize(ds)) ycw += ds[hrand(isize(ds))];
}
else if(currentmap->strict_tree_rules()) {
if(for_yendor && i < arb::current.yendor_backsteps) {
println(hlog, i, " < ", arb::current.yendor_backsteps);
ycw.spin = 0;
}
else {
if(!launched) {
t = ycw.at->master->fieldval;
bignum b = expansion.get_descendants(length-i, t);
if(!full_id.approx_int()) goto stupid;
p.full_id_0 = full_id = hrand(b);
/* it may happen that the subtree dies out */
launched = true;
}
ycw.spin = 0;
auto& r = rulegen::treestates[t];
for(int ri=0; ri<isize(r.rules); ri++) {
int tch = r.rules[ri];
if(tch < 0) continue;
auto& sub_id = expansion.get_descendants(length-1-i, tch);
if(full_id < sub_id) {
t = tch; ycw += ri; break;
}
full_id.addmul(sub_id, -1);
}
}
}
else if(trees_known() && WDIM == 2) {
auto sdist = [start] (cell *c) { return celldistance(start.at, c); };
if(i == 0) {
t = type_in(expansion, randomdir ? start.at : start.cpeek(), sdist);
ycw--;
if(valence() == 3) ycw--;
bignum b = get_expansion().get_descendants(randomdir ? length : length-1, t);
p.full_id_0 = full_id = hrand(b);
}
#if DEBUG_YENDORGEN
printf("#%3d t%d %s / %s\n", i, t, full_id.get_str(100).c_str(), expansion.get_descendants(length-i, t).get_str(100).c_str());
for(int tch: expansion.children[t]) {
printf(" t%d %s\n", tch, expansion.get_descendants(length-i-1, t).get_str(100).c_str());
}
#endif
if(i == 1)
onlychild = true;
if(!onlychild) ycw++;
if(valence() == 3) ycw++;
onlychild = false;
for(int tch: expansion.children[t]) {
ycw++;
if(i < 2) tch = type_in(expansion, ycw.cpeek(), sdist);
auto& sub_id = expansion.get_descendants(length-1-i, tch);
if(full_id < sub_id) { t = tch; break; }
full_id.addmul(sub_id, -1);
onlychild = true;
}
}
else if(WDIM == 3) {
cell *prev = p.path[max(i-3, 0)];
int d = celldistance(prev, ycw.at);
vector<int> next;
forCellIdCM(c, i, ycw.at) if(celldistance(prev, c) > d) next.push_back(i);
if(!isize(next)) {
println(hlog, "error: no more cells for i=", i);
ycw.spin = hrand(ycw.at->type);
}
else {
ycw.spin = hrand_elt(next);
}
}
else {
stupid:
// stupid
ycw += rev;
// well, make it a bit more clever on bitruncated a4 grids
if(a4 && BITRUNCATED && S7 <= 5) {
if(ycw.at->type == 8 && ycw.cpeek()->type != 8)
ycw++;
if(hrand(100) < 10) {
if(euclid ? (turns&1) : (hrand(100) < 50))
ycw+=2;
else
ycw-=2;
turns++;
}
}
}
if(for_yendor) while(p.last_id < i && (p.path[p.last_id]->land == laMirror || inmirror(p.path[p.last_id]))) {
p.last_id++;
setdist(p.path[p.last_id], 7, nullptr);
}
if(for_yendor && inmirror(ycw.at)) ycw = mirror::reflect(ycw);
ycw += wstep;
p.path[i+1] = ycw.at;
}
p.last = ycw + rev;
}
return p;
}
}

View File

@ -57,7 +57,7 @@ EX }
EX void glError(const char* GLcall, const char* file, const int line) {
GLenum errCode = glGetError();
if(errCode!=GL_NO_ERROR) {
println(hlog, format("OPENGL ERROR #%i: in file %s on line %i :: %s",errCode,file, line, GLcall));
println(hlog, hr::format("OPENGL ERROR #%i: in file %s on line %i :: %s",errCode,file, line, GLcall));
}
}
@ -75,7 +75,7 @@ struct glwrap {
void glwrap::act(const char *when) {
GLenum errCode = glGetError();
if(errCode!=GL_NO_ERROR) {
println(hlog, format("GL error %i %s: %s:%i", errCode, when, msg, line));
println(hlog, hr::format("GL error %i %s: %s:%i", errCode, when, msg, line));
}
}
@ -124,11 +124,14 @@ struct glmatrix {
color[2] = b;
color[3] = 1;
}
colored_vertex(hyperpoint h, color_t col) {
coords = pointtogl(h);
void set_color(color_t col) {
for(int i=0; i<4; i++)
color[i] = part(col, 3-i) / 255.0;
}
colored_vertex(hyperpoint h, color_t col) {
coords = pointtogl(h);
set_color(col);
}
};
struct textured_vertex {
@ -153,7 +156,7 @@ struct glmatrix {
#endif
bool glew = false;
EX bool glew = false;
bool current_depthtest, current_depthwrite;
ld fogbase;
@ -208,6 +211,14 @@ EX glmatrix tmtogl(const transmatrix& T) {
return tmp;
}
EX transmatrix gltotm(const glmatrix& T) {
transmatrix tmp;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
tmp[i][j] = T[i][j];
return tmp;
}
EX glmatrix tmtogl_transpose(const transmatrix& T) {
glmatrix tmp;
for(int i=0; i<4; i++)
@ -237,10 +248,8 @@ EX glmatrix& as_glmatrix(GLfloat o[16]) {
return tmp;
}
#if HDR
constexpr ld vnear_default = 1e-3;
constexpr ld vfar_default = 1e9;
#endif
EX ld vnear_default = 1e-3;
EX ld vfar_default = 1e9;
EX glmatrix frustum(ld x, ld y, ld vnear IS(vnear_default), ld vfar IS(vfar_default)) {
GLfloat frustum[16] = {
@ -266,7 +275,7 @@ EX glmatrix translate(ld x, ld y, ld z) {
// /* shaders */
glmatrix projection;
EX glmatrix projection;
EX void new_projection() {
WITHSHADER({
@ -319,11 +328,11 @@ EX int compileShader(int type, const string& s) {
GLint status;
if(debug_gl) {
println(hlog, "===\n");
println(hlog, "=== ", full_geometry_name(), " @ ", models::get_model_name(pmodel));
int lineno = 1;
string cline = "";
for(char c: s+"\n") {
if(c == '\n') println(hlog, format("%4d : ", lineno), cline), lineno++, cline = "";
if(c == '\n') println(hlog, hr::format("%4d : ", lineno), cline), lineno++, cline = "";
else cline += c;
}
println(hlog, "===");
@ -655,7 +664,10 @@ EX void full_enable(shared_ptr<GLprogram> p) {
current_projection[0][0] = -1e8;
}, {})
id_modelview();
#if MINIMIZE_GL_CALLS
#else
current_linewidth = -1;
#endif
/* if(current_depthwrite) glDepthMask(GL_TRUE);
else glDepthMask(GL_FALSE);
if(current_depthtest) glEnable(GL_DEPTH_TEST);
@ -697,6 +709,7 @@ void init() {
#if CAP_GLEW
if(!glew) {
glew = true;
glewExperimental = GL_TRUE;
printf("Initializing GLEW\n");
GLenum err = glewInit();
if (GLEW_OK != err) {

View File

@ -47,6 +47,11 @@ EX namespace gp {
loc operator /(int i) {
return loc(first/i, second/i);
}
loc conj() {
if(S3 == 4) return loc(first, -second);
return loc(first+second, -second);
}
};
@ -58,7 +63,8 @@ EX namespace gp {
};
#endif
EX local_info draw_li;
EX local_info current_li;
EX cell *li_for;
EX loc eudir(int d) {
if(S3 == 3) {
@ -101,12 +107,15 @@ EX namespace gp {
EX int fixg6(int x) { return gmod(x, SG6); }
const int GOLDBERG_LIMIT_HALF = GOLDBERG_LIMIT/2;
const int GOLDBERG_MASK_HALF = GOLDBERG_MASK/2;
EX int get_code(const local_info& li) {
return
((li.relative.first & 15) << 0) +
((li.relative.second & 15) << 4) +
((fixg6(li.total_dir)) << 8) +
((li.last_dir & 15) << 12);
((li.relative.first & GOLDBERG_MASK_HALF) << 0) +
((li.relative.second & GOLDBERG_MASK_HALF) << (GOLDBERG_BITS-1)) +
((fixg6(li.total_dir)) << (2*GOLDBERG_BITS-2)) +
((li.last_dir & 15) << (2*GOLDBERG_BITS+2));
}
EX local_info get_local_info(cell *c) {
@ -162,9 +171,9 @@ EX namespace gp {
// goldberg_map[y][x].cw is the cellwalker in this triangle at position (x,y)
// facing local direction 0
goldberg_mapping_t goldberg_map[32][32];
goldberg_mapping_t goldberg_map[GOLDBERG_LIMIT][GOLDBERG_LIMIT];
void clear_mapping() {
for(int y=0; y<32; y++) for(int x=0; x<32; x++) {
for(int y=0; y<GOLDBERG_LIMIT; y++) for(int x=0; x<GOLDBERG_LIMIT; x++) {
goldberg_map[y][x].cw.at = NULL;
goldberg_map[y][x].rdir = -1;
goldberg_map[y][x].mindir = 0;
@ -172,7 +181,7 @@ EX namespace gp {
}
goldberg_mapping_t& get_mapping(loc c) {
return goldberg_map[c.second&31][c.first&31];
return goldberg_map[c.second&GOLDBERG_MASK][c.first&GOLDBERG_MASK];
}
int spawn;
@ -225,12 +234,12 @@ EX namespace gp {
auto& wc = get_mapping(at);
auto wcw = get_localwalk(wc, dir);
auto& wc1 = get_mapping(at + eudir(dir));
DEBB0(DF_GP, (format(" md:%02d s:%d", wc.mindir, wc.cw.spin)); )
DEBB0(DF_GP, (" connection ", at, "/", dir, " ", wc.cw+dir, "=", wcw, " ~ ", at+eudir(dir), "/", dir1); )
DEBB0(DF_GP, (hr::format(" md:%02d s:%d", wc.mindir, wc.cw.spin)); )
DEBB0(DF_GP, (" connection ", at, "/", dir, " ", wc.cw+dir, "=", wcw, " ~ ", at+eudir(dir), "/", dir1, " "); )
if(!wc1.cw.at) {
wc1.start = wc.start;
if(peek(wcw)) {
DEBB0(DF_GP, ("(pulled) "); )
DEBB0(DF_GP, (" (pulled) "); )
set_localwalk(wc1, dir1, wcw + wstep);
if(do_adjm) wc1.adjm = wc.adjm * get_adj(wcw.at, wcw.spin);
}
@ -240,14 +249,14 @@ EX namespace gp {
set_localwalk(wc1, dir1, wcw + wstep);
if(do_adjm) wc1.adjm = wc.adjm;
spawn++;
DEBB0(DF_GP, ("(created) "); )
DEBB0(DF_GP, (" (created) "); )
}
}
DEBB0(DF_GP, (wc1.cw+dir1, " "));
auto wcw1 = get_localwalk(wc1, dir1);
if(peek(wcw)) {
if(wcw+wstep != wcw1) {
DEBB(DF_GP, ("FAIL: ", wcw, " / ", wcw1); exit(1); )
DEBB(DF_GP, ("FAIL: ", wcw, " connected to ", wcw+wstep, " not to ", wcw1); exit(1); )
}
else {
DEBB(DF_GP, ("(was there)"));
@ -265,6 +274,8 @@ EX namespace gp {
if(do_adjm) {
get_adj(wcw.at, wcw.spin) = inverse(wc.adjm) * wc1.adjm;
get_adj(wcw1.at, wcw1.spin) = inverse(wc1.adjm) * wc.adjm;
if(geom3::flipped) gp_swapped.emplace(wcw.at, wcw.spin);
if(geom3::flipped) gp_swapped.emplace(wcw1.at, wcw1.spin);
}
}
@ -274,6 +285,7 @@ EX namespace gp {
}
EX map<pair<cell*, int>, transmatrix> gp_adj;
EX set<pair<cell*, int>> gp_swapped;
EX transmatrix& get_adj(cell *c, int i) { return gp_adj[make_pair(c,i)]; }
@ -287,7 +299,10 @@ EX namespace gp {
EX void extend_map(cell *c, int d) {
DEBB(DF_GP, ("EXTEND ",c, " ", d));
indenter ind(2);
if(c->master->c7 != c) {
auto c1 = c;
auto d1 = d;
while(c->master->c7 != c) {
DEBB(DF_GP, (c, " direction 0 corresponds to ", c->move(0), " direction ", c->c.spin(0)); )
d = c->c.spin(0);
@ -297,10 +312,17 @@ EX namespace gp {
extend_map(c, d);
extend_map(c, c->c.fix(d-1));
extend_map(c, c->c.fix(d+1));
if(S3 == 4 && !c->move(d))
if(S3 == 4 && !c1->move(d1)) {
for(int i=0; i<S7; i++)
for(int j=0; j<S7; j++)
extend_map(createStep(c->master, i)->c7, j);
}
if(S3 == 4 && !c1->move(d1)) {
for(int i=0; i<S7; i++)
for(int i1=0; i1<S7; i1++)
for(int j=0; j<S7; j++)
extend_map(createStep(createStep(c->master, i), i1)->c7, j);
}
return;
}
@ -345,7 +367,17 @@ EX namespace gp {
}
}
auto fix_mirrors = [&] {
if(ac1.cw.mirrored != hs.mirrored) ac1.cw--;
if(ac2.cw.mirrored != hs.mirrored) ac2.cw--;
if(S3 == 4) {
auto& ac3 = get_mapping(vc[2]);
if(ac3.cw.mirrored != hs.mirrored) ac3.cw--;
}
};
if(S3 == 4 && param == loc(1,1)) {
fix_mirrors();
conn(loc(0,0), 1);
conn(loc(0,1), 0);
conn(loc(0,1), 1);
@ -353,11 +385,54 @@ EX namespace gp {
conn(loc(0,1), 3);
return;
}
if(S3 == 4 && param.first == param.second && nonorientable) {
fix_mirrors();
int size = param.first;
// go along the boundary of the 'diamond'
for(int dir=0; dir<4; dir++) {
int dir_orth = (dir+1) & 3;
loc at = vc[dir];
for(int i=0; i<size; i++) {
if(!pull(at, dir)) break;
at = at + eudir(dir);
if(!pull(at, dir_orth)) break;
at = at + eudir(dir_orth);
}
}
// build the skeleton
for(int dir=0; dir<4; dir++) {
int dir_orth = (dir+1) & 3;
for(int i=0; i<size; i++) {
conn(vc[dir] + eudir(dir_orth) * i, dir_orth);
}
}
// fill everything
for(int y=0; y<2*size; y++) {
int xdist = min(y, 2*size-y);
for(int x=0; x<xdist; x++)
for(int d=0; d<4; d++) {
conn(loc(x, y), d);
conn(loc(-x, y), d);
}
}
return;
}
if(nonorientable && param.first == param.second) {
int x = param.first;
if(ac1.cw.mirrored != hs.mirrored) ac1.cw--;
if(ac2.cw.mirrored != hs.mirrored) ac2.cw--;
fix_mirrors();
for(int d=0; d<3; d++) for(int k=0; k<3; k++)
for(int i=0; i<x; i++) {
@ -574,22 +649,24 @@ EX namespace gp {
}
if(sp>SG3) sp -= SG6;
return normalize(spin(2*M_PI*sp/S7) * cornmul(T, corner));
return normalize(spin(TAU*sp/S7) * cornmul(T, corner));
}
transmatrix dir_matrix(int i) {
auto ddspin = [] (int d) -> transmatrix {
return spin(M_PI - d * 2 * M_PI / S7 - cgi.hexshift);
return spin(M_PI - d * TAU / S7 - cgi.hexshift);
};
return spin(-cgi.gpdata->alpha) * build_matrix(
C0,
ddspin(i) * xpush0(cgi.tessf),
ddspin(i+1) * xpush0(cgi.tessf),
geom3::flipped ? C02 : tile_center(),
geom3::flipped ? ddspin(i) * xpush0(cgi.tessf) : ddspin(i) * lxpush0(cgi.tessf),
geom3::flipped ? ddspin(i+1) * xpush0(cgi.tessf) : ddspin(i+1) * lxpush0(cgi.tessf),
C03
);
}
void prepare_matrices() {
EX void prepare_matrices(bool inv) {
if(!(GOLDBERG_INV || inv)) return;
if(embedded_plane) geom3::light_flip(true);
cgi.gpdata->corners = inverse(build_matrix(
loctoh_ort(loc(0,0)),
loctoh_ort(param),
@ -597,18 +674,33 @@ EX namespace gp {
C03
));
cgi.gpdata->Tf.resize(S7);
/* should work directly without flipping but it does not... flipping for now */
for(int i=0; i<S7; i++) {
transmatrix T = dir_matrix(i);
for(int x=-16; x<16; x++)
for(int y=-16; y<16; y++)
for(int x=-GOLDBERG_LIMIT_HALF; x<GOLDBERG_LIMIT_HALF; x++)
for(int y=-GOLDBERG_LIMIT_HALF; y<GOLDBERG_LIMIT_HALF; y++)
for(int d=0; d<(S3==3?6:4); d++) {
loc at = loc(x, y);
hyperpoint h = atz(T, cgi.gpdata->corners, at, 6);
hyperpoint hl = atz(T, cgi.gpdata->corners, at + eudir(d), 6);
cgi.gpdata->Tf[i][x&31][y&31][d] = rgpushxto0(h) * rspintox(gpushxto0(h) * hl) * spin(M_PI);
auto& res = cgi.gpdata->Tf[i][x&GOLDBERG_MASK][y&GOLDBERG_MASK][d];
res = rgpushxto0(h) * rspintox(gpushxto0(h) * hl) * spin180();
}
}
if(geom3::flipped) {
geom3::light_flip(false);
for(int i=0; i<S7; i++) {
for(int x=-GOLDBERG_LIMIT_HALF; x<GOLDBERG_LIMIT_HALF; x++)
for(int y=-GOLDBERG_LIMIT_HALF; y<GOLDBERG_LIMIT_HALF; y++)
for(int d=0; d<(S3==3?6:4); d++) {
auto& T = cgi.gpdata->Tf[i][x&GOLDBERG_MASK][y&GOLDBERG_MASK][d];
T = cgi.emb->base_to_actual(T);
}
} }
}
EX hyperpoint get_corner_position(const local_info& li, int cid, ld cf IS(3)) {
@ -616,7 +708,7 @@ EX namespace gp {
if(i == -1)
return atz(dir_matrix(cid), cgi.gpdata->corners, li.relative, 0, cf);
else {
auto& cellmatrix = cgi.gpdata->Tf[i][li.relative.first&31][li.relative.second&31][fixg6(li.total_dir)];
auto& cellmatrix = cgi.gpdata->Tf[i][li.relative.first&GOLDBERG_MASK][li.relative.second&GOLDBERG_MASK][fixg6(li.total_dir)];
return inverse(cellmatrix) * atz(dir_matrix(i), cgi.gpdata->corners, li.relative, fixg6(cid + li.total_dir), cf);
}
}
@ -657,19 +749,28 @@ EX namespace gp {
cgi.base_distlimit = 2 * param.first + 2 * param.second + 1;
if(cgi.base_distlimit > SEE_ALL)
cgi.base_distlimit = SEE_ALL;
prepare_matrices();
DEBB(DF_GEOM | DF_POLY, ("scale = ", scale));
}
}
loc config;
loc internal_representation(loc v) {
EX bool rotate_and_check_limits(loc& v) {
int& x = v.first, &y = v.second;
while(x < 0 || y < 0 || (x == 0 && y > 0))
v = v * loc(0, 1);
if(x > 8) x = 8;
if(y > 8) y = 8;
return 2*(x+y) < (1<<GOLDBERG_BITS);
}
EX bool check_limits(loc v) {
return rotate_and_check_limits(v);
}
loc internal_representation(loc v) {
int& x = v.first, &y = v.second;
while(!rotate_and_check_limits(v)) {
if(x > y) x--; else y--;
}
if(S3 == 3 && y > x) v = v * loc(1, -1);
return v;
}
@ -689,7 +790,7 @@ EX namespace gp {
return eVariation::goldberg;
}
void whirl_set(loc xy) {
EX void whirl_set(loc xy) {
xy = internal_representation(xy);
if(xy.second && xy.second != xy.first && nonorientable) {
addMessage(XLAT("This does not work in non-orientable geometries"));
@ -712,6 +813,15 @@ EX namespace gp {
screens = g;
}
EX bool check_whirl_set(loc xy) {
if(!check_limits(xy)) {
addMessage(XLAT("Outside of the supported limits"));
return false;
}
whirl_set(xy);
return true;
}
string helptext() {
return XLAT(
"Goldberg polyhedra are obtained by adding extra hexagons to a dodecahedron. "
@ -724,7 +834,7 @@ EX namespace gp {
void show() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
dialog::init(XLAT("variations"));
int min_quality_chess = 0;
@ -786,11 +896,14 @@ EX namespace gp {
}
dialog::addBreak(100);
int max_goldberg = (1<<GOLDBERG_BITS)/2 - 1;
dialog::addSelItem("x", its(config.first), 'x');
dialog::add_action([] { dialog::editNumber(config.first, 0, 8, 1, 1, "x", helptext()); });
dialog::add_action([max_goldberg] { dialog::editNumber(config.first, 0, max_goldberg, 1, 1, "x", helptext()); });
dialog::addSelItem("y", its(config.second), 'y');
dialog::add_action([] { dialog::editNumber(config.second, 0, 8, 1, 1, "y", helptext()); });
dialog::add_action([max_goldberg] { dialog::editNumber(config.second, 0, max_goldberg, 1, 1, "y", helptext()); });
if(!check_limits(config))
dialog::addInfo(XLAT("Outside of the supported limits"));
if(config.second && config.second != config.first && nonorientable) {
dialog::addInfo(XLAT("This does not work in non-orientable geometries"));
}
@ -811,7 +924,7 @@ EX namespace gp {
dialog::addBoolItem(XLAT("irregular"), IRREGULAR, 'i');
dialog::add_action(dialog::add_confirmation([=] () {
if(min_quality && !irr::bitruncations_requested) irr::bitruncations_requested++;
if(euclid && (!bounded || nonorientable)) {
if(euclid && (!closed_manifold || nonorientable)) {
println(hlog, XLAT("To create Euclidean irregular tesselations, first enable a torus"));
return;
}
@ -870,24 +983,24 @@ EX namespace gp {
auto p = univ_param();
if(S3 == 3 && !UNTRUNCATED) {
println(hlog, "set param to ", p * loc(1,1));
whirl_set(p * loc(1, 1));
if(!check_whirl_set(p * loc(1, 1))) return;
set_variation(eVariation::untruncated);
start_game();
config = human_representation(univ_param());
}
else if(S3 == 4 && !UNRECTIFIED) {
whirl_set(p * loc(1, 1));
if(!check_whirl_set(p * loc(1, 1))) return;
set_variation(eVariation::unrectified);
start_game();
config = human_representation(univ_param());
}
else if(S3 == 3 && UNTRUNCATED) {
println(hlog, "whirl_set to ", (p * loc(1,1)) / 3);
whirl_set((p * loc(1,1)) / 3);
if(!check_whirl_set((p * loc(1,1)) / 3)) return;
config = human_representation(univ_param());
}
else if(S3 == 4 && UNRECTIFIED) {
whirl_set((p * loc(1,1)) / 2);
if(!check_whirl_set((p * loc(1,1)) / 2)) return;
config = human_representation(univ_param());
}
});
@ -1078,6 +1191,7 @@ EX namespace gp {
return S3 == 3 ? XLAT("chamfered") : XLAT("expanded");
else if(GOLDBERG && param == loc(3, 0) && S3 == 3)
return XLAT("2x bitruncated");
#if MAXMDIM >= 4
else if(variation == eVariation::subcubes)
return XLAT("subcubed") + "(" + its(reg3::subcube_count) + ")";
else if(variation == eVariation::dual_subcubes)
@ -1086,6 +1200,7 @@ EX namespace gp {
return XLAT("bitruncated-subcubed") + "(" + its(reg3::subcube_count) + ")";
else if(variation == eVariation::coxeter)
return XLAT("subdivided") + "(" + its(reg3::coxeter_param) + ")";
#endif
else {
auto p = human_representation(param);
string s = "GP(" + its(p.first) + "," + its(p.second) + ")";
@ -1154,6 +1269,7 @@ EX namespace gp {
}
hrmap_inverse() {
underlying_map = nullptr;
if(0) {
println(hlog, "making ucgi");
dynamicval<eVariation> gva(variation, variation_for(param));
@ -1177,11 +1293,13 @@ EX namespace gp {
cell *create_move(cell *parent, int d) {
if(UNRECTIFIED) {
cellwalker cw(mapping[parent], d);
bool b = cw.mirrored;
in_underlying([&] {
cw += wstep;
cw --;
cw += wstep;
cw --;
if(cw.mirrored != b) cw++;
});
cw.at = get_mapped(cw.at, 0);
parent->c.connect(d, cw.at, cw.spin, cw.mirrored);
@ -1262,11 +1380,11 @@ EX namespace gp {
in_underlying([&] {
if(GOLDBERG) {
gp::draw_li = gp::get_local_info(c1);
gp::current_li = gp::get_local_info(c1);
}
else {
gp::draw_li.relative.first = shvid(c1);
gp::draw_li.relative.second = shift[c];
gp::current_li.relative.first = shvid(c1);
gp::current_li.relative.second = shift[c];
}
});
@ -1289,11 +1407,6 @@ EX namespace gp {
return gp::get_plainshape_id(c);
}
int full_shvid(cell *c) override {
gp::draw_li = gp::get_local_info(c);
return shvid(c);
}
hyperpoint get_corner(cell *c, int cid, ld cf) override {
if(UNTRUNCATED) {
cell *c1 = gp::get_mapped(c);
@ -1329,11 +1442,17 @@ EX namespace gp {
return C0;
}
};
EX hrmap* new_inverse() { return new hrmap_inverse; }
hrmap_inverse* inv_map() { return (hrmap_inverse*)currentmap; }
EX bool inverse_pseudohept(cell *c) {
cell *c1 = inv_map()->mapping[c];
if(!c1) return false;
return UIU(pseudohept(c1));
}
EX hrmap* get_underlying_map() { return inv_map()->underlying_map; }
EX cell* get_mapped(cell *c) { return inv_map()->get_mapped(c, 0); }
EX int untruncated_shift(cell *c) { return inv_map()->shift[c]; }
@ -1361,5 +1480,9 @@ EX namespace gp {
#endif
auto hooksw = addHook(hooks_swapdim, 100, [] {
for(auto& p: gp_adj) swapmatrix(p.second);
});
}}

1517
graph.cpp

File diff suppressed because it is too large Load Diff

181
help.cpp
View File

@ -14,7 +14,7 @@ EX function<void()> help_delegate;
#if HDR
struct help_extension {
char key;
int key;
string text;
string subtext;
color_t color;
@ -85,7 +85,7 @@ vector<string> extra_keys_3d = {
"move mouse = rotate camera (in rug, only with lctrl)",
};
void buildHelpText() {
EX void buildHelpText() {
DEBBI(DF_GRAPH, ("buildHelpText"));
help = XLAT("Welcome to HyperRogue");
@ -97,23 +97,23 @@ void buildHelpText() {
#endif
help += XLAT("! (version %1)\n\n", VER);
help += XLAT(
if(!game_keys_scroll) help += XLAT(
"You have been trapped in a strange, non-Euclidean world. Collect as much treasure as possible "
"before being caught by monsters. The more treasure you collect, the more "
"monsters come to hunt you, as long as you are in the same land type. The "
"Orbs of Yendor are the ultimate treasure; get at least one of them to win the game!"
);
help += XLAT(" (press ESC for some hints about it).");
help += "\n\n";
if(!game_keys_scroll) help += XLAT(" (press ESC for some hints about it).");
if(!game_keys_scroll) help += "\n\n";
if(!shmup::on && !hardcore)
if(!shmup::on && !hardcore && !game_keys_scroll)
help += XLAT(
"You can fight most monsters by moving into their location. "
"The monster could also kill you by moving into your location, but the game "
"automatically cancels all moves which result in that.\n\n"
);
if(shmup::on) {
if(shmup::on && !game_keys_scroll) {
help += XLAT(
"Shmup (shoot'em up) mode: You can play a hyperbolic shoot'em up game. The game is based "
"on the usual turn-based grid-based HyperRogue, but there are some changes. You fight by "
@ -122,14 +122,14 @@ void buildHelpText() {
"adapted too.\n\n");
}
if(shmup::on && multi::players > 1) {
if(shmup::on && multi::players > 1 && !game_keys_scroll) {
help += XLAT(
"Multiplayer: Play cooperatively (locally); treasures, kills, and deaths are calculated "
"for each player too, for more competitive play. Orbs and treasures are shared, orbs drain "
"faster, knives recharge slower, and player characters are not allowed to separate.\n\n");
}
if(multi::players > 1 && !shmup::on) {
if(multi::players > 1 && !shmup::on && !game_keys_scroll) {
help += XLAT(
"Turn-based multiplayer: Turns are executed in parallel. A player can leave the game "
"by pressing a designated key (useful when about to get killed or lost). The following "
@ -143,11 +143,11 @@ void buildHelpText() {
}
#if CAP_INV
if(inv::on)
if(inv::on && !game_keys_scroll)
help += XLAT(
inv::helptext
);
else
else if(!game_keys_scroll)
#endif
help += XLAT(
"There are many lands in HyperRogue. Collect 10 treasure "
@ -156,7 +156,7 @@ void buildHelpText() {
"get access to new lands. At 25 treasures "
"this type of Orbs starts appearing in other lands as well. Press 'o' to "
"get the details of all the Lands.\n\n");
help += "\n\n";
if(!game_keys_scroll) help += "\n\n";
#if ISMOBILE
help += XLAT(
@ -166,11 +166,17 @@ void buildHelpText() {
"numbers displayed to get their meanings.\n"
);
#else
if(DEFAULTCONTROL)
if(DEFAULTCONTROL && !game_keys_scroll)
help += XLAT(
"Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Space. "
"To save the game you need an Orb of Safety. Press 'v' for the main menu (configuration, special modes, etc.), ESC for the quest status.\n\n"
);
else if(DEFAULTCONTROL && WDIM == 2)
help += XLAT(
"You are currently in a visualization. Press wasd to scroll, qe to rotate. You can also use the arrow keys. ESC for menu.\n\n");
else if(DEFAULTCONTROL && WDIM == 3)
help += XLAT(
"You are currently in a visualization. Press wasdqe to rotate the camera, ijklyh to move. You can also use the arrow keys and Home/End and PgUp/PgDn. ESC for menu.\n\n");
help += XLAT(
"You can right click any element to get more information about it.\n\n"
);
@ -179,9 +185,10 @@ void buildHelpText() {
#endif
#endif
help += XLAT("See more on the website: ")
+ "http//roguetemple.com/z/hyper/\n\n";
+ "https://roguetemple.com/z/hyper/\n\n";
#if CAP_TOUR
if(!tour::on)
help += XLAT("Try the Guided Tour to help with understanding the "
"geometry of HyperRogue (menu -> special modes).\n\n");
#endif
@ -211,6 +218,7 @@ void buildHelpText() {
}
EX string standard_help() {
if(nohelp == 2) return "";
return XLAT("Press F1 or right click for help");
}
@ -228,11 +236,12 @@ EX void buildCredits() {
help += XLAT(
"special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n",
"Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct, "
"wonderfullizardofoz, Piotr Migdał, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman, "
"wonderfullizardofoz, Piotr Migdał, Tehora Rogue, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman, "
"Kojiguchi Kazuki, baconcow, Alan, SurelyYouJest, hotdogPi, DivisionByZero, xXxWeedGokuxXx, jpystynen, Dmitry Marakasov, Alexandre Moine, Arthur O'Dwyer, "
"Triple_Agent_AAA, bluetailedgnat, Allalinor, Shitford, KittyTac, Christopher King, KosGD, TravelDemon, Bubbles, rdococ, frozenlake, MagmaMcFry, "
"Snakebird Priestess, roaringdragon2, Stopping Dog, bengineer8, Sir Light IJIJ, ShadeBlade, Saplou, shnourok, Ralith, madasa, 6% remaining, Chimera245, Remik Pi, alien foxcat thing, "
"Piotr Grochowski, Ann, still-flow, tyzone, Paradoxica, LottieRatWorld"
"Piotr Grochowski, Ann, still-flow, tyzone, Paradoxica, LottieRatWorld, aismallard, albatross, EncodedSpirit, Jacob Mandelson, CrashTuvai, cvoight, jennlbw, Kali Ranya, spiritbackup, Dylan, L_Lord, AntiRogue, "
"masonlgreen, A human, Pasu4"
);
#ifdef EXTRALICENSE
help += EXTRALICENSE;
@ -269,7 +278,7 @@ EX string helptitle(string s, color_t col) {
string princessReviveHelp() {
if(inv::on) return "";
string h = "\n\n" +
XLAT("Killed %1 can be revived with Orb of the Love, after you collect 20 more $$$.", moPrincess);
XLAT("Killed %1 can be revived with an Orb of Love, after you collect 20 more $$$.", moPrincess);
if(princess::reviveAt)
h += "\n\n" +
XLAT("%The1 will be revivable at %2 $$$", moPrincess, its(princess::reviveAt));
@ -337,7 +346,18 @@ string power_help =
EX string generateHelpForItem(eItem it) {
string help = helptitle(XLATN(iinf[it].name), iinf[it].color);
if(shmup::on && isShmupLifeOrb(it)) {
int cnt = 0;
help += XLAT(
"The following Orbs act an extra lives in the shmup mode:");
for(int i=0; i<ittypes; i++) {
eItem it2 = eItem(i);
if(isShmupLifeOrb(it2)) help += cnt++ ? XLAT(", %1", it2) : XLAT(" %1", it2);
}
}
else
#if CAP_CRYSTAL
if(it == itCompass && cryst)
help += crystal::compass_help();
@ -391,7 +411,7 @@ EX string generateHelpForItem(eItem it) {
help += XLAT("You can press 'g' or click them in the list to drop a Dead Orb.");
#endif
if(it == itOrbLightning || it == itOrbFlash)
help += XLAT("\n\nThis Orb is triggered on your first attack or illegal move.");
help += XLAT("\n\nThis Orb is triggered on your first direct melee attack or illegal move.");
if(it == itOrbShield)
help += XLAT("\n\nThis Orb protects you from attacks, scents, and insulates you "
"from electricity. It does not let you go through deadly terrain, but "
@ -507,6 +527,33 @@ EX string generateHelpForItem(eItem it) {
}
}
}
int oc = orbcharges(it); if(oc) {
if(items[itOrbIntensity]) {
int oc2 = intensify(oc);
help += XLAT("\n\nOrb charges gained on pickup: %1 (increased to %2 by %the3)", its(oc), its(oc2), itOrbIntensity);
}
else
help += XLAT("\n\nOrb charges gained on pickup: %1", its(oc));
}
int ac = 0;
if(among(it, itOrbFrog, itOrbPhasing, itOrbDash)) ac = 5;
if(among(it, itOrbSummon)) ac = 20;
if(among(it, itOrbPsi)) ac = 30;
if(among(it, itOrbStunning)) ac = 10;
if(among(it, itOrbMorph)) ac = 3;
if(among(it, itOrbIllusion)) ac = 5;
if(among(it, itOrbDragon)) ac = 5;
if(among(it, itOrbAir)) ac = 1;
if(ac) {
if(items[itOrbEnergy])
help += XLAT("\n\nActivation cost: %1 charges (reduced to %2 by %the3)\n", its(ac), its((1+ac)/2), itOrbEnergy);
else
help += XLAT("\n\nActivation cost: %1 charges\n", its(ac));
}
if(it == itOrb37 && (S7 != 7 || !BITRUNCATED))
help += "\n\n" + other_geometry() + forbidden_unmarked();
@ -533,6 +580,20 @@ EX string generateHelpForItem(eItem it) {
return help;
}
void mine_dialog() {
cmode = sm::SIDE;
gamescreen();
dialog::init("Minefield graphics");
add_edit(numerical_minefield);
add_edit(mine_zero_display);
add_edit(mine_opacity);
add_edit(mine_hollow);
add_edit(mine_markers);
dialog::addItem(XLAT("minefield colors"), 'c');
dialog::add_action_push([] { edit_color_table(minecolors); });
dialog::display();
}
void addMinefieldExplanation(string& s) {
s += XLAT(
@ -547,6 +608,8 @@ void addMinefieldExplanation(string& s) {
#else
s += XLAT("Known mines may be marked by touching while in drag mode. Your allies won't step on marked mines.");
#endif
help_extensions.push_back(help_extension{'c', XLAT("configure"), [] () { pushScreen(mine_dialog); } });
}
EX string generateHelpForWall(eWall w) {
@ -565,8 +628,7 @@ EX string generateHelpForWall(eWall w) {
void buteol(string& s, int current, int req) {
int siz = isize(s);
if(s[siz-1] == '\n') s.resize(siz-1);
char buf[100]; sprintf(buf, " (%d/%d)", current, req);
s += buf; s += "\n";
s += hr::format(" (%d/%d)\n", current, req);
}
EX string generateHelpForMonster(eMonster m) {
@ -679,10 +741,12 @@ void add_reqs(eLand l, string& s) {
#define COND(x,y) s += (y);
#define ITEMS_TOTAL(list, z) \
{ int now = 0; string t = "("; for(eItem i: list) { if(t!="(") t += " | "; t += XLATN(iinf[i].name); now += items[i]; } t += ")"; s += XLAT("Treasure required: %1 x %2.\n", its(z), t); buteol(s, now, z); }
#define INMODE(x) ;
#define ACCONLY(z) s += XLAT("Accessible only from %the1.\n", z);
#define ACCONLY2(z,x) s += XLAT("Accessible only from %the1 or %the2.\n", z, x);
#define ACCONLY3(z,y,x) s += XLAT("Accessible only from %the1 or %the2.\n", z, y, x);
#define ACCONLY3(z,y,x) s += XLAT("Accessible only from %the1, %2, or %3.\n", z, y, x);
#define ACCONLYF(z) s += XLAT("Accessible only from %the1 (until finished).\n", z);
#define IFINGAME(land, ok, fallback) if(isLandIngame(land)) { ok } else { s += XLAT("Alternative rule when %the1 is not in the game:\n", land); fallback }
#include "content.cpp"
case landtypes: return;
@ -825,7 +889,10 @@ int windtotal;
EX hookset<void(cell*)> hooks_mouseover;
template<class T> void set_help_to(T t) {
help = bygen([t] { gotoHelpFor(t); });
help = bygen([t] {
gotoHelpFor(t);
help_extensions.push_back(help_extension{'h', XLAT("HyperRogue help"), [] () { buildHelpText(); }});
});
}
EX void describeMouseover() {
@ -857,9 +924,9 @@ EX void describeMouseover() {
if(shmup::on)
out += " (" + its(c->landparam)+")";
else {
bool b = c->landparam >= tide[(turncount-1) % tidalsize];
bool b = c->landparam >= tide[turncount % tidalsize];
int t = 1;
for(; t < 1000 && b == (c->landparam >= tide[(turncount+t-1) % tidalsize]); t++) ;
for(; t < 1000 && b == (c->landparam >= tide[(turncount+t) % tidalsize]); t++) ;
if(b)
out += " (" + turnstring(t) + XLAT(" to surface") + ")";
else
@ -868,7 +935,7 @@ EX void describeMouseover() {
}
#if CAP_FIELD
else if(c->land == laVolcano) {
int id = lavatide(c, -1)/4;
int id = lavatide(c, 0)/4;
if(id < 96/4)
out += " (" + turnstring(96/4-id) + XLAT(" to go cold") + ")";
else
@ -906,7 +973,7 @@ EX void describeMouseover() {
}
if(buggyGeneration) {
char buf[80]; sprintf(buf, " %p H=%d M=%d", hr::voidp(c), c->landparam, c->mpdist); out += buf;
out += hr::format(" %p H=%d M=%d", hr::voidp(c), c->landparam, c->mpdist);
}
if(randomPatternsMode)
@ -941,10 +1008,18 @@ EX void describeMouseover() {
if(c->wall && !(c->wall == waChasm && c->land == laDual && ctof(c)) &&
!(c->land == laMemory) &&
!((c->wall == waFloorA || c->wall == waFloorB) && c->item)) {
out += ", "; out += XLAT1(winf[c->wall].name);
eWall w = c->wall;
if(isAlch(w))
w = conditional_flip_slime(mousing ? det(mouseoverV.T) < 0 : det(View) < 0, w);
out += ", "; out += XLAT1(winf[w].name);
if(c->wall == waRose) out += " (" + its(7-rosephase) + ")";
if(c->wall == waTerraWarrior) out += " (" + its(c->landparam) + ")";
if(c->wall == waTerraWarrior) out += " (" + its(c->wparam) + ")";
#if CAP_COMPLEX2
if(isDie(c->wall)) out += " (" + dice::describe(c) + ")";
#endif
if((c->wall == waBigTree || c->wall == waSmallTree) && c->land != laDryForest)
help =
@ -972,6 +1047,10 @@ EX void describeMouseover() {
else if(c->monst) {
out += ", "; out += XLAT1(minf[c->monst].name);
#if CAP_COMPLEX2
if(isDie(c->monst))
out += " (" + dice::describe(c) + ")";
#endif
if(hasHitpoints(c->monst))
out += " (" + its(c->hitpoints)+" HP)";
if(isMutantIvy(c))
@ -1051,16 +1130,7 @@ EX void describeMouseover() {
#endif
}
EX void showHelp() {
cmode = sm::HELP | sm::DOTOUR;
getcstat = SDLK_ESCAPE;
if(help == "HELPFUN") {
help_delegate();
return;
}
gamescreen(2);
string help2;
EX void addHelpWithTitle() {
if(help[0] == '@') {
int iv = help.find("\t");
int id = help.find("\n");
@ -1071,29 +1141,46 @@ EX void showHelp() {
dialog::init("help", forecolor, 120, 100);
dialog::addHelp(help);
}
}
EX void showHelp() {
cmode = sm::HELP | sm::DOTOUR | sm::DARKEN;
getcstat = SDLK_ESCAPE;
if(help == "HELPFUN") {
help_delegate();
return;
}
gamescreen();
string help2;
addHelpWithTitle();
bool in_list = false;
for(auto& he: help_extensions) {
if(!in_list && he.key == dialog::first_list_fake_key) {
dialog::start_list(1000, 1000, 'a');
in_list = true;
}
if(in_list && (he.key < dialog::first_list_fake_key || he.key > dialog::first_list_fake_key + 1000)) {
in_list = false;
dialog::end_list();
}
if(he.subtext != "")
dialog::addSelItem(he.text, he.subtext, he.key);
else
dialog::addItem(he.text, he.key);
dialog::add_action(he.action);
dialog::lastItem().color = he.color;
}
if(in_list) dialog::end_list();
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
for(auto& he: help_extensions)
if(uni == he.key) {
// we need to copy he.action
// as otherwise it could clear the extensions,
// leading to errors
auto act = he.action;
act();
return;
}
if(sym == SDLK_F1) {
auto i = help;
buildHelpText();

View File

@ -25,6 +25,7 @@ cell *newCell(int type, heptagon *master);
*/
EX hstate transition(hstate s, int dir) {
if(embedded_plane) return IPF(transition(s, dir));
if(sphere) {
if(S7 == 4) {
if(s == hsOrigin) return dir == 0 ? hsB0 : hsB1;
@ -136,8 +137,8 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fix
int d1 = (d+S7-1)%S7;
bool missing0 = !h->move(0)->move(d1);
if(missing0) {
if(s == 1)
h->distance = h->move(0)->distance + 1;
if(s == 1 && h->move(0)->s != hsOrigin)
h->distance = h->move(0)->distance + 1;
}
else {
heptagon* h1 = createStep(h->move(0), d1);

View File

@ -40,12 +40,12 @@ namespace spiral {
CY = band[0]->h;
SX = out->w;
SY = out->h;
ld prec = 2*M_PI*M_PI;
ld k = -2*M_PI*M_PI / log(2.6180339);
ld k = -prec / log(2.6180339);
// cxld mnoznik = cxld(0, M_PI) / cxld(k, M_PI);
cxld factor = cxld(0, -CY/2/M_PI/M_PI) * cxld(k, M_PI);
cxld factor = cxld(0, -CY/prec) * cxld(k, M_PI);
Yshift = CY * k / M_PI;
@ -81,19 +81,22 @@ namespace spiral {
void loop(vector<SDL_Surface*> _band) {
renderbuffer rb(vid.xres, vid.yres, false);
if(vid.usingGL) {
rb.make_surface();
out = rb.srf;
}
else
out = s;
band = _band;
out = s;
precompute();
if(CX == 0) return;
shiftx = shifty = 0;
velx=1; vely=1;
bool dosave = false;
bool saveGL = vid.wantGL;
vid.wantGL = false;
apply_screen_settings();
out = s;
while(true) {
time_t timer;
@ -101,15 +104,40 @@ namespace spiral {
char buf[128];
strftime(buf, 128, "spiral-%y%m%d-%H%M%S" IMAGEEXT, localtime(&timer));
SDL_LockSurface(s);
SDL_LockSurface(out);
draw();
if(dosave) { dosave = false; IMAGESAVE(s, buf); }
SDL_UnlockSurface(s);
if(vid.usingGL) {
calcparam();
setGLProjection();
current_display->next_shader_flags = GF_TEXTURE;
dynamicval<eModel> m(pmodel, mdPixel);
glhr::color2(0xFFFFFFFF);
glhr::set_depthtest(false);
glhr::current_vertices = NULL;
current_display->set_all(0,0);
vector<glhr::textured_vertex> rtver(4);
for(int i=0; i<4; i++) {
int cx[4] = {0, 1, 1, 0};
int cy[4] = {0, 0, 1, 1};
rtver[i].texture[0] = cx[i] * rb.x * 1. / rb.tx;
rtver[i].texture[1] = 1 - cy[i] * rb.y * 1. / rb.ty;
rtver[i].coords[0] = vid.xres * cx[i] - current_display->xcenter;
rtver[i].coords[1] = vid.yres * cy[i] - current_display->ycenter;
rtver[i].coords[2] = 0;
rtver[i].coords[3] = 1;
}
glhr::prepare(rtver);
rb.use_as_texture();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
if(dosave) { dosave = false; IMAGESAVE(out, buf); }
SDL_UnlockSurface(out);
if(displayhelp) {
displaystr(SX/2, vid.fsize*2, 0, vid.fsize, "arrows = navigate, ESC = return, h = hide help", forecolor, 8);
displaystr(SX/2, SY - vid.fsize*2, 0, vid.fsize, XLAT("s = save to " IMAGEEXT, buf), forecolor, 8);
glflush();
}
present_surface();
present_screen();
shiftx += velx; shifty += vely;
SDL_Event event;
@ -150,8 +178,6 @@ namespace spiral {
breakloop:
quickmap.clear();
vid.wantGL = saveGL;
apply_screen_settings();
}
}
@ -164,14 +190,16 @@ EX namespace history {
int lastprogress;
EX void progress_screen() {
gamescreen(0);
gamescreen();
mouseovers = "";
}
EX int progress_each = 250;
EX void progress(string str) {
#if CAP_SDL
int tick = SDL_GetTicks();
if(tick > lastprogress + 250) {
if(tick > lastprogress + progress_each) {
lastprogress = tick;
msgs.clear();
addMessage(str);
@ -344,7 +372,7 @@ EX namespace history {
v[ph+1]->at * C0;
View = xpush(-(phase-ph) * hdist(now, next)) * View;
if(WDIM == 2 || prod) {
if(WDIM == 2 || mproduct) {
View = models::rotmatrix() * View;
}
else {
@ -425,10 +453,15 @@ EX namespace history {
if(1) {
// block for RAII
dynamicval<videopar> dv(vid, vid);
dynamicval<ld> dr(models::rotation, 0);
dynamicval<trans23> dr(models::rotation, Id);
dynamicval<bool> di(inHighQual, true);
renderbuffer glbuf(bandfull, bandfull, vid.usingGL);
glbuf.make_surface(); if(!glbuf.srf) {
addMessage(XLAT("Could not create an image of that size."));
return;
}
vid.xres = vid.yres = bandfull;
glbuf.enable(); current_display->radius = bandhalf;
calcparam();
@ -442,7 +475,7 @@ EX namespace history {
auto save_band_segment = [&] {
string fname = name_format;
replace_str(fname, "$DATE", timebuf);
replace_str(fname, "$ID", format("%03d", segid++));
replace_str(fname, "$ID", hr::format("%03d", segid++));
IMAGESAVE(band, fname.c_str());
if(dospiral)
@ -452,7 +485,8 @@ EX namespace history {
};
if(!band) {
addMessage("Could not create an image of that size.");
addMessage(XLAT("Could not create an image of that size."));
return;
}
else {
@ -470,10 +504,7 @@ EX namespace history {
pushScreen(progress_screen);
char buf[128];
sprintf(buf, "#%03d", segid);
progress(s0 + buf + " ("+its(j+bonus)+"/"+its(siz+bonus+bonus-1)+")"); */
progress(s0 + hr::format("#%03d (%d/%d)", segid, j+bonus, siz+bonus+bonus-1)); */
// calcparam(); current_display->radius = bandhalf;
phase = j; movetophase();
@ -503,6 +534,10 @@ EX namespace history {
len -= bandsegment; xpos -= bandsegment;
seglen = min(int(len), bandsegment);
band = SDL_CreateRGBSurface(SDL_SWSURFACE, seglen, bandfull,32,0,0,0,0);
if(!band) {
addMessage(XLAT("Could not create an image of that size."));
return;
}
goto drawsegment;
}
xpos += bwidth;
@ -542,7 +577,7 @@ EX namespace history {
EX void history_menu() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
gamescreen();
dialog::init(XLAT("history mode"));
@ -721,19 +756,19 @@ EX namespace history {
history::includeHistory = false;
}) + addHook(hooks_configfile, 0, [] {
addsaver(autobandhistory, "include history"); // check!
param_f(lvspeed, "lvspeed", "lineview speed");
addsaver(extra_line_steps, "lineview extension");
param_b(autobandhistory, "include history"); // check!
param_f(lvspeed, parameter_names("lvspeed", "lineview speed"));
param_f(extra_line_steps, "lineview extension");
addsaver(bandhalf, "band width");
addsaver(bandsegment, "band segment");
addsaver(autoband, "automatic band");
addsaver(autobandhistory, "automatic band history");
addsaver(dospiral, "do spiral");
param_i(bandhalf, "band width");
param_i(bandsegment, "band segment");
param_b(autoband, "automatic band");
param_b(autobandhistory, "automatic band history");
param_b(dospiral, "do spiral");
#if CAP_SHOT && CAP_SDL
addsaver(band_format_auto, "band_format_auto");
addsaver(band_format_now, "band_format_now");
param_str(band_format_auto, "band_format_auto");
param_str(band_format_now, "band_format_now");
#endif
});

View File

@ -1 +0,0 @@
М■Иmц0 ┘╘:n▌╕q t .А╚М:|▄жя╡┘C┼┼" :@M─фШ(И▐s░R║╧V┴V│сл*яэY2┤dгёRxоv(x^*|>aИ╔≈Ч╞ЩK=┘zВЙ4Цs$Ф▐└└оp┌rw╟├ш\x гВ4/С_j 8/Ш┘7p┬°ШyXя|ВШ1©▒>D~УСcЮлГвЯ╝≥оoФЭ6АЖРrч'yyЁД Ъ~иъчоЫK┴зhтNci5╨ч║┼[▓╚и╣╫E;Xrк░eв▄м`П╬│щ*ЗVQ╠W▒╙Ц╝К╗ь╚I5ЯЭ⌡╗ьkH╣ьУv#Уп╣3БY;#·╣D_Ь█?xhLХН

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +0,0 @@
<EFBFBD>•ωRΤ@ΖK`ρDΕµEEAE±*{° ψI6wΟGσ<47>µ{<7B>LΟ&T±UI6Ώώ<CE8F>έσMgwόΟΒ%ΎCΗ3Λt,™ƒ?+ζΊf®­^π|Wώή%ΩΙ<E2809A>έ<1C>θf&>ίΰ+Βk<CE92>2?4d ζωΌSKή¥·ω7`,ΧΧ]`½δΊ®ζWα…§GΨ…»s\χoωNKΏ5Η<0F>~Όaςυ³βZ#Ή\οΆ:o«σ<C2AB>πGrιΫα<E28099>ηΰώ±α³™δ²Ι¥ΟΛp<13>ƒ®ϋ¥ΙβsYwn5ό‡π_rι?(®uR/ΉάΗσύ>μΓϊΞ>σ½δrήΦa@[oω=βoΝ>ςy•ψK“λ}³Ώ·Ar9'λ†ΛΊs~™ηJ³οϋ ύ—\Ξ³ζO¥ϊ—zΝεΊzp<7A>®Οηϋ=£—\ζΡ|Ϋθ?Α^—}φΰΨ9a½<61>ΙεΌυΰ†Ϊχ¶ήq9?Ο½ύΛ9μΟα1ό4λuzΗεώjήε<CEAE>γΎ<CEB3>όjυγψ‡f>ο€ε]ύXξζΑκ»όw\ώ<>X~άΩ<CEAC>ζς=ZSΌύ~I.ϋ—\φ)Ήχ»χ—ώy<02>£ƒ΄Β 1<><31>WO 0<>b<EFBFBD>ΒC (NsLσ £43
~Φ*ΆJGΊ<47>·QW3lΥd<12>ZI`'<27>^ΠΩE Ίf}2<>­Εετ5²vϋΤ'χW•φ©Η*µkκ«υ¤ρϋDΛ"Γ~Y©¨.ιHΤ<48>WuθQWΥFό^"Ρ Χ9Α"¥3U:΅JeTΚω|buά&¶Ώ$<24>q„#ς…5#γµ£rxΟ¬Λ λ0Ζ9β(ϋ3lbΓΌ »a]`>­%‰kµαΜ<CEB1>ΨZCρ<43>ΞΞ> Β IάTζz6>π¨ν<C2A8>έ7ΊqMG)jΩ9<CEA9>Sf­³<C2AD>Κ·we“†絧γσ3<#ί™ϊΪ<CF8A>΄Υu:ή<>"<22>†½¥§γσS<Ν
¥γΈL•+™Ρρ:&<26>Ώ“¬4λ”qλΔSsp­l®Φ'”§ Zν:YSgάzΞu<CE9E>uvΟυ<%bΚ|:Ά<>ο¦<<0F>Ψ ω23WΚ

Binary file not shown.

Binary file not shown.

BIN
honeycombs/336h-c0.dat Normal file

Binary file not shown.

BIN
honeycombs/336h-c7.dat Normal file

Binary file not shown.

BIN
honeycombs/336h.dat Normal file

Binary file not shown.

BIN
honeycombs/344h-c0.dat Normal file

Binary file not shown.

BIN
honeycombs/344h-c7.dat Normal file

Binary file not shown.

BIN
honeycombs/344h.dat Normal file

Binary file not shown.

BIN
honeycombs/345h.dat Normal file

Binary file not shown.

BIN
honeycombs/353h-c0.dat Normal file

Binary file not shown.

BIN
honeycombs/353h-c7.dat Normal file

Binary file not shown.

BIN
honeycombs/353h.dat Normal file

Binary file not shown.

BIN
honeycombs/354h.dat Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More