Compare commits
767 Commits
Author | SHA1 | Date |
---|---|---|
Zeno Rogue | bb14c55997 | |
Zeno Rogue | b74b77463c | |
Zeno Rogue | 1e6793fa0a | |
Zeno Rogue | 78585f7ec2 | |
Zeno Rogue | b86eaa5693 | |
Zeno Rogue | 046deb799c | |
Zeno Rogue | 59fe423728 | |
Zeno Rogue | 2fccfdf0c5 | |
Zeno Rogue | 93dcc68acb | |
Zeno Rogue | 94c02b5082 | |
Zeno Rogue | 05309e3272 | |
Zeno Rogue | d059eb028c | |
Jacob Mandelson | 56cb3618d4 | |
Zeno Rogue | c80b34140f | |
Zeno Rogue | 078d16a4e4 | |
Zeno Rogue | 520314c2c5 | |
Zeno Rogue | 6a086e9764 | |
Zeno Rogue | 13ff317948 | |
Zeno Rogue | c5cc8be04f | |
Zeno Rogue | f80492f365 | |
Zeno Rogue | 70747f938d | |
Zeno Rogue | 00644cb2ef | |
Zeno Rogue | d4cb90fe1c | |
Zeno Rogue | 7cfda649be | |
Zeno Rogue | 4f868faee4 | |
Zeno Rogue | 22e0d8264f | |
Zeno Rogue | cd11bc2332 | |
Zeno Rogue | 43f998453e | |
Zeno Rogue | 0c0dcaba45 | |
Zeno Rogue | 20ce218bec | |
Zeno Rogue | 249dff7382 | |
Zeno Rogue | df5deaba4b | |
Zeno Rogue | 517f540800 | |
Zeno Rogue | 5877690cce | |
Zeno Rogue | c9b7e0ac1d | |
Zeno Rogue | 226881020d | |
Zeno Rogue | 809351e6a5 | |
Zeno Rogue | 99564ddfc9 | |
Zeno Rogue | 59c52a8176 | |
Zeno Rogue | 7af403490a | |
Zeno Rogue | 2314eaba29 | |
Zeno Rogue | 5d34760290 | |
Zeno Rogue | 50d70097cb | |
Zeno Rogue | c16c064b21 | |
Zeno Rogue | 448397ab1d | |
Zeno Rogue | b482dabb84 | |
Zeno Rogue | 478be692de | |
Zeno Rogue | dda979ad14 | |
Zeno Rogue | 9485495e48 | |
Zeno Rogue | d4a610c2b6 | |
Zeno Rogue | 003ca36ee5 | |
Zeno Rogue | 9752cdede1 | |
Zeno Rogue | fbd2cc6b9d | |
Zeno Rogue | 5324d3d068 | |
Zeno Rogue | d34070f709 | |
Zeno Rogue | 5d576c3344 | |
Zeno Rogue | c6c040eead | |
Zeno Rogue | aec2463f2f | |
Zeno Rogue | ba44e111ca | |
Zeno Rogue | 43d1fd3db8 | |
Zeno Rogue | 727ae8a260 | |
Zeno Rogue | 99bc842c57 | |
Zeno Rogue | a9d6def718 | |
Zeno Rogue | 0d5723dd69 | |
Zeno Rogue | ab0ca74328 | |
Zeno Rogue | e66f071521 | |
Zeno Rogue | b7bfe746cb | |
Zeno Rogue | 093044ba83 | |
Zeno Rogue | 3c29b987ce | |
Zeno Rogue | a755f26075 | |
Zeno Rogue | c1bacb0695 | |
Zeno Rogue | e2c81eeae7 | |
Zeno Rogue | fcc3cae938 | |
Zeno Rogue | 3b3e9e2de6 | |
Zeno Rogue | 5901d9598d | |
Zeno Rogue | 6bf198946c | |
Zeno Rogue | a3261b21da | |
Zeno Rogue | 3da7e4c020 | |
Zeno Rogue | ce09e4910e | |
Zeno Rogue | 95d7ffee08 | |
Zeno Rogue | 82a7077019 | |
Zeno Rogue | 1cc90a6f76 | |
Zeno Rogue | 1323ec446a | |
Zeno Rogue | 8db11dc683 | |
Zeno Rogue | 502469a54a | |
Zeno Rogue | 0df75589ca | |
Zeno Rogue | 358554d60e | |
Zeno Rogue | c594aea40e | |
Zeno Rogue | 03c549b010 | |
Zeno Rogue | 937a291485 | |
Zeno Rogue | 0e09775669 | |
Zeno Rogue | 5c03f9c7fe | |
Zeno Rogue | 8321751cb0 | |
Zeno Rogue | bfacda7207 | |
Zeno Rogue | 4f761c70cb | |
Zeno Rogue | 3ca75bec8e | |
Zeno Rogue | 54443e365d | |
Zeno Rogue | 6ca2051c96 | |
Zeno Rogue | e5e89c4800 | |
Zeno Rogue | bb6df35bf2 | |
Zeno Rogue | ba05c94d7b | |
Zeno Rogue | 90c7f6e927 | |
Zeno Rogue | e6417951de | |
Zeno Rogue | f823a53f84 | |
Zeno Rogue | 83575d9d7d | |
Zeno Rogue | d381caba1f | |
Zeno Rogue | 78cd26f456 | |
Zeno Rogue | 96be05484a | |
Zeno Rogue | 4d57041c9f | |
Zeno Rogue | 5022b76d75 | |
Zeno Rogue | 8caf343390 | |
Zeno Rogue | 203c11f6e1 | |
Zeno Rogue | 322b21e999 | |
Zeno Rogue | f445d02707 | |
Zeno Rogue | 888a34dea6 | |
Zeno Rogue | a20158ab65 | |
Zeno Rogue | a703448144 | |
Zeno Rogue | 480916e4db | |
Zeno Rogue | 998a74800c | |
Zeno Rogue | f4796a10f4 | |
Zeno Rogue | aa4bf4d818 | |
Zeno Rogue | ff8bb20a55 | |
Zeno Rogue | 57691737f0 | |
Zeno Rogue | a4b9b9b0a5 | |
Zeno Rogue | 1c74774bfa | |
Zeno Rogue | a80a73458a | |
Zeno Rogue | d7bde6f175 | |
Zeno Rogue | 9f711627f1 | |
Zeno Rogue | 89763be7d2 | |
Zeno Rogue | 03b89f053b | |
Zeno Rogue | 441f825566 | |
Zeno Rogue | f2d8b4d95e | |
Zeno Rogue | 73dbccbb0e | |
Jacob Mandelson | efc2ce90e0 | |
Zeno Rogue | 7b3d2c2626 | |
Zeno Rogue | 126f45a714 | |
Jacob Mandelson | 11837d9614 | |
Zeno Rogue | 64569f1818 | |
Jacob Mandelson | cd2152ffad | |
Zeno Rogue | eee39b0340 | |
Zeno Rogue | 937c830571 | |
Zeno Rogue | 4ec627b1a1 | |
Zeno Rogue | 1a70e54e24 | |
Zeno Rogue | a70a9dc663 | |
Zeno Rogue | 879549ca5d | |
Zeno Rogue | 7982ea0e58 | |
Zeno Rogue | 7b99248c06 | |
Zeno Rogue | dc136cc937 | |
Jacob Mandelson | 3f78c11e6c | |
Jacob Mandelson | 1dd4da5135 | |
Jacob Mandelson | 601274e67a | |
Zeno Rogue | 7581ba887b | |
Zeno Rogue | 6b03aca3c0 | |
Zeno Rogue | 80df589bd2 | |
Zeno Rogue | 159b47e72a | |
Zeno Rogue | 9a33e63f53 | |
Zeno Rogue | 10184f9087 | |
Zeno Rogue | 6b0dd547bd | |
Zeno Rogue | 542e2520c1 | |
Zeno Rogue | f2d81746a7 | |
Zeno Rogue | a130fbbc50 | |
Zeno Rogue | 2097fde609 | |
Zeno Rogue | bc5e1d78c9 | |
Zeno Rogue | e324ae07f3 | |
Zeno Rogue | 215be1ea17 | |
Zeno Rogue | 53461e6c5a | |
Zeno Rogue | 7a81b6b0de | |
Zeno Rogue | 723422e137 | |
Zeno Rogue | 50881f519f | |
Zeno Rogue | df67249ec0 | |
Zeno Rogue | 0a9714e657 | |
Zeno Rogue | 5eb7cfc17a | |
Zeno Rogue | 000bfd4b97 | |
Zeno Rogue | 0b0ad4abe3 | |
Zeno Rogue | 305d546ae1 | |
Zeno Rogue | c369c08bc9 | |
Zeno Rogue | 52f9cc820b | |
Zeno Rogue | 4c81c0cc5d | |
Zeno Rogue | 51ecd882e1 | |
Zeno Rogue | 9ba9797068 | |
Zeno Rogue | ba972ea8d8 | |
Zeno Rogue | e4b0ebbd89 | |
Zeno Rogue | 35ddcf6fe1 | |
Zeno Rogue | 7c2aca91a4 | |
Zeno Rogue | 43702b82a1 | |
Zeno Rogue | 43a3e8f030 | |
Zeno Rogue | ce825db2c0 | |
Zeno Rogue | b8a7e6e093 | |
Zeno Rogue | 962efb3152 | |
Zeno Rogue | 84666ade8c | |
Zeno Rogue | 9aa15f96e1 | |
Zeno Rogue | bc22d17a16 | |
Zeno Rogue | d9a03ab1d3 | |
Zeno Rogue | 5ae3bc02d1 | |
Zeno Rogue | aafced83aa | |
Zeno Rogue | 33aacfa289 | |
Zeno Rogue | d074606cae | |
Zeno Rogue | 6aecf921bf | |
Zeno Rogue | fa99e83019 | |
Zeno Rogue | 1003808999 | |
Zeno Rogue | 5085853fb4 | |
Zeno Rogue | 9372ecb8f8 | |
Zeno Rogue | 690b2164db | |
Zeno Rogue | 16e3daeab5 | |
Zeno Rogue | 0a16e53561 | |
Zeno Rogue | 443be1acda | |
Zeno Rogue | ba9c41bed2 | |
Zeno Rogue | 329ad76c3c | |
Zeno Rogue | de20daf708 | |
Zeno Rogue | f229c489cd | |
Zeno Rogue | 1e3347590b | |
Zeno Rogue | fd1960191e | |
Zeno Rogue | 942fd9dafb | |
Zeno Rogue | f1e91a1614 | |
Zeno Rogue | e71ddf1140 | |
Zeno Rogue | a0ba84d70c | |
Zeno Rogue | 404b964f28 | |
Jacob Mandelson | b56d2d21bf | |
Zeno Rogue | 27fb2d92d7 | |
Zeno Rogue | ec9be47a83 | |
Jacob Mandelson | 14519dc258 | |
Jacob Mandelson | c3ef9c2733 | |
Jacob Mandelson | c29517b5b0 | |
Zeno Rogue | e91c11ffb7 | |
Zeno Rogue | 7d3d3a0869 | |
Tokarak | d0d4b24f91 | |
Tokarak | 2659d08b78 | |
Tokarak | 45db9977a0 | |
Tokarak | aa78aacdf3 | |
Tokarak | fd128d24c6 | |
Jacob Mandelson | d756224f8d | |
Zeno Rogue | fbea2d91ce | |
Zeno Rogue | d4f449d994 | |
Zeno Rogue | 9807b1b3ba | |
Zeno Rogue | 4d761385ac | |
Zeno Rogue | 05b6cdea3e | |
Zeno Rogue | 10646933db | |
Zeno Rogue | 521b452436 | |
Zeno Rogue | 0323e4100e | |
Zeno Rogue | 0708c0e2bc | |
Zeno Rogue | b7db56812e | |
Zeno Rogue | 7fc90f116b | |
Zeno Rogue | 824fa9a732 | |
Zeno Rogue | 92603dddcc | |
Zeno Rogue | 32d329d81e | |
Zeno Rogue | b9608dcd4c | |
Zeno Rogue | 977bd8ca9d | |
Zeno Rogue | 869c63cb88 | |
Zeno Rogue | 5377147b1a | |
Zeno Rogue | e83d38e267 | |
Zeno Rogue | 1fc02631c8 | |
Zeno Rogue | edff317759 | |
Jacob Mandelson | b8de8155da | |
Zeno Rogue | 9bc4e21f10 | |
Zeno Rogue | a328568ee5 | |
Zeno Rogue | 494fc4ec11 | |
Zeno Rogue | 6f7e5b4d6a | |
Zeno Rogue | ccea416237 | |
Zeno Rogue | 4a908273d0 | |
Zeno Rogue | 5efacd787d | |
Zeno Rogue | b07987b2f4 | |
Zeno Rogue | 84ada5184f | |
Zeno Rogue | 14b68f0b64 | |
Zeno Rogue | 960485ec8e | |
Zeno Rogue | e032e619c0 | |
Zeno Rogue | 57f6fb5f71 | |
Zeno Rogue | d2cd6fa2c1 | |
Zeno Rogue | 8a407f4505 | |
Zeno Rogue | 6abb82174e | |
Zeno Rogue | dea9fea67f | |
Zeno Rogue | d618b10889 | |
Zeno Rogue | d250abf1a4 | |
Zeno Rogue | 89563ebde9 | |
Zeno Rogue | 445c240c79 | |
Zeno Rogue | 15b711e099 | |
Zeno Rogue | 8002f42d71 | |
Zeno Rogue | 79f2940683 | |
Zeno Rogue | 0ec4e46bf0 | |
Zeno Rogue | c55550de57 | |
Zeno Rogue | 886a7ff43e | |
Zeno Rogue | deb207e4c3 | |
Zeno Rogue | 819d815d59 | |
Zeno Rogue | b20288557e | |
Zeno Rogue | 4a8eb08340 | |
Zeno Rogue | 007a111eab | |
Zeno Rogue | 65e9f68bc7 | |
Zeno Rogue | 3e30a7ded1 | |
Zeno Rogue | 5f8d250940 | |
Zeno Rogue | dee90f8d7c | |
Zeno Rogue | d43b19625e | |
Zeno Rogue | f32a2708b4 | |
Zeno Rogue | be27fc0fce | |
Zeno Rogue | 61720cec5e | |
Zeno Rogue | 7cf1643c5d | |
Zeno Rogue | 3791daf9e3 | |
Zeno Rogue | e9941d29d3 | |
Zeno Rogue | afd4a3f4e3 | |
Zeno Rogue | 66a79fe2cd | |
Zeno Rogue | 350963852c | |
Zeno Rogue | a650fe7faf | |
Zeno Rogue | fdf83820f2 | |
Zeno Rogue | 6b723977dd | |
Zeno Rogue | 1b3aecc10c | |
Zeno Rogue | e762da439c | |
Zeno Rogue | 7f023b2459 | |
Zeno Rogue | 2a9ae3071d | |
Zeno Rogue | de21375f40 | |
Zeno Rogue | 7bc2715a43 | |
Zeno Rogue | 04c15fc9c6 | |
Zeno Rogue | 9430c26970 | |
Zeno Rogue | 616607dc8e | |
Zeno Rogue | 86f5a040c9 | |
Zeno Rogue | 37b498203c | |
Zeno Rogue | 77a4bb4160 | |
Zeno Rogue | 5bdade94b6 | |
Zeno Rogue | 0b526cbdfb | |
Zeno Rogue | a82d9b2266 | |
Zeno Rogue | 0e018df878 | |
Zeno Rogue | 1c5709a3c9 | |
Zeno Rogue | c230e03a0a | |
Zeno Rogue | b71cd1e44d | |
Zeno Rogue | ef936d7b0e | |
Zeno Rogue | 97f8c5ed72 | |
Zeno Rogue | 94bf06f7dc | |
Zeno Rogue | 261800d765 | |
Zeno Rogue | 2b2cc4e8a9 | |
Zeno Rogue | cbccf4936d | |
Zeno Rogue | 68f5ad6e92 | |
Zeno Rogue | 9f44f98b0a | |
Zeno Rogue | 5bb4b69c23 | |
Zeno Rogue | 9cc370a2d2 | |
Zeno Rogue | 26e61783b2 | |
Zeno Rogue | d0d354b53a | |
Zeno Rogue | 78a1615c6c | |
Zeno Rogue | 125b271889 | |
Zeno Rogue | c85b4d2f2b | |
Zeno Rogue | 424186b10d | |
Zeno Rogue | 4421143ae5 | |
Jacob Mandelson | ee293310b6 | |
Jacob Mandelson | a40e72f1d8 | |
Jacob Mandelson | 3bd67f466a | |
Zeno Rogue | ddb9fbd58e | |
Zeno Rogue | b152bac377 | |
Jacob Mandelson | a626ede2bf | |
Jacob Mandelson | 1f2692a4fb | |
Jacob Mandelson | e31c9dc263 | |
Jacob Mandelson | 7d04b0c717 | |
Jacob Mandelson | 0f84812d15 | |
Jacob Mandelson | 80f90dec52 | |
Zeno Rogue | e840e39ba0 | |
Zeno Rogue | fa9c2da41d | |
Zeno Rogue | f291bbb1d1 | |
Zeno Rogue | 2de61962f9 | |
Zeno Rogue | 43fc692b47 | |
Zeno Rogue | 87ac19febe | |
Zeno Rogue | 2379228ab4 | |
Zeno Rogue | 5aac5fd2a3 | |
Zeno Rogue | 46eaee44ef | |
Zeno Rogue | 21d3f8bec4 | |
Zeno Rogue | c2d06dc05b | |
Zeno Rogue | 21a782cd28 | |
Zeno Rogue | bf512e39ce | |
Zeno Rogue | de5ddc3034 | |
Zeno Rogue | b4b00baa5e | |
Zeno Rogue | 648dd67dc7 | |
Zeno Rogue | 30f6fbc16c | |
Zeno Rogue | 00b5fe3a22 | |
Zeno Rogue | 55493cc364 | |
Zeno Rogue | 3b1918535f | |
Zeno Rogue | 650108bad3 | |
Zeno Rogue | 79e74e8d53 | |
Zeno Rogue | 3ed43b8c7d | |
Zeno Rogue | 5508fb7183 | |
Zeno Rogue | 6c682510bc | |
Zeno Rogue | 6d9f7e791b | |
Zeno Rogue | e343ed9c3f | |
Zeno Rogue | 8af2a43f5e | |
Zeno Rogue | e33f26d51f | |
Zeno Rogue | 60980bcb8b | |
Zeno Rogue | bcc026173e | |
Zeno Rogue | d86f70886d | |
Zeno Rogue | 2a7e2e96ca | |
Zeno Rogue | a91f74c86c | |
Zeno Rogue | 285c71e10f | |
Zeno Rogue | a28c62416f | |
Zeno Rogue | bfd1945d7b | |
Zeno Rogue | f271ba6b4d | |
Zeno Rogue | f87a7c5f1c | |
Zeno Rogue | 9ce5c63708 | |
Jacob Mandelson | 56c8838101 | |
Zeno Rogue | 9a590ecc42 | |
Zeno Rogue | eb1488b24f | |
Zeno Rogue | 26328f5493 | |
Zeno Rogue | 52081a916a | |
Jacob Mandelson | 08a774dfd4 | |
Jacob Mandelson | acd88377a9 | |
Zeno Rogue | 51f59cc2fa | |
Zeno Rogue | 5f552799e5 | |
Zeno Rogue | f883322ecd | |
Zeno Rogue | 8c06e184c8 | |
Zeno Rogue | b8a5c7528b | |
Zeno Rogue | 11aa7d5216 | |
Zeno Rogue | 0ea461fa7e | |
Zeno Rogue | bdd2b5e9fd | |
Zeno Rogue | 8ce805372d | |
Zeno Rogue | 072041db06 | |
Zeno Rogue | 4c6c44cc26 | |
Zeno Rogue | 31471fc6c5 | |
Zeno Rogue | 7ad46d8e80 | |
Zeno Rogue | 34ab44d1e1 | |
Zeno Rogue | 66a3a3df6c | |
Zeno Rogue | 0c34e9fd34 | |
Zeno Rogue | cb8a3f5424 | |
Zeno Rogue | fc808d448b | |
Zeno Rogue | 7ad955dcff | |
Zeno Rogue | 17b84bb4fb | |
Zeno Rogue | 902986d473 | |
Zeno Rogue | 9bc978ce16 | |
Zeno Rogue | 6f81743488 | |
Zeno Rogue | f4607b63f4 | |
Zeno Rogue | 6e3be8a92c | |
Zeno Rogue | 02efdec4b7 | |
Zeno Rogue | 18247ec98f | |
Zeno Rogue | eb4b7177f3 | |
Zeno Rogue | 517f4af193 | |
Zeno Rogue | 2f1bb092b8 | |
Zeno Rogue | ffda562f7c | |
Zeno Rogue | c5a4cc2255 | |
Zeno Rogue | dbc51d2f94 | |
Zeno Rogue | 3da65f4cd5 | |
Zeno Rogue | 0c7aa7cbe3 | |
Zeno Rogue | 79527688cf | |
Zeno Rogue | 364a563423 | |
Zeno Rogue | a6b30fa564 | |
Zeno Rogue | eb3406d7dc | |
Zeno Rogue | 95ed035180 | |
Zeno Rogue | 3d01ce808f | |
Zeno Rogue | 558b8d7aff | |
Zeno Rogue | 0de012923a | |
Zeno Rogue | 7a352ccf43 | |
Zeno Rogue | 98831aff7e | |
Zeno Rogue | 17c254e2b4 | |
Zeno Rogue | 4fbce2ae5a | |
Zeno Rogue | cdc1696929 | |
Zeno Rogue | 2fc42cb114 | |
Zeno Rogue | 73884482aa | |
Zeno Rogue | 8c57e8b746 | |
Zeno Rogue | f5c5a5f876 | |
Jacob Mandelson | 12c464eb99 | |
Zeno Rogue | 8e31c51bc9 | |
Zeno Rogue | 71cbc8e221 | |
Zeno Rogue | bce07e5914 | |
Zeno Rogue | ed8b7d5d1d | |
Zeno Rogue | 5c24213092 | |
Zeno Rogue | a282ac314e | |
Zeno Rogue | 5ab9bf8f11 | |
Zeno Rogue | 61303fcab6 | |
Zeno Rogue | 517f4a833c | |
Jacob Mandelson | 27db11064c | |
Zeno Rogue | 062fb577b2 | |
Zeno Rogue | 4338ec2b43 | |
Zeno Rogue | cd7af38e2e | |
Zeno Rogue | 24c196db15 | |
Zeno Rogue | 548e2609ce | |
Zeno Rogue | d2d6167eb9 | |
Zeno Rogue | 86402cf979 | |
Zeno Rogue | 38825f3a31 | |
Zeno Rogue | 560cc91e95 | |
Zeno Rogue | ffc06b981f | |
Zeno Rogue | 0cdd6f8d5d | |
Zeno Rogue | c63969a21b | |
Zeno Rogue | 7802194248 | |
Zeno Rogue | a79a7f63a1 | |
Zeno Rogue | 928ab73fff | |
Zeno Rogue | ac33354358 | |
Zeno Rogue | 39ddc3dc33 | |
Zeno Rogue | 68a3d20d83 | |
Zeno Rogue | 6ef4a8a5e9 | |
Zeno Rogue | 16cb1090e8 | |
Zeno Rogue | 176ea28a24 | |
Zeno Rogue | 9bebbd8f4e | |
Zeno Rogue | 4ca8a7e394 | |
Zeno Rogue | 8946317475 | |
Zeno Rogue | 9ca0993d6f | |
Zeno Rogue | 2a892012b2 | |
Zeno Rogue | 53b0701d95 | |
Zeno Rogue | 439040c90c | |
Zeno Rogue | a840b96104 | |
Zeno Rogue | fe7e122613 | |
Zeno Rogue | 2dccf0d3ab | |
Zeno Rogue | c69bed4d12 | |
Zeno Rogue | c94e927929 | |
Zeno Rogue | 2dd4ef868b | |
Zeno Rogue | 34d3d67ace | |
Zeno Rogue | 2add515fbf | |
Zeno Rogue | 79165ae014 | |
Zeno Rogue | 9d4d085973 | |
Zeno Rogue | 45a9e0c85a | |
Zeno Rogue | c336e9d385 | |
Zeno Rogue | 8984cd8cd2 | |
Zeno Rogue | f76ccef90f | |
Zeno Rogue | 858db697d8 | |
Zeno Rogue | 8185657768 | |
Zeno Rogue | 0c6d286fa8 | |
Zeno Rogue | 76c6195d19 | |
Zeno Rogue | 95dc72a582 | |
Zeno Rogue | c91dc341ae | |
Zeno Rogue | b84e751d96 | |
Zeno Rogue | ed9081cfd5 | |
Zeno Rogue | da0bf9a035 | |
Zeno Rogue | 6030402441 | |
Zeno Rogue | 4b97f300ff | |
Zeno Rogue | 0c0bf1dd84 | |
Zeno Rogue | 1926fd8434 | |
Zeno Rogue | 6b8adfde9e | |
Zeno Rogue | 85fc2773b1 | |
Zeno Rogue | 669814efce | |
Zeno Rogue | 1f6bee5701 | |
Zeno Rogue | b2c8bb96d6 | |
Zeno Rogue | 87f7b2a593 | |
Zeno Rogue | f7a25ff2d1 | |
Zeno Rogue | a163c80ba1 | |
Zeno Rogue | b3b1611f33 | |
Zeno Rogue | 89a46a8cd1 | |
Zeno Rogue | a50a87f095 | |
Zeno Rogue | 33060a884c | |
Zeno Rogue | 9caa4daa62 | |
Zeno Rogue | 8e55cc9ebd | |
Zeno Rogue | 4e134c56b6 | |
Zeno Rogue | 8129cfd726 | |
Zeno Rogue | 3645a9b85e | |
Zeno Rogue | b0d117e646 | |
Zeno Rogue | 4f82c3eb8e | |
Zeno Rogue | c36da1985c | |
Zeno Rogue | e8ecccdf53 | |
Zeno Rogue | 11869c796b | |
Zeno Rogue | a012e6103a | |
Zeno Rogue | ddc7cddb91 | |
Zeno Rogue | daebe28d4f | |
Zeno Rogue | 3ef09bded2 | |
Zeno Rogue | f99a473720 | |
Zeno Rogue | dd37a1c6c7 | |
Zeno Rogue | 41e28c34b2 | |
Zeno Rogue | 9da8206a9f | |
Zeno Rogue | a233d3a7a6 | |
Zeno Rogue | 3a35d351c4 | |
Zeno Rogue | 079094799d | |
Zeno Rogue | 4ddccfed8e | |
Zeno Rogue | 44265f6d61 | |
Zeno Rogue | ddb06573df | |
Zeno Rogue | 1924a03d7a | |
Zeno Rogue | 33d48a76b3 | |
Zeno Rogue | f3398e70c3 | |
Zeno Rogue | c81e2bf7e8 | |
Zeno Rogue | e5458c5f80 | |
Zeno Rogue | e6a4d987bb | |
Zeno Rogue | f8fb7d5950 | |
Zeno Rogue | 7e46b4b5bb | |
Zeno Rogue | 845237c756 | |
Zeno Rogue | 9f5b13dfab | |
Zeno Rogue | 63b6576eb6 | |
Jacob Mandelson | db72295775 | |
Jacob Mandelson | 36bdc5d3f0 | |
Zeno Rogue | 5fb0099fbb | |
Zeno Rogue | ff19ceb438 | |
Zeno Rogue | 99f4b8698b | |
Zeno Rogue | 67a77befb9 | |
Zeno Rogue | 1c0bf5def3 | |
Zeno Rogue | 0ab6974cd9 | |
Zeno Rogue | fb1f3d8f13 | |
Zeno Rogue | 72029b3fbe | |
Zeno Rogue | c63eebc15f | |
Zeno Rogue | b9d8aaee13 | |
Zeno Rogue | ef93305313 | |
Zeno Rogue | fb5e4d25bb | |
Zeno Rogue | 2c171f7be4 | |
Zeno Rogue | 64a89e732f | |
Zeno Rogue | 7b3532a594 | |
Zeno Rogue | 70b7e24e96 | |
Zeno Rogue | 9326220310 | |
Zeno Rogue | c2f1f4371c | |
Zeno Rogue | 9e4c883001 | |
Zeno Rogue | eeb6373338 | |
Zeno Rogue | 6db4adb91c | |
Zeno Rogue | ec4b02d754 | |
Zeno Rogue | d4247e7b13 | |
Zeno Rogue | a74cdeeacc | |
Zeno Rogue | 2239d72bc8 | |
Zeno Rogue | 4d680e13c4 | |
Zeno Rogue | 23423e4016 | |
Zeno Rogue | 7a7af2a536 | |
Zeno Rogue | 9fbc73025e | |
Zeno Rogue | 66ea0804cf | |
Zeno Rogue | cab3cfe2f9 | |
Zeno Rogue | f62fcc12fc | |
Zeno Rogue | 9031b32cf4 | |
Zeno Rogue | 5076343223 | |
Zeno Rogue | dd5e9dbc6e | |
Zeno Rogue | 1d4dac0a50 | |
Zeno Rogue | 4aa707f197 | |
Zeno Rogue | 3670be5700 | |
Zeno Rogue | 78b75baf3a | |
Zeno Rogue | b617bc12a7 | |
Zeno Rogue | 6e695b5262 | |
Zeno Rogue | 2668841e5a | |
Zeno Rogue | 283fe020fc | |
Zeno Rogue | e1a78fe1ac | |
Zeno Rogue | f9b8551529 | |
Zeno Rogue | 8ac3bb29ab | |
Zeno Rogue | 8568f6489c | |
Zeno Rogue | 49ca18aef3 | |
Zeno Rogue | 3b341bb34b | |
Zeno Rogue | 77e5efa28f | |
Zeno Rogue | 50e5cc2c5a | |
Zeno Rogue | 0293680ea1 | |
Zeno Rogue | f3d28c9105 | |
Arthur O'Dwyer | 62629f3e70 | |
Zeno Rogue | b70b339f52 | |
Zeno Rogue | 529e27ea2f | |
Zeno Rogue | c89d98e832 | |
Zeno Rogue | 089db20356 | |
Zeno Rogue | 572866b67a | |
Zeno Rogue | b2668e4cf5 | |
Zeno Rogue | 01ede9681e | |
Zeno Rogue | bb22d363c8 | |
Zeno Rogue | fd1be4beb8 | |
Zeno Rogue | 04f31aa637 | |
Arthur O'Dwyer | 28880f2985 | |
Arthur O'Dwyer | 10d0ed8900 | |
Arthur O'Dwyer | ced3bbcad4 | |
Zeno Rogue | a250a4d430 | |
Zeno Rogue | c1584e9ece | |
Zeno Rogue | e3357c9b26 | |
Zeno Rogue | 29d50a9f21 | |
Zeno Rogue | 0b2aee0b40 | |
Zeno Rogue | 4b5a1621e8 | |
Zeno Rogue | 6a9ed169eb | |
Zeno Rogue | 838b34762e | |
Zeno Rogue | 18d042b9eb | |
Zeno Rogue | 0e1d7c024e | |
Zeno Rogue | 73e98644d3 | |
Zeno Rogue | 9e999ef30f | |
Zeno Rogue | b7f55e9f87 | |
Zeno Rogue | 01748ac77b | |
Zeno Rogue | 610d64d22a | |
Zeno Rogue | a5ada45164 | |
Zeno Rogue | 442a7d3c74 | |
Zeno Rogue | b123900b52 | |
Zeno Rogue | 37d558944e | |
Zeno Rogue | 56b5d52534 | |
Zeno Rogue | 42c47d0388 | |
Zeno Rogue | 36607319fd | |
Zeno Rogue | f37c4ba165 | |
Zeno Rogue | b9eac3f6ae | |
Zeno Rogue | 933361d394 | |
Zeno Rogue | 83b49caa5f | |
Zeno Rogue | f2f62cf296 | |
Zeno Rogue | 27bedb19ed | |
Zeno Rogue | 27b572a44a | |
Zeno Rogue | cfa01d878c | |
Zeno Rogue | 937da384e7 | |
Zeno Rogue | f3a0855df2 | |
Zeno Rogue | e22c34b343 | |
Zeno Rogue | b018582f44 | |
Zeno Rogue | ccb5068964 | |
Zeno Rogue | 63fc2c9c92 | |
Zeno Rogue | 53324a9eeb | |
Zeno Rogue | 1b76ab495e | |
Zeno Rogue | 97be7618e6 | |
Zeno Rogue | 74f1a93dc3 | |
Zeno Rogue | 246034f4cb | |
Zeno Rogue | 260c30c218 | |
Zeno Rogue | 394f8052b4 | |
Zeno Rogue | 44e9c3e317 | |
Zeno Rogue | 000726f450 | |
Zeno Rogue | 535d86a1c8 | |
Zeno Rogue | a70940b3ee | |
Zeno Rogue | 590d8021c6 | |
Zeno Rogue | 07857e612a | |
Zeno Rogue | beb679ccab | |
Zeno Rogue | 67d38feabd | |
Zeno Rogue | 3e1228b7c7 | |
Zeno Rogue | dff8db44b0 | |
Zeno Rogue | 757579fb18 | |
Zeno Rogue | 3eb2813667 | |
Zeno Rogue | cb05649732 | |
Zeno Rogue | 3069dbd316 | |
Zeno Rogue | a7cf3c4d1c | |
Zeno Rogue | e4562be1f5 | |
Zeno Rogue | d9d92bfd84 | |
Zeno Rogue | b98ac1c487 | |
Zeno Rogue | 6806a0e7e3 | |
Zeno Rogue | ea193d23b1 | |
Zeno Rogue | 9ab2b2bbd8 | |
Zeno Rogue | 3a3317d0be | |
Zeno Rogue | e666faba31 | |
Zeno Rogue | 392d3c075f | |
Zeno Rogue | c9a9a38188 | |
Zeno Rogue | f50964d576 | |
Zeno Rogue | 22636060dc | |
Zeno Rogue | b4e280c43f | |
Zeno Rogue | dc95d4c3e6 | |
Zeno Rogue | d8f64b62ac | |
Zeno Rogue | 5cc7a4e527 | |
Zeno Rogue | fe6d7abec2 | |
Zeno Rogue | f212f6173b | |
Zeno Rogue | 8a124f6890 | |
Zeno Rogue | 563d16c9c1 | |
Zeno Rogue | 4668321e4e | |
Zeno Rogue | b6f13b953b | |
Zeno Rogue | 4d4874f7ac | |
Zeno Rogue | 234a691ab6 | |
Zeno Rogue | 5057f10358 | |
Zeno Rogue | a13ba9bdbe | |
Zeno Rogue | c914bf86e0 | |
Zeno Rogue | e658a471da | |
Zeno Rogue | a088d46e6d | |
Zeno Rogue | 1554caa7b4 | |
Zeno Rogue | c896b3ecd6 | |
Zeno Rogue | debdcae057 | |
Zeno Rogue | 22947c7fd1 | |
Zeno Rogue | 522436ba96 | |
Zeno Rogue | 4ca3d41ad5 | |
Zeno Rogue | 7a09ab2cb0 | |
Zeno Rogue | c42a06772b | |
Zeno Rogue | 4c59d87a34 | |
Zeno Rogue | fb3b526ae6 | |
Zeno Rogue | 301236d154 | |
Zeno Rogue | d2c601834a | |
Zeno Rogue | 097ded1bd0 | |
Zeno Rogue | 07aa843f18 | |
Zeno Rogue | 0cdbb0f8f4 | |
Zeno Rogue | b31ceaf3df | |
Zeno Rogue | 108f4fb437 | |
Zeno Rogue | 38baf6605a | |
Zeno Rogue | 861543b9e5 | |
Zeno Rogue | 1211de5603 | |
Zeno Rogue | bcc86e7b30 | |
Zeno Rogue | 9e46638733 | |
Zeno Rogue | ec5e774613 | |
Zeno Rogue | c75f7b9cd4 | |
Zeno Rogue | 919725eabb | |
Zeno Rogue | 9ecd621fe8 | |
Zeno Rogue | 56be838b40 | |
Zeno Rogue | 32911e2b67 | |
Zeno Rogue | 4b61d63ef5 | |
Zeno Rogue | a830fa73b3 | |
Zeno Rogue | 0167e284cc | |
Zeno Rogue | 9a9ecd3c8c | |
Zeno Rogue | 286f98fb49 | |
Zeno Rogue | 2c0afce4ca | |
Zeno Rogue | dfb3626568 | |
Zeno Rogue | 34574ad050 | |
Zeno Rogue | 0168e4c7a8 | |
Zeno Rogue | 92cf27a056 | |
Zeno Rogue | ac336f7035 | |
Zeno Rogue | aebcabb99c | |
Zeno Rogue | 754e774bcf | |
Zeno Rogue | c6ccee56f9 | |
Zeno Rogue | 554e9c5cfc | |
Zeno Rogue | a041016446 | |
Zeno Rogue | f972170869 | |
Zeno Rogue | e218b0b19f | |
Zeno Rogue | 901521631f | |
Zeno Rogue | 41fda7545e | |
Zeno Rogue | aa729c912c | |
Zeno Rogue | 59dd09173a |
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
193
.travis.yml
193
.travis.yml
|
@ -1,193 +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.
|
||||
export CXXFLAGS_EARLY=-Werror
|
||||
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
|
|
@ -1278,17 +1278,11 @@ void geometry_information::make_3d_models() {
|
|||
finishshape();
|
||||
}
|
||||
|
||||
hpcshape& geometry_information::generate_pipe(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);
|
||||
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);
|
||||
|
||||
#if CAP_GL
|
||||
auto& utt = models_texture;
|
||||
auto& utt = cgi.models_texture;
|
||||
if(floor_textures) {
|
||||
pipe.tinf = &utt;
|
||||
pipe.texture_offset = isize(utt.tvertices);
|
||||
|
@ -1300,9 +1294,9 @@ hpcshape& geometry_information::generate_pipe(ld length, ld width, ePipeEnd endt
|
|||
auto at = [&] (ld i, ld a, ld z = 1, ld s = 1) {
|
||||
a += 0.5;
|
||||
ld alpha = TAU * a / MAX_R;
|
||||
hpcpush(xpush(i * length / MAX_X) * cspin(1, 2, alpha) * ypush0(width*z));
|
||||
cgi.hpcpush(f(i / MAX_X, alpha, z));
|
||||
#if CAP_GL
|
||||
if(floor_textures) utt.tvertices.push_back(glhr::makevertex(0, pers ? 0.549 - s * 0.45 * sin(alpha) : 0.999, 0));
|
||||
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++) {
|
||||
|
@ -1324,7 +1318,7 @@ hpcshape& geometry_information::generate_pipe(ld length, ld width, ePipeEnd endt
|
|||
|
||||
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 * width/length * .9; // .9 to prevent Z-fighting
|
||||
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);
|
||||
|
@ -1343,6 +1337,42 @@ hpcshape& geometry_information::generate_pipe(ld length, ld width, ePipeEnd endt
|
|||
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
|
||||
|
|
39
Makefile
39
Makefile
|
@ -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,7 +89,7 @@ ifeq (${OS},osx)
|
|||
endif
|
||||
|
||||
ifeq (${TOOLCHAIN},clang)
|
||||
CXXFLAGS_STD = -std=c++11
|
||||
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
|
||||
|
@ -88,7 +97,7 @@ ifeq (${TOOLCHAIN},clang)
|
|||
endif
|
||||
|
||||
ifeq (${TOOLCHAIN},gcc)
|
||||
CXXFLAGS_STD = -std=c++11
|
||||
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
|
||||
|
@ -96,7 +105,7 @@ ifeq (${TOOLCHAIN},gcc)
|
|||
endif
|
||||
|
||||
ifeq (${TOOLCHAIN},mingw)
|
||||
CXXFLAGS_STD = -std=c++11
|
||||
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
|
||||
|
@ -173,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
|
||||
|
||||
|
|
16
README.md
16
README.md
|
@ -1,11 +1,4 @@
|
|||
# HyperRogue
|
||||
<p>
|
||||
<a href="https://travis-ci.org/zenorogue/hyperrogue/builds">
|
||||
<img src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=Makefile&label=make" alt="TravisCI badge">
|
||||
<img src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=mymake&label=mymake" alt="TravisCI badge">
|
||||
<img src="https://badges.herokuapp.com/travis/zenorogue/hyperrogue?branch=master&env=TRAVIS_BUILD_SYSTEM=emscripten&label=web" alt="TravisCI badge">
|
||||
</a>
|
||||
</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).
|
||||
|
@ -62,15 +55,13 @@ 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.
|
||||
|
@ -83,3 +74,6 @@ 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].
|
||||
|
|
136
achievement.cpp
136
achievement.cpp
|
@ -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_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,6 +131,7 @@ 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 && flags != rg::special_geometry_nicewalls) {
|
||||
if(!BITRUNCATED) return true;
|
||||
|
@ -115,6 +139,7 @@ EX bool wrongMode(char flags) {
|
|||
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;
|
||||
|
@ -130,6 +155,7 @@ EX bool wrongMode(char flags) {
|
|||
if(tour::on) return true;
|
||||
#endif
|
||||
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)
|
||||
|
@ -139,6 +165,7 @@ EX bool wrongMode(char flags) {
|
|||
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;
|
||||
|
@ -159,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)) {
|
||||
|
@ -193,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'.
|
||||
|
@ -229,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 && !disksize)
|
||||
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 && !disksize)
|
||||
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");
|
||||
|
@ -313,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 && !disksize)
|
||||
achievement_gain("GRAILH", rg::special_geometry_nicewalls);
|
||||
achievement_gain("GRAILH", specgeom_heptagonal());
|
||||
#if CAP_CRYSTAL
|
||||
if(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside && !disksize)
|
||||
achievement_gain("GRAIL4D", rg::special_geometry);
|
||||
if(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside && !disksize)
|
||||
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");
|
||||
|
@ -603,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 && !disksize)
|
||||
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;
|
||||
|
@ -619,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)) {
|
||||
|
@ -633,7 +675,7 @@ 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); )
|
||||
|
@ -654,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
|
||||
}
|
||||
|
@ -737,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;
|
||||
|
@ -775,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;
|
||||
|
@ -785,6 +833,7 @@ 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;
|
||||
|
@ -801,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;
|
||||
}
|
||||
|
||||
|
@ -864,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;
|
||||
|
@ -876,6 +929,7 @@ EX void achievement_victory(bool hyper) {
|
|||
if(tactic::on) return;
|
||||
if(!ls::nice_walls()) return;
|
||||
if(ineligible_starting_land) return;
|
||||
if(use_custom_land_list) return;
|
||||
LATE( achievement_victory(hyper); )
|
||||
DEBB(DF_STEAM, ("after checks"))
|
||||
|
||||
|
@ -958,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 + "(?)";
|
||||
|
@ -995,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; }
|
||||
|
@ -1031,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
|
||||
|
||||
}
|
||||
|
|
|
@ -220,8 +220,7 @@ void ensure_geometry(eGeometryClass c) {
|
|||
|
||||
if(specialland != laCanvas) {
|
||||
canvas_default_wall = waInvisibleFloor;
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
enable_canvas();
|
||||
}
|
||||
start_game();
|
||||
|
@ -365,6 +364,7 @@ EX void load_tile(exp_parser& ep, arbi_tiling& c, bool unit) {
|
|||
cc.symmetric_value = 0;
|
||||
cc.flags = 0;
|
||||
cc.repeat_value = 1;
|
||||
cc.apeirogonal = false;
|
||||
bool is_symmetric = false;
|
||||
while(ep.next() != ')') {
|
||||
cld dist = 1;
|
||||
|
@ -1282,7 +1282,7 @@ void connection_debugger() {
|
|||
|
||||
curvepoint(sh[0]);
|
||||
|
||||
color_t col = colortables['A'][id];
|
||||
color_t col = ccolor::shape.ctab[id];
|
||||
col = darkena(col, 0, 0xFF);
|
||||
|
||||
if(&p == &last) {
|
||||
|
@ -1637,16 +1637,21 @@ struct hrmap_arbi : hrmap {
|
|||
|
||||
EX hrmap *new_map() { return new hrmap_arbi; }
|
||||
|
||||
EX void run(string fname) {
|
||||
EX void run_raw(string fname) {
|
||||
stop_game();
|
||||
eGeometry g = geometry;
|
||||
arbi_tiling t = current;
|
||||
auto v = variation;
|
||||
set_geometry(gArbitrary);
|
||||
try {
|
||||
load(fname);
|
||||
ginf[gArbitrary].tiling_name = current.name;
|
||||
tes = fname;
|
||||
convert::base_geometry = gArbitrary;
|
||||
}
|
||||
|
||||
EX void run(string fname) {
|
||||
eGeometry g = geometry;
|
||||
arbi_tiling t = current;
|
||||
auto v = variation;
|
||||
try {
|
||||
run_raw(fname);
|
||||
}
|
||||
catch(hr_polygon_error& poly) {
|
||||
set_geometry(g);
|
||||
|
@ -1713,7 +1718,7 @@ EX void set_sliders() {
|
|||
dialog::addSelItem(sl.name, fts(sl.current), ch++);
|
||||
dialog::add_action([&] {
|
||||
dialog::editNumber(sl.current, sl.min, sl.max, 1, sl.zero, sl.name, sl.name);
|
||||
dialog::reaction = [] { sliders_changed(false, false); };
|
||||
dialog::get_di().reaction = [] { sliders_changed(false, false); };
|
||||
});
|
||||
}
|
||||
if(isize(current.intsliders))
|
||||
|
@ -1722,7 +1727,7 @@ EX void set_sliders() {
|
|||
dialog::addSelItem(sl.name, its(sl.current), ch++);
|
||||
dialog::add_action([&] {
|
||||
dialog::editNumber(sl.current, sl.min, sl.max, 1, sl.zero, sl.name, sl.name);
|
||||
dialog::reaction = [] { sliders_changed(true, true); };
|
||||
dialog::get_di().reaction = [] { sliders_changed(true, true); };
|
||||
});
|
||||
}
|
||||
dialog::addInfo(slider_error);
|
||||
|
@ -1733,7 +1738,7 @@ EX void set_sliders() {
|
|||
/** convert a tessellation (e.g. Archimedean, regular, etc.) to the arb::current internal representation */
|
||||
EX namespace convert {
|
||||
|
||||
EX eGeometry base_geometry;
|
||||
EX eGeometry base_geometry = gArbitrary;
|
||||
EX eVariation base_variation;
|
||||
|
||||
struct id_record {
|
||||
|
@ -1867,17 +1872,34 @@ EX void convert_max() {
|
|||
|
||||
EX void convert_minimize(int N, vector<int>& old_shvids, map<int, int>& old_to_new) {
|
||||
vector<pair<int, int>> address;
|
||||
vector<int> next;
|
||||
vector<int> address_start;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
int q = identification[old_shvids[i]].modval;
|
||||
int c = isize(address);
|
||||
address_start.push_back(c);
|
||||
for(int j=0; j<q; j++) {
|
||||
address.emplace_back(i, j);
|
||||
next.emplace_back(j == q-1 ? c : c+j+1);
|
||||
}
|
||||
}
|
||||
|
||||
int K = isize(address);
|
||||
vector<int> next(K), step(K);
|
||||
|
||||
for(int k=0; k<K; k++) {
|
||||
auto i = address[k].first;
|
||||
auto j = address[k].second;
|
||||
|
||||
auto& id = identification[old_shvids[i]];
|
||||
next[k] = address_start[i] + (j+1) % id.modval;
|
||||
|
||||
cell *s = id.sample;
|
||||
cellwalker cw(s, j);
|
||||
cw += wstep;
|
||||
auto idx = get_identification(cw.at);
|
||||
step[k] = address_start[old_to_new.at(idx.target)] + gmod(cw.spin - idx.shift, idx.modval);
|
||||
}
|
||||
|
||||
vector<array<ld, 3> > dists(K);
|
||||
for(int i=0; i<K; i++) {
|
||||
auto pi = address[i];
|
||||
|
@ -1910,11 +1932,18 @@ EX void convert_minimize(int N, vector<int>& old_shvids, map<int, int>& old_to_n
|
|||
|
||||
int chg = 1;
|
||||
while(chg) {
|
||||
for(auto& eq: equal) println(hlog, eq);
|
||||
if(debugflags & DF_GEOM) {
|
||||
println(hlog, "current table of equals:");
|
||||
int eqid = 0;
|
||||
for(auto& eq: equal) {
|
||||
println(hlog, eq, " for ", eqid, ": ", address[eqid], " next= ", next[eqid], " step= ", step[eqid]);
|
||||
eqid++;
|
||||
}
|
||||
}
|
||||
chg = 0;
|
||||
for(int i=0; i<K; i++)
|
||||
for(int j=0; j<K; j++)
|
||||
if(equal[i][j] && !equal[next[i]][next[j]]) {
|
||||
if(equal[i][j] && (!equal[next[i]][next[j]] || !equal[step[i]][step[j]])) {
|
||||
equal[i][j] = false;
|
||||
chg++;
|
||||
}
|
||||
|
@ -1963,7 +1992,8 @@ EX void convert() {
|
|||
|
||||
auto& ac = arb::current;
|
||||
ac.order++;
|
||||
ac.comment = ac.filename = "converted from: " + full_geometry_name();
|
||||
ac.filename = full_geometry_name();
|
||||
ac.comment = "converted from: " + ac.filename;
|
||||
ac.cscale = cgi.scalefactor;
|
||||
ac.boundary_ratio = 1;
|
||||
ac.floor_scale = cgi.hexvdist / cgi.scalefactor;
|
||||
|
@ -1973,6 +2003,7 @@ EX void convert() {
|
|||
|
||||
ginf[gArbitrary].g = cginf.g;
|
||||
ginf[gArbitrary].flags = cgflags & qCLOSED;
|
||||
ginf[gArbitrary].tiling_name = full_geometry_name();
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
auto id = identification[old_shvids[i]];
|
||||
|
@ -1983,6 +2014,10 @@ EX void convert() {
|
|||
sh.vertices.clear();
|
||||
sh.connections.clear();
|
||||
sh.cycle_length = id.modval;
|
||||
if(arcm::in())
|
||||
sh.orig_id = arcm::get_graphical_id(s);
|
||||
else
|
||||
sh.orig_id = shvid(s);
|
||||
sh.repeat_value = t / id.modval;
|
||||
sh.flags = hr::pseudohept(s) ? arcm::sfPH : 0;
|
||||
#if CAP_ARCM
|
||||
|
@ -2057,7 +2092,7 @@ int readArgs() {
|
|||
else if(argis("-tes") || argis("-arbi")) {
|
||||
PHASEFROM(2);
|
||||
shift();
|
||||
run(args());
|
||||
run_raw(args());
|
||||
}
|
||||
else if(argis("-tes-opt")) {
|
||||
arg::run_arguments(current.options);
|
||||
|
|
146
archimedean.cpp
146
archimedean.cpp
|
@ -96,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
|
||||
|
@ -291,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];
|
||||
|
@ -299,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++) {
|
||||
|
@ -348,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);
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ 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])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,9 +432,8 @@ void archimedean_tiling::compute_geometry() {
|
|||
if(gg.kind == gcHyperbolic) arr[gArchimedean].g = arr[gNormal].g;
|
||||
set_flag(arr[gArchimedean].flags, qCLOSED, gg.kind == gcSphere);
|
||||
}
|
||||
if(geom3::flipped) swap(geom3::ginf_backup[gArchimedean].g, ginf[gArchimedean].g);
|
||||
|
||||
DEBB(DF_GEOM, (format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum))));
|
||||
DEBB(DF_GEOM, (hr::format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum))));
|
||||
|
||||
bool infake = fake::in();
|
||||
|
||||
|
@ -516,7 +515,7 @@ void archimedean_tiling::compute_geometry() {
|
|||
|
||||
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);
|
||||
|
@ -538,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, ());
|
||||
}
|
||||
|
||||
|
@ -573,13 +572,14 @@ EX bool use_gmatrix = true;
|
|||
* not used by arcm itself, but used in fake arcm
|
||||
*/
|
||||
|
||||
EX geometry_information *alt_cgip;
|
||||
EX geometry_information *alt_cgip[2];
|
||||
|
||||
EX geometry_information *find_alt_cgip() {
|
||||
if(alt_cgip) return alt_cgip;
|
||||
auto& galt_cgip = alt_cgip[embedded_plane];
|
||||
if(galt_cgip) return galt_cgip;
|
||||
check_cgi();
|
||||
cgi.require_basics();
|
||||
return alt_cgip = cgip;
|
||||
return galt_cgip = cgip;
|
||||
}
|
||||
|
||||
struct hrmap_archimedean : hrmap {
|
||||
|
@ -601,6 +601,9 @@ struct hrmap_archimedean : hrmap {
|
|||
heptagon *alt = NULL;
|
||||
|
||||
if(hyperbolic) {
|
||||
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());
|
||||
|
@ -609,8 +612,13 @@ struct hrmap_archimedean : hrmap {
|
|||
alt->alt = alt;
|
||||
current_altmap = newAltMap(alt);
|
||||
}
|
||||
if(f) geom3::light_flip(true);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -661,6 +669,19 @@ struct hrmap_archimedean : hrmap {
|
|||
|
||||
heptagon *create_step(heptagon *h, int d) override {
|
||||
|
||||
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);
|
||||
|
@ -681,6 +702,7 @@ struct hrmap_archimedean : hrmap {
|
|||
transmatrix U = Id;
|
||||
|
||||
if(hyperbolic) {
|
||||
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());
|
||||
|
@ -915,7 +937,7 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -923,15 +945,15 @@ void connect_digons_too(heptspin h1, heptspin h2) {
|
|||
void connectHeptagons(heptspin hi, heptspin hs) {
|
||||
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);
|
||||
|
@ -1056,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;
|
||||
|
@ -1063,17 +1099,9 @@ 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;
|
||||
shift(); load_symbol(args(), true);
|
||||
showstartmenu = false;
|
||||
}
|
||||
}
|
||||
else if(argis("-dual")) { PHASEFROM(2); set_variation(eVariation::dual); }
|
||||
else if(argis("-d:arcm"))
|
||||
launch_dialog(show);
|
||||
|
@ -1096,12 +1124,17 @@ auto hooksw = addHook(hooks_swapdim, 100, [] {
|
|||
|
||||
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 = nullptr;
|
||||
alt_cgip[0] = nullptr;
|
||||
alt_cgip[1] = nullptr;
|
||||
});
|
||||
#endif
|
||||
|
||||
|
@ -1313,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;
|
||||
|
@ -1347,7 +1390,7 @@ EX void show() {
|
|||
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);
|
||||
|
@ -1375,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;
|
||||
|
@ -1434,13 +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('R'));
|
||||
dialog::add_action(setcanvas(ccolor::shape_mirror));
|
||||
}
|
||||
else {
|
||||
dialog::addBreak(100);
|
||||
|
@ -1450,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);
|
||||
|
||||
|
@ -1481,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;
|
||||
}
|
||||
|
@ -1540,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;
|
||||
|
|
57
attack.cpp
57
attack.cpp
|
@ -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;
|
||||
|
||||
|
@ -337,6 +340,10 @@ EX eWall conditional_flip_slime(bool flip, eWall t) {
|
|||
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) {
|
||||
if(c->wall == waTemporary) {
|
||||
changes.ccell(c);
|
||||
|
@ -345,6 +352,7 @@ EX void spillfix(cell* c, eWall t, int rad) {
|
|||
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) {
|
||||
|
@ -359,6 +367,7 @@ EX void spill(cell* c, eWall t, int rad) {
|
|||
si.second.spill_b > si.second.spill_a ? waFloorB :
|
||||
isAlchAny(si.second.orig) ? si.second.orig :
|
||||
waNone;
|
||||
chainspill(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,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;
|
||||
|
@ -752,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) {
|
||||
|
@ -934,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
|
||||
|
@ -1106,11 +1130,11 @@ EX bool should_switchplace(cell *c1, cell *c2) {
|
|||
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)) addMessage(XLAT("Cannot switch places with %the1!", 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(m.vmsg(miRESTRICTED)) 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;
|
||||
|
@ -1222,11 +1246,13 @@ 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;
|
||||
}
|
||||
|
@ -1279,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);
|
||||
|
@ -1291,9 +1318,9 @@ EX void stabbingAttack(movei mi, eMonster who, int bonuskill IS(0)) {
|
|||
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;
|
||||
|
@ -1337,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++;
|
||||
|
@ -1350,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");
|
||||
|
|
143
barriers.cpp
143
barriers.cpp
|
@ -34,7 +34,7 @@ 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) {
|
||||
|
@ -324,12 +324,15 @@ 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;
|
||||
}
|
||||
|
@ -556,7 +559,9 @@ EX bool isbar4(cell *c) {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -612,6 +617,12 @@ EX void extendBarrier(cell *c) {
|
|||
if(buildBarrier6(cw, 2)) return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -677,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);
|
||||
|
||||
|
@ -722,20 +734,27 @@ EX bool buildBarrier6(cellwalker cw, int type) {
|
|||
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);
|
||||
|
@ -749,40 +768,82 @@ 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;
|
||||
|
@ -871,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)
|
||||
|
@ -1095,6 +1157,7 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ struct display_data {
|
|||
transmatrix radar_transform_post;
|
||||
|
||||
ld eyewidth();
|
||||
bool stereo_active();
|
||||
bool separate_eyes();
|
||||
bool in_anaglyph();
|
||||
|
||||
void set_viewport(int ed);
|
||||
|
@ -108,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) {
|
||||
|
@ -1516,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) {
|
||||
|
@ -1531,11 +1533,14 @@ 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(mhybrid) geometry = hybrid::underlying;
|
||||
|
@ -1544,19 +1549,26 @@ EX void initialize_all() {
|
|||
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() {
|
||||
|
|
350
bigstuff.cpp
350
bigstuff.cpp
|
@ -219,6 +219,182 @@ void hrmap::extend_altmap(heptagon *h, int levs, bool link_cdata) {
|
|||
}
|
||||
}
|
||||
|
||||
void new_voronoi_root(heptagon *h, int dist, int dir, eLand next) {
|
||||
heptagon *alt = init_heptagon(h->type);
|
||||
allmaps.push_back(newAltMap(alt));
|
||||
alt->s = hsA;
|
||||
alt->alt = alt;
|
||||
alt->cdata = (cdata*) h;
|
||||
alt->distance = dist;
|
||||
vector<pair<heptagon*, heptagon*>> altpairs;
|
||||
altpairs.emplace_back(h, alt);
|
||||
altmap::relspin(alt) = dir;
|
||||
|
||||
hv_land[alt] = next;
|
||||
|
||||
while(alt->distance > -100) {
|
||||
auto alt1 = createStep(alt, 0);
|
||||
alt1->alt = alt->alt;
|
||||
auto h1 = createStep(h, dir);
|
||||
if(h1->alt) return;
|
||||
altpairs.emplace_back(h1, alt1);
|
||||
h1->alt = alt1;
|
||||
|
||||
auto dir_alt = alt->c.spin(0);
|
||||
auto dir_h = h->c.spin(dir);
|
||||
|
||||
dir = altmap::relspin(alt1) = gmod(dir_h - dir_alt, alt->type);
|
||||
|
||||
h = h1; alt = alt1;
|
||||
}
|
||||
|
||||
for(auto p: altpairs) p.first->alt = p.second;
|
||||
}
|
||||
|
||||
|
||||
struct cand_info {
|
||||
int best, bqty;
|
||||
heptagon *candidate;
|
||||
vector<int> free_dirs;
|
||||
};
|
||||
|
||||
cand_info voronoi_candidate(heptagon *h) {
|
||||
cand_info ci;
|
||||
ci.best = 999999; ci.bqty = 0;
|
||||
|
||||
for(int i=0; i<h->type; i++) {
|
||||
heptagon *ho = createStep(h, i);
|
||||
int ri = h->c.spin(i);
|
||||
auto hoa = ho->alt;
|
||||
if(hoa && hoa->alt) {
|
||||
auto relspin = altmap::relspin(hoa);
|
||||
/* we want ho->move(ri) which is hoa->move(ri - relspin) */
|
||||
int dir = gmod(ri - relspin, hoa->type);
|
||||
heptagon *hoa1 = createStep(hoa, dir);
|
||||
if(!hoa1->alt) hoa1->alt = hoa->alt;
|
||||
auto dist = hoa1->distance;
|
||||
if(dist < ci.best) {
|
||||
ci.best = dist;
|
||||
ci.bqty = 0;
|
||||
}
|
||||
if(dist == ci.best && ci.candidate != hoa1) {
|
||||
ci.bqty++;
|
||||
ci.candidate = hoa1;
|
||||
int rb = hoa->c.spin(dir);
|
||||
/* hoa1->alt->move(rb) is h->move(rb+relspin to compute) */
|
||||
altmap::relspin(ci.candidate) = gmod(i - rb, ci.candidate->type);
|
||||
}
|
||||
}
|
||||
else ci.free_dirs.push_back(i);
|
||||
}
|
||||
return ci;
|
||||
}
|
||||
|
||||
vector<eLand> list_adjacent_lands(heptagon *h) {
|
||||
vector<eLand> res;
|
||||
for(int i=0; i<h->type; i++) {
|
||||
heptspin hs = heptspin(h, i);
|
||||
hs += wstep;
|
||||
auto alt = hs.at->alt;
|
||||
if(!alt) continue;
|
||||
alt = alt->alt;
|
||||
res.push_back(hv_land.at(alt));
|
||||
// go arround the region of alt using the 'butterfly' method, to find the other two lands which seem adjacent
|
||||
for(int d: {-1, 1}) {
|
||||
auto hs1 = hs;
|
||||
for(int i=0; i<100; i++) {
|
||||
hs1 += d;
|
||||
hs1 += wstep;
|
||||
if(!hs1.at->alt) { hs1 += wstep; continue; }
|
||||
auto alt1 = hs1.at->alt->alt;
|
||||
if(alt1 != alt) {
|
||||
res.push_back(hv_land.at(alt1)); break;
|
||||
}
|
||||
hs1 += d;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(res.empty()) return { laBarrier };
|
||||
return res;
|
||||
}
|
||||
|
||||
void extend_altmap_voronoi(heptagon *h) {
|
||||
if(h->alt) return;
|
||||
|
||||
auto ci = voronoi_candidate(h);
|
||||
|
||||
if(ci.bqty == 0) {
|
||||
new_voronoi_root(h, -30, hrand(h->type), firstland);
|
||||
return;
|
||||
}
|
||||
else if(ci.bqty > 0 && isize(ci.free_dirs)) {
|
||||
auto& expansion = get_expansion();
|
||||
ld growth = expansion.get_growth();
|
||||
ld odds = pow(growth, ci.candidate->distance) * isize(ci.free_dirs);
|
||||
if(hrandf() < odds / (1 + odds)) {
|
||||
vector<eLand> lands_list = list_adjacent_lands(h);
|
||||
|
||||
auto dist = ci.candidate->distance;
|
||||
// in PURE, could be a tie, or the new root could win
|
||||
if(PURE) dist -= hrand(2);
|
||||
// in BITRUNCATED, it could change too.. need a better formula probably
|
||||
if(BITRUNCATED) dist += hrand(3) - 1;
|
||||
// do not care about others...
|
||||
new_voronoi_root(h, dist, hrand_elt(ci.free_dirs), getNewLand2(lands_list));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
h->alt = ci.candidate;
|
||||
}
|
||||
|
||||
EX pair<heptagon*, int> get_voronoi_winner(cell *c) {
|
||||
if(c == c->master->c7) {
|
||||
extend_altmap_voronoi(c->master);
|
||||
auto ci = voronoi_candidate(c->master);
|
||||
if(ci.bqty == 1) return { ci.candidate->alt, ci.best };
|
||||
else return { nullptr, ci.best };
|
||||
}
|
||||
else if(!BITRUNCATED) return get_voronoi_winner(c->master->c7);
|
||||
else {
|
||||
vector<heptagon*> nearh;
|
||||
for(int i=0; i<c->type; i++) {
|
||||
c->cmove(i);
|
||||
if(c->move(i)->master->c7 == c->move(i)) nearh.push_back(c->move(i)->master);
|
||||
}
|
||||
for(auto h: nearh) extend_altmap_voronoi(h);
|
||||
for(auto h: nearh) if(!h->alt) return { nullptr, 0 };
|
||||
pair<heptagon*, int> best = {nullptr, 999999};
|
||||
int bqty = 0;
|
||||
for(auto h: nearh) {
|
||||
vector<int> dists;
|
||||
for(auto h1: nearh) {
|
||||
if(h == h1) dists.push_back(h->alt->distance);
|
||||
else {
|
||||
for(int i=0; i<h->type; i++) if(h->cmove(i) == h1) {
|
||||
auto ha1 = createStep(h->alt, gmod(i - altmap::relspin(h->alt), h->type));
|
||||
dists.push_back(ha1->distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
sort(dists.begin(), dists.end());
|
||||
int gdist;
|
||||
if(dists.back() == dists[0]) gdist = dists[0] - 1;
|
||||
else if(dists.back() == dists[0] + 2) gdist = dists[0] + 1;
|
||||
else gdist = dists[0];
|
||||
if(gdist < best.second) {
|
||||
best.second = gdist; bqty = 0;
|
||||
}
|
||||
if(gdist == best.second) {
|
||||
bqty++;
|
||||
if(bqty == 1 || best.first == h->alt->alt) best.first = h->alt->alt;
|
||||
else best.first = nullptr;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
}
|
||||
|
||||
#if MAXMDIM >= 4
|
||||
EX int hrandom_adjacent(cellwalker cw) {
|
||||
auto& da = currentmap->dirdist(cw);
|
||||
|
@ -335,7 +511,12 @@ EX void beCIsland(cell *c) {
|
|||
}
|
||||
|
||||
EX void generateTreasureIsland(cell *c) {
|
||||
if(ls::voronoi_structure()) {
|
||||
if(c->land != laCaribbean) return;
|
||||
}
|
||||
else {
|
||||
gen_alt(c);
|
||||
}
|
||||
if(isOnCIsland(c)) return;
|
||||
|
||||
bool src = hrand(100) < 10;
|
||||
|
@ -348,13 +529,18 @@ EX void generateTreasureIsland(cell *c) {
|
|||
for(int i=0; i<c->type; i++) {
|
||||
cell *c2 = createMov(c, i);
|
||||
if(!eubinary) currentmap->extend_altmap(c2->master);
|
||||
if(greater_alt(c, c2)) {
|
||||
auto ok = [&] (cell *c2) {
|
||||
if(ls::hv_structure() && get_voronoi_winner(c2).first != get_voronoi_winner(c).first) return false;
|
||||
return true;
|
||||
};
|
||||
if(ok(c2) && greater_alt(c, c2)) {
|
||||
ctab.push_back(c2);
|
||||
qlo = i; qhi = i;
|
||||
while(true && isize(ctab) < c->type) {
|
||||
qlo--;
|
||||
c2 = c->cmodmove(qlo);
|
||||
if(!have_alt(c2)) break;
|
||||
if(!ok(c2)) break;
|
||||
if(celldistAlt(c2) >= celldistAlt(c)) break;
|
||||
ctab.push_back(c2);
|
||||
}
|
||||
|
@ -362,6 +548,7 @@ EX void generateTreasureIsland(cell *c) {
|
|||
qhi++;
|
||||
c2 = c->cmodmove(qhi);
|
||||
if(!have_alt(c2)) break;
|
||||
if(!ok(c2)) break;
|
||||
if(celldistAlt(c2) >= celldistAlt(c)) break;
|
||||
ctab.push_back(c2);
|
||||
}
|
||||
|
@ -375,6 +562,7 @@ EX void generateTreasureIsland(cell *c) {
|
|||
return;
|
||||
}
|
||||
cell* c2 = c->cmodmove((qlo+qhi)/2);
|
||||
if(ls::voronoi_structure() && c2->land != laCaribbean) c2->land = laCaribbean;
|
||||
generateTreasureIsland(c2);
|
||||
if(!src) {
|
||||
c->wall = c2->wall;
|
||||
|
@ -515,6 +703,9 @@ EX int coastval(cell *c, eLand base) {
|
|||
if(!c->landparam) return UNKNOWN;
|
||||
return c->landparam & 255;
|
||||
}
|
||||
else if(base == laWestWall) {
|
||||
if(c->land != base) return 0;
|
||||
}
|
||||
else {
|
||||
if(c->land == laOceanWall || c->land == laCaribbean || c->land == laWhirlpool ||
|
||||
c->land == laLivefjord || c->land == laWarpSea || c->land == laKraken || c->land == laDocks || c->land == laBrownian)
|
||||
|
@ -817,7 +1008,7 @@ EX void buildEquidistant(cell *c) {
|
|||
if(c->landparam > 30 && b == laOcean && !generatingEquidistant && !mhybrid && hrand(10) < 5 && chance)
|
||||
buildAnotherEquidistant(c);
|
||||
|
||||
if(c->landparam > HAUNTED_RADIUS+5 && b == laGraveyard && !generatingEquidistant && !mhybrid && hrand(100) < (PURE?25:5) && items[itBone] >= U10 && chance)
|
||||
if(c->landparam > HAUNTED_RADIUS+5 && b == laGraveyard && !generatingEquidistant && !mhybrid && hrand(100) < (PURE?25:5) && landUnlockedIngame(laHaunted) && chance)
|
||||
buildAnotherEquidistant(c);
|
||||
}
|
||||
|
||||
|
@ -944,6 +1135,7 @@ EX void setLandSphere(cell *c) {
|
|||
vector<eLand> euland;
|
||||
map<int, eLand> euland3;
|
||||
map<int, eLand> euland3_hash;
|
||||
EX map<array<int, 3>, eLand> landscape_lands;
|
||||
|
||||
EX eLand& get_euland(int c) {
|
||||
euland.resize(max_vec);
|
||||
|
@ -956,6 +1148,8 @@ EX void clear_euland(eLand first) {
|
|||
if(!nonisotropic) euland[0] = euland[1] = euland[max_vec-1] = first;
|
||||
euland3.clear();
|
||||
euland3[0] = first;
|
||||
landscape_lands.clear();
|
||||
landscape_lands[make_array(0,0,0)] = first;
|
||||
}
|
||||
|
||||
bool valid_wall_at(int c) {
|
||||
|
@ -1135,7 +1329,7 @@ EX void setLandEuclid(cell *c) {
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
setland(c, specialland);
|
||||
if(!c->land) setland(c, specialland);
|
||||
if(ls::any_nowall()) {
|
||||
auto co = euc2_coordinates(c);
|
||||
int y = co.second;
|
||||
|
@ -1434,7 +1628,9 @@ EX bool extend_alt(cell *c, eLand horoland, eLand overland, bool extend_in_singl
|
|||
return false;
|
||||
}
|
||||
|
||||
EX bool can_start_horo(cell *c) {
|
||||
EX bool can_start_horo(cell *c, bool allowed_in_horo IS(false)) {
|
||||
if(ls::voronoi_structure()) return false;
|
||||
if(!allowed_in_horo && ls::horodisk_structure()) return false;
|
||||
if(yendor::on && !among(c->land, laCaribbean, laStorms))
|
||||
return false;
|
||||
return ctof(c) && !have_alt(c) && horo_ok() && !randomPatternsMode && !racing::on;
|
||||
|
@ -1579,6 +1775,21 @@ EX void build_walls(cell *c, cell *from) {
|
|||
else if(good_for_wall(c) && isWarpedType(c->land) && hrand(10000) < 3000 && c->land &&
|
||||
buildBarrierNowall(c, eLand(c->land ^ laWarpSea ^ laWarpCoast))) { }
|
||||
|
||||
else if(land_structure == lsVineWalls) {
|
||||
int ev = emeraldval(c);
|
||||
if((ev | 11) == 43 && c->bardir == NODIR) {
|
||||
for(int i=0; i<c->type; i++) if(emeraldval(c->cmove(i)) == ev-4) {
|
||||
bool oldleft = true;
|
||||
for(int j=1; j<=3; j++)
|
||||
if(c->modmove(i+j) && c->modmove(i+j)->mpdist < c->mpdist)
|
||||
oldleft = false;
|
||||
buildBarrierStrong(c, i, oldleft, getNewLand(c->land));
|
||||
extendBarrier(c);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
else if(ls::single()) return;
|
||||
|
||||
else if(geometry == gNormal && celldist(c) < 3 && !GOLDBERG) {
|
||||
|
@ -1599,11 +1810,11 @@ EX void build_walls(cell *c, cell *from) {
|
|||
return;
|
||||
}
|
||||
|
||||
else if(good_for_wall(c) && c->land == laCrossroads4 && hrand(10000) < 7000 && c->land && !c->master->alt && !tactic::on && !racing::on &&
|
||||
else if(good_for_wall(c) && ls::any_wall() && c->land == laCrossroads4 && hrand(10000) < 7000 && c->land && !c->master->alt && !tactic::on && !racing::on &&
|
||||
buildBarrierNowall(c, getNewLand(laCrossroads4))) ;
|
||||
|
||||
else if(good_for_wall(c) && hrand(I10000) < 20 && !generatingEquidistant && !yendor::on && !tactic::on && !racing::on && !isCrossroads(c->land) &&
|
||||
gold() >= R200 && !weirdhyperbolic && !c->master->alt && c->bardir != NOBARRIERS &&
|
||||
else if(good_for_wall(c) && ls::any_wall() && hrand(I10000) < 20 && !generatingEquidistant && !yendor::on && !tactic::on && !racing::on && !isCrossroads(c->land) &&
|
||||
landUnlockedIngame(laCrossroads4) && !weirdhyperbolic && !c->master->alt && c->bardir != NOBARRIERS &&
|
||||
!inmirror(c) && !isSealand(c->land) && !isHaunted(c->land) && !isGravityLand(c->land) &&
|
||||
(c->land != laRlyeh || rlyehComplete()) &&
|
||||
c->land != laTortoise && c->land != laPrairie && c->land &&
|
||||
|
@ -1656,10 +1867,14 @@ EX void start_camelot(cell *c) {
|
|||
heptagon *alt = create_altmap(c, ls::single() ? 2 : rtr+(hyperbolic && WDIM == 3 ? 11 : 14), ls::single() ? hsA : hsOrigin);
|
||||
if(alt) {
|
||||
altmap::radius(alt) = rtr;
|
||||
altmap::orig_land(alt) = c->land;
|
||||
altmap::orig_land(alt) = ls::horodisk_structure() ? laCrossroads : c->land;
|
||||
hv_land[alt] = laCamelot;
|
||||
}
|
||||
}
|
||||
|
||||
EX bool debug_voronoi;
|
||||
EX map<heptagon*, eLand> hv_land;
|
||||
|
||||
EX void build_horocycles(cell *c, cell *from) {
|
||||
|
||||
bool deepOcean = deep_ocean_at(c, from);
|
||||
|
@ -1671,7 +1886,7 @@ EX void build_horocycles(cell *c, cell *from) {
|
|||
|
||||
// buildbigstuff
|
||||
|
||||
if(ls::any_order() && bearsCamelot(c->land) && can_start_horo(c) && !bt::in() &&
|
||||
if(ls::any_order() && (ls::horodisk_structure() || bearsCamelot(c->land)) && can_start_horo(c, true) && !bt::in() && !ls::voronoi_structure() &&
|
||||
#if MAXMDIM >= 4
|
||||
!(hyperbolic && WDIM == 3 && !reg3::in_hrmap_rule_or_subrule()) &&
|
||||
#endif
|
||||
|
@ -1679,13 +1894,13 @@ EX void build_horocycles(cell *c, cell *from) {
|
|||
items[itEmerald] >= U5)))
|
||||
start_camelot(c);
|
||||
|
||||
if(c->land == laRlyeh && can_start_horo(c) && (quickfind(laTemple) || peace::on || (hrand(I2000) < 100 && items[itStatue] >= U5)))
|
||||
if(c->land == laRlyeh && can_start_horo(c) && (quickfind(laTemple) || (hrand(I2000) < 100 && landUnlockedIngame(laTemple))))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
if(c->land == laJungle && can_start_horo(c) && (quickfind(laMountain) || (hrand(I2000) < 100 && landUnlocked(laMountain))))
|
||||
if(c->land == laJungle && can_start_horo(c) && (quickfind(laMountain) || (hrand(I2000) < 100 && landUnlockedIngame(laMountain))))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
if(c->land == laOvergrown && can_start_horo(c) && (quickfind(laClearing) || (hrand(I2000) < 25 && items[itMutant] >= U5 && isLandIngame(laClearing)))) {
|
||||
if(c->land == laOvergrown && can_start_horo(c) && (quickfind(laClearing) || (hrand(I2000) < 25 && landUnlockedIngame(laClearing)))) {
|
||||
heptagon *h = create_altmap(c, horo_gen_distance(), hsA);
|
||||
if(h) clearing::bpdata[h].root = NULL;
|
||||
}
|
||||
|
@ -1697,24 +1912,33 @@ EX void build_horocycles(cell *c, cell *from) {
|
|||
|
||||
if(c->land == laOcean && deepOcean && !generatingEquidistant && !peace::on && can_start_horo(c) &&
|
||||
(quickfind(laWhirlpool) || (
|
||||
hrand(2000) < (PURE ? 500 : 1000))))
|
||||
hrand(2000) < (PURE ? 500 : 1000) && landUnlockedIngame(laWhirlpool))))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
#if CAP_COMPLEX2
|
||||
if(c->land == laOcean && deepOcean && !generatingEquidistant && hrand(10000) < 20 && no_barriers_in_radius(c, 2) && hyperbolic && !quotient && !tactic::on && !safety)
|
||||
if(c->land == laOcean && deepOcean && !generatingEquidistant && hrand(10000) < 20 && no_barriers_in_radius(c, 2) && hyperbolic && !quotient && !tactic::on && !safety && !ls::hv_structure()
|
||||
&& landUnlockedIngame(laBrownian))
|
||||
brownian::init_further(c);
|
||||
#endif
|
||||
|
||||
if(c->land == laCaribbean && can_start_horo(c))
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
if(ls::horodisk_structure() && can_start_horo(c, true)) {
|
||||
auto m = create_altmap(c, horo_gen_distance(), hsA);
|
||||
if(m) {
|
||||
hv_land[m] = getNewLand(laCrossroads);
|
||||
clearing::bpdata[m].root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(c->land == laCanvas && can_start_horo(c) && ls::any_order())
|
||||
create_altmap(c, horo_gen_distance(), hsA);
|
||||
|
||||
if(c->land == laPalace && can_start_horo(c) && !princess::generating && !shmup::on && multi::players == 1 && !weirdhyperbolic &&
|
||||
(princess::forceMouse ? canReachPlayer(from, moMouse) :
|
||||
(hrand(2000) < (peace::on ? 100 : 20))) &&
|
||||
(princess::challenge || kills[moVizier] || peace::on)) {
|
||||
landUnlockedIngame(laPrincessQuest)) {
|
||||
create_altmap(c, PRADIUS0, hsOrigin, waPalace);
|
||||
celllister cl(c, 5, 1000000, NULL);
|
||||
for(cell *c: cl.lst) if(c->master->alt) currentmap->extend_altmap(c->master);
|
||||
|
@ -1857,6 +2081,9 @@ EX void buildCamelot(cell *c) {
|
|||
if(c->land == laNone) printf("Camelot\n"); // NONEDEBUG
|
||||
}
|
||||
}
|
||||
else if(ls::hv_structure()) {
|
||||
setland(c, eLand(altmap::orig_land(c->master->alt->alt)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1950,9 +2177,38 @@ EX void gen_temple(cell *c) {
|
|||
else c->landparam = 2;
|
||||
}
|
||||
|
||||
/* -2 should be perfect */
|
||||
EX int horodisk_from = -2;
|
||||
|
||||
EX void pick_hv_subland(cell *c, eLand l, int depth) {
|
||||
if(l == laElementalWall) {
|
||||
auto land_at = [] (int dp) {
|
||||
int i = dp - 12;
|
||||
if((i & 7) == 7) return laElementalWall;
|
||||
i >>= 3;
|
||||
eLand tab[4] = { laEAir, laEWater, laEEarth, laEFire };
|
||||
return tab[i&3];
|
||||
};
|
||||
|
||||
setland(c, land_at(depth));
|
||||
if(c->land == laElementalWall) {
|
||||
c->barleft = land_at(depth-1);
|
||||
c->barright = land_at(depth+1);
|
||||
if(hrand(100) < 75)
|
||||
c->wall = getElementalWall(hrand(2) ? c->barleft : c->barright);
|
||||
}
|
||||
}
|
||||
else if(l == laWarpCoast) {
|
||||
int i = (depth & 8);
|
||||
setland(c, i ? laWarpCoast : laWarpSea);
|
||||
}
|
||||
else setland(c, l);
|
||||
}
|
||||
|
||||
EX void moreBigStuff(cell *c) {
|
||||
if(disable_bigstuff) return;
|
||||
|
||||
if(!ls::hv_structure())
|
||||
if((bearsCamelot(c->land) && !euclid && !quotient && !nil) || c->land == laCamelot)
|
||||
if(have_alt(c)) if(!(bt::in() && specialland != laCamelot))
|
||||
buildCamelot(c);
|
||||
|
@ -1967,11 +2223,49 @@ EX void moreBigStuff(cell *c) {
|
|||
c->wall = waSea;
|
||||
}
|
||||
|
||||
extend_alt(c, laPalace, laPalace, false, PRADIUS1);
|
||||
if(ls::voronoi_structure()) {
|
||||
auto p = get_voronoi_winner(c);
|
||||
auto ph = p.first;
|
||||
if(ph) {
|
||||
eLand l = hv_land[ph];
|
||||
pick_hv_subland(c, l, p.second);
|
||||
if(isEquidLand(l)) c->landparam = 1-p.second;
|
||||
}
|
||||
else {
|
||||
setland(c, laBarrier);
|
||||
}
|
||||
}
|
||||
|
||||
if(ls::horodisk_structure()) {
|
||||
if(have_alt(c) && masterAlt(c) <= 0) {
|
||||
gen_alt(c);
|
||||
preventbarriers(c);
|
||||
}
|
||||
if(have_alt(c) && hv_land[c->master->alt->alt] == laCamelot) {
|
||||
buildCamelot(c);
|
||||
}
|
||||
else if(have_alt(c) && celldistAlt(c) <= horodisk_from) {
|
||||
eLand l = hv_land[c->master->alt->alt];
|
||||
pick_hv_subland(c, l, celldistAlt(c));
|
||||
if(l == laCaribbean) generateTreasureIsland(c);
|
||||
if(l == laWhirlpool && celldistAlt(c) >= -1) {
|
||||
setland(c, laOcean);
|
||||
c->landparam = 30;
|
||||
}
|
||||
if(l == laWestWall && celldistAlt(c) >= -1) {
|
||||
setland(c, laCrossroads);
|
||||
}
|
||||
if(isEquidLand(l)) c->landparam = 1-celldistAlt(c);
|
||||
}
|
||||
else
|
||||
setland(c, laCrossroads);
|
||||
}
|
||||
|
||||
if(!ls::hv_structure()) extend_alt(c, laPalace, laPalace, false, PRADIUS1);
|
||||
|
||||
extend_alt(c, laCanvas, laCanvas);
|
||||
|
||||
if(extend_alt(c, laStorms, laStorms, false)) {
|
||||
if(!ls::hv_structure() && extend_alt(c, laStorms, laStorms, false)) {
|
||||
int d = celldistAlt(c);
|
||||
if(d <= -2) {
|
||||
c->wall = eubinary ? waCharged : (altmap::which(c->master->alt->alt) & 1) ? waCharged : waGrounded;
|
||||
|
@ -1990,10 +2284,12 @@ EX void moreBigStuff(cell *c) {
|
|||
c->wall = waColumn;
|
||||
}
|
||||
|
||||
else if(extend_alt(c, laTemple, laRlyeh))
|
||||
else if(!ls::hv_structure() && extend_alt(c, laTemple, laRlyeh))
|
||||
gen_temple(c);
|
||||
|
||||
if(extend_alt(c, laClearing, laOvergrown)) {
|
||||
if(ls::hv_structure() && c->land == laTemple) gen_temple(c);
|
||||
|
||||
if(!ls::hv_structure() && extend_alt(c, laClearing, laOvergrown)) {
|
||||
if(in_single_horo(c, laClearing)) {
|
||||
c->land = laClearing, c->wall = waNone;
|
||||
}
|
||||
|
@ -2001,11 +2297,21 @@ EX void moreBigStuff(cell *c) {
|
|||
c->wall = waSmallTree, c->monst = moNone, c->item = itNone, c->landparam = 1;
|
||||
}
|
||||
|
||||
if(extend_alt(c, laMountain, laJungle) && in_single_horo(c, laMountain)) {
|
||||
if(ls::horodisk_structure() && c->land == laClearing) {
|
||||
if(celldistAlt(c) >= -1)
|
||||
c->wall = waSmallTree, c->monst = moNone, c->item = itNone, c->landparam = 1;
|
||||
}
|
||||
|
||||
if(ls::voronoi_structure() && c->land == laClearing) {
|
||||
if(celldistAlt(c) == -20)
|
||||
c->wall = waSmallTree, c->monst = moNone, c->item = itNone, c->landparam = 1;
|
||||
}
|
||||
|
||||
if(!ls::hv_structure() && extend_alt(c, laMountain, laJungle) && in_single_horo(c, laMountain)) {
|
||||
c->land = laMountain, c->wall = waNone;
|
||||
}
|
||||
|
||||
if(extend_alt(c, laWhirlpool, laOcean) && in_single_horo(c, laWhirlpool))
|
||||
if(!ls::hv_structure() && extend_alt(c, laWhirlpool, laOcean) && in_single_horo(c, laWhirlpool))
|
||||
c->land = laWhirlpool, c->wall = waSea, c->monst = moNone, c->item = itNone;
|
||||
}
|
||||
|
||||
|
@ -2031,7 +2337,7 @@ EX void pregen() {
|
|||
currentlands.clear();
|
||||
if(ls::any_chaos() && !ls::std_chaos())
|
||||
for(eLand l: land_over)
|
||||
if(landUnlocked(l) && isLandIngame(l))
|
||||
if(landUnlockedIngame(l))
|
||||
currentlands.push_back(l);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -854,15 +854,36 @@ 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)
|
||||
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;
|
||||
else if(geometry == gHoroTris)
|
||||
|
||||
case gHoroTris:
|
||||
return c->c.spin(S7-1) == 0 && (c->master->distance & 1);
|
||||
else
|
||||
|
||||
default:
|
||||
return (c->master->zebraval == 1) && (c->master->distance & 1);
|
||||
}
|
||||
}
|
||||
|
||||
EX pair<gp::loc, gp::loc> gpvalue(heptagon *h) {
|
||||
int d = h->c.spin(S7-1);
|
||||
|
|
49
cell.cpp
49
cell.cpp
|
@ -99,11 +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;
|
||||
virtual bool link_alt(heptagon *h, heptagon *alt, hstate firststate, int dir) override;
|
||||
virtual void on_dim_change();
|
||||
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*);
|
||||
|
@ -554,8 +554,10 @@ EX void 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();
|
||||
|
@ -605,17 +607,17 @@ 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))));
|
||||
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))));
|
||||
DEBB(DF_MEMORY, (hr::format("DEL %p\n", hr::voidp(c))));
|
||||
gp::delete_mapped(c);
|
||||
destroy_cell(c);
|
||||
}
|
||||
|
@ -669,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)); }
|
||||
|
@ -770,9 +772,9 @@ 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) {
|
||||
|
@ -861,12 +863,12 @@ EX int updir_alt(heptagon *h) {
|
|||
|
||||
|
||||
#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
|
||||
|
@ -1467,14 +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);
|
||||
}
|
||||
|
@ -1630,7 +1633,7 @@ EX vector<adj_data> adj_minefield_cells_full(cell *c) {
|
|||
if(hdist(h, T * h2) < 1e-6) shares = true;
|
||||
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));
|
||||
|
|
220
celldrawer.cpp
220
celldrawer.cpp
|
@ -67,6 +67,8 @@ struct celldrawer {
|
|||
void radar_grid();
|
||||
|
||||
void do_viewdist();
|
||||
|
||||
void draw_bowpath();
|
||||
};
|
||||
|
||||
inline void drawcell(cell *c, const shiftmatrix& V) {
|
||||
|
@ -77,8 +79,8 @@ inline void drawcell(cell *c, const shiftmatrix& V) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static const int trapcol[4] = {0x904040, 0xA02020, 0xD00000, 0x303030};
|
||||
static const int terracol[8] = {0xD000, 0xE25050, 0xD0D0D0, 0x606060, 0x303030, 0x181818, 0x0080, 0x8080};
|
||||
static constexpr int trapcol[4] = {0x904040, 0xA02020, 0xD00000, 0x303030};
|
||||
static constexpr int terracol[8] = {0xD000, 0xE25050, 0xD0D0D0, 0x606060, 0x303030, 0x181818, 0x0080, 0x8080};
|
||||
|
||||
void celldrawer::addaura() {
|
||||
hr::addaura(tC0(V), darkened(aura_color), fd);
|
||||
|
@ -92,6 +94,14 @@ void eclectic_red(color_t& col) {
|
|||
|
||||
constexpr ld spinspeed = .75 / M_PI;
|
||||
|
||||
EX color_t apply_mine_knowledge(color_t wcol, cell* c) {
|
||||
if(mine::marked_safe(c))
|
||||
return gradient(wcol, 0x40FF40, 0, 0.2, 1);
|
||||
if(mine::marked_mine(c))
|
||||
return gradient(wcol, 0xFF4040, -1, vid.ispeed ? sintick(100) : 1, 1);
|
||||
return wcol;
|
||||
}
|
||||
|
||||
void celldrawer::setcolors() {
|
||||
|
||||
wcol = fcol = winf[c->wall].color;
|
||||
|
@ -274,7 +284,7 @@ void celldrawer::setcolors() {
|
|||
if(c->wall == waWaxWall) wcol = c->landparam;
|
||||
if(items[itOrbInvis] && c->wall == waNone && c->landparam)
|
||||
fcol = gradient(fcol, 0xFF0000, 0, c->landparam, 100);
|
||||
if(c->bardir == NOBARRIERS && c->barleft)
|
||||
if(among(int(c->bardir), NOBARRIERS, NOBARRIERS2) && c->barleft)
|
||||
fcol = minf[moBug0+c->barright].color;
|
||||
break;
|
||||
case laSwitch:
|
||||
|
@ -366,11 +376,12 @@ void celldrawer::setcolors() {
|
|||
#if CAP_FIELD
|
||||
case laPrairie:
|
||||
if(prairie::isriver(c)) {
|
||||
fcol = flip_dark(c->LHU.fi.rval, 0x402000, 0x503000);
|
||||
fcol = flip_dark(prairie::get_val(c), 0x402000, 0x503000);
|
||||
}
|
||||
else {
|
||||
fcol = 0x004000 + 0x001000 * c->LHU.fi.walldist;
|
||||
fcol += 0x10000 * (255 - 511 / (1 + max((int) c->LHU.fi.flowerdist, 1)));
|
||||
if(ls::hv_structure()) fcol = prairie::nearriver(c) ? 0x40FF00 : 0x40D000;
|
||||
// fcol += 0x1 * (511 / (1 + max((int) c->LHU.fi.walldist2, 1)));
|
||||
}
|
||||
break;
|
||||
|
@ -538,10 +549,7 @@ void celldrawer::setcolors() {
|
|||
|
||||
case waMineUnknown: case waMineMine:
|
||||
#if CAP_COMPLEX2
|
||||
if(mine::marked_safe(c))
|
||||
fcol = wcol = gradient(wcol, 0x40FF40, 0, 0.2, 1);
|
||||
else if(mine::marked_mine(c))
|
||||
fcol = wcol = gradient(wcol, 0xFF4040, -1, vid.ispeed ? sintick(100) : 1, 1);
|
||||
if(!mine_markers) fcol = wcol = apply_mine_knowledge(wcol, c);
|
||||
goto fallthrough;
|
||||
#endif
|
||||
|
||||
|
@ -844,13 +852,6 @@ void celldrawer::draw_grid() {
|
|||
|
||||
int prec = grid_prec();
|
||||
|
||||
if(vid.grid && c->bardir != NODIR && c->bardir != NOBARRIERS && c->land != laHauntedWall &&
|
||||
c->barleft != NOWALLSEP_USED && GDIM == 2) {
|
||||
color_t col = darkena(0x505050, 0, 0xFF);
|
||||
gridline(V, C0, tC0(cgi.heptmove[c->bardir]), col, prec+1);
|
||||
gridline(V, C0, tC0(cgi.hexmove[c->bardir]), col, prec+1);
|
||||
}
|
||||
|
||||
if(inmirrorcount) return;
|
||||
|
||||
if(vid.grid || (c->land == laAsteroids && !(WDIM == 2 && GDIM == 3))) ; else return;
|
||||
|
@ -968,7 +969,7 @@ void celldrawer::draw_halfvine() {
|
|||
}
|
||||
|
||||
else if(wmspatial || GDIM == 3) {
|
||||
floorshape& shar = *((wmplain || GDIM == 3) ? (floorshape*)&cgi.shFloor : (floorshape*)&cgi.shFeatherFloor);
|
||||
floorshape& shar = *(GDIM == 3 ? (floorshape*)&cgi.shFullFloor : wmplain ? (floorshape*)&cgi.shFloor : (floorshape*)&cgi.shFeatherFloor);
|
||||
|
||||
set_floor(shar);
|
||||
|
||||
|
@ -1335,7 +1336,7 @@ void celldrawer::set_land_floor(const shiftmatrix& Vf) {
|
|||
if(shmup::on || GDIM == 3)
|
||||
shmup_gravity_floor();
|
||||
else
|
||||
set_towerfloor();
|
||||
set_towerfloor(ls::hv_structure() ? celldistAltPlus : coastvalEdge);
|
||||
break;
|
||||
|
||||
case laBrownian:
|
||||
|
@ -1383,6 +1384,39 @@ bool celldrawer::set_randompattern_floor() {
|
|||
}
|
||||
|
||||
EX bool numerical_minefield;
|
||||
EX int mine_zero_display = 1;
|
||||
EX bool mine_hollow;
|
||||
EX bool mine_markers;
|
||||
|
||||
EX void draw_mine_numbers(int mines, const shiftmatrix& V, int ct6) {
|
||||
auto hollow = [&] (hpcshape& sh, color_t col) {
|
||||
if(mine_hollow) {
|
||||
dynamicval<color_t> dc(poly_outline, col);
|
||||
queuepoly(V, sh, 0);
|
||||
}
|
||||
else
|
||||
queuepoly(V, sh, col);
|
||||
};
|
||||
if(mines == 0 && mine_zero_display < (WDIM == 3 ? 1 : 2)) return;
|
||||
if(numerical_minefield) {
|
||||
string label = its(mines);
|
||||
queuestr(V, (mines >= 10 ? .5 : 1) * mapfontscale / 100, label, darkened(minecolors[mines]), 8);
|
||||
}
|
||||
else {
|
||||
if(mines >= isize(minecolors)) hollow(cgi.shBigMineMark[ct6], darkena(minecolors[mines/isize(minecolors)], 0, 0xFF));
|
||||
hollow(cgi.shMineMark[ct6], darkena(minecolors[mines], 0, 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
EX void draw_mine_markers(cell *c, const shiftmatrix& V) {
|
||||
if(mine_markers && !mine::marked_safe(c)) {
|
||||
color_t col = 0xFF4040;
|
||||
if(mine::marked_mine(c))
|
||||
col = gradient(winf[waMineMine].color, col, -1, vid.ispeed ? sintick(100) : 1, 1);
|
||||
dynamicval<color_t> dc(poly_outline, (col << 8) | 0xFF);
|
||||
queuepoly(V, cgi.shJoint, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void celldrawer::draw_features() {
|
||||
char xch = winf[c->wall].glyph;
|
||||
|
@ -1628,18 +1662,12 @@ void celldrawer::draw_features() {
|
|||
|
||||
case waMineOpen: {
|
||||
int mines = countMinesAround(c);
|
||||
if(numerical_minefield) {
|
||||
if(mines) {
|
||||
string label = its(mines);
|
||||
queuestr(V, mines >= 10 ? .5 : 1, label, darkened(minecolors[mines]), 8);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(mines >= isize(minecolors))
|
||||
queuepoly(V, cgi.shBigMineMark[ct6], darkena(minecolors[mines/isize(minecolors)], 0, 0xFF));
|
||||
if(mines)
|
||||
queuepoly(V, cgi.shMineMark[ct6], darkena(minecolors[mines], 0, 0xFF));
|
||||
draw_mine_numbers(mines, V, ct6);
|
||||
break;
|
||||
}
|
||||
|
||||
case waMineUnknown: case waMineMine: {
|
||||
draw_mine_markers(c, V);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1769,6 +1797,9 @@ void celldrawer::draw_features_and_walls_3d() {
|
|||
if(anyshiftclick) return;
|
||||
}
|
||||
|
||||
if(among(c->wall, waMineUnknown, waMineMine))
|
||||
draw_mine_markers(c, face_the_player(V));
|
||||
|
||||
if(isWall3(c, wcol)) {
|
||||
if(!no_wall_rendering) {
|
||||
if(c->wall == waChasm && c->land == laMemory && !in_perspective()) {
|
||||
|
@ -1845,6 +1876,12 @@ void celldrawer::draw_features_and_walls_3d() {
|
|||
queuepoly(V, cgi.shPlainWall3D[ofs + a], darkena(wcol2 - d * get_darkval(c, a), 0, 0xFF));
|
||||
}
|
||||
}
|
||||
if(WDIM == 3 && c->wall == waRose) {
|
||||
color_t col = winf[waRose].color;
|
||||
color_t col2 = (col << 8) | 0xFF;
|
||||
if(rosephase == 7) col2 = 0xFFFFFFFF;
|
||||
addradar(V, winf[waRose].glyph, col, col2);
|
||||
}
|
||||
} }
|
||||
else {
|
||||
if(!no_wall_rendering) for(int a=0; a<c->type; a++) if(c->move(a)) {
|
||||
|
@ -1872,9 +1909,7 @@ void celldrawer::draw_features_and_walls_3d() {
|
|||
}
|
||||
else {
|
||||
int mines = countMinesAround(c);
|
||||
if(mines >= isize(minecolors))
|
||||
queuepoly(face_the_player(V), cgi.shBigMineMark[0], darkena(minecolors[mines/isize(minecolors)], 0, 0xFF));
|
||||
queuepoly(face_the_player(V), cgi.shMineMark[0], darkena(minecolors[mines], 0, 0xFF));
|
||||
draw_mine_numbers(mines, face_the_player(V), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1941,7 +1976,7 @@ void celldrawer::check_rotations() {
|
|||
else
|
||||
ds.total += unshift(tC0(V));
|
||||
ds.qty++;
|
||||
ds.point = cgi.emb->normalize_flat(ds.total);
|
||||
ds.point = cgi.emb->normalize_flat(ds.total / ds.qty);
|
||||
if(mproduct) ds.point = orthogonal_move(ds.point, ds.depth / ds.qty);
|
||||
if(side == 2) for(int i=0; i<3; i++) ds.point[i] = -ds.point[i];
|
||||
if(side == 1) ds.point = spin(-90._deg) * ds.point;
|
||||
|
@ -1960,6 +1995,8 @@ void celldrawer::check_rotations() {
|
|||
int side = 0;
|
||||
if(cwt.at->land == laDungeon) side = 2;
|
||||
if(cwt.at->land == laWestWall) side = 1;
|
||||
if(cwt.at->land == laIvoryTower && ls::hv_structure()) side = 2;
|
||||
if(cwt.at->land == laDungeon && ls::hv_structure()) side = 0;
|
||||
if(models::do_rotate >= 1)
|
||||
use_if_less(edgeDepth(c), edgeDepth(old), cwt.at->landparam / 10., side);
|
||||
}
|
||||
|
@ -2024,6 +2061,7 @@ void celldrawer::bookkeeping() {
|
|||
modist2 = modist; mouseover2 = mouseover;
|
||||
modist = dist;
|
||||
mouseover = c;
|
||||
mouseoverV = V;
|
||||
}
|
||||
else if(dist < modist2) {
|
||||
modist2 = dist;
|
||||
|
@ -2073,7 +2111,7 @@ void celldrawer::draw_cellstat() {
|
|||
|
||||
if(c->land == laMirrored || c->land == laMirrorWall2 || c->land == laMirrored2) {
|
||||
string label = its(c->landparam);
|
||||
queuestr(V, 1 * .2, label, 0xFFFFFFFF, 1);
|
||||
queuestr(V, mapfontscale / 500, label, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
if(debug_tiles && mod_allowed()) {
|
||||
|
@ -2099,17 +2137,22 @@ void celldrawer::draw_cellstat() {
|
|||
#endif
|
||||
else
|
||||
label = its(shvid(c));
|
||||
queuestr(V, .5, label, 0xFFFFFFFF, 1);
|
||||
queuestr(V, mapfontscale / 200, label, 0xFFFFFFFF, 1);
|
||||
for(int i=0; i<c->type; i++) {
|
||||
queuestr(V * rgpushxto0(currentmap->get_corner(c, i, 4)), .2, its(i), 0xFFFFFFFF, 1);
|
||||
queuestr(V * rgpushxto0(mid(currentmap->get_corner(c, i, 4), currentmap->get_corner(c, i+1, 5))), .2, its(i), 0xFFFFFFFF, 1);
|
||||
queuestr(V * rgpushxto0(currentmap->get_corner(c, i, 4)), mapfontscale / 500, its(i), 0xFFFFFFFF, 1);
|
||||
queuestr(V * rgpushxto0(mid(currentmap->get_corner(c, i, 4), currentmap->get_corner(c, i+1, 5))), mapfontscale / 500, its(i), 0xFFFFFFFF, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(debug_voronoi && ls::hv_structure() && mod_allowed()) {
|
||||
auto p = get_voronoi_winner(c);
|
||||
queuestr(V, mapfontscale / 500, its(p.second), index_pointer_int(p.first) * 0x7F3015, 1);
|
||||
}
|
||||
|
||||
if(cmode & sm::TORUSCONFIG) {
|
||||
auto p = euc::coord_display(V, c);
|
||||
if(p.second != "")
|
||||
queuestr(V, p.first ? .2 : .6, p.second, p.first ? 0xFFFFFFD0 : 0xFFFF0040, 1);
|
||||
queuestr(V, (p.first ? .2 : .6) * mapfontscale / 100, p.second, p.first ? 0xFFFFFFD0 : 0xFFFF0040, 1);
|
||||
}
|
||||
|
||||
#if CAP_EDIT
|
||||
|
@ -2124,13 +2167,13 @@ void celldrawer::draw_cellstat() {
|
|||
|
||||
string label = its(si.id & 255);
|
||||
color_t col = forecolor ^ colorhash(si.id >> 8);
|
||||
queuestr(V, .5, label, 0xFF000000 + col);
|
||||
queuestr(V, mapfontscale / 200, label, 0xFF000000 + col);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(debug_cellnames && pointer_indices.count(c)) {
|
||||
shstream ss; print(ss, c);
|
||||
queuestr(V, .5, ss.s, 0xFFFFFFFF);
|
||||
queuestr(V, mapfontscale / 200, ss.s, 0xFFFFFFFF);
|
||||
queuepoly(V * ddspin(c, 0), cgi.shAsymmetric, darkena(0x000000, 0, 0xC0));
|
||||
}
|
||||
}
|
||||
|
@ -2222,9 +2265,6 @@ void celldrawer::draw_wall_full() {
|
|||
else if(patterns::whichShape == '2')
|
||||
set_floor(cgi.shMFloor3);
|
||||
|
||||
else if(embedded_plane && qfi.fshape == &cgi.shFloor)
|
||||
set_floor(cgi.shFullFloor);
|
||||
|
||||
#if CAP_TEXTURE
|
||||
else if(GDIM == 2 && texture::config.apply(c, Vf, darkena(fcol, fd, 0xFF))) ;
|
||||
#endif
|
||||
|
@ -2261,6 +2301,8 @@ void celldrawer::draw_wall_full() {
|
|||
|
||||
else set_land_floor(Vf);
|
||||
|
||||
if(embedded_plane && qfi.fshape == &cgi.shFloor) set_floor(cgi.shFullFloor);
|
||||
|
||||
// actually draw the floor
|
||||
|
||||
if(chasmg == 2) ;
|
||||
|
@ -2487,20 +2529,13 @@ void celldrawer::draw_item_full() {
|
|||
if(doHighlight()) asciiborder = kind_outline(it) >> 8;
|
||||
|
||||
if(it == itCompass && isPlayerOn(c)) {
|
||||
cell *c1 = c ? findcompass(c) : NULL;
|
||||
if(c1) {
|
||||
shiftmatrix P = ggmatrix(c1);
|
||||
shiftpoint P1 = tC0(P);
|
||||
|
||||
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
|
||||
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
addauraspecial(P1, 0xFF0000, 0);
|
||||
}
|
||||
shiftpoint dummy;
|
||||
mark_compass(c, dummy);
|
||||
}
|
||||
}
|
||||
|
||||
if(it) {
|
||||
if((c->land == laWhirlwind || c->item == itBabyTortoise || c->land == laWestWall) && c->wall != waBoat) {
|
||||
if(c->wall != waBoat) {
|
||||
double footphase = 0;
|
||||
applyAnimation(c, Vboat, footphase, LAYER_BOAT);
|
||||
}
|
||||
|
@ -2571,7 +2606,7 @@ void celldrawer::draw_monster_full() {
|
|||
bool dm = drawMonster(V, c->type, c, moncol, asciicol);
|
||||
if(dm) onradar = false;
|
||||
#if CAP_SHAPES
|
||||
if(isize(ptds) != q) {
|
||||
if(isize(ptds) != q && !(c == lmouseover_distant && isDie(c->monst))) {
|
||||
if(WDIM == 2 && GDIM == 3 && abs(cgi.SLEV[sl] - cgi.FLOOR) > 1e-6)
|
||||
pushdown(c, q, V, cgi.SLEV[sl] - cgi.FLOOR, false, false);
|
||||
if(GDIM ==2 && abs(geom3::factor_to_lev(zlevel(tC0(Vboat.T)))) > 1e-6)
|
||||
|
@ -2617,6 +2652,8 @@ void celldrawer::add_map_effects() {
|
|||
}
|
||||
}
|
||||
|
||||
draw_bowpath();
|
||||
|
||||
if(c->land == laBlizzard) {
|
||||
if(vid.backeffects) {
|
||||
if(c->cpdist <= getDistLimit())
|
||||
|
@ -2682,6 +2719,65 @@ void celldrawer::add_map_effects() {
|
|||
draw_gravity_particles();
|
||||
}
|
||||
|
||||
void celldrawer::draw_bowpath() {
|
||||
auto v = at_or_null(bow::bowpath_map, c);
|
||||
if(!v) return;
|
||||
for(auto& m: *v) {
|
||||
|
||||
hyperpoint h0 = C0, t0 = Hypc, h1 = C0, t1 = Hypc;
|
||||
bool birth = m.flags & bow::bpFIRST;
|
||||
|
||||
if(!birth) {
|
||||
ld d = cellgfxdist(c, m.prev.spin) / 2;
|
||||
h0 = ddspin(c, m.prev.spin) * xpush0(d);
|
||||
t0 = ddspin(c, m.prev.spin) * xpush(d) * xtangent(-d*2);
|
||||
}
|
||||
else birth = true;
|
||||
|
||||
if(!(m.flags & bow::bpLAST)) {
|
||||
ld d = cellgfxdist(c, m.next.spin) / 2;
|
||||
h1 = ddspin(c, m.next.spin) * xpush0(d);
|
||||
t1 = ddspin(c, m.next.spin) * xpush(d) * xtangent(-d*2);
|
||||
}
|
||||
|
||||
ld t = frac(ptick(PURE?500:250));
|
||||
|
||||
color_t arrow_color = getcs().swordcolor;
|
||||
|
||||
if(m.flags & bow::bpCOPIED) {
|
||||
arrow_color &= 0xFF;
|
||||
arrow_color |= mirrorcolor(m.next.mirrored != cwt.mirrored ? 1 : 0) << 8;
|
||||
}
|
||||
|
||||
color_t arrow_color_trans = arrow_color & 0xFFFFFF00;
|
||||
if(bow::fire_mode) arrow_color = gradient(arrow_color_trans, arrow_color, 0, 0.25, 1);
|
||||
|
||||
auto V1 = shmup::at_missile_level(V);
|
||||
|
||||
if(birth) {
|
||||
if(t > 0.8) {
|
||||
hyperpoint h = h1 + t1 * (1-t);
|
||||
hyperpoint tg = -t1;
|
||||
|
||||
poly_outline = OUTLINE_TRANS;
|
||||
queuepoly(V1 * rgpushxto0(h) * rspintox(gpushxto0(h) * tg), cgi.shTrapArrow, gradient(arrow_color_trans, arrow_color, 0.8, t, 1));
|
||||
poly_outline = OUTLINE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
hyperpoint h = h0 * (1-t) * (1-t) * (1 + 2 * t) + t0 * (1-t) * (1-t) * t + h1 * t * t * (3 - 2 * t) + t1 * t * t * (1-t);
|
||||
h = normalize(h);
|
||||
|
||||
hyperpoint tg = (h1 - h0) * 6 * t * (1-t) + (3 * t*t - 4*t + 1) * t0 + (2*t-3*t*t) * t1;
|
||||
|
||||
poly_outline = OUTLINE_TRANS;
|
||||
queuepoly(V1 * rgpushxto0(h) * rspintox(gpushxto0(h) * tg), cgi.shTrapArrow, arrow_color);
|
||||
poly_outline = OUTLINE_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void celldrawer::draw_gravity_particles() {
|
||||
unsigned int u = (unsigned int)(size_t)(c);
|
||||
u = ((u * 137) + (u % 1000) * 51) % 1000;
|
||||
|
@ -2784,7 +2880,7 @@ void celldrawer::draw() {
|
|||
|
||||
if(callhandlers(false, hooks_drawcell, c, V)) return;
|
||||
|
||||
if(history::on || inHighQual || WDIM == 3 || sightrange_bonus > gamerange_bonus) checkTide(c);
|
||||
checkTide(c);
|
||||
|
||||
if(1) {
|
||||
|
||||
|
@ -2891,7 +2987,7 @@ void celldrawer::draw() {
|
|||
string s = s0+asciichar;
|
||||
dynamicval<color_t> p(poly_outline, asciiborder << 8);
|
||||
if(!wmascii3)
|
||||
queuestrn(V, 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
else if(highwall(c) && conegraph(c)) {
|
||||
const int layers = 1 << detaillevel;
|
||||
string s1 = s0+asciichar1;
|
||||
|
@ -2899,7 +2995,7 @@ void celldrawer::draw() {
|
|||
for(int z=0; z<layers; z++)
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, geom3::actual_wall_height(), z, layers)), 1. - z * .5 / layers, s1, darkenedby(gradient(bordcolor, asciicol1, -layers, z, layers), darken), 1);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), asciicol == asciicol1 && asciichar == asciichar1 ? .5 : 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), (asciicol == asciicol1 && asciichar == asciichar1 ? .5 : 1) * mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
else if(highwall(c)) {
|
||||
const int layers = 1 << detaillevel;
|
||||
|
@ -2908,15 +3004,15 @@ void celldrawer::draw() {
|
|||
for(int z=0; z<layers; z++)
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, geom3::actual_wall_height(), z, layers)), 1, s1, darkenedby(gradient(bordcolor, asciicol1, -layers, z, layers), darken), 1);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.WALL), mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
else if((sl = snakelevel(c))) {
|
||||
string s1 = s0+asciichar1;
|
||||
poly_outline = bordcolor << 8;
|
||||
for(int z=0; z<sl*4; z++) if(z%4 == 0)
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, cgi.slev * sl, z, sl*4)), 1, s1, darkenedby(gradient(bordcolor, asciicol1, -sl, z, sl*4), darken), 1);
|
||||
queuestrn(orthogonal_move_fol(V, zgrad0(0, cgi.slev * sl, z, sl*4)), mapfontscale / 100, s1, darkenedby(gradient(bordcolor, asciicol1, -sl, z, sl*4), darken), 1);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.SLEV[sl]), 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.SLEV[sl]), mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
// else if(c->wall == waChasm) {
|
||||
// const int layers = 1 << detaillevel;
|
||||
|
@ -2925,12 +3021,12 @@ void celldrawer::draw() {
|
|||
else if(chasmgraph(c)) {
|
||||
string s1 = s0+asciichar1;
|
||||
poly_outline = bordcolor << 8;
|
||||
queuestrn(orthogonal_move_fol(V, cgi.BOTTOM), 1, s1, darkenedby(gradient(bordcolor, asciicol1, 0, 0.3, 1), darken), 2);
|
||||
queuestrn(orthogonal_move_fol(V, cgi.BOTTOM), mapfontscale / 100, s1, darkenedby(gradient(bordcolor, asciicol1, 0, 0.3, 1), darken), 2);
|
||||
poly_outline = asciiborder << 8;
|
||||
queuestrn(V, 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
else
|
||||
queuestrn(V, 1, s, darkenedby(asciicol, darken), 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(asciicol, darken), 2);
|
||||
}
|
||||
|
||||
draw_grid();
|
||||
|
|
328
changelog.txt
328
changelog.txt
|
@ -4972,3 +4972,331 @@ Mostly embedding-related improvements:
|
|||
- 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
|
||||
|
||||
2024-06-06 19:06 Update 13.0n
|
||||
|
||||
Bugfixes:
|
||||
- (v13.0m) fixed a bug with smart range
|
||||
- (v13.0m) partially fixed a bug with non-enterable characters in string edit in SDL2 (Windows)
|
||||
- fixed some bugs with not recognizing modes from earlier versions (for saved score purposes)
|
||||
- fixed land search in Overview
|
||||
- fixed a problem when loading saved maps from tes files
|
||||
- YASC code explanation now appears when it should (not when it should not)
|
||||
|
||||
Gameplay:
|
||||
- boats now erase rose waves when moved
|
||||
- illegal moves into dice now become kills if you have an Orb of Slaying
|
||||
- in Chaos mode, crossroads now appear if Hyperstones are unlocked (thanks to jlm)
|
||||
|
||||
Modes:
|
||||
- improved custom mode manager: it now displays all the modes you have tried (with PTM/YC/saved scores), and also you can name modes
|
||||
|
||||
2024-06-06 19:06 Update 13.0o
|
||||
Fixed a crash on load.
|
||||
|
|
174
checkmove.cpp
174
checkmove.cpp
|
@ -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,13 +177,11 @@ 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;
|
||||
|
@ -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)
|
||||
|
@ -239,7 +257,7 @@ EX bool monstersnear_aux() {
|
|||
/** 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 = moPlayer; who_kills_me_cell = nullptr;
|
||||
return true;
|
||||
}
|
||||
pmi.push_back(pmi0);
|
||||
|
@ -280,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;
|
||||
|
@ -295,15 +417,17 @@ EX void checkmove() {
|
|||
if(hardcore) return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -322,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) {
|
||||
|
@ -339,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);
|
||||
|
|
350
classes.cpp
350
classes.cpp
|
@ -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;
|
||||
|
@ -631,23 +633,23 @@ enum eCanvasFloor { caflNone, caflM, caflFull, caflWarp, caflStar, caflCloud, ca
|
|||
caflPalace, caflDemon, caflCave, caflDesert, caflPower, caflRose, caflTurtle, caflDragon, caflReptile,
|
||||
caflHive, caflSwitch, caflTower, caflEND };
|
||||
|
||||
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);
|
||||
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;
|
||||
|
@ -788,76 +790,76 @@ struct geometryinfo {
|
|||
eVariation default_variation;
|
||||
};
|
||||
|
||||
static const flagtype qCLOSED = 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 const flagtype qAPERIODIC = Flag(29);
|
||||
static const flagtype qHAT = Flag(30);
|
||||
static constexpr flagtype qAPERIODIC = Flag(29);
|
||||
static constexpr flagtype qHAT = Flag(30);
|
||||
|
||||
static const flagtype qFRACTAL = Flag(31);
|
||||
static constexpr flagtype qFRACTAL = Flag(31);
|
||||
|
||||
// note: dnext assumes that x&7 equals 7
|
||||
static const int SEE_ALL = 50;
|
||||
static constexpr int SEE_ALL = 50;
|
||||
// note: check_football_colorability in arbitrile.cpp assumes OINF is divisible by 3
|
||||
static const int OINF = 123;
|
||||
static constexpr int OINF = 123;
|
||||
|
||||
extern eGeometry geometry;
|
||||
extern eVariation variation;
|
||||
#endif
|
||||
|
||||
#if HDR
|
||||
static const flagtype qsNONOR = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE;
|
||||
static const flagtype qsNONORE = qsNONOR | qELLIPTIC;
|
||||
static const flagtype qsBQ = qANYQ | qSMALL | qCLOSED;
|
||||
static const flagtype qsSMALL = qANYQ | qSMALL | qCLOSED;
|
||||
static const flagtype qsSMALLN = qANYQ | qSMALL | qCLOSED | qNONORIENTABLE;
|
||||
static const flagtype qsZEBRA = qANYQ | qSMALL | qCLOSED | qZEBRA;
|
||||
static const flagtype qsFIELD = qANYQ | qFIELD | qCLOSED;
|
||||
static const flagtype qsDOCKS = qANYQ | qSMALL | qCLOSED | qDOCKS;
|
||||
static const flagtype qsSMALLB = qSMALL | qCLOSED;
|
||||
static const flagtype qsSMALLBF = qsSMALLB | qsFIELD | qANYQ;
|
||||
static const flagtype qsSMALLBE = qsSMALLB | qELLIPTIC | qANYQ;
|
||||
static const flagtype qsBP = qBINARY | qKITE;
|
||||
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 | qCLOSED | qSINGLE;
|
||||
static constexpr flagtype qsSINGLE = qANYQ | qSMALL | qCLOSED | qSINGLE;
|
||||
#endif
|
||||
|
||||
EX geometryinfo1 giEuclid2 = { gcEuclid, 2, 2, 3, {1,1, 0,0 } };
|
||||
|
@ -974,31 +976,31 @@ EX vector<geometryinfo> ginf = {
|
|||
|
||||
#if HDR
|
||||
namespace mf {
|
||||
static const flagtype azimuthal = 1;
|
||||
static const flagtype cylindrical = 2; /* usually you want 'band' */
|
||||
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; usually you want 'band' or 'pseudoband' */
|
||||
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 const flagtype technical = 16384; /* don't display in the list */
|
||||
static const flagtype product_special = (1<<15);
|
||||
static const flagtype axial = (1<<16);
|
||||
static const flagtype perspective = (1<<17);
|
||||
static const flagtype orientation = (1<<18);
|
||||
static const flagtype transition = (1<<19);
|
||||
static const flagtype werner = (1<<20);
|
||||
static const flagtype horocyclic = (1<<21);
|
||||
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 | orientation);
|
||||
static const flagtype pseudoband = (pseudocylindrical | uses_bandshift | orientation);
|
||||
static constexpr flagtype band = (cylindrical | pseudocylindrical | uses_bandshift | orientation);
|
||||
static constexpr flagtype pseudoband = (pseudocylindrical | uses_bandshift | orientation);
|
||||
}
|
||||
|
||||
struct modelinfo {
|
||||
|
@ -1030,7 +1032,7 @@ enum eModel : int {
|
|||
// 39..48
|
||||
mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint, mdLiePerspective, mdLieOrthogonal, mdRelPerspective, mdRelOrthogonal,
|
||||
// 49..50
|
||||
mdHorocyclicEqa, mdConformalSquare,
|
||||
mdHorocyclicEqa, mdConformalSquare, mdFisheye2, mdPolar,
|
||||
// 51..
|
||||
mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
|
||||
};
|
||||
|
@ -1094,6 +1096,8 @@ EX vector<modelinfo> mdinf = {
|
|||
{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},
|
||||
|
|
|
@ -25,7 +25,7 @@ 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]; }
|
||||
|
|
104
commandline.cpp
104
commandline.cpp
|
@ -105,19 +105,16 @@ EX namespace arg {
|
|||
EX bool argis(const string& s) { if(args()[0] == '-' && args()[1] == '-') return args().substr(1) == s; return args() == s; }
|
||||
|
||||
EX color_t argcolor(int bits) {
|
||||
string s = args();
|
||||
auto p = find_color_by_name(s);
|
||||
if(p && bits == 24) return p->second;
|
||||
if(p && bits == 32) return (p->second << 8) | 0xFF;
|
||||
return strtoll(argcs(), NULL, 16);
|
||||
return parsecolor(args(), bits == 32);
|
||||
}
|
||||
|
||||
int parameter_id;
|
||||
|
||||
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();
|
||||
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
|
||||
|
@ -259,12 +256,13 @@ 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(TAU * 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("-rotate-up")) {
|
||||
start_game();
|
||||
|
@ -272,13 +270,6 @@ int arg::readCommon() {
|
|||
View = spin90() * spintox(S.T*C0) * View;
|
||||
playermoved = false;
|
||||
}
|
||||
else if(argis("-rotate3")) {
|
||||
PHASE(3); start_game();
|
||||
shift(); ld a = argf();
|
||||
shift(); ld b = argf();
|
||||
View = View * cspin(1, 2, TAU * a / b);
|
||||
playermoved = false;
|
||||
}
|
||||
else if(argis("-face-vertex")) {
|
||||
PHASE(3); start_game();
|
||||
auto &ss = currentmap->get_cellshape(cwt.at);
|
||||
|
@ -289,23 +280,21 @@ int arg::readCommon() {
|
|||
PHASE(3); start_game();
|
||||
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;
|
||||
}
|
||||
else if(argis("-grotatei")) {
|
||||
PHASE(3); start_game();
|
||||
shift(); int i = argi();
|
||||
shift(); int j = argi();
|
||||
shift(); rotate_view(cspin(i, j, argf()));
|
||||
playermoved = false;
|
||||
if(i == 1) {
|
||||
rotate_view(spintox(h));
|
||||
rotate_view(cspin90(0, 2));
|
||||
}
|
||||
else if(argis("-cview")) {
|
||||
PHASE(3); start_game();
|
||||
View = Id; playermoved = false;
|
||||
}
|
||||
else if(argis("-exit")) {
|
||||
PHASE(3);
|
||||
|
@ -342,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");
|
||||
printf("+ Lands:\n");
|
||||
for(int i=1; i<landtypes; i++)
|
||||
printf(" %s\n", linf[i].name);
|
||||
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);
|
||||
}
|
||||
|
@ -432,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() {
|
||||
|
@ -464,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) {
|
||||
|
|
212
complex.cpp
212
complex.cpp
|
@ -215,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)
|
||||
|
@ -644,7 +648,7 @@ struct info {
|
|||
if(newdist == OUT_OF_PRISON && princess::challenge) {
|
||||
addMessage(XLAT("Congratulations! Your score is %1.", its(i->value)));
|
||||
achievement_gain_once("PRINCESS2", rg::princess);
|
||||
if(!cheater) achievement_score(36, i->value);
|
||||
if(!cheater) achievement_score(LB_PRINCESS, i->value);
|
||||
LATE( showMissionScreen(); )
|
||||
}
|
||||
}
|
||||
|
@ -738,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));
|
||||
|
@ -908,6 +912,9 @@ EX namespace clearing {
|
|||
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;
|
||||
gen_alt(c);
|
||||
|
@ -1172,10 +1179,10 @@ 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) {
|
||||
|
@ -1210,6 +1217,7 @@ 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
|
||||
|
@ -1453,7 +1461,7 @@ EX namespace mirror {
|
|||
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);
|
||||
|
@ -1633,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;
|
||||
|
@ -1680,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));
|
||||
|
@ -1990,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++)
|
||||
|
@ -2018,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);
|
||||
|
@ -2119,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;
|
||||
|
@ -2471,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;
|
||||
eItem it = c->item;
|
||||
collectItem(c, c);
|
||||
if(it && !c->item) animate_item_throw(c, cwt.at, it);
|
||||
if(saf) return;
|
||||
}
|
||||
c->wall = waSea;
|
||||
|
@ -2506,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 {
|
||||
|
@ -2936,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);
|
||||
|
@ -3037,6 +3056,7 @@ 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) {
|
||||
|
@ -3177,48 +3197,62 @@ 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;
|
||||
}
|
||||
|
@ -3322,9 +3356,7 @@ EX namespace prairie {
|
|||
return true;
|
||||
}
|
||||
|
||||
EX void generateTreasure(cell *c) {
|
||||
// if(nearriver(c) && op
|
||||
if(enter && nearriver(c) && opposite(c) && thisriver(c)) {
|
||||
EX void generateTreasure_here(cell *c) {
|
||||
int hr = hrand(100);
|
||||
if(hr == 0 && items[itGreenGrass] >= 10 && !inv::on) {
|
||||
c->item = itOrbBull;
|
||||
|
@ -3334,8 +3366,27 @@ EX namespace prairie {
|
|||
placePrizeOrb(c);
|
||||
// if(c->item) orbs.push_back(c);
|
||||
}
|
||||
else tchoices.push_back(c);
|
||||
else if(!ls::hv_structure())
|
||||
tchoices.push_back(c);
|
||||
}
|
||||
|
||||
EX void generateTreasure(cell *c) {
|
||||
// if(nearriver(c) && op
|
||||
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;
|
||||
}
|
||||
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() {
|
||||
|
@ -3369,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;
|
||||
|
@ -3456,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) {
|
||||
|
@ -3477,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
|
||||
|
@ -3509,6 +3562,7 @@ 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) {
|
||||
|
@ -3542,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;
|
||||
|
@ -3996,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;
|
||||
|
@ -4048,17 +4115,17 @@ 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) {
|
||||
|
@ -4068,7 +4135,7 @@ EX namespace dungeon {
|
|||
|
||||
bool rdepths[5];
|
||||
for(int i=0; i<5; i++) {
|
||||
if(coastvalEdge(c2) == 0) {
|
||||
if(cvfun(c2) == 0) {
|
||||
rdepths[i] = false;
|
||||
}
|
||||
else {
|
||||
|
@ -4078,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; }
|
||||
}
|
||||
|
@ -4089,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4127,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);
|
||||
}
|
||||
}
|
||||
|
@ -4147,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 {
|
||||
|
@ -4159,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; }
|
||||
}
|
||||
|
@ -4198,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);
|
||||
|
@ -4212,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;
|
||||
|
@ -4221,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)) {
|
||||
|
@ -4243,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) {
|
||||
|
@ -4269,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++;
|
||||
|
|
23
complex2.cpp
23
complex2.cpp
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -291,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 {
|
||||
|
@ -354,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;
|
||||
|
@ -905,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 {
|
||||
|
@ -1197,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;
|
||||
|
|
1992
config.cpp
1992
config.cpp
File diff suppressed because it is too large
Load Diff
148
content.cpp
148
content.cpp
|
@ -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."
|
||||
)
|
||||
|
@ -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,
|
||||
|
@ -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(), lands_for_hell(), 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
|
||||
|
|
103
control.cpp
103
control.cpp
|
@ -34,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)
|
||||
|
@ -67,6 +67,7 @@ EX ld shiftmul = 1;
|
|||
|
||||
EX cell *mouseover, *mouseover2, *lmouseover, *lmouseover_distant;
|
||||
EX ld modist, modist2;
|
||||
EX shiftmatrix mouseoverV;
|
||||
|
||||
EX int lastt;
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -375,6 +406,7 @@ EX void full_ystrafe_camera(ld 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;
|
||||
|
@ -430,7 +462,7 @@ 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(cspin(0, 1, v * camera_rot_speed));
|
||||
didsomething = true;
|
||||
|
@ -523,7 +555,7 @@ EX void handleKeyNormal(int sym, int uni) {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -554,9 +586,11 @@ EX void handleKeyNormal(int sym, int uni) {
|
|||
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 && !game_keys_scroll) movepcto(-1, 1);
|
||||
|
@ -572,7 +606,9 @@ EX void handleKeyNormal(int sym, int uni) {
|
|||
}
|
||||
|
||||
if(sym == SDLK_ESCAPE) {
|
||||
if(viewdists)
|
||||
if(bow::fire_mode)
|
||||
bow::switch_fire_mode();
|
||||
else if(viewdists)
|
||||
viewdists = false;
|
||||
else
|
||||
showMissionScreen();
|
||||
|
@ -613,9 +649,13 @@ EX void handleKeyNormal(int sym, int uni) {
|
|||
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)
|
||||
|
@ -674,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
|
||||
|
@ -702,11 +745,10 @@ 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);
|
||||
}
|
||||
|
||||
/* visualization only -- the HyperRogue movement keys should move the camera */
|
||||
EX bool game_keys_scroll;
|
||||
EX purehookset hooks_control;
|
||||
|
||||
EX void mainloopiter() {
|
||||
GLWRAP;
|
||||
|
@ -751,6 +793,7 @@ EX void mainloopiter() {
|
|||
|
||||
mousepan = cmode & sm::NORMAL;
|
||||
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) {
|
||||
|
@ -860,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 {
|
||||
|
@ -905,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);
|
||||
|
@ -945,7 +988,7 @@ EX void mainloopiter() {
|
|||
}
|
||||
else sc_ticks = ticks;
|
||||
|
||||
if(game_keys_scroll && !shmup::on && (cmode & sm::NORMAL) && !keystate[SDLK_LALT] && !keystate[SDLK_RALT]) {
|
||||
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.;
|
||||
|
@ -974,6 +1017,8 @@ EX void mainloopiter() {
|
|||
#endif
|
||||
achievement_pump();
|
||||
|
||||
callhooks(hooks_control);
|
||||
|
||||
for(auto d: dialog::key_queue) {
|
||||
println(hlog, "handling key ", d);
|
||||
handlekey(d, d);
|
||||
|
@ -985,6 +1030,7 @@ EX void mainloopiter() {
|
|||
fix_mouseh();
|
||||
#if CAP_SDLJOY
|
||||
if(joydir.d != -1) checkjoy();
|
||||
if(joystick_done && joythread) { joythread->join(); delete joythread; joystick_done = false; }
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1000,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
|
||||
|
@ -1086,6 +1131,17 @@ 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;
|
||||
|
@ -1290,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.));
|
||||
|
|
|
@ -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 }
|
||||
|
||||
}
|
||||
|
22
crystal.cpp
22
crystal.cpp
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -1318,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)];
|
||||
}
|
||||
|
||||
|
@ -1500,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(); });
|
||||
};
|
||||
|
@ -1512,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();
|
||||
|
@ -1562,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) {
|
||||
|
@ -1597,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;
|
||||
|
|
14
debug.cpp
14
debug.cpp
|
@ -280,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 {
|
||||
|
@ -308,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");
|
||||
|
@ -326,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] () {
|
||||
|
@ -390,7 +388,7 @@ struct debugScreen {
|
|||
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);
|
||||
|
@ -421,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');
|
||||
};
|
||||
});
|
||||
|
@ -662,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);
|
||||
|
@ -814,7 +815,6 @@ int read_cheat_args() {
|
|||
}
|
||||
else if(argis("-lands")) {
|
||||
PHASEFROM(2);
|
||||
cheat();
|
||||
stop_game();
|
||||
shift(); land_structure = (eLandStructure) (argi());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -103,11 +103,11 @@ void init() {
|
|||
for(int a=0; a<100; a++) {
|
||||
ld nq7 = q7 + q8;
|
||||
ld nq8 = q7 * 5 + q8 * 6;
|
||||
println(hlog, format("%.20f", val = (nq7 + nq8) / (q7 + q8)));
|
||||
println(hlog, hr::format("%.20f", val = (nq7 + nq8) / (q7 + q8)));
|
||||
q7 = nq7; q8 = nq8;
|
||||
}
|
||||
val = sqrt(val);
|
||||
println(hlog, "root: ", format("%.20f", 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++)
|
||||
|
@ -283,7 +283,7 @@ string matcode(transmatrix T) {
|
|||
swap(h[1], h[2]); swap(h[0], h[1]);
|
||||
// return lalign(0, h);
|
||||
|
||||
return format("R%dA%03dL%.3f", ialpha/60, hangle, hypot_d(2, h));
|
||||
return hr::format("R%dA%03dL%.3f", ialpha/60, hangle, hypot_d(2, h));
|
||||
}
|
||||
|
||||
int ghatid(string s) {
|
||||
|
@ -431,7 +431,7 @@ void hatframe() {
|
|||
}
|
||||
|
||||
string writematrix(transmatrix T) {
|
||||
return format("mt(%.10f,%.10f,%.10f, %.10f,%.10f,%.10f, %.10f,%.10f,%.10f)",
|
||||
return hr::format("mt(%.10f,%.10f,%.10f, %.10f,%.10f,%.10f, %.10f,%.10f,%.10f)",
|
||||
T[0][0],
|
||||
T[0][1],
|
||||
T[0][2],
|
||||
|
@ -456,7 +456,7 @@ void hatter() {
|
|||
dialog::add_key_action('a', [] {
|
||||
hatcorners_add.push_back(sh);
|
||||
println(hlog, "hatcorners = {");
|
||||
for(auto h: hatcorners_add) println(hlog, format(" pt(%.10f,%.10f),", h[0], h[1]));
|
||||
for(auto h: hatcorners_add) println(hlog, hr::format(" pt(%.10f,%.10f),", h[0], h[1]));
|
||||
println(hlog, " }");
|
||||
});
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ void do_recording() {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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); }
|
||||
};
|
||||
}
|
|
@ -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)+"]"; }
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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())
|
||||
```
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1079,7 +1079,7 @@ void test_current(string tesname) {
|
|||
case 'O': Out("overts;oedges", lalign(0, count_vertex_orbits(), ";", count_edge_orbits()));
|
||||
case 'U': Out("vshapes;vverts;vedges;ushapes;uverts;uedges;xea;xeb;xec", count_uniform());
|
||||
case 'L': Out("mirror_rules", arb::current.mirror_rules);
|
||||
case 'B': Out("listshape;listvalence", format("%lld;%lld", get_shapelist(), get_valence_list()));
|
||||
case 'B': Out("listshape;listvalence", hr::format("%lld;%lld", get_shapelist(), get_valence_list()));
|
||||
case 'F': Out("maxdist", max_dist());
|
||||
|
||||
case 'f': Out("file", tesname);
|
||||
|
@ -1091,7 +1091,7 @@ void test_current(string tesname) {
|
|||
case '1': Out("single", single_live_branches);
|
||||
case '2': Out("double", double_live_branches);
|
||||
case 'p': Out("premini", states_premini);
|
||||
case 'K': Out("movecount", format("%ld", rulegen::movecount));
|
||||
case 'K': Out("movecount", hr::format("%ld", rulegen::movecount));
|
||||
}
|
||||
println(*test_out);
|
||||
test_out->flush();
|
||||
|
|
|
@ -235,11 +235,11 @@ void build_sols(int PRECX, int PRECY, int PRECZ) {
|
|||
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));
|
||||
println(hlog, "error = ", xerr);
|
||||
|
@ -265,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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -469,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
526
dialogs.cpp
526
dialogs.cpp
|
@ -15,9 +15,9 @@ EX namespace dialog {
|
|||
#if HDR
|
||||
#define IFM(x) (mousing?"":x)
|
||||
|
||||
static const int DONT_SHOW = 16;
|
||||
static constexpr int DONT_SHOW = 16;
|
||||
|
||||
enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diIntSlider, diSlider, diBigItem, diKeyboard, diCustom, diColorItem, diListStart, diListEnd};
|
||||
enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diIntSlider, diSlider, diBigItem, diKeyboard, diCustom, diColorItem, diListStart, diListEnd, diMatrixItem};
|
||||
|
||||
struct item {
|
||||
tDialogItem type;
|
||||
|
@ -29,6 +29,7 @@ EX namespace dialog {
|
|||
double param;
|
||||
int p1, p2, p3;
|
||||
int position;
|
||||
void *ptr;
|
||||
reaction_t customfun;
|
||||
item(tDialogItem t = diBreak);
|
||||
};
|
||||
|
@ -46,23 +47,61 @@ EX namespace dialog {
|
|||
const static scaler asinhic = {asinh, sinh, false};
|
||||
const static scaler asinhic100 = {[] (ld x) { return asinh(x*100); }, [] (ld x) { return sinh(x)/100; }, false};
|
||||
|
||||
struct numberEditor {
|
||||
/** extendable dialog */
|
||||
struct extdialog : funbase {
|
||||
string title, help;
|
||||
int dialogflags;
|
||||
reaction_t reaction;
|
||||
reaction_t reaction_final;
|
||||
reaction_t extra_options;
|
||||
virtual void draw() = 0;
|
||||
void operator() () { draw(); }
|
||||
virtual ~extdialog() {};
|
||||
extdialog();
|
||||
/** Pop screen, then call the final reaction. A bit more complex because it eeds to backup reaction_final due to popScreen */
|
||||
void popfinal() { auto rf = std::move(reaction_final); popScreen(); if(rf) rf(); }
|
||||
};
|
||||
|
||||
/** number dialog */
|
||||
struct number_dialog : extdialog {
|
||||
ld *editwhat;
|
||||
string s;
|
||||
ld vmin, vmax, step, dft;
|
||||
string title, help;
|
||||
scaler sc;
|
||||
int *intval; ld intbuf;
|
||||
bool animatable;
|
||||
bool *boolval;
|
||||
void draw() override;
|
||||
void apply_edit();
|
||||
void apply_slider();
|
||||
string disp(ld x);
|
||||
void reset_str() { s = disp(*editwhat); }
|
||||
};
|
||||
|
||||
extern numberEditor ne;
|
||||
|
||||
inline void scaleLog() { ne.sc = logarithmic; }
|
||||
inline void scaleSinh() { ne.sc = asinhic; }
|
||||
inline void scaleSinh100() { ne.sc = asinhic100; }
|
||||
/** bool dialog */
|
||||
struct bool_dialog : extdialog {
|
||||
bool *editwhat, dft;
|
||||
reaction_t switcher;
|
||||
void draw() override;
|
||||
};
|
||||
#endif
|
||||
|
||||
EX number_dialog& get_ne() {
|
||||
auto ptr = dynamic_cast<number_dialog*> (screens.back().target_base());
|
||||
if(!ptr) throw hr_exception("get_ne() called without number dialog");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
EX extdialog& get_di() {
|
||||
auto ptr = dynamic_cast<extdialog*> (screens.back().target_base());
|
||||
if(!ptr) throw hr_exception("get_di() called without extdialog");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
EX void scaleLog() { get_ne().sc = logarithmic; }
|
||||
EX void scaleSinh() { get_ne().sc = asinhic; }
|
||||
EX void scaleSinh100() { get_ne().sc = asinhic100; }
|
||||
|
||||
EX color_t dialogcolor = 0xC0C0C0;
|
||||
EX color_t dialogcolor_clicked = 0xFF8000;
|
||||
EX color_t dialogcolor_selected = 0xFFD500;
|
||||
|
@ -184,12 +223,16 @@ EX namespace dialog {
|
|||
EX string keyname(int k) {
|
||||
if(k == 0) return "";
|
||||
if(k == SDLK_ESCAPE) return "Esc";
|
||||
if(k == SDLK_F5) return "F5";
|
||||
if(k == SDLK_F10) return "F10";
|
||||
if(k == SDLK_F9) return "F9";
|
||||
if(k == SDLK_F1) return "F1";
|
||||
if(k == SDLK_F4) return "F4";
|
||||
if(k == SDLK_F2) return "F2";
|
||||
if(k == SDLK_F3) return "F3";
|
||||
if(k == SDLK_F4) return "F4";
|
||||
if(k == SDLK_F5) return "F5";
|
||||
if(k == SDLK_F6) return "F6";
|
||||
if(k == SDLK_F7) return "F7";
|
||||
if(k == SDLK_F8) return "F8";
|
||||
if(k == SDLK_F9) return "F9";
|
||||
if(k == SDLK_F10) return "F10";
|
||||
if(k >= 10000 && k < 10500) return "";
|
||||
if(k == SDLK_HOME) return "Home";
|
||||
if(k == SDLK_BACKSPACE) return "Backspace";
|
||||
|
@ -268,6 +311,39 @@ EX namespace dialog {
|
|||
it.param = value & 0xFF;
|
||||
}
|
||||
|
||||
ld as_degrees(transmatrix T) {
|
||||
hyperpoint h = T * point31(1, 0, 0);
|
||||
ld alpha = atan2(-h[1], h[0]);
|
||||
if(alpha == 0) alpha = 0;
|
||||
return alpha / degree;
|
||||
}
|
||||
|
||||
EX void addMatrixItem(string body, transmatrix& value, int key, int dim IS(GDIM)) {
|
||||
addSelItem(body, COLORBAR, key);
|
||||
auto& it = items.back();
|
||||
it.type = diMatrixItem;
|
||||
it.ptr = &value;
|
||||
it.value = "";
|
||||
if(dim == 2) it.value = fts(as_degrees(value)) + "°";
|
||||
if(dim == 3) {
|
||||
for(int k=0; k<3; k++) {
|
||||
if(value[k][k] != 1) continue;
|
||||
int i=(k+1)%3;
|
||||
int j=(i+1)%3;
|
||||
if(i > j) swap(i, j);
|
||||
hyperpoint h = Hypc; h[i] = 1;
|
||||
h = value * h;
|
||||
ld alpha = atan2(-h[j], h[i]);
|
||||
if(alpha == 0) alpha = 0;
|
||||
it.value = fts(alpha / degree) + "° ";
|
||||
it.value += ('X' + i);
|
||||
it.value += ('X' + j);
|
||||
}
|
||||
if(eqmatrix(value, Id)) it.value = "Id";
|
||||
}
|
||||
it.p1 = dim;
|
||||
}
|
||||
|
||||
EX void addHelp(string body) {
|
||||
item it(diHelp);
|
||||
it.body = body;
|
||||
|
@ -339,8 +415,6 @@ EX namespace dialog {
|
|||
|
||||
EX int dcenter, dwidth;
|
||||
|
||||
EX int dialogflags;
|
||||
|
||||
EX int displayLong(string str, int siz, int y, bool measure) {
|
||||
|
||||
int last = 0;
|
||||
|
@ -543,6 +617,41 @@ EX namespace dialog {
|
|||
}
|
||||
}
|
||||
|
||||
EX void visualize_matrix(const trans23& T, ld x, ld y, ld r, int dim, ld tsize) {
|
||||
vector<hyperpoint> pts;
|
||||
for(int a=0; a<dim; a++) {
|
||||
hyperpoint h = C0; h[a] = r;
|
||||
pts.push_back(T.get() * h);
|
||||
}
|
||||
|
||||
flat_model_enabler fme;
|
||||
initquickqueue();
|
||||
ld pix = 1 / (2 * cgi.hcrossf / cgi.crossf);
|
||||
shiftmatrix V = shiftless(atscreenpos(x, y, pix));
|
||||
|
||||
for(int i=0; i<=360; i++)
|
||||
curvepoint(hyperpoint(r * sin(i*degree), r*cos(i*degree), 1, 1));
|
||||
queuecurve(V, 0xFFFFFFFF, 0x202020FF, PPR::LINE);
|
||||
|
||||
color_t cols[3] = {0xFF8080FF, 0x80FF80FF, 0x8080FFFF};
|
||||
for(int a=0; a<dim; a++) {
|
||||
auto pt = pts[a]; pt[2] = 1; pt[3] = 1;
|
||||
curvepoint(hyperpoint(0,0,1,1));
|
||||
curvepoint(pt);
|
||||
// queueline(V * hyperpoint(0,0,1,1), V * pt, cols[a], 0);
|
||||
queuecurve(V, cols[a], 0, PPR::LINE);
|
||||
}
|
||||
if(dim == 3) for(int a=0; a<dim; a++) {
|
||||
auto pt = pts[a]; ld val = -pt[2] * tsize / r / 5;
|
||||
curvepoint(hyperpoint(pt[0], pt[1]+val, 1, 1));
|
||||
curvepoint(hyperpoint(pt[0]-val, pt[1]-val*sqrt(3)/2, 1, 1));
|
||||
curvepoint(hyperpoint(pt[0]+val, pt[1]-val*sqrt(3)/2, 1, 1));
|
||||
curvepoint(hyperpoint(pt[0], pt[1]+val, 1, 1));
|
||||
queuecurve(V, cols[a], cols[a] & 0xFFFFFF80, PPR::LINE);
|
||||
}
|
||||
quickqueue();
|
||||
}
|
||||
|
||||
EX void display() {
|
||||
|
||||
callhooks(hooks_display_dialog);
|
||||
|
@ -694,7 +803,7 @@ EX namespace dialog {
|
|||
continue;
|
||||
}
|
||||
else list_left -= size;
|
||||
if(list_next_key) { key_actions[list_next_key] = key_actions[I.key]; I.key = list_next_key++; }
|
||||
if(list_next_key) { if(key_actions.count(I.key)) key_actions[list_next_key] = key_actions[I.key]; I.key = list_next_key++; }
|
||||
}
|
||||
|
||||
top = tothei;
|
||||
|
@ -708,7 +817,7 @@ EX namespace dialog {
|
|||
displayfr(dcenter, mid, 2, dfsize * I.scale/100, I.body, I.color, 8);
|
||||
if(xthis) getcstat = I.key;
|
||||
}
|
||||
else if(among(I.type, diItem, diBigItem, diColorItem)) {
|
||||
else if(among(I.type, diItem, diBigItem, diColorItem, diMatrixItem)) {
|
||||
bool xthis = (mousey >= top && mousey < tothei);
|
||||
if(cmode & sm::DIALOG_STRICT_X)
|
||||
xthis = xthis && (mousex >= dcenter - dialogwidth/2 && mousex <= dcenter + dialogwidth/2);
|
||||
|
@ -750,8 +859,10 @@ EX namespace dialog {
|
|||
}
|
||||
else {
|
||||
int siz = dfsize * I.scale/100;
|
||||
while(siz > 6 && textwidth(siz, I.value) >= vid.xres - valuex) siz--;
|
||||
displayfr(valuex, mid, 2, siz, I.value, I.colorv, 0);
|
||||
while(siz > 6 && textwidth(siz, I.value) + (I.type == diMatrixItem ? siz*3/2 : 0) >= vid.xres - valuex) siz--;
|
||||
displayfr(valuex + (I.type == diMatrixItem ? siz*3/2 : 0), mid, 2, siz, I.value, I.colorv, 0);
|
||||
|
||||
if(I.type == diMatrixItem) visualize_matrix(*((transmatrix*)I.ptr), valuex + siz/2, mid, siz/2, I.p1, vid.fsize);
|
||||
}
|
||||
}
|
||||
if(xthis) getcstat = I.key;
|
||||
|
@ -808,7 +919,7 @@ EX namespace dialog {
|
|||
}
|
||||
|
||||
bool isitem(item& it) {
|
||||
return among(it.type, diItem, diBigItem, diColorItem);
|
||||
return among(it.type, diItem, diBigItem, diColorItem, diMatrixItem);
|
||||
}
|
||||
|
||||
EX void handle_actions(int &sym, int &uni) {
|
||||
|
@ -918,7 +1029,11 @@ EX namespace dialog {
|
|||
|
||||
color_t *colorPointer;
|
||||
|
||||
EX void handleKeyColor(int sym, int uni) {
|
||||
struct color_dialog : extdialog {
|
||||
void draw() override;
|
||||
};
|
||||
|
||||
EX void handleKeyColor(int sym, int uni, struct color_dialog& ne) {
|
||||
unsigned& color = *colorPointer;
|
||||
int shift = colorAlpha ? 0 : 8;
|
||||
|
||||
|
@ -933,9 +1048,8 @@ EX namespace dialog {
|
|||
for(int i=0; i<10; i++) if(colorhistory[i] == (color << shift))
|
||||
inHistory = true;
|
||||
if(!inHistory) { colorhistory[lch] = (color << shift); lch++; lch %= 10; }
|
||||
popScreen();
|
||||
if(reaction) reaction();
|
||||
if(reaction_final) reaction_final();
|
||||
if(ne.reaction) ne.reaction();
|
||||
ne.popfinal();
|
||||
}
|
||||
else if(uni >= '0' && uni <= '9') {
|
||||
color = colorhistory[uni - '0'] >> shift;
|
||||
|
@ -957,15 +1071,12 @@ EX namespace dialog {
|
|||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[colorp] += abs(shiftmul) < .6 ? 1 : 17;
|
||||
}
|
||||
else if(doexiton(sym, uni)) {
|
||||
popScreen();
|
||||
if(reaction_final) reaction_final();
|
||||
}
|
||||
else if(doexiton(sym, uni)) ne.popfinal();
|
||||
}
|
||||
|
||||
EX bool colorAlpha;
|
||||
|
||||
EX void drawColorDialog() {
|
||||
void color_dialog::draw() {
|
||||
cmode = sm::NUMBER | dialogflags;
|
||||
if(cmode & sm::SIDE) gamescreen();
|
||||
else emptyscreen();
|
||||
|
@ -1024,25 +1135,132 @@ EX namespace dialog {
|
|||
getcstat = 'A' + i, inslider = true, slider_x = mousex;
|
||||
}
|
||||
|
||||
displayColorButton(dcenter, vid.yres/2+vid.fsize * 6, XLAT("select this color") + " : " + format(colorAlpha ? "%08X" : "%06X", color), ' ', 8, 0, color >> (colorAlpha ? ash : 0));
|
||||
displayColorButton(dcenter, vid.yres/2+vid.fsize * 6, XLAT("select this color") + " : " + hr::format(colorAlpha ? "%08X" : "%06X", color), ' ', 8, 0, color >> (colorAlpha ? ash : 0));
|
||||
|
||||
if(extra_options) extra_options();
|
||||
|
||||
keyhandler = handleKeyColor;
|
||||
keyhandler = [this] (int sym, int uni) { return handleKeyColor(sym, uni, self); };
|
||||
}
|
||||
|
||||
EX void openColorDialog(unsigned int& col, unsigned int *pal IS(palette)) {
|
||||
color_dialog cd;
|
||||
colorPointer = &col; palette = pal;
|
||||
colorAlpha = true;
|
||||
dialogflags = 0;
|
||||
pushScreen(drawColorDialog);
|
||||
reaction = reaction_t();
|
||||
extra_options = reaction_t();
|
||||
pushScreen(cd);
|
||||
}
|
||||
|
||||
EX numberEditor ne;
|
||||
#if HDR
|
||||
struct matrix_dialog : extdialog {
|
||||
transmatrix *edit_matrix;
|
||||
int dim;
|
||||
void draw() override;
|
||||
void large_viz();
|
||||
};
|
||||
#endif
|
||||
|
||||
void matrix_dialog::large_viz() {
|
||||
addCustom(500, [this] {
|
||||
int siz = dfsize * 5;
|
||||
int mid = (top + tothei) / 2;
|
||||
vid.linewidth *= 3;
|
||||
visualize_matrix(*edit_matrix, dcenter, mid, siz/2, dim, vid.fsize * 2);
|
||||
vid.linewidth /= 3;
|
||||
});
|
||||
}
|
||||
|
||||
void matrix_dialog::draw() {
|
||||
cmode = dialogflags;
|
||||
gamescreen();
|
||||
init(title);
|
||||
addHelp(help);
|
||||
large_viz();
|
||||
addBreak(100);
|
||||
addItem("reset", 'r');
|
||||
dialog::add_action([this] { *edit_matrix = Id; });
|
||||
if(dim == 2) {
|
||||
static ld angle;
|
||||
angle = as_degrees(*edit_matrix);
|
||||
addSelItem("enter angle", fts(angle) + "°", 'a');
|
||||
dialog::add_action([this] {
|
||||
editNumber(angle, -180, 180, 90, 0, title, help);
|
||||
auto& ne = get_ne();
|
||||
auto re = reaction;
|
||||
ne.extra_options = [this] { large_viz(); };
|
||||
ne.reaction = [re, this] { *edit_matrix = spin(angle * degree); if(re) re(); };
|
||||
ne.reaction_final = reaction;
|
||||
ne.animatable = false;
|
||||
ne.dialogflags |= dialogflags;
|
||||
});
|
||||
}
|
||||
if(dim == 3) {
|
||||
transmatrix cur = *edit_matrix;
|
||||
auto rot_but = [this, cur] (int i, int j, string title, char key) {
|
||||
addItem(title, key);
|
||||
dialog::add_action([i, j, title, this, cur] {
|
||||
static ld angle; angle = 0;
|
||||
editNumber(angle, -180, 180, 90, 0, title, XLAT("Angle to rotate by."));
|
||||
auto& ne = get_ne();
|
||||
auto re = reaction;
|
||||
ne.extra_options = [this] { large_viz(); };
|
||||
ne.reaction = [re, i, j, this, cur] { *edit_matrix = cspin(i, j, angle * degree) * cur; if(re) re(); };
|
||||
ne.reaction_final = reaction;
|
||||
ne.animatable = false;
|
||||
ne.dialogflags |= dialogflags;
|
||||
});
|
||||
};
|
||||
rot_but(0, 2, "rotate in XZ", 'x');
|
||||
rot_but(1, 2, "rotate in YZ", 'y');
|
||||
rot_but(0, 1, "rotate in XY", 'z');
|
||||
}
|
||||
|
||||
#if !ISMOBILE
|
||||
addBoolItem("mouse control", dialogflags & sm::MOUSEAIM, 'm');
|
||||
dialog::add_action([this] { dialogflags ^= sm::MOUSEAIM; });
|
||||
if(dialogflags & sm::MOUSEAIM) {
|
||||
*edit_matrix = cspin(0, 2, mouseaim_x) * *edit_matrix;
|
||||
*edit_matrix = cspin(1, 2, mouseaim_y) * *edit_matrix;
|
||||
mouseaim_x = mouseaim_y = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static string formula;
|
||||
formula = "?";
|
||||
anims::get_parameter_animation(anims::find_param(edit_matrix), formula);
|
||||
addSelItem("enter formula", formula, 'f');
|
||||
dialog::add_action([this] {
|
||||
if(formula == "?") formula = "id";
|
||||
anims::get_parameter_animation(anims::find_param(edit_matrix), formula);
|
||||
dialog::edit_string(formula, "formula", XLAT("dxy(n) = rotate n degrees from x to y\n\nd-degree, r-radian, t-turn\n\nexample: dxy(30)*dyz(45)"));
|
||||
dialog::get_di().extra_options = [this] { large_viz(); };
|
||||
dialog::get_di().reaction = [this] {
|
||||
try {
|
||||
*edit_matrix = parsematrix(formula);
|
||||
auto p = anims::find_param(edit_matrix);
|
||||
if(p) p->load_as_animation(formula);
|
||||
}
|
||||
catch(hr_parse_exception&) { }
|
||||
catch(param_exception&) { }
|
||||
};
|
||||
dialog::get_di().dialogflags |= dialogflags;
|
||||
});
|
||||
if(extra_options) extra_options();
|
||||
addBack();
|
||||
display();
|
||||
}
|
||||
|
||||
EX void editMatrix(transmatrix& T, string t, string h, int dim) {
|
||||
matrix_dialog m;
|
||||
m.edit_matrix = &T;
|
||||
m.title = t;
|
||||
m.help = h;
|
||||
m.dim = dim;
|
||||
pushScreen(m);
|
||||
}
|
||||
|
||||
EX bool editingDetail() {
|
||||
auto ptr = dynamic_cast<number_dialog*> (screens.back().target_base());
|
||||
if(!ptr) return false;
|
||||
auto& ne = get_ne();
|
||||
return ne.editwhat == &vid.highdetail || ne.editwhat == &vid.middetail;
|
||||
}
|
||||
|
||||
|
@ -1051,32 +1269,31 @@ EX namespace dialog {
|
|||
else return int(x-.5);
|
||||
}
|
||||
|
||||
EX string disp(ld x) {
|
||||
string number_dialog::disp(ld x) {
|
||||
if(dialogflags & sm::HEXEDIT) return "0x" + itsh((unsigned long long)(x));
|
||||
else if(ne.intval) return its(ldtoint(x));
|
||||
else return fts(x); }
|
||||
if(intval) return its(ldtoint(x));
|
||||
return fts(x);
|
||||
}
|
||||
|
||||
EX reaction_t reaction;
|
||||
EX reaction_t reaction_final;
|
||||
|
||||
EX reaction_t extra_options;
|
||||
|
||||
EX void apply_slider() {
|
||||
void number_dialog::apply_slider() {
|
||||
auto &ne = self;
|
||||
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
|
||||
if(reaction) reaction();
|
||||
if(ne.reaction) ne.reaction();
|
||||
if(ne.intval) *ne.editwhat = *ne.intval;
|
||||
ne.s = disp(*ne.editwhat);
|
||||
reset_str();
|
||||
#if CAP_ANIMATIONS
|
||||
anims::deanimate(*ne.editwhat);
|
||||
anims::deanimate(anims::find_param(ne.editwhat));
|
||||
#endif
|
||||
}
|
||||
|
||||
EX void use_hexeditor() {
|
||||
dialogflags |= sm::HEXEDIT;
|
||||
ne.s = disp(*ne.editwhat);
|
||||
auto& ne = get_ne();
|
||||
ne.dialogflags |= sm::HEXEDIT;
|
||||
ne.reset_str();
|
||||
}
|
||||
|
||||
EX void apply_edit() {
|
||||
void number_dialog::apply_edit() {
|
||||
auto& ne = self;
|
||||
try {
|
||||
exp_parser ep;
|
||||
ep.s = ne.s;
|
||||
|
@ -1085,17 +1302,22 @@ EX namespace dialog {
|
|||
*ne.editwhat = x;
|
||||
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
|
||||
#if CAP_ANIMATIONS
|
||||
if(ne.animatable) anims::animate_parameter(*ne.editwhat, ne.s, reaction ? reaction : reaction_final);
|
||||
if(ne.animatable) {
|
||||
auto p = anims::find_param(ne.intval ? (void*) ne.intval : (void*) ne.editwhat);
|
||||
if(p) p->load_as_animation(ne.s);
|
||||
}
|
||||
#endif
|
||||
if(reaction) reaction();
|
||||
}
|
||||
catch(const hr_parse_exception&) {
|
||||
}
|
||||
catch(param_exception&) { }
|
||||
}
|
||||
|
||||
EX void bound_low(ld val) {
|
||||
auto r = reaction;
|
||||
reaction = [r, val] () {
|
||||
auto& ne = get_ne();
|
||||
auto r = ne.reaction;
|
||||
ne.reaction = [r, val, &ne] () {
|
||||
if(*ne.editwhat < val) {
|
||||
*ne.editwhat = val;
|
||||
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
|
||||
|
@ -1105,8 +1327,9 @@ EX namespace dialog {
|
|||
}
|
||||
|
||||
EX void bound_up(ld val) {
|
||||
auto r = reaction;
|
||||
reaction = [r, val] () {
|
||||
auto& ne = get_ne();
|
||||
auto r = ne.reaction;
|
||||
ne.reaction = [r, val, &ne] () {
|
||||
if(*ne.editwhat > val) {
|
||||
*ne.editwhat = val;
|
||||
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
|
||||
|
@ -1126,7 +1349,13 @@ EX namespace dialog {
|
|||
|
||||
EX bool onscreen_keyboard = ISMOBILE;
|
||||
|
||||
EX void number_dialog_help() {
|
||||
struct number_dialog_help {
|
||||
number_dialog *ptr;
|
||||
void operator() ();
|
||||
};
|
||||
|
||||
void number_dialog_help :: operator() () {
|
||||
auto ne = *ptr;
|
||||
init("number dialog help");
|
||||
dialog::addBreak(100);
|
||||
dialog::addHelp(XLAT("You can enter formulas in this dialog."));
|
||||
|
@ -1136,7 +1365,7 @@ EX namespace dialog {
|
|||
dialog::addBreak(100);
|
||||
dialog::addHelp(XLAT("Constants and variables available:"));
|
||||
addHelp(available_constants());
|
||||
if(ne.animatable) {
|
||||
if(ptr && ne.animatable) {
|
||||
dialog::addBreak(100);
|
||||
dialog::addHelp(XLAT("Animations:"));
|
||||
dialog::addHelp(XLAT("a..b -- animate linearly from a to b"));
|
||||
|
@ -1151,16 +1380,14 @@ EX namespace dialog {
|
|||
|
||||
#if CAP_ANIMATIONS
|
||||
dialog::addBreak(50);
|
||||
auto f = find_edit(ne.intval ? (void*) ne.intval : (void*) ne.editwhat);
|
||||
auto f = find_edit(!ptr ? nullptr : ne.intval ? (void*) ne.intval : (void*) ne.editwhat);
|
||||
if(f)
|
||||
dialog::addHelp(XLAT("Parameter names, e.g. '%1'", f->parameter_name));
|
||||
dialog::addHelp(XLAT("Parameter names, e.g. '%1'", f->name));
|
||||
else
|
||||
dialog::addHelp(XLAT("Parameter names"));
|
||||
dialog::addBreak(50);
|
||||
for(auto& ap: anims::aps) {
|
||||
string what = "?";
|
||||
for(auto& p: params) if(p.second->affects(ap.value)) what = p.first;
|
||||
dialog::addInfo(what + " = " + ap.formula);
|
||||
dialog::addInfo(ap.par->name + " = " + ap.formula);
|
||||
}
|
||||
#endif
|
||||
dialog::addBreak(50);
|
||||
|
@ -1169,17 +1396,18 @@ EX namespace dialog {
|
|||
}
|
||||
|
||||
EX void parser_help() {
|
||||
ne.editwhat = nullptr;
|
||||
ne.intval = nullptr;
|
||||
number_dialog_help ndh;
|
||||
ndh.ptr = nullptr;
|
||||
addItem("help", SDLK_F1);
|
||||
add_action_push(number_dialog_help);
|
||||
add_action_push(ndh);
|
||||
}
|
||||
|
||||
EX void drawNumberDialog() {
|
||||
void number_dialog::draw() {
|
||||
cmode = sm::NUMBER | dialogflags;
|
||||
gamescreen();
|
||||
init(ne.title);
|
||||
addInfo(ne.s);
|
||||
init(title);
|
||||
addInfo(s);
|
||||
auto& ne = self;
|
||||
if(ne.intval && ne.sc.direct == &identity_f)
|
||||
addIntSlider(int(ne.vmin), int(*ne.editwhat), int(ne.vmax), 500);
|
||||
else
|
||||
|
@ -1194,7 +1422,7 @@ EX namespace dialog {
|
|||
addSelItem(XLAT("default value"), disp(ne.dft), SDLK_HOME);
|
||||
add_edit(onscreen_keyboard);
|
||||
addItem("help", SDLK_F1);
|
||||
add_action_push(number_dialog_help);
|
||||
add_action([this] { number_dialog_help ndh; ndh.ptr = this; pushScreen(ndh); });
|
||||
|
||||
addBreak(100);
|
||||
|
||||
|
@ -1213,7 +1441,7 @@ EX namespace dialog {
|
|||
|
||||
display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
keyhandler = [this, &ne] (int sym, int uni) {
|
||||
handleNavigation(sym, uni);
|
||||
if((uni >= '0' && uni <= '9') || among(uni, '.', '+', '-', '*', '/', '^', '(', ')', ',', '|', 3) || (uni >= 'a' && uni <= 'z')) {
|
||||
if(uni == 3) ne.s += "pi";
|
||||
|
@ -1268,10 +1496,46 @@ EX namespace dialog {
|
|||
|
||||
apply_slider();
|
||||
}
|
||||
else if(doexiton(sym, uni)) { popScreen(); if(reaction_final) reaction_final(); }
|
||||
else if(doexiton(sym, uni)) ne.popfinal();
|
||||
};
|
||||
}
|
||||
|
||||
void bool_dialog::draw() {
|
||||
cmode = dialogflags;
|
||||
gamescreen();
|
||||
init(title);
|
||||
|
||||
dialog::addBreak(100);
|
||||
|
||||
auto switch_to = [this] (bool b) {
|
||||
bool do_switch = (*editwhat != b);
|
||||
auto sw = switcher;
|
||||
auto re = reaction;
|
||||
popScreen();
|
||||
if(do_switch) { sw(); if(re) re(); }
|
||||
};
|
||||
|
||||
dialog::addBoolItem(XLAT("disable"), false, '0');
|
||||
dialog::add_action([switch_to] { switch_to(false); });
|
||||
|
||||
dialog::addBoolItem(XLAT("enable"), true, '1');
|
||||
dialog::add_action([switch_to] { switch_to(true); });
|
||||
|
||||
dialog::addBoolItem(XLAT("switch"), !*editwhat, 's');
|
||||
dialog::add_action([switch_to, this] { switch_to(!*editwhat); });
|
||||
|
||||
dialog::addBoolItem(XLAT("set default"), dft, 'd');
|
||||
dialog::add_action([switch_to, this] { switch_to(dft); });
|
||||
|
||||
dialog::addBreak(100);
|
||||
|
||||
if(help != "") addHelp(help);
|
||||
|
||||
if(extra_options) extra_options();
|
||||
|
||||
display();
|
||||
}
|
||||
|
||||
int nlpage = 1;
|
||||
int wheelshift = 0;
|
||||
|
||||
|
@ -1323,9 +1587,17 @@ EX namespace dialog {
|
|||
return true;
|
||||
}
|
||||
|
||||
EX void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) {
|
||||
extdialog::extdialog() {
|
||||
dialogflags = 0;
|
||||
if(cmode & sm::SIDE) dialogflags |= sm::MAYDARK | sm::SIDE;
|
||||
reaction = reaction_t();
|
||||
reaction_final = reaction_t();
|
||||
extra_options = reaction_t();
|
||||
}
|
||||
|
||||
EX number_dialog& editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) {
|
||||
number_dialog ne;
|
||||
ne.editwhat = &x;
|
||||
ne.s = disp(x);
|
||||
ne.vmin = vmin;
|
||||
ne.vmax = vmax;
|
||||
ne.step = step;
|
||||
|
@ -1334,23 +1606,32 @@ EX namespace dialog {
|
|||
ne.help = help;
|
||||
ne.sc = identity;
|
||||
ne.intval = NULL;
|
||||
dialogflags = 0;
|
||||
if(cmode & sm::SIDE) dialogflags |= sm::MAYDARK | sm::SIDE;
|
||||
cmode |= sm::NUMBER;
|
||||
pushScreen(drawNumberDialog);
|
||||
reaction = reaction_t();
|
||||
reaction_final = reaction_t();
|
||||
extra_options = reaction_t();
|
||||
ne.animatable = true;
|
||||
#if CAP_ANIMATIONS
|
||||
anims::get_parameter_animation(x, ne.s);
|
||||
anims::get_parameter_animation(anims::find_param(&x), ne.s);
|
||||
#endif
|
||||
ne.reset_str();
|
||||
pushScreen(ne);
|
||||
return get_ne();
|
||||
}
|
||||
|
||||
EX void editNumber(int& x, int vmin, int vmax, ld step, int dft, string title, string help) {
|
||||
editNumber(ne.intbuf, vmin, vmax, step, dft, title, help);
|
||||
ne.intbuf = x; ne.intval = &x; ne.s = its(x);
|
||||
ne.animatable = false;
|
||||
EX extdialog& editBool(bool& b, bool dft, string title, string help, const reaction_t& switcher) {
|
||||
bool_dialog be;
|
||||
be.editwhat = &b;
|
||||
be.dft = dft;
|
||||
be.title = title;
|
||||
be.help = help;
|
||||
be.switcher = switcher;
|
||||
pushScreen(be);
|
||||
return get_di();
|
||||
}
|
||||
|
||||
EX number_dialog& editNumber(int& x, int vmin, int vmax, ld step, int dft, string title, string help) {
|
||||
ld tmp;
|
||||
auto& ne = editNumber(tmp, vmin, vmax, step, dft, title, help);
|
||||
ne.editwhat = &ne.intbuf; ne.intbuf = x; ne.intval = &x; ne.s = its(x);
|
||||
anims::get_parameter_animation(anims::find_param(&x), ne.s);
|
||||
return ne;
|
||||
}
|
||||
|
||||
EX void helpToEdit(int& x, int vmin, int vmax, int step, int dft) {
|
||||
|
@ -1388,7 +1669,11 @@ EX namespace dialog {
|
|||
|
||||
bool search_mode;
|
||||
|
||||
EX void drawFileDialog() {
|
||||
struct file_dialog : extdialog {
|
||||
void draw() override;
|
||||
};
|
||||
|
||||
void file_dialog::draw() {
|
||||
cmode = sm::NUMBER | dialogflags | sm::DIALOG_WIDE;
|
||||
gamescreen();
|
||||
init(filecaption);
|
||||
|
@ -1465,8 +1750,8 @@ EX namespace dialog {
|
|||
else {
|
||||
str1 = where + vf;
|
||||
if(s == str1) {
|
||||
popScreen();
|
||||
if(!file_action()) pushScreen(drawFileDialog);
|
||||
bool ac = file_action();
|
||||
if(ac) popScreen();
|
||||
}
|
||||
s = str1;
|
||||
}
|
||||
|
@ -1494,9 +1779,8 @@ EX namespace dialog {
|
|||
popScreen();
|
||||
}
|
||||
else if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER) {
|
||||
// we pop and re-push, in case if action opens something
|
||||
popScreen();
|
||||
if(!file_action()) pushScreen(drawFileDialog);
|
||||
bool ac = file_action();
|
||||
if(ac) popScreen();
|
||||
}
|
||||
else if(sym == SDLK_BACKSPACE && i) {
|
||||
s.erase(i-1, 1);
|
||||
|
@ -1512,11 +1796,12 @@ EX namespace dialog {
|
|||
}
|
||||
|
||||
EX void openFileDialog(string& filename, string fcap, string ext, bool_reaction_t action) {
|
||||
file_dialog fd;
|
||||
cfileptr = &filename;
|
||||
filecaption = fcap;
|
||||
cfileext = ext;
|
||||
file_action = action;
|
||||
pushScreen(dialog::drawFileDialog);
|
||||
pushScreen(fd);
|
||||
}
|
||||
|
||||
// infix/v/vpush
|
||||
|
@ -1579,10 +1864,23 @@ EX namespace dialog {
|
|||
dialog::v.push_back(make_pair(s, color));
|
||||
}
|
||||
|
||||
int editpos = 0;
|
||||
EX string *edited_string;
|
||||
EX string editchecker(int sym, int uni) {
|
||||
if(uni >= 32 && uni < 127) return string("") + char(uni);
|
||||
return "";
|
||||
}
|
||||
|
||||
EX string view_edited_string() {
|
||||
#if HDR
|
||||
struct string_dialog : extdialog {
|
||||
int editpos = 0;
|
||||
string *edited_string;
|
||||
string view_edited_string();
|
||||
void draw() override;
|
||||
void start_editing(string& s);
|
||||
bool handle_edit_string(int sym, int uni, function<string(int, int)> checker = editchecker);
|
||||
};
|
||||
#endif
|
||||
|
||||
string string_dialog::view_edited_string() {
|
||||
string cs = *edited_string;
|
||||
if(editpos < 0) editpos = 0;
|
||||
if(editpos > isize(cs)) editpos = isize(cs);
|
||||
|
@ -1590,17 +1888,12 @@ EX namespace dialog {
|
|||
return cs;
|
||||
}
|
||||
|
||||
EX void start_editing(string& s) {
|
||||
void string_dialog::start_editing(string& s) {
|
||||
edited_string = &s;
|
||||
editpos = isize(s);
|
||||
}
|
||||
|
||||
EX string editchecker(int sym, int uni) {
|
||||
if(uni >= 32 && uni < 127) return string("") + char(uni);
|
||||
return "";
|
||||
}
|
||||
|
||||
EX bool handle_edit_string(int sym, int uni, function<string(int, int)> checker IS(editchecker)) {
|
||||
bool string_dialog::handle_edit_string(int sym, int uni, function<string(int, int)> checker) {
|
||||
auto& es = *edited_string;
|
||||
string u2;
|
||||
if(DKEY == SDLK_LEFT) editpos--;
|
||||
|
@ -1609,21 +1902,23 @@ EX namespace dialog {
|
|||
if(editpos == 0) return true;
|
||||
es.replace(editpos-1, 1, "");
|
||||
editpos--;
|
||||
if(reaction) reaction();
|
||||
}
|
||||
else if((u2 = checker(sym, uni)) != "") {
|
||||
for(char c: u2) {
|
||||
es.insert(editpos, 1, c);
|
||||
editpos ++;
|
||||
}
|
||||
if(reaction) reaction();
|
||||
}
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
EX void string_edit_dialog() {
|
||||
void string_dialog::draw() {
|
||||
cmode = sm::NUMBER | dialogflags;
|
||||
gamescreen();
|
||||
init(ne.title);
|
||||
init(title);
|
||||
addInfo(view_edited_string());
|
||||
addBreak(100);
|
||||
formula_keyboard(true);
|
||||
|
@ -1631,34 +1926,27 @@ EX namespace dialog {
|
|||
dialog::addBack();
|
||||
addBreak(100);
|
||||
|
||||
if(ne.help != "") {
|
||||
addHelp(ne.help);
|
||||
if(help != "") {
|
||||
addHelp(help);
|
||||
}
|
||||
|
||||
if(extra_options) extra_options();
|
||||
|
||||
display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
keyhandler = [this] (int sym, int uni) {
|
||||
handleNavigation(sym, uni);
|
||||
if(handle_edit_string(sym, uni)) ;
|
||||
else if(doexiton(sym, uni)) {
|
||||
popScreen();
|
||||
if(reaction_final) reaction_final();
|
||||
}
|
||||
else if(doexiton(sym, uni)) popfinal();
|
||||
};
|
||||
}
|
||||
|
||||
EX void edit_string(string& s, string title, string help) {
|
||||
start_editing(s);
|
||||
string_dialog ne;
|
||||
ne.title = title;
|
||||
ne.help = help;
|
||||
dialogflags = 0;
|
||||
if(cmode & sm::SIDE) dialogflags |= sm::MAYDARK | sm::SIDE;
|
||||
cmode |= sm::NUMBER;
|
||||
pushScreen(string_edit_dialog);
|
||||
reaction = reaction_t();
|
||||
extra_options = reaction_t();
|
||||
ne.start_editing(s);
|
||||
pushScreen(ne);
|
||||
}
|
||||
|
||||
EX void confirm_dialog(const string& text, const reaction_t& act) {
|
||||
|
|
164
drawing.cpp
164
drawing.cpp
|
@ -9,37 +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 const int POLY_APEIROGONAL = (1<<29); // only vertices indexed up to she are drawn as the boundary
|
||||
static const int POLY_NO_FOG = (1<<30); // disable fog for this
|
||||
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.
|
||||
*
|
||||
|
@ -229,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();
|
||||
|
@ -237,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();
|
||||
|
@ -313,12 +313,11 @@ EX bool two_sided_model() {
|
|||
#endif
|
||||
if(GDIM == 3) return false;
|
||||
if(in_vr_sphere) return true;
|
||||
if(models::is_hyperboloid(pmodel)) return !euclid && !in_vr;
|
||||
if(pmodel == mdHemisphere || pmodel == mdHyperboloid) return !in_vr;
|
||||
// if(pmodel == mdHemisphere) return true;
|
||||
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;
|
||||
|
@ -353,13 +352,12 @@ 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 == 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 && hyperbolic) {
|
||||
if(pmodel == mdHemisphere && !sphere) {
|
||||
hyperpoint res;
|
||||
applymodel(shiftless(H), res);
|
||||
return res[2] < 0 ? -1 : 1;
|
||||
|
@ -369,8 +367,9 @@ EX int get_side(const hyperpoint& 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]);
|
||||
return (models::sin_ball * H1[2] > models::cos_ball * H1[1]) ? 1 : -1;
|
||||
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));
|
||||
|
@ -475,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];
|
||||
|
@ -664,7 +663,7 @@ 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(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();
|
||||
lprio = prio;
|
||||
|
@ -718,7 +717,7 @@ void dqi_poly::gldraw() {
|
|||
|
||||
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) {
|
||||
|
@ -925,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]);
|
||||
|
||||
|
@ -989,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) {
|
||||
|
@ -1020,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;
|
||||
}
|
||||
|
@ -1550,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]));
|
||||
|
@ -1575,15 +1591,15 @@ 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]);
|
||||
shiftpoint o = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]);
|
||||
if(nonisotropic || gproduct) {
|
||||
o = lp_apply(inverse_exp(o, iTable, false));
|
||||
o[3] = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1667,7 +1683,7 @@ bool broken_projection(dqi_poly& p0) {
|
|||
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;
|
||||
|
@ -1692,7 +1708,7 @@ bool broken_projection(dqi_poly& p0) {
|
|||
|
||||
/* 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;
|
||||
|
@ -1875,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;
|
||||
|
@ -1959,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;
|
||||
|
@ -2030,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;
|
||||
}
|
||||
|
@ -2120,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;
|
||||
|
@ -2418,7 +2434,7 @@ EX void draw_main() {
|
|||
}
|
||||
|
||||
if(pmodel == mdHemisphere && sphere && hemi_side == 0 && !vrhr::rendering()) {
|
||||
hemi_side = models::sin_ball > 0 ? 1 : -1;
|
||||
hemi_side = (pconf.ball() * hyperpoint(0,1,0,1)) [2] < 0 ? 1 : -1;
|
||||
draw_main();
|
||||
|
||||
if(pconf.show_hyperboloid_flat) {
|
||||
|
@ -2429,6 +2445,11 @@ EX void draw_main() {
|
|||
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;
|
||||
|
@ -2602,7 +2623,7 @@ EX void drawqueue() {
|
|||
}
|
||||
|
||||
#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);
|
||||
|
@ -2630,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
|
||||
|
@ -2745,9 +2766,14 @@ EX void curvepoint_first() {
|
|||
curvedata.push_back(curvedata[curvestart]);
|
||||
}
|
||||
|
||||
EX dqi_poly& queuecurve(const shiftmatrix& V, color_t linecol, color_t fillcol, PPR prio) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ EX namespace geom3 {
|
|||
ans += " torus";
|
||||
}
|
||||
if(among(sp, seSol, seNIH, seSolN)) {
|
||||
if((meuclid && !PURE) && !bt::in()) ans += " pure or bin";
|
||||
if((meuclid && !PURE) || !bt::in()) ans += " pure or bin";
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
@ -132,13 +132,30 @@ EX namespace geom3 {
|
|||
|
||||
EX geometry_information* unflipped;
|
||||
|
||||
EX void light_flip(bool f) {
|
||||
if(f != flipped) {
|
||||
if(!flipped) unflipped = cgip;
|
||||
EX void light_flip_geom() {
|
||||
indenter ind(2);
|
||||
swap(ginf[geometry].g, geom3::ginf_backup[geometry].g);
|
||||
swap(ginf[geometry].flags, geom3::ginf_backup[geometry].flags);
|
||||
if(!flipped) cgip = unflipped;
|
||||
if(fake::in()) {
|
||||
// println(hlog, "warning: flipping while still in fake");
|
||||
FPIU(light_flip_geom());
|
||||
}
|
||||
// hyperbolic arcm needs gNormal for cdata. Also swap gSphere and gEuclid for compute_geometry
|
||||
else if(arcm::in()) {
|
||||
dynamicval<eGeometry> g(geometry, gNormal); light_flip_geom();
|
||||
geometry = gSphere; light_flip_geom();
|
||||
geometry = gEuclid; light_flip_geom();
|
||||
}
|
||||
}
|
||||
|
||||
EX void light_flip(bool f) {
|
||||
if(f != flipped) {
|
||||
if(!flipped) cgip->use_count++;
|
||||
if(!flipped) unflipped = cgip;
|
||||
light_flip_geom();
|
||||
flipped = f;
|
||||
if(!flipped) cgip = unflipped;
|
||||
if(!flipped) cgip->use_count--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +182,12 @@ EX namespace geom3 {
|
|||
}
|
||||
if(vid.always3 && ginf_backup.empty()) {
|
||||
ginf_backup = ginf;
|
||||
for(geometryinfo& gi: ginf) {
|
||||
for(geometryinfo& gi: ginf)
|
||||
apply_always3_to(gi);
|
||||
}
|
||||
}
|
||||
|
||||
EX void apply_always3_to(geometryinfo& gi) {
|
||||
auto &g = gi.g;
|
||||
if(vid.always3 && g.gameplay_dimension == 2 && g.graphical_dimension == 2) {
|
||||
/* same-in-same by default */
|
||||
|
@ -199,8 +221,6 @@ EX namespace geom3 {
|
|||
g.gameplay_dimension = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EX void configure_clifford_torus() {
|
||||
#if CAP_RUG
|
||||
|
@ -378,10 +398,12 @@ struct emb_none : embedding_method {
|
|||
return rgpushxto0(i);
|
||||
}
|
||||
hyperpoint flatten(hyperpoint a) override {
|
||||
if(gproduct) return a / exp(zlevel(a));
|
||||
if(gproduct || GDIM == 2) return a / exp(zlevel(a));
|
||||
return embedding_method::flatten(a);
|
||||
}
|
||||
|
||||
hyperpoint normalize_flat(hyperpoint a) override { return gproduct ? flatten(a) : normalize(a); }
|
||||
|
||||
transmatrix base_to_actual(const transmatrix& T) override { return T; }
|
||||
hyperpoint base_to_actual(hyperpoint h) override { return h; }
|
||||
transmatrix actual_to_base(const transmatrix& T) override { return T; }
|
||||
|
@ -498,7 +520,7 @@ struct emb_actual : embedding_method {
|
|||
/** embed in the 3D variant of the same geometry */
|
||||
|
||||
struct emb_same_in_same : emb_actual {
|
||||
virtual bool is_same_in_same() override { return true; }
|
||||
bool is_same_in_same() override { return true; }
|
||||
transmatrix intermediate_to_actual_translation(hyperpoint i) override { return rgpushxto0(logical_to_actual(i)); }
|
||||
hyperpoint actual_to_intermediate(hyperpoint a) override { return actual_to_logical(a); }
|
||||
hyperpoint orthogonal_move(const hyperpoint& h, ld z) override {
|
||||
|
@ -521,7 +543,7 @@ struct emb_same_in_same : emb_actual {
|
|||
for(int i=0; i<4; i++) T[i][2] = T[i][3], T[i][3] = 0;
|
||||
for(int i=0; i<4; i++) T[2][i] = T[3][i], T[3][i] = 0;
|
||||
T[3][3] = 1;
|
||||
fixmatrix(T);
|
||||
if(MDIM == 3) fixmatrix(T); else IPF(fixmatrix(T));
|
||||
for(int i=0; i<MDIM; i++) for(int j=0; j<MDIM; j++) if(isnan(T[i][j])) return Id;
|
||||
return T;
|
||||
}
|
||||
|
@ -579,7 +601,7 @@ struct emb_same_in_same : emb_actual {
|
|||
/** embed in the product geometry */
|
||||
|
||||
struct emb_product_embedding : emb_actual {
|
||||
virtual bool is_product_embedding() override { return true; }
|
||||
bool is_product_embedding() override { return true; }
|
||||
transmatrix intermediate_to_actual_translation(hyperpoint i) override { return rgpushxto0(logical_to_actual(i)); }
|
||||
hyperpoint actual_to_intermediate(hyperpoint a) override { return actual_to_logical(a); }
|
||||
hyperpoint flatten(hyperpoint h) override { h /= exp(zlevel(h)); return h; }
|
||||
|
@ -891,7 +913,7 @@ struct emb_euc_cylinder_sl2 : emb_euc_cylinder_twisted {
|
|||
struct emb_euc_in_sph : emb_euclid_noniso {
|
||||
bool is_euc_in_sph() override { return true; }
|
||||
ld center_z() override { return 1; }
|
||||
// virtual ld height_limit(ld sign) override { return sign < 0 ? 0 : 90._deg; }
|
||||
// ld height_limit(ld sign) override { return sign < 0 ? 0 : 90._deg; }
|
||||
hyperpoint actual_to_intermediate(hyperpoint a) override {
|
||||
ld tx = hypot(a[0], a[2]);
|
||||
ld ty = hypot(a[1], a[3]);
|
||||
|
@ -1367,7 +1389,9 @@ geom3::eSpatialEmbedding embed_by_name(string ss) {
|
|||
return seNone;
|
||||
}
|
||||
|
||||
#if CAP_COMMANDLINE
|
||||
auto ah_embed = arg::add2("-seo", [] { arg::shift(); invoke_embed(embed_by_name(arg::args())); })
|
||||
+ arg::add2("-never-invert", [] { never_invert = true; });
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -304,8 +304,6 @@ EX vector<int> bfs_reachedfrom;
|
|||
/** calculate cpdist, 'have' flags, and do general fixings */
|
||||
EX void bfs() {
|
||||
|
||||
calcTidalPhase();
|
||||
|
||||
yendor::onpath();
|
||||
|
||||
int dcs = isize(dcal);
|
||||
|
@ -330,12 +328,9 @@ EX void bfs() {
|
|||
|
||||
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);
|
||||
bfs_reachedfrom.push_back(hrand(c->type));
|
||||
if(!invismove) targets.push_back(c);
|
||||
|
@ -373,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;
|
||||
}
|
||||
|
@ -381,7 +376,7 @@ EX void bfs() {
|
|||
|
||||
// remove treasures
|
||||
if(!peace::on && c2->item && c2->cpdist == distlimit && itemclass(c2->item) == IC_TREASURE &&
|
||||
c2->item != itBabyTortoise && WDIM != 3 &&
|
||||
!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; }
|
||||
|
@ -436,8 +431,6 @@ EX void bfs() {
|
|||
dcal.push_back(c2);
|
||||
bfs_reachedfrom.push_back(c->c.spin(i));
|
||||
|
||||
checkTide(c2);
|
||||
|
||||
if(c2->wall == waBigStatue && c2->land != laTemple)
|
||||
statuecount++;
|
||||
|
||||
|
@ -549,11 +542,6 @@ EX void bfs() {
|
|||
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;
|
||||
|
||||
buildAirmap();
|
||||
|
@ -832,6 +820,15 @@ EX void findWormIvy(cell *c) {
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -869,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);
|
||||
|
|
13
euclid.cpp
13
euclid.cpp
|
@ -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];
|
||||
|
@ -71,8 +71,7 @@ EX namespace euc {
|
|||
break;
|
||||
|
||||
default:
|
||||
printf("euc::get_shifttable() called in geometry that is not euclid3");
|
||||
exit(1);
|
||||
throw hr_exception("euc::get_shifttable() called in geometry that is not euclid3");
|
||||
}
|
||||
|
||||
// reverse everything
|
||||
|
@ -963,7 +962,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));
|
||||
|
@ -1046,7 +1045,7 @@ EX namespace euc {
|
|||
"not implemented.)"
|
||||
)
|
||||
);
|
||||
dialog::extra_options = show_fundamental;
|
||||
dialog::get_di().extra_options = show_fundamental;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -409,6 +409,7 @@ EX bool sizes_known() {
|
|||
if(aperiodic) return false;
|
||||
if(currentmap->strict_tree_rules()) return true;
|
||||
if(arb::in()) return false;
|
||||
if(INVERSE) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -554,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); }
|
||||
|
@ -645,7 +655,7 @@ void celldrawer::do_viewdist() {
|
|||
if(!dist_label_colored) dc = dist_label_color;
|
||||
|
||||
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() {
|
||||
|
@ -809,7 +819,7 @@ void expansion_analyzer::view_distances_dialog() {
|
|||
scrolling_distances = false;
|
||||
dialog::editNumber(last_distance, 0, 3000, 1, 0, XLAT("display distances up to"), "");
|
||||
dialog::bound_low(0);
|
||||
dialog::extra_options = [] {
|
||||
dialog::get_di().extra_options = [] {
|
||||
add_edit(auto_extend);
|
||||
};
|
||||
});
|
||||
|
|
|
@ -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 {
|
||||
string 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);
|
||||
|
|
48
fake.cpp
48
fake.cpp
|
@ -54,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();
|
||||
|
@ -74,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;
|
||||
}
|
||||
|
@ -90,6 +92,13 @@ EX namespace fake {
|
|||
|
||||
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);
|
||||
}
|
||||
|
@ -100,6 +109,12 @@ EX namespace fake {
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -592,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;
|
||||
|
@ -706,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');
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -272,7 +272,7 @@ struct fpattern {
|
|||
|
||||
void build();
|
||||
|
||||
static const int MAXDIST = 120;
|
||||
static constexpr int MAXDIST = 120;
|
||||
|
||||
vector<char> disthep;
|
||||
vector<char> disthex;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -507,7 +507,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
|
|||
}
|
||||
}
|
||||
|
||||
else if(arb::in() || aperiodic) {
|
||||
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));
|
||||
|
@ -526,7 +526,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
|
|||
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;
|
||||
|
@ -535,19 +535,19 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
|
|||
int id = 0;
|
||||
arb::shape *sh = nullptr;
|
||||
if(arb::in()) {
|
||||
int id = arb::id_of(c->master);
|
||||
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(arb::current_or_slided(), id, cor-1, id, cor-2, false) * actual[cor-3];
|
||||
if(j == cor-2) next = arb::get_adj(arb::current_or_slided(), id, cor-2, id, cor-1, false) * actual[1];
|
||||
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; }
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1000,7 @@ EX namespace gp {
|
|||
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);
|
||||
|
||||
|
@ -1092,6 +1092,7 @@ 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)
|
||||
|
@ -1380,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);
|
||||
|
||||
|
|
2
game.cpp
2
game.cpp
|
@ -347,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);
|
||||
|
|
43
geom-exp.cpp
43
geom-exp.cpp
|
@ -153,10 +153,7 @@ EX bool showquotients;
|
|||
|
||||
string validclasses[4] = {" (X)", " (½)", "", " (!)"};
|
||||
|
||||
EX void ge_land_selection() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
|
||||
EX void gen_landvisited() {
|
||||
if(cheater) for(int i=0; i<landtypes; i++) landvisited[i] = true;
|
||||
|
||||
for(int i=0; i<landtypes; i++)
|
||||
|
@ -177,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;
|
||||
|
@ -554,7 +558,7 @@ EX string geometry_name() {
|
|||
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;
|
||||
|
@ -690,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
|
||||
|
@ -705,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);
|
||||
});
|
||||
}
|
||||
|
@ -719,7 +723,7 @@ 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(); };
|
||||
}
|
||||
|
||||
#if HDR
|
||||
|
@ -940,6 +944,13 @@ EX geometry_data compute_geometry_data() {
|
|||
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;
|
||||
|
||||
|
@ -1013,7 +1024,7 @@ EX void showEuclideanMenu() {
|
|||
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::reaction = ray::reset_raycaster;
|
||||
dialog::get_ne().reaction = ray::reset_raycaster;
|
||||
});
|
||||
}
|
||||
else if(mhybrid) {
|
||||
|
@ -1067,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
|
||||
|
@ -1086,11 +1097,11 @@ EX void showEuclideanMenu() {
|
|||
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();
|
||||
|
@ -1109,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) {
|
||||
|
@ -1147,11 +1158,7 @@ EX void showEuclideanMenu() {
|
|||
}
|
||||
|
||||
dialog::addSelItem(XLAT("size of the world"), gd.size_str, '3');
|
||||
|
||||
if(WDIM == 2 || reg3::exact_rules()) dialog::add_action([] {
|
||||
if(!viewdists) { enable_viewdists(); pushScreen(viewdist_configure_dialog); }
|
||||
else if(viewdists) viewdists = false;
|
||||
});
|
||||
add_size_action();
|
||||
|
||||
if(closed_manifold) {
|
||||
dialog::addSelItem(XLAT("Euler characteristics"), its(gd.euler), 0);
|
||||
|
|
39
geometry.cpp
39
geometry.cpp
|
@ -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]; };
|
||||
|
||||
|
@ -57,15 +57,15 @@ struct hpcshape {
|
|||
#define GOLDBERG_BITS 5
|
||||
#endif
|
||||
|
||||
static const int GOLDBERG_LIMIT = (1<<GOLDBERG_BITS);
|
||||
static const int GOLDBERG_MASK = (GOLDBERG_LIMIT-1);
|
||||
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;
|
||||
|
@ -359,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
|
||||
|
@ -543,7 +545,9 @@ hpcshape
|
|||
void require_usershapes() { if(usershape_state == usershape_changes) return; usershape_state = usershape_changes; prepare_usershapes(); }
|
||||
int timestamp;
|
||||
|
||||
hpcshape& generate_pipe(ld length, ld width, ePipeEnd endtype = ePipeEnd::sharp);
|
||||
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;
|
||||
|
||||
|
@ -569,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);
|
||||
}
|
||||
|
@ -693,7 +695,7 @@ void geometry_information::prepare_basics() {
|
|||
: 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];
|
||||
|
@ -780,13 +782,13 @@ void geometry_information::prepare_basics() {
|
|||
if(msphere && geuclid) scalefactor *= (1 + vid.depth);
|
||||
if(msphere && ghyperbolic) scalefactor *= sinh(1 + vid.depth);
|
||||
|
||||
if(scale_used()) {
|
||||
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;
|
||||
|
||||
if(cgi.emb->is_euc_in_hyp()) {
|
||||
|
@ -1114,9 +1116,9 @@ EX namespace geom3 {
|
|||
EX void switch_tpp() {
|
||||
if(dual::split(switch_fpp)) return;
|
||||
if(rug::rugged) rug::close();
|
||||
if(pmodel == mdDisk && pconf.camera_angle) {
|
||||
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;
|
||||
|
@ -1124,7 +1126,7 @@ EX namespace geom3 {
|
|||
}
|
||||
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;
|
||||
|
@ -1175,7 +1177,7 @@ EX namespace geom3 {
|
|||
}
|
||||
|
||||
EX void apply_settings_full() {
|
||||
if(vid.always3) {
|
||||
if(cgip && vid.always3) {
|
||||
changing_embedded_settings = true;
|
||||
geom3::switch_fpp();
|
||||
#if MAXMDIM >= 4
|
||||
|
@ -1190,7 +1192,7 @@ EX namespace geom3 {
|
|||
|
||||
EX void apply_settings_light() {
|
||||
#if MAXMDIM >= 4
|
||||
if(vid.always3) {
|
||||
if(cgip && vid.always3) {
|
||||
changing_embedded_settings = true;
|
||||
geom3::switch_always3();
|
||||
geom3::switch_always3();
|
||||
|
@ -1310,7 +1312,7 @@ EX string cgi_string() {
|
|||
V("RS:", fts(geom3::euclid_embed_rotate));
|
||||
}
|
||||
|
||||
if(scale_used()) V("CS", fts(vid.creature_scale));
|
||||
if(vid.creature_scale != 1) V("CS", fts(vid.creature_scale));
|
||||
|
||||
if(WDIM == 3) V("HTW", fts(vid.height_width));
|
||||
|
||||
|
@ -1335,7 +1337,8 @@ EX void check_cgi() {
|
|||
if(mhybrid) hybrid::underlying_cgip->timestamp = ntimestamp;
|
||||
if(fake::in()) fake::underlying_cgip->timestamp = ntimestamp;
|
||||
#if CAP_ARCM
|
||||
if(arcm::alt_cgip) arcm::alt_cgip->timestamp = ntimestamp;
|
||||
if(arcm::alt_cgip[0]) arcm::alt_cgip[0]->timestamp = ntimestamp;
|
||||
if(arcm::alt_cgip[1]) arcm::alt_cgip[1]->timestamp = ntimestamp;
|
||||
#endif
|
||||
|
||||
int limit = 4;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
6
glhr.cpp
6
glhr.cpp
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ EX int compileShader(int type, const string& s) {
|
|||
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, "===");
|
||||
|
|
31
goldberg.cpp
31
goldberg.cpp
|
@ -234,7 +234,7 @@ 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, (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;
|
||||
|
@ -813,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. "
|
||||
|
@ -887,10 +896,11 @@ 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"));
|
||||
|
@ -973,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());
|
||||
}
|
||||
});
|
||||
|
@ -1259,6 +1269,7 @@ EX namespace gp {
|
|||
}
|
||||
|
||||
hrmap_inverse() {
|
||||
underlying_map = nullptr;
|
||||
if(0) {
|
||||
println(hlog, "making ucgi");
|
||||
dynamicval<eVariation> gva(variation, variation_for(param));
|
||||
|
@ -1436,6 +1447,12 @@ EX namespace gp {
|
|||
|
||||
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]; }
|
||||
|
|
260
graph.cpp
260
graph.cpp
|
@ -22,9 +22,6 @@ EX bool spatial_graphics;
|
|||
EX bool wmspatial, wmescher, wmplain, wmblack, wmascii, wmascii3;
|
||||
EX bool mmspatial, mmhigh, mmmon, mmitem;
|
||||
|
||||
EX ld panini_alpha = 0;
|
||||
EX ld stereo_alpha = 0;
|
||||
|
||||
EX int detaillevel = 0;
|
||||
|
||||
EX bool first_cell_to_draw = true;
|
||||
|
@ -212,6 +209,7 @@ void drawSpeed(const shiftmatrix& V, ld scale=1) {
|
|||
}
|
||||
|
||||
void drawSafety(const shiftmatrix& V, int ct) {
|
||||
if(inHighQual) return;
|
||||
#if CAP_QUEUE
|
||||
ld ds = ptick(50);
|
||||
color_t col = darkena(iinf[itOrbSafety].color, 0, 0xFF);
|
||||
|
@ -774,9 +772,10 @@ EX shiftmatrix face_the_player(const shiftmatrix V) {
|
|||
if(vrhr::enabled) {
|
||||
shiftpoint h = tC0(V);
|
||||
hyperpoint uh = unshift(h);
|
||||
return shiftless(cspin90(1, 2) * lrspintox(cspin90(2, 1) * uh) * xpush(hdist0(uh)) * cspin90(0, 2) * spin270());
|
||||
return shiftless(cspin90(1, 2) * rspintox(cspin90(2, 1) * uh) * xpush(hdist0(uh)) * cspin90(0, 2) * spin270());
|
||||
}
|
||||
#endif
|
||||
|
||||
return rgpushxto0(tC0(V));
|
||||
}
|
||||
|
||||
|
@ -849,12 +848,42 @@ EX void draw_ascii(const shiftmatrix& V, char glyph, color_t col, ld size) {
|
|||
string s = s0 + glyph;
|
||||
int id = isize(ptds);
|
||||
if(WDIM == 2 && GDIM == 3)
|
||||
queuestrn(V * lzpush(cgi.FLOOR - cgi.scalefactor * size / 4), size, s, darkenedby(col, darken), 0);
|
||||
queuestrn(V * lzpush(cgi.FLOOR - cgi.scalefactor * size / 4), size * mapfontscale / 100, s, darkenedby(col, darken), 0);
|
||||
else
|
||||
queuestrn(V, 1, s, darkenedby(col, darken), GDIM == 3 ? 0 : 2);
|
||||
queuestrn(V, mapfontscale / 100, s, darkenedby(col, darken), GDIM == 3 ? 0 : 2);
|
||||
while(id < isize(ptds)) ptds[id++]->prio = PPR::MONSTER_BODY;
|
||||
}
|
||||
|
||||
EX void queue_goal_text(shiftpoint P1, ld sizemul, const string& s, color_t color) {
|
||||
#if CAP_VR
|
||||
if(vrhr::enabled) {
|
||||
auto e = inverse_exp(P1);
|
||||
e = e * 3 / hypot_d(GDIM, e);
|
||||
auto T = face_the_player(shiftless(rgpushxto0(direct_exp(e))));
|
||||
queuestrn(T, sizemul * mapfontscale / 100, s, color);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
queuestr(P1, vid.fsize * sizemul, s, color);
|
||||
}
|
||||
|
||||
EX bool mark_compass(cell *c, shiftpoint& P1) {
|
||||
cell *c1 = c ? findcompass(c) : NULL;
|
||||
if(!c1) return false;
|
||||
|
||||
shiftmatrix P = ggmatrix(c1);
|
||||
P1 = tC0(P);
|
||||
|
||||
if(isPlayerOn(c)) {
|
||||
queue_goal_text(P1, 2, "X", 0x10100 * int(128 + 100 * sintick(150)));
|
||||
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
|
||||
queue_goal_text(P1, 1, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
addauraspecial(P1, 0xFF0000, 0);
|
||||
addradar(P, 'X', iinf[itCompass].color, 0xFF, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int pticks, bool hidden) {
|
||||
if(!it) return false;
|
||||
char xch = iinf[it].glyph;
|
||||
|
@ -933,6 +962,11 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
|||
queuepoly(Vit * spinptick(750, 0), cgi.shTriangle, darkena(icol, 0, 255));
|
||||
}
|
||||
|
||||
else if(it == itCrossbow) {
|
||||
queuepoly(Vit, cgi.shCrossbowIcon, getcs().bowcolor);
|
||||
queuepoly(Vit, cgi.shCrossbowstringIcon, getcs().bowcolor2);
|
||||
}
|
||||
|
||||
else if(it == itBabyTortoise) {
|
||||
int bits = c ? tortoise::babymap[c] : tortoise::last;
|
||||
int over = c && c->monst == moTortoise;
|
||||
|
@ -951,18 +985,8 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
|
|||
else
|
||||
#endif
|
||||
if(1) {
|
||||
cell *c1 = c ? findcompass(c) : NULL;
|
||||
if(c1) {
|
||||
shiftmatrix P = ggmatrix(c1);
|
||||
shiftpoint P1 = tC0(P);
|
||||
|
||||
if(isPlayerOn(c)) {
|
||||
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
|
||||
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
|
||||
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
addauraspecial(P1, 0xFF0000, 0);
|
||||
}
|
||||
|
||||
shiftpoint P1;
|
||||
if(mark_compass(c, P1)) {
|
||||
V2 = V * lrspintox(inverse_shift(V, P1));
|
||||
}
|
||||
else V2 = V;
|
||||
|
@ -1410,6 +1434,21 @@ EX void drawPlayer(eMonster m, cell *where, const shiftmatrix& V, color_t col, d
|
|||
queuepoly(VWPN, cgi.shTrophy, racing::trophy[multi::cpid]);
|
||||
#endif
|
||||
}
|
||||
else if(bow::crossbow_mode() && cs.charid < 4) {
|
||||
queuepoly(VWPN, cgi.shCrossbow, fc(314, cs.bowcolor, 3));
|
||||
int ti = items[itCrossbow];
|
||||
if(shmup::on) {
|
||||
ti = shmup::getPlayer()->nextshot - shmup::curtime;
|
||||
if(ti <= 0) ti = 0;
|
||||
else ti = 1 + ti / 500;
|
||||
}
|
||||
shiftmatrix VWPN1 = VWPN, VWPN2 = VWPN;
|
||||
if(GDIM == 3) { ld h = cgi.human_height; VWPN1 = VWPN * lzpush(-h/60); VWPN2 = VWPN * lzpush(-h/30); }
|
||||
if(ti <= 1) queuepoly(VWPN1, cgi.shCrossbowstringLoaded, fc(314, cs.bowcolor2, 3));
|
||||
else if(ti <= 2) queuepoly(VWPN1, cgi.shCrossbowstringSemiloaded, fc(314, cs.bowcolor2, 3));
|
||||
else queuepoly(VWPN1, cgi.shCrossbowstringUnloaded, fc(314, cs.bowcolor2, 3));
|
||||
if(ti == 0) queuepoly(VWPN2, cgi.shCrossbowBolt, fc(314, cs.swordcolor, 3));
|
||||
}
|
||||
else if(items[itOrbThorns])
|
||||
queuepoly(VWPN, cgi.shHedgehogBladePlayer, items[itOrbDiscord] ? watercolor(0) : 0x00FF00FF);
|
||||
else if(!shmup::on && items[itOrbDiscord])
|
||||
|
@ -1521,7 +1560,24 @@ void drawMimic(eMonster m, cell *where, const shiftmatrix& V, color_t col, doubl
|
|||
const transmatrix VBS = otherbodyparts(V, darkena(col, 0, 0x40), m, footphase);
|
||||
queuepoly(VBODY * VBS, (cs.charid&1) ? cgi.shFemaleBody : cgi.shPBody, darkena(col, 0, 0X80));
|
||||
|
||||
if(!shmup::on) {
|
||||
if(bow::crossbow_mode() && cs.charid < 4) {
|
||||
shiftmatrix VWPN = cs.lefthanded ? VBODY * VBS * lmirror() : VBODY * VBS;
|
||||
color_t col1 = darkena(col, 0, 0x40);
|
||||
queuepoly(VWPN, cgi.shCrossbow, col1);
|
||||
int ti = items[itCrossbow];
|
||||
if(shmup::on) {
|
||||
ti = shmup::getPlayer()->nextshot - shmup::curtime;
|
||||
if(ti <= 0) ti = 0;
|
||||
else ti = 1 + ti / 500;
|
||||
}
|
||||
shiftmatrix VWPN1 = VWPN, VWPN2 = VWPN;
|
||||
if(GDIM == 3) { ld h = cgi.human_height; VWPN1 = VWPN * lzpush(-h/60); VWPN2 = VWPN * lzpush(-h/30); }
|
||||
if(ti <= 1) queuepoly(VWPN1, cgi.shCrossbowstringLoaded, col1);
|
||||
else if(ti <= 2) queuepoly(VWPN1, cgi.shCrossbowstringSemiloaded, col1);
|
||||
else queuepoly(VWPN1, cgi.shCrossbowstringUnloaded, col1);
|
||||
if(ti == 0) queuepoly(VWPN2, cgi.shCrossbowBolt, col1);
|
||||
}
|
||||
else if(!shmup::on) {
|
||||
bool emp = items[itOrbEmpathy] && m != moShadow;
|
||||
if(items[itOrbThorns] && emp)
|
||||
queuepoly(VBODY * VBS, cgi.shHedgehogBladePlayer, darkena(col, 0, 0x40));
|
||||
|
@ -3069,7 +3125,7 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col
|
|||
col = mirrorcolor(geometry == gElliptic ? det(Vs.T) < 0 : mirr);
|
||||
if(!mouseout() && !nospins && GDIM == 2) {
|
||||
shiftpoint P2 = Vs * inverse_shift(inmirrorcount ? ocwtV : cwtV, mouseh);
|
||||
queuestr(P2, 10, "x", 0xFF00);
|
||||
queuestr(P2, 10*mapfontscale/100, "x", 0xFF00);
|
||||
}
|
||||
if(!nospins && flipplayer) Vs = Vs * lpispin();
|
||||
|
||||
|
@ -3201,7 +3257,7 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col
|
|||
hyperpoint h = inverse_shift(ocwtV, mouseh);
|
||||
if(flipplayer) h = lpispin() * h;
|
||||
shiftpoint P2 = Vs * h;
|
||||
queuestr(P2, 10, "x", 0xFF00);
|
||||
queuestr(P2, mapfontscale / 10, "x", 0xFF00);
|
||||
}
|
||||
|
||||
if(hide_player()) {
|
||||
|
@ -3239,7 +3295,7 @@ EX int haveaura() {
|
|||
if(sphere && mdAzimuthalEqui()) return 0;
|
||||
if(among(pmodel, mdJoukowsky, mdJoukowskyInverted) && hyperbolic && pconf.model_transition < 1)
|
||||
return 2;
|
||||
if(pmodel == mdFisheye) return 1;
|
||||
if(among(pmodel, mdFisheye, mdFisheye2)) return 1;
|
||||
return pmodel == mdDisk && (!sphere || pconf.alpha > 10) && !euclid;
|
||||
}
|
||||
|
||||
|
@ -3343,7 +3399,7 @@ EX void drawaura() {
|
|||
ld hx = (x * 1. - current_display->xcenter) / rad;
|
||||
ld hy = (y * 1. - current_display->ycenter) / rad / pconf.stretch;
|
||||
|
||||
if(pconf.camera_angle) camrotate(hx, hy);
|
||||
if(!models::camera_straight) camrotate(hx, hy);
|
||||
|
||||
ld fac = sqrt(hx*hx+hy*hy);
|
||||
if(fac < 1) continue;
|
||||
|
@ -3400,11 +3456,12 @@ EX void drawaura() {
|
|||
ld s = sin(rr);
|
||||
|
||||
if(joukowsky) {
|
||||
ld c1 = c, s1 = s;
|
||||
hyperpoint v(c, s, 0, 1);
|
||||
if(inversion)
|
||||
models::apply_orientation(s1, c1);
|
||||
models::ori_to_scr(v);
|
||||
else
|
||||
models::apply_orientation(c1, s1);
|
||||
models::scr_to_ori(v);
|
||||
ld c1 = v[0], s1 = v[1];
|
||||
|
||||
ld& mt = pconf.model_transition;
|
||||
ld mt2 = 1 - mt;
|
||||
|
@ -3418,16 +3475,11 @@ EX void drawaura() {
|
|||
ld x = rad0 * c;
|
||||
ld y = rad0 * s;
|
||||
|
||||
if(pconf.camera_angle) {
|
||||
ld z = rad0;
|
||||
|
||||
ld cam = pconf.camera_angle * degree;
|
||||
GLfloat cc = cos(cam);
|
||||
GLfloat ss = sin(cam);
|
||||
|
||||
tie(y, z) = make_pair(y * cc - z * ss, z * cc + y * ss);
|
||||
x *= rad0 / z;
|
||||
y *= rad0 / z;
|
||||
if(!models::camera_straight) {
|
||||
hyperpoint p = hyperpoint(x, y, rad0, 1);
|
||||
p = rot_inverse(pconf.cam()) * p;
|
||||
x = p[0] * rad0 / p[2];
|
||||
y = p[1] * rad0 / p[2];
|
||||
}
|
||||
cx[r][z][0] = x;
|
||||
cx[r][z][1] = y * pconf.stretch;
|
||||
|
@ -3543,7 +3595,7 @@ void draw_movement_arrows(cell *c, const transmatrix& V, int df) {
|
|||
transmatrix T = iso_inverse(Centered) * rgpushxto0(Centered * tC0(V)) * lrspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2);
|
||||
|
||||
if(vid.axes >= 5)
|
||||
queuestr(shiftless(T), keysize, s0 + key, col >> 8, 1);
|
||||
queuestr(shiftless(T), keysize * mapfontscale / 100, s0 + key, col >> 8, 1);
|
||||
|
||||
else
|
||||
queuepoly(shiftless(T), cgi.shArrow, col);
|
||||
|
@ -3551,7 +3603,7 @@ void draw_movement_arrows(cell *c, const transmatrix& V, int df) {
|
|||
else if(!confusingGeometry()) break;
|
||||
}
|
||||
}
|
||||
if(keylist != "") queuestr(shiftless(V), keysize, keylist, col >> 8, 1);
|
||||
if(keylist != "") queuestr(shiftless(V), keysize * mapfontscale / 100, keylist, col >> 8, 1);
|
||||
}
|
||||
|
||||
EX int celldistAltPlus(cell *c) { return 1000000 + celldistAlt(c); }
|
||||
|
@ -3978,12 +4030,16 @@ EX int colorhash(color_t i) {
|
|||
return (i * 0x471211 + i*i*0x124159 + i*i*i*0x982165) & 0xFFFFFF;
|
||||
}
|
||||
|
||||
EX int mine_opacity = 255;
|
||||
|
||||
EX bool isWall3(cell *c, color_t& wcol) {
|
||||
if(c->wall == waRose) { wcol = gradient(0, wcol, -5 - 5 * (7-rosephase), sintick(50 * (8 - rosephase)), 1); }
|
||||
if(isWall(c)) return true;
|
||||
if(c->wall == waChasm && c->land == laMemory && (anyshiftclick || !(cgflags & qFRACTAL))) { wcol = 0x606000; return true; }
|
||||
if(c->wall == waInvisibleFloor) return false;
|
||||
// if(chasmgraph(c)) return true;
|
||||
if(among(c->wall, waMirror, waCloud, waMineUnknown, waMineMine)) return true;
|
||||
if(among(c->wall, waMirror, waCloud)) return true;
|
||||
if(among(c->wall, waMineUnknown, waMineMine) && mine_opacity == 255) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4026,6 +4082,8 @@ EX color_t transcolor(cell *c, cell *c2, color_t wcol) {
|
|||
}
|
||||
if(among(c->wall, waRubble, waDeadfloor2) && !snakelevel(c2)) return darkena3(winf[c->wall].color, 0, 0x40);
|
||||
if(c->wall == waMagma && c2->wall != waMagma) return darkena3(magma_color(lavatide(c, -1)/4), 0, 0x80);
|
||||
if(among(c->wall, waMineUnknown, waMineMine) && !among(c2->wall, waMineMine, waMineUnknown) && mine_opacity > 0 && mine_opacity < 255)
|
||||
return 0xFFFFFF00 | mine_opacity;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4088,10 +4146,14 @@ EX ld threshold, xyz_threshold;
|
|||
|
||||
EX bool clip_checked = false;
|
||||
|
||||
EX bool other_stereo_mode() {
|
||||
return vid.stereo_mode != sOFF;
|
||||
}
|
||||
|
||||
void make_clipping_planes() {
|
||||
#if MAXMDIM >= 4
|
||||
clip_checked = false;
|
||||
if(!frustum_culling || PIU(sphere) || experimental || vid.stereo_mode == sODS || panini_alpha || stereo_alpha || gproduct || embedded_plane) return;
|
||||
if(!frustum_culling || PIU(sphere) || experimental || other_stereo_mode() || gproduct || embedded_plane) return;
|
||||
|
||||
if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe())
|
||||
threshold = sin_auto(cgi.corner_bonus), xyz_threshold = 0, clip_checked = true;
|
||||
|
@ -4200,11 +4262,19 @@ EX void gridline(const shiftmatrix& V1, const hyperpoint h1, const shiftmatrix&
|
|||
ld d = (c1 <= 0 || c2 <= 0) ? 99 : hdist(V1.T*h1, U2*h2);
|
||||
|
||||
#if MAXMDIM >= 4
|
||||
if(WDIM == 3 && fat_edges) {
|
||||
if(GDIM == 3 && fat_edges) {
|
||||
if(nonisotropic) {
|
||||
auto nV1 = V1 * rgpushxto0(h1);
|
||||
hyperpoint U2 = inverse_shift(nV1, V2*rgpushxto0(h2)) * C0;
|
||||
auto& p = cgi.get_pipe_noniso(U2, vid.linewidth, ePipeEnd::ball);
|
||||
queuepoly(nV1, p, col);
|
||||
return;
|
||||
}
|
||||
|
||||
shiftmatrix T = V1 * rgpushxto0(h1);
|
||||
transmatrix S = rspintox(inverse_shift(T, V2) * h2);
|
||||
transmatrix U = rspintoc(inverse_shift(T*S, shiftless(C0)), 2, 1);
|
||||
auto& p = queuepoly(T * S * U, cgi.generate_pipe(d, vid.linewidth, ePipeEnd::ball), col);
|
||||
auto& p = queuepoly(T * S * U, cgi.get_pipe_iso(d, vid.linewidth, ePipeEnd::ball), col);
|
||||
p.intester = xpush0(d/2);
|
||||
return;
|
||||
}
|
||||
|
@ -4719,7 +4789,7 @@ EX void drawMarkers() {
|
|||
#if CAP_QUEUE
|
||||
if(haveMount())
|
||||
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, dragon::target)) {
|
||||
queuestr(V, 1, "X",
|
||||
queuestr(V, mapfontscale/100, "X",
|
||||
gradient(0, iinf[itOrbDomination].color, -1, sintick(dragon::whichturn == turncount ? 75 : 150), 1));
|
||||
}
|
||||
#endif
|
||||
|
@ -4731,31 +4801,31 @@ EX void drawMarkers() {
|
|||
using namespace yendor;
|
||||
if(yii < isize(yi) && !yi[yii].found) {
|
||||
cell *keycell = NULL;
|
||||
int i;
|
||||
for(i=0; i<YDIST; i++)
|
||||
int last_i = 0;
|
||||
for(int i=0; i<YDIST; i++)
|
||||
if(yi[yii].path[i]->cpdist <= get_sightrange_ambush()) {
|
||||
keycell = yi[yii].path[i];
|
||||
keycell = yi[yii].path[i]; last_i = i;
|
||||
}
|
||||
if(keycell) {
|
||||
for(; i<YDIST; i++) {
|
||||
for(int i = last_i+1; i<YDIST; i++) {
|
||||
cell *c = yi[yii].path[i];
|
||||
if(inscreenrange(c))
|
||||
keycell = c;
|
||||
}
|
||||
shiftpoint H = tC0(ggmatrix(keycell));
|
||||
#if CAP_QUEUE
|
||||
queuestr(H, 2*vid.fsize, "X", 0x10101 * int(128 + 100 * sintick(150)));
|
||||
queue_goal_text(H, 2, "X", 0x10101 * int(128 + 100 * sintick(150)));
|
||||
int cd = celldistance(yi[yii].key(), cwt.at);
|
||||
if(cd == DISTANCE_UNKNOWN) for(int i2 = 0; i2<YDIST; i2++) {
|
||||
int cd2 = celldistance(cwt.at, yi[yii].path[i2]);
|
||||
if(cd2 != DISTANCE_UNKNOWN) {
|
||||
cd = cd2 + (YDIST-1-i2);
|
||||
println(hlog, "i2 = ", i2, " cd = ", celldistance(cwt.at, keycell));
|
||||
}
|
||||
}
|
||||
queuestr(H, vid.fsize, its(cd), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
queue_goal_text(H, 1, its(cd), 0x10101 * int(128 - 100 * sintick(150)));
|
||||
#endif
|
||||
addauraspecial(H, iinf[itOrbYendor].color, 0);
|
||||
addradar(ggmatrix(keycell), 'X', iinf[itKey].color, kind_outline(itKey), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4860,7 +4930,11 @@ EX void drawMarkers() {
|
|||
multi::cpid = 0;
|
||||
orbToTarget = targetRangedOrb(mouseover, roCheck);
|
||||
#if CAP_QUEUE
|
||||
if(orbToTarget == itOrbSummon) {
|
||||
if(bow::fire_mode) {
|
||||
queuestr(mousex, mousey, 0, vid.fsize, "+", getcs().bowcolor >> 8);
|
||||
orbToTarget = itNone;
|
||||
}
|
||||
else if(orbToTarget == itOrbSummon) {
|
||||
monsterToSummon = summonedAt(mouseover);
|
||||
queuestr(mousex, mousey, 0, vid.fsize, s0+minf[monsterToSummon].glyph, minf[monsterToSummon].color);
|
||||
queuecircleat(mouseover, 0.6, darkena(minf[monsterToSummon].color, 0, 0xFF));
|
||||
|
@ -4884,9 +4958,10 @@ EX void drawMarkers() {
|
|||
}
|
||||
if(items[itOrbAir] && mouseover->cpdist > 1) {
|
||||
cell *c1 = mouseover;
|
||||
int dir = c1->monst == moVoidBeast ? -1 : 1;
|
||||
for(int it=0; it<10; it++) {
|
||||
int di;
|
||||
auto mib = blowoff_destination(c1, di);
|
||||
auto mib = blowoff_destination_dir(c1, di, dir);
|
||||
if(!mib.proper()) break;
|
||||
auto& c2 = mib.t;
|
||||
shiftmatrix T1 = ggmatrix(c1);
|
||||
|
@ -4947,12 +5022,12 @@ EX void draw_flash(struct flashdata& f, const shiftmatrix& V, bool& kill) {
|
|||
int r = 2;
|
||||
apply_neon(col, r);
|
||||
if(GDIM == 3 || sphere)
|
||||
queuestr(V, (1 - tim * 1. / f.size) * f.angle, f.text, col, r);
|
||||
queuestr(V, (1 - tim * 1. / f.size) * f.angle * mapfontscale / 100, f.text, col, r);
|
||||
else if(!kill) {
|
||||
shiftpoint h = tC0(V);
|
||||
if(hdist0(h) > .1) {
|
||||
transmatrix V2 = rspintox(h.h) * xpush(hdist0(h.h) * (1 / (1 - tim * 1. / f.size)));
|
||||
queuestr(shiftless(V2, h.shift), f.angle, f.text, col, r);
|
||||
queuestr(shiftless(V2, h.shift), f.angle * mapfontscale / 100, f.text, col, r);
|
||||
}
|
||||
}
|
||||
if(static_bubbles) {
|
||||
|
@ -5450,6 +5525,11 @@ EX ld min_scale = 1e-6;
|
|||
|
||||
EX int forced_center_down = ISANDROID ? 2 : ISIOS ? 40 : 40;
|
||||
|
||||
EX ld get_stereo_param() {
|
||||
if(among(vid.stereo_mode, sPanini, sStereographic)) return vid.stereo_param;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EX void calcparam() {
|
||||
|
||||
DEBBI(DF_GRAPH, ("calc param"));
|
||||
|
@ -5511,7 +5591,7 @@ EX void calcparam() {
|
|||
cd->ycenter += cd->scrsize * pconf.yposition;
|
||||
|
||||
ld fov = vid.fov * degree / 2;
|
||||
cd->tanfov = sin(fov) / (cos(fov) + (panini_alpha ? panini_alpha : stereo_alpha));
|
||||
cd->tanfov = sin(fov) / (cos(fov) + get_stereo_param());
|
||||
|
||||
callhooks(hooks_calcparam);
|
||||
reset_projection();
|
||||
|
@ -5594,6 +5674,8 @@ EX bool just_refreshing;
|
|||
EX int menu_darkening = 2;
|
||||
EX bool centered_menus = false;
|
||||
|
||||
EX string menu_format = "";
|
||||
|
||||
EX void gamescreen() {
|
||||
|
||||
if(cmode & sm::NOSCR) {
|
||||
|
@ -5719,13 +5801,15 @@ EX void normalscreen() {
|
|||
cmode = sm::NORMAL | sm::DOTOUR | sm::CENTER;
|
||||
if(viewdists && show_distance_lists) cmode |= sm::SIDE | sm::MAYDARK;
|
||||
gamescreen(); drawStats();
|
||||
if(nomenukey || ISMOBILE)
|
||||
if(menu_format != "")
|
||||
displayButton(vid.xres-8, vid.yres-vid.fsize, eval_programmable_string(menu_format), 'v', 16);
|
||||
else if(nomenukey || ISMOBILE)
|
||||
;
|
||||
#if CAP_TOUR
|
||||
else if(tour::on)
|
||||
displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(ESC) tour menu"), SDLK_ESCAPE, 16);
|
||||
else
|
||||
#endif
|
||||
else
|
||||
displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(v) menu"), 'v', 16);
|
||||
keyhandler = handleKeyNormal;
|
||||
|
||||
|
@ -5755,33 +5839,34 @@ EX cfunction current_screen_cfunction() {
|
|||
|
||||
#if HDR
|
||||
namespace sm {
|
||||
static const int NORMAL = 1;
|
||||
static const int MISSION = 2;
|
||||
static const int HELP = 4;
|
||||
static const int MAP = 8;
|
||||
static const int DRAW = 16;
|
||||
static const int NUMBER = 32;
|
||||
static const int SHMUPCONFIG = 64;
|
||||
static const int OVERVIEW = 128;
|
||||
static const int SIDE = 256;
|
||||
static const int DOTOUR = 512;
|
||||
static const int CENTER = 1024;
|
||||
static const int ZOOMABLE = 4096;
|
||||
static const int TORUSCONFIG = 8192;
|
||||
static const int MAYDARK = 16384;
|
||||
static const int DIALOG_STRICT_X = 32768; // do not interpret dialog clicks outside of the X region
|
||||
static const int EXPANSION = (1<<16);
|
||||
static const int HEXEDIT = (1<<17);
|
||||
static const int VR_MENU = (1<<18); // always show the menu in VR
|
||||
static const int SHOWCURSOR = (1<<19); // despite MAP/DRAW always show the cursor, no panning
|
||||
static const int PANNING = (1<<20); // smooth scrolling works
|
||||
static const int DARKEN = (1<<21); // darken the game background
|
||||
static const int NOSCR = (1<<22); // do not show the game background
|
||||
static const int AUTO_VALUES = (1<<23); // automatic place for values
|
||||
static const int NARROW_LINES = (1<<24); // do make the lines narrower if we needed to reduce width
|
||||
static const int EDIT_BEFORE_WALLS = (1<<25); // mouseover targets before walls
|
||||
static const int EDIT_INSIDE_WALLS = (1<<26); // mouseover targets inside walls
|
||||
static const int DIALOG_WIDE = (1<<27); // make dialogs wide
|
||||
static constexpr int NORMAL = 1;
|
||||
static constexpr int MISSION = 2;
|
||||
static constexpr int HELP = 4;
|
||||
static constexpr int MAP = 8;
|
||||
static constexpr int DRAW = 16;
|
||||
static constexpr int NUMBER = 32;
|
||||
static constexpr int SHMUPCONFIG = 64;
|
||||
static constexpr int OVERVIEW = 128;
|
||||
static constexpr int SIDE = 256;
|
||||
static constexpr int DOTOUR = 512;
|
||||
static constexpr int CENTER = 1024;
|
||||
static constexpr int ZOOMABLE = 4096;
|
||||
static constexpr int TORUSCONFIG = 8192;
|
||||
static constexpr int MAYDARK = 16384;
|
||||
static constexpr int DIALOG_STRICT_X = 32768; // do not interpret dialog clicks outside of the X region
|
||||
static constexpr int EXPANSION = (1<<16);
|
||||
static constexpr int HEXEDIT = (1<<17);
|
||||
static constexpr int VR_MENU = (1<<18); // always show the menu in VR
|
||||
static constexpr int SHOWCURSOR = (1<<19); // despite MAP/DRAW always show the cursor, no panning
|
||||
static constexpr int PANNING = (1<<20); // smooth scrolling works
|
||||
static constexpr int DARKEN = (1<<21); // darken the game background
|
||||
static constexpr int NOSCR = (1<<22); // do not show the game background
|
||||
static constexpr int AUTO_VALUES = (1<<23); // automatic place for values
|
||||
static constexpr int NARROW_LINES = (1<<24); // do make the lines narrower if we needed to reduce width
|
||||
static constexpr int EDIT_BEFORE_WALLS = (1<<25); // mouseover targets before walls
|
||||
static constexpr int EDIT_INSIDE_WALLS = (1<<26); // mouseover targets inside walls
|
||||
static constexpr int DIALOG_WIDE = (1<<27); // make dialogs wide
|
||||
static constexpr int MOUSEAIM = (1<<28); // mouse aiming active here
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -5849,8 +5934,11 @@ EX void drawscreen() {
|
|||
color_t col = linf[cwt.at->land].color;
|
||||
if(cwt.at->land == laRedRock) col = 0xC00000;
|
||||
if(titlecolor) col = titlecolor;
|
||||
if(nohelp != 1)
|
||||
displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, mouseovers, col, 8);
|
||||
if(nohelp != 1) {
|
||||
int size = vid.fsize;
|
||||
while(size > 3 && textwidth(size, mouseovers) > vid.xres) size--;
|
||||
displayfr(vid.xres/2, vid.fsize, 2, size, mouseovers, col, 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
drawmessages();
|
||||
|
|
94
help.cpp
94
help.cpp
|
@ -236,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, aismallard, albatross, EncodedSpirit, Jacob Mandelson, CrashTuvai, cvoight, jennlbw, Kali Ranya, spiritbackup"
|
||||
"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;
|
||||
|
@ -410,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 "
|
||||
|
@ -527,6 +528,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();
|
||||
|
||||
|
@ -552,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(
|
||||
|
@ -567,7 +609,7 @@ void addMinefieldExplanation(string& s) {
|
|||
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{'n', XLAT("toggle numerical display"), [] () { numerical_minefield = !numerical_minefield; }});
|
||||
help_extensions.push_back(help_extension{'c', XLAT("configure"), [] () { pushScreen(mine_dialog); } });
|
||||
}
|
||||
|
||||
EX string generateHelpForWall(eWall w) {
|
||||
|
@ -586,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) {
|
||||
|
@ -700,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, %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;
|
||||
|
@ -881,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
|
||||
|
@ -892,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
|
||||
|
@ -930,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)
|
||||
|
@ -965,7 +1008,12 @@ 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->wparam) + ")";
|
||||
|
@ -1082,16 +1130,7 @@ EX void describeMouseover() {
|
|||
#endif
|
||||
}
|
||||
|
||||
EX void showHelp() {
|
||||
cmode = sm::HELP | sm::DOTOUR | sm::DARKEN;
|
||||
getcstat = SDLK_ESCAPE;
|
||||
if(help == "HELPFUN") {
|
||||
help_delegate();
|
||||
return;
|
||||
}
|
||||
|
||||
gamescreen();
|
||||
string help2;
|
||||
EX void addHelpWithTitle() {
|
||||
if(help[0] == '@') {
|
||||
int iv = help.find("\t");
|
||||
int id = help.find("\n");
|
||||
|
@ -1102,6 +1141,19 @@ 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;
|
||||
|
||||
|
|
41
history.cpp
41
history.cpp
|
@ -453,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();
|
||||
|
@ -470,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)
|
||||
|
@ -480,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 {
|
||||
|
||||
|
@ -498,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();
|
||||
|
@ -531,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;
|
||||
|
@ -749,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
|
||||
});
|
||||
|
||||
|
|
69
hprint.cpp
69
hprint.cpp
|
@ -33,9 +33,10 @@ EX int debugflags = DF_INIT | DF_ERROR | DF_WARN | DF_MSG | DF_TIME | DF_LOG;
|
|||
|
||||
EX string s0;
|
||||
|
||||
EX string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; }
|
||||
EX string its(int i) { return hr::format("%d", i); }
|
||||
|
||||
EX string itsh8(int i) {static char buf[16]; sprintf(buf, "%08X", i); return buf; }
|
||||
EX string itsh8(int i) { return hr::format("%08X", i); }
|
||||
EX string itsh6(int i) { return hr::format("%06X", i); }
|
||||
|
||||
EX string fts(ld x, int prec IS(6)) {
|
||||
std::stringstream ss;
|
||||
|
@ -46,13 +47,18 @@ EX string fts(ld x, int prec IS(6)) {
|
|||
|
||||
EX map<void*, int> pointer_indices;
|
||||
|
||||
EX string index_pointer(void *v) {
|
||||
if(v == nullptr) return "0";
|
||||
EX int index_pointer_int(void *v) {
|
||||
if(v == nullptr) return 0;
|
||||
if(!pointer_indices.count(v)) {
|
||||
int s = isize(pointer_indices);
|
||||
int s = isize(pointer_indices) + 1;
|
||||
pointer_indices[v] = s;
|
||||
}
|
||||
int i = pointer_indices[v];
|
||||
return pointer_indices[v];
|
||||
}
|
||||
|
||||
EX string index_pointer(void *v) {
|
||||
int i = index_pointer_int(v);
|
||||
if(!i) return "0";
|
||||
string res;
|
||||
while(true) { res += ('A' + (i % 26)); i /= 26; if(!i) break; i--; }
|
||||
return res;
|
||||
|
@ -139,7 +145,10 @@ template<class T, class U> void hread(hstream& hs, map<T,U>& a) {
|
|||
template<class C, class C1, class... CS> void hwrite(hstream& hs, const C& c, const C1& c1, const CS&... cs) { hwrite(hs, c); hwrite(hs, c1, cs...); }
|
||||
template<class C, class C1, class... CS> void hread(hstream& hs, C& c, C1& c1, CS&... cs) { hread(hs, c); hread(hs, c1, cs...); }
|
||||
|
||||
struct hstream_exception : hr_exception { hstream_exception() {} };
|
||||
struct hstream_exception : hr_exception {
|
||||
hstream_exception() : hr_exception("hstream_exception") {}
|
||||
hstream_exception(const std::string &s) : hr_exception(s) {}
|
||||
};
|
||||
|
||||
struct fhstream : hstream {
|
||||
FILE *f;
|
||||
|
@ -150,7 +159,7 @@ struct fhstream : hstream {
|
|||
void write_chars(const char* c, size_t i) override { if(fwrite(c, i, 1, f) != 1) throw hstream_exception(); }
|
||||
void read_chars(char* c, size_t i) override { if(fread(c, i, 1, f) != 1) throw hstream_exception(); }
|
||||
char read_char() override { char c; read_chars(&c, 1); return c; }
|
||||
virtual void flush() override { fflush(f); }
|
||||
void flush() override { fflush(f); }
|
||||
};
|
||||
|
||||
struct shstream : hstream {
|
||||
|
@ -399,9 +408,9 @@ EX string llts(long long i) {
|
|||
if(i < 10) return its((int) i);
|
||||
return llts(i/10) + its(i%10);
|
||||
}
|
||||
EX string itsh(unsigned int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
|
||||
EX string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
|
||||
EX string itsh2(int i) {static char buf[16]; sprintf(buf, "%02X", i); return buf; }
|
||||
EX string itsh(unsigned int i) { return hr::format("%03X", i); }
|
||||
EX string itsh(int i) { return hr::format("%03X", i); }
|
||||
EX string itsh2(int i) { return hr::format("%02X", i); }
|
||||
|
||||
EX string itsh(unsigned long long i) {
|
||||
int i0 = int(i);
|
||||
|
@ -442,11 +451,23 @@ EX shiftpoint kz(shiftpoint h) {
|
|||
return h;
|
||||
}
|
||||
|
||||
EX bool scan(shstream& hs, ld& val) {
|
||||
int npos;
|
||||
int qty = sscanf(hs.s.c_str() + hs.pos, "%lf%n", &val, &npos);
|
||||
if(qty == 1) { hs.pos += npos; return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
#if HDR
|
||||
template<class T> vector<T> kz(vector<T> v) {
|
||||
for(auto& el: v) el = kz(el);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<class T, size_t N> array<T,N> kz(array<T,N> v) {
|
||||
for(auto& el: v) el = kz(el);
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
EX string pick123() { return cts('1' + rand() % 3); }
|
||||
|
@ -471,9 +492,7 @@ template<class T> T deserialize(const string& s) {
|
|||
EX string as_hexstring(string o) {
|
||||
string res;
|
||||
for(char x: o) {
|
||||
char buf[4];
|
||||
sprintf(buf, "%02X", (unsigned char)(x));
|
||||
res += buf;
|
||||
res += hr::format("%02X", (unsigned char)(x));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -495,8 +514,8 @@ EX string from_hexstring(string o) {
|
|||
EX string as_cstring(string o) {
|
||||
string s = "string(\"";
|
||||
for(char c: o)
|
||||
s += format("\\x%02x", (unsigned char) c);
|
||||
s += format("\", %d)", isize(o));
|
||||
s += hr::format("\\x%02x", (unsigned char) c);
|
||||
s += hr::format("\", %d)", isize(o));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -508,7 +527,7 @@ EX string as_nice_cstring(string o) {
|
|||
else if(c == 10)
|
||||
s += "\\n";
|
||||
else
|
||||
s += format("\\x%02x", (unsigned char) c);
|
||||
s += hr::format("\\x%02x", (unsigned char) c);
|
||||
s += "\"";
|
||||
return s;
|
||||
}
|
||||
|
@ -540,4 +559,20 @@ template<class... T> string lalign(int len, T... t) {
|
|||
return hs.s;
|
||||
}
|
||||
#endif
|
||||
|
||||
map<string, string> last;
|
||||
|
||||
EX void debug_view(string context, string s) {
|
||||
string& old = last[context];
|
||||
if(s != old) { old = s; println(hlog, s); }
|
||||
}
|
||||
|
||||
EX vector<string> split_string(const string& s, char sep) {
|
||||
vector<string> res;
|
||||
string next = "";
|
||||
for(char c: s) if(c == sep) { res.push_back(next); next = ""; } else next += c;
|
||||
res.push_back(next);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
71
hud.cpp
71
hud.cpp
|
@ -46,6 +46,7 @@ EX int subclass(int i) {
|
|||
#define GLYPH_TARGET 512
|
||||
#define GLYPH_INSQUARE 1024
|
||||
#define GLYPH_INLANDSCAPE 2048
|
||||
#define GLYPH_ACTIVE 4096
|
||||
|
||||
#if HDR
|
||||
enum eGlyphsortorder {
|
||||
|
@ -68,6 +69,7 @@ int& ikmerge(int i) {
|
|||
|
||||
bool ikappear(int i) {
|
||||
if(i == itInventory && inv::on) return true;
|
||||
if(i == itCrossbow && bow::crossbow_mode()) return true;
|
||||
return ikmerge(i);
|
||||
}
|
||||
|
||||
|
@ -142,7 +144,11 @@ int glyphflags(int gid) {
|
|||
int f = 0;
|
||||
if(gid < ittypes) {
|
||||
eItem i = eItem(gid);
|
||||
if(itemclass(i) == IC_NAI && i != itFatigue) f |= GLYPH_NONUMBER;
|
||||
if(itemclass(i) == IC_NAI && i != itFatigue && i != itCrossbow) f |= GLYPH_NONUMBER;
|
||||
if(i == itCrossbow) {
|
||||
if(items[i] == 0) f |= GLYPH_NONUMBER;
|
||||
if(bow::fire_mode) f |= GLYPH_ACTIVE;
|
||||
}
|
||||
if(isElementalShard(i)) {
|
||||
f |= GLYPH_LOCAL | GLYPH_INSQUARE;
|
||||
if(i == localshardof(cwt.at->land)) f |= GLYPH_LOCAL2;
|
||||
|
@ -229,6 +235,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, color_t color, int
|
|||
if(glyph == ']') bsize = bsize*1.5;
|
||||
if(glyph == 'x') bsize = bsize*1.5;
|
||||
if(it == itWarning) bsize *= 2;
|
||||
if(it == itCrossbow) bsize *= 2;
|
||||
if(it == itBombEgg || it == itTrollEgg || it == itDodeca) bsize = bsize*3/2;
|
||||
int icol = color;
|
||||
icol -= (color & 0xFCFCFC) >> 2;
|
||||
|
@ -266,6 +273,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, color_t color, int
|
|||
if(flags & GLYPH_LOCAL2) fl += "+";
|
||||
else if(flags & GLYPH_LOCAL) fl += "-";
|
||||
if(flags & GLYPH_DEMON) fl += "X";
|
||||
if(flags & GLYPH_ACTIVE) fl += "A";
|
||||
if(flags & GLYPH_MARKOVER) str += "!";
|
||||
|
||||
if(fl != "")
|
||||
|
@ -326,6 +334,17 @@ void displayglyph2(int cx, int cy, int buttonsize, int i) {
|
|||
mouseovers += XLAT(" (click to use)");
|
||||
getcstat = 'i';
|
||||
}
|
||||
if(it == itCrossbow) {
|
||||
if(items[it])
|
||||
mouseovers += XLAT(" (turns to reload: %1)", its(items[it]));
|
||||
else if(items[it] && bow::fire_mode)
|
||||
mouseovers += XLAT(" (fire mode on / turns to reload: %1)", its(items[it]));
|
||||
else if(bow::fire_mode)
|
||||
mouseovers += XLAT(" (fire mode on)");
|
||||
else
|
||||
mouseovers += XLAT(" (click to fire)");
|
||||
getcstat = 'f';
|
||||
}
|
||||
if(imp & GLYPH_LOCAL) mouseovers += XLAT(" (local treasure)");
|
||||
help = generateHelpForItem(it);
|
||||
}
|
||||
|
@ -429,6 +448,34 @@ EX void draw_crosshair() {
|
|||
|
||||
EX bool less_in_portrait, less_in_landscape;
|
||||
|
||||
EX string mode_description() {
|
||||
string md;
|
||||
if(autocheat) md += " god";
|
||||
if(casual) md += " casual";
|
||||
else if(cheater) md += " cheat";
|
||||
if(inv::on) md += " inv";
|
||||
if(tour::on) md += " tour";
|
||||
if(shmup::on) md += " shmup";
|
||||
if(multi::players > 1) md += " P" + its(multi::players);
|
||||
if(pureHardcore()) md += " hardcore";
|
||||
else if(hardcore) md += " partial hardcore";
|
||||
if(daily::on) md += " strange";
|
||||
if(bow::crossbow_mode()) md += " b/" + bow::bowName[bow::style];
|
||||
if(land_structure != default_land_structure())
|
||||
md += " " + land_structure_name(true);
|
||||
if(randomPatternsMode) md += " RPM";
|
||||
if(use_custom_land_list) md += " custom";
|
||||
if(geometry != gNormal || !BITRUNCATED)
|
||||
md = md + " " + full_geometry_name();
|
||||
return md;
|
||||
}
|
||||
|
||||
EX string mode_description1() {
|
||||
string md = mode_description();
|
||||
if(md == "") return "standard";
|
||||
return md.substr(1);
|
||||
}
|
||||
|
||||
EX void drawStats() {
|
||||
if(vid.stereo_mode == sLR) return;
|
||||
draw_crosshair();
|
||||
|
@ -672,27 +719,13 @@ EX void drawStats() {
|
|||
}
|
||||
string vers = VER;
|
||||
if(true) {
|
||||
if(casual) vers += " casual";
|
||||
if(autocheat) vers += " god";
|
||||
else if(cheater) vers += " cheat";
|
||||
if(yendor::on) vers += " Yendor";
|
||||
if(tactic::on) vers += " PTM";
|
||||
if(inv::on) vers += " inv";
|
||||
if(tour::on) vers += " tour";
|
||||
if(shmup::on) vers += " shmup";
|
||||
if(multi::players > 1) vers += " P" + its(multi::players);
|
||||
if(pureHardcore()) vers += " hardcore";
|
||||
else if(hardcore) vers += " partial hardcore";
|
||||
if(modename.count(current_modecode)) vers += " '" + modename[current_modecode] + "' ";
|
||||
vers += mode_description();
|
||||
if(peace::on) vers += " peace";
|
||||
if(racing::on) vers += " racing";
|
||||
if(daily::on) vers += " strange";
|
||||
if(land_structure != default_land_structure())
|
||||
vers += land_structure_name(true);
|
||||
if(princess::challenge) vers += " Princess";
|
||||
if(randomPatternsMode) vers += " RPM";
|
||||
|
||||
if(geometry != gNormal || !BITRUNCATED)
|
||||
vers = vers + " " + full_geometry_name();
|
||||
if(yendor::on) vers += " Yendor";
|
||||
if(tactic::on) vers += " PTM";
|
||||
}
|
||||
if(!nofps) vers += XLAT(" fps: ") + its(calcfps());
|
||||
|
||||
|
|
|
@ -126,15 +126,14 @@
|
|||
#include "inforder.cpp"
|
||||
#include "vr.cpp"
|
||||
#include "intra.cpp"
|
||||
#include "crossbow.cpp"
|
||||
|
||||
#if CAP_ROGUEVIZ
|
||||
#include "rogueviz/rogueviz-all.cpp"
|
||||
#endif
|
||||
|
||||
#if CAP_DAILY
|
||||
#include "private/daily.cpp"
|
||||
#else
|
||||
namespace hr { namespace daily { bool on; } }
|
||||
#if !CAP_DAILY
|
||||
namespace hr { namespace daily { bool on; int historical; } }
|
||||
#endif
|
||||
|
||||
#include "mobile.cpp"
|
||||
|
|
75
hyper.h
75
hyper.h
|
@ -13,8 +13,8 @@
|
|||
#define _HYPER_H_
|
||||
|
||||
// version numbers
|
||||
#define VER "12.1q"
|
||||
#define VERNUM_HEX 0xA931
|
||||
#define VER "13.0o"
|
||||
#define VERNUM_HEX 0xAA0F
|
||||
|
||||
#include "sysconfig.h"
|
||||
|
||||
|
@ -221,15 +221,6 @@ void addMessage(string s, char spamtype = 0);
|
|||
|
||||
#define NUMWITCH 7
|
||||
|
||||
// achievements
|
||||
|
||||
#define LB_YENDOR_CHALLENGE 40
|
||||
#define LB_PURE_TACTICS 41
|
||||
#define NUMLEADER 87
|
||||
#define LB_PURE_TACTICS_SHMUP 49
|
||||
#define LB_PURE_TACTICS_COOP 50
|
||||
#define LB_RACING 81
|
||||
|
||||
#if ISMOBILE || ISWEB || ISPANDORA || 1
|
||||
typedef double ld;
|
||||
#define LDF "%lf"
|
||||
|
@ -246,11 +237,11 @@ typedef unsigned color_t;
|
|||
|
||||
struct charstyle {
|
||||
int charid;
|
||||
color_t skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor, eyecolor;
|
||||
color_t skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor, eyecolor, bowcolor, bowcolor2;
|
||||
bool lefthanded;
|
||||
};
|
||||
|
||||
enum eStereo { sOFF, sAnaglyph, sLR, sODS };
|
||||
enum eStereo { sOFF, sAnaglyph, sLR, sODS, sPanini, sStereographic, sEquirectangular, sCylindrical };
|
||||
|
||||
enum eModel : int;
|
||||
|
||||
|
@ -258,10 +249,11 @@ enum eModel : int;
|
|||
struct projection_configuration {
|
||||
eModel model; /**< which projection, see classes.cpp */
|
||||
ld xposition, yposition; /**< move the center to another position */
|
||||
ld scale, alpha, camera_angle, fisheye_param, twopoint_param, axial_angle, stretch, ballangle, ballproj, euclid_to_sphere;
|
||||
ld scale, alpha, fisheye_param, fisheye_alpha, twopoint_param, axial_angle, stretch, ballproj, euclid_to_sphere;
|
||||
ld clip_min, clip_max;
|
||||
ld model_orientation, halfplane_scale, model_orientation_yz;
|
||||
ld halfplane_scale;
|
||||
ld collignon_parameter;
|
||||
ld offside, offside2;
|
||||
ld aitoff_parameter, miller_parameter, loximuthal_parameter, winkel_parameter;
|
||||
bool show_hyperboloid_flat;
|
||||
bool collignon_reflected;
|
||||
|
@ -287,30 +279,15 @@ struct projection_configuration {
|
|||
bool dualfocus_autoscale;
|
||||
|
||||
int back_and_front; /* 0 = do not, 1 = do, 2 = only back */
|
||||
struct trans23 *ptr_model_orientation;
|
||||
struct transmatrix *ptr_ball;
|
||||
struct transmatrix *ptr_camera;
|
||||
|
||||
projection_configuration() {
|
||||
formula = "z^2"; top_z = 5; model_transition = 1; spiral_angle = 70; spiral_x = 10; spiral_y = 7;
|
||||
rotational_nil = 1;
|
||||
right_spiral_multiplier = 1;
|
||||
any_spiral_multiplier = 1;
|
||||
sphere_spiral_multiplier = 2;
|
||||
spiral_cone = 360;
|
||||
use_atan = false;
|
||||
product_z_scale = 1;
|
||||
aitoff_parameter = .5;
|
||||
miller_parameter = .8;
|
||||
loximuthal_parameter = 0;
|
||||
winkel_parameter = .5;
|
||||
show_hyperboloid_flat = true;
|
||||
depth_scaling = 1;
|
||||
vr_angle = 0;
|
||||
hyperboloid_scaling = 1;
|
||||
vr_zshift = 0;
|
||||
vr_scale_factor = 1;
|
||||
back_and_front = 0;
|
||||
dualfocus_autoscale = false;
|
||||
axial_angle = 90;
|
||||
}
|
||||
projection_configuration();
|
||||
|
||||
trans23& mori() { return *ptr_model_orientation; }
|
||||
transmatrix& ball() { return *ptr_ball; }
|
||||
transmatrix& cam() { return *ptr_camera; }
|
||||
};
|
||||
|
||||
enum eThreatLevel { tlNoThreat, tlSpam, tlNormal, tlHighThreat };
|
||||
|
@ -410,6 +387,7 @@ struct videopar {
|
|||
int cells_generated_limit; // limit on cells generated per frame
|
||||
|
||||
eStereo stereo_mode;
|
||||
ld stereo_param;
|
||||
ld ipd;
|
||||
ld lr_eyewidth, anaglyph_eyewidth;
|
||||
ld fov;
|
||||
|
@ -565,7 +543,7 @@ public:
|
|||
|
||||
using purehookset = hookset<void()>;
|
||||
|
||||
static const int NOHINT = -1;
|
||||
static constexpr int NOHINT = -1;
|
||||
|
||||
typedef function<void()> reaction_t;
|
||||
typedef function<bool()> bool_reaction_t;
|
||||
|
@ -579,7 +557,7 @@ typedef function<int(struct cell*)> cellfunction;
|
|||
// passable flags
|
||||
|
||||
#define SAGEMELT .1
|
||||
#define PT(x, y) ((tactic::on || quotient == 2 || daily::on) ? (y) : inv::on ? min(2*(y),x) : (x))
|
||||
#define PT(x, y) rebalance_treasure(x, y, c->land)
|
||||
#define ROCKSNAKELENGTH 50
|
||||
#define WORMLENGTH 15
|
||||
#define PRIZEMUL 7
|
||||
|
@ -651,6 +629,7 @@ typedef function<int(struct cell*)> cellfunction;
|
|||
#define AF_PLAGUE Flag(32) // Orb of Plague (do not check adjacency)
|
||||
#define AF_PSI Flag(33) // Orb of the Mind
|
||||
#define AF_WEAK Flag(34) // Curse of Weakness
|
||||
#define AF_BOW Flag(35) // crossbow attack
|
||||
|
||||
#if CAP_SDL
|
||||
|
||||
|
@ -679,7 +658,7 @@ struct finalizer {
|
|||
~finalizer() { f(); }
|
||||
};
|
||||
|
||||
static const int MAXPLAYER = 7;
|
||||
static constexpr int MAXPLAYER = 7;
|
||||
|
||||
#define DEFAULTCONTROL (multi::players == 1 && !shmup::on && !multi::alwaysuse)
|
||||
#define DEFAULTNOR(sym) (DEFAULTCONTROL || multi::notremapped(sym))
|
||||
|
@ -791,7 +770,8 @@ enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMul
|
|||
#endif
|
||||
#define pmodel (pconf.model)
|
||||
|
||||
static const int DISTANCE_UNKNOWN = 127;
|
||||
static constexpr int DISTANCE_UNKNOWN = 127;
|
||||
static constexpr int DISTANCE_UNKNOWN_BIG = 99999999;
|
||||
|
||||
template<class T, class U> int addHook(hookset<T>& m, int prio, U&& hook) {
|
||||
return m.add(prio, static_cast<U&&>(hook));
|
||||
|
@ -820,7 +800,7 @@ string XLAT(string);
|
|||
#define DKEY (get_direction_key(sym, uni))
|
||||
#define DIRECTIONKEY (interpret_as_direction(sym, uni) ? uni : 0)
|
||||
|
||||
namespace scores { void load(); }
|
||||
namespace scores { void load(); void load_only(); extern int which_mode; }
|
||||
|
||||
#if ISMOBILE
|
||||
namespace leader { void showMenu(); void handleKey(int sym, int uni); }
|
||||
|
@ -875,9 +855,9 @@ template<class T, class U> void eliminate_if(vector<T>& data, U pred) {
|
|||
data[i] = data.back(), data.pop_back(), i--;
|
||||
}
|
||||
|
||||
template<class T> array<T, 4> make_array(T a, T b, T c, T d) { array<T,4> x; x[0] = a; x[1] = b; x[2] = c; x[3] = d; return x; }
|
||||
template<class T> array<T, 3> make_array(T a, T b, T c) { array<T,3> x; x[0] = a; x[1] = b; x[2] = c; return x; }
|
||||
template<class T> array<T, 2> make_array(T a, T b) { array<T,2> x; x[0] = a; x[1] = b; return x; }
|
||||
template<class T> constexpr array<T, 4> make_array(T a, T b, T c, T d) { return array<T,4>{a,b,c,d}; }
|
||||
template<class T> constexpr array<T, 3> make_array(T a, T b, T c) { return array<T,3>{a,b,c}; }
|
||||
template<class T> constexpr array<T, 2> make_array(T a, T b) { return array<T,2>{a,b}; }
|
||||
|
||||
// Find in a std::map or std::unordered_map, or return null.
|
||||
template<class Map, class Key>
|
||||
|
@ -900,6 +880,7 @@ template<class T> T& atmod(vector<T>& container, int index) {
|
|||
|
||||
namespace daily {
|
||||
extern bool on;
|
||||
extern int historical;
|
||||
extern int daily_id;
|
||||
void setup();
|
||||
void split();
|
||||
|
@ -949,7 +930,7 @@ template<class T> ld binsearch(ld dmin, ld dmax, const T& f, int iterations = 20
|
|||
return dmin;
|
||||
}
|
||||
|
||||
static const int max_vec = (1<<14);
|
||||
static constexpr int max_vec = (1<<14);
|
||||
extern bool needConfirmationEvenIfSaved();
|
||||
|
||||
typedef unsigned long long flagtype;
|
||||
|
|
|
@ -8,11 +8,15 @@ namespace hr {
|
|||
template<class Sig>
|
||||
class function;
|
||||
|
||||
/* callable objects derived from funbase can be retrieved from hr::function using target_base */
|
||||
struct funbase { virtual ~funbase() {} };
|
||||
|
||||
template<class R, class... Args>
|
||||
struct function_state_base {
|
||||
virtual R call(Args...) const = 0;
|
||||
virtual function_state_base *clone() const = 0;
|
||||
virtual ~function_state_base() {}
|
||||
virtual funbase* as_funbase() = 0;
|
||||
};
|
||||
|
||||
template<class T, class R, class... Args>
|
||||
|
@ -25,6 +29,10 @@ struct function_state : function_state_base<R, Args...> {
|
|||
function_state_base<R, Args...> *clone() const override {
|
||||
return new function_state(*this);
|
||||
}
|
||||
funbase* as_funbase() override {
|
||||
if(std::is_base_of<funbase, T>::value) return (funbase*) (&t_);
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<class R, class... Args>
|
||||
|
@ -65,6 +73,10 @@ public:
|
|||
if(!ptr) return nullptr;
|
||||
return &ptr->t_;
|
||||
}
|
||||
|
||||
struct funbase* target_base() {
|
||||
return ptr_->as_funbase();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hr
|
||||
|
|
|
@ -203,6 +203,30 @@ constexpr transmatrix Id = diag(1,1,1,1);
|
|||
/** zero matrix */
|
||||
constexpr transmatrix Zero = diag(0,0,0,0);
|
||||
|
||||
/** a transmatrix with 2D and 3D version, useful for configuration */
|
||||
struct trans23 {
|
||||
transmatrix v2, v3;
|
||||
transmatrix& get() { return MDIM == 3 ? v2 : v3; }
|
||||
const transmatrix& get() const { return MDIM == 3 ? v2 : v3; }
|
||||
trans23() { v2 = Id; v3 = Id; }
|
||||
trans23(const transmatrix& T) { v2 = T; v3 = T; }
|
||||
trans23(const transmatrix& T2, const transmatrix& T3) { v2 = T2; v3 = T3; }
|
||||
bool operator == (const trans23& b) const;
|
||||
bool operator != (const trans23& b) const { return !(self == b); }
|
||||
trans23 operator * (trans23 T) {
|
||||
trans23 t;
|
||||
auto& dim = cginf.g.homogeneous_dimension;
|
||||
dynamicval<int> d1(dim, dim);
|
||||
dim = 3; t.v2 = v2 * T.v2;
|
||||
dim = 4; t.v3 = v3 * T.v3;
|
||||
return t;
|
||||
}
|
||||
friend trans23 operator * (transmatrix M, trans23 T) {
|
||||
trans23 t(M);
|
||||
return t * T;
|
||||
}
|
||||
};
|
||||
|
||||
/** mirror image */
|
||||
constexpr transmatrix Mirror = diag(1,-1,1,1);
|
||||
|
||||
|
@ -235,6 +259,8 @@ constexpr hyperpoint C03 = hyperpoint(0,0,0,1);
|
|||
#define C0 (MDIM == 3 ? C02 : C03)
|
||||
#endif
|
||||
|
||||
bool trans23::operator == (const trans23& b) const { return eqmatrix(v2, b.v2) && eqmatrix(v3, b.v3); }
|
||||
|
||||
// basic functions and types
|
||||
//===========================
|
||||
|
||||
|
@ -1167,6 +1193,16 @@ EX transmatrix iso_inverse(const transmatrix& T) {
|
|||
return inverse(T);
|
||||
}
|
||||
|
||||
/** inverse a guaranteed rotation */
|
||||
EX transmatrix rot_inverse(const transmatrix& T) {
|
||||
return transpose(T);
|
||||
}
|
||||
|
||||
/** inverse a guaranteed rotation */
|
||||
EX trans23 rot_inverse(const trans23& T) {
|
||||
return trans23(rot_inverse(T.v2), rot_inverse(T.v3));
|
||||
}
|
||||
|
||||
/** \brief T inverse a matrix T = O*S, where O is isometry and S is a scaling matrix (todo optimize) */
|
||||
EX transmatrix z_inverse(const transmatrix& T) {
|
||||
return inverse(T);
|
||||
|
@ -1325,14 +1361,17 @@ EX shiftmatrix orthogonal_move(const shiftmatrix& t, double level) {
|
|||
return shiftless(orthogonal_move(t.T, level), t.shift);
|
||||
}
|
||||
|
||||
/** fix a 3x3 matrix into a 4x4 matrix */
|
||||
EX transmatrix fix4(transmatrix t) {
|
||||
/** fix a 3x3 matrix into a 4x4 matrix, in place */
|
||||
EX void fix4(transmatrix& t) {
|
||||
#if MAXMDIM > 3
|
||||
if(ldebug) println(hlog, "fix4 performed");
|
||||
for(int i=0; i<4; i++) t[3][i] = t[i][3] = i == 3;
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
/** fix a 3x3 matrix into a 4x4 matrix, as a function */
|
||||
EX transmatrix fix4_f(transmatrix t) { fix4(t); return t; }
|
||||
|
||||
EX transmatrix xyscale(const transmatrix& t, double fac) {
|
||||
transmatrix res;
|
||||
for(int i=0; i<MXDIM; i++) {
|
||||
|
@ -1650,6 +1689,22 @@ EX hyperpoint inverse_exp(const shiftpoint h, flagtype prec IS(pNORMAL)) {
|
|||
return v;
|
||||
}
|
||||
|
||||
/** more precise */
|
||||
EX hyperpoint inverse_exp_newton(hyperpoint h, int iter) {
|
||||
auto approx = inverse_exp(shiftless(h));
|
||||
for(int i=0; i<iter; i++) {
|
||||
transmatrix T;
|
||||
ld eps = 1e-3;
|
||||
hyperpoint cur = direct_exp(approx);
|
||||
println(hlog, approx, " error = ", hdist(cur, h), " iteration ", i, "/", iter);
|
||||
for(int i=0; i<3; i++)
|
||||
set_column(T, i, direct_exp(approx + ctangent(i, eps)) - h);
|
||||
set_column(T, 3, C03);
|
||||
approx = approx - inverse(T) * (cur - h) * eps;
|
||||
}
|
||||
return approx;
|
||||
}
|
||||
|
||||
EX ld geo_dist(const hyperpoint h1, const hyperpoint h2, flagtype prec IS(pNORMAL)) {
|
||||
if(!nonisotropic) return hdist(h1, h2);
|
||||
return hypot_d(3, inverse_exp(shiftless(nisot::translate(h1, -1) * h2, prec)));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.roguetemple.hyperroid"
|
||||
android:versionCode="12080" android:versionName="12.0v"
|
||||
android:versionCode="13001" android:versionName="13.0a"
|
||||
android:installLocation="auto">
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> -->
|
||||
<!-- <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="9" /> -->
|
||||
|
|
|
@ -456,7 +456,7 @@ public class HyperRogue extends Activity implements SensorEventListener {
|
|||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra)
|
||||
{
|
||||
/* Toast.makeText(getApplicationContext(), String.format("Error(%s%s)", what, extra),
|
||||
/* Toast.makeText(getApplicationContext(), String.hr::format("Error(%s%s)", what, extra),
|
||||
Toast.LENGTH_SHORT).show(); */
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ void gdpush(int t);
|
|||
|
||||
void shareScore(MOBPAR_FORMAL);
|
||||
|
||||
const char *scorefile;
|
||||
std::string scorefile;
|
||||
|
||||
bool settingsChanged = false;
|
||||
|
||||
|
@ -203,14 +203,13 @@ extern "C" void
|
|||
Java_com_roguetemple_hyperroid_HyperRogue_setFilesDir(MOBPAR_FORMAL, jstring dir)
|
||||
{
|
||||
const char *nativeString = env->GetStringUTFChars(dir, 0);
|
||||
sscorefile = nativeString; sscorefile += "/hyperrogue.log";
|
||||
scorefile = nativeString; scorefile += "/hyperrogue.log";
|
||||
sconffile = nativeString; sconffile += "/hyperrogue.ini";
|
||||
scachefile = nativeString; scachefile += "/scorecache.txt";
|
||||
levelfile = nativeString; levelfile += "/hyperrogue.lev";
|
||||
picfile = nativeString; picfile += "/hyperrogue.pic";
|
||||
scorefile = sscorefile.c_str();
|
||||
conffile = sconffile.c_str();
|
||||
chmod(scorefile, 0777);
|
||||
chmod(scorefile.c_str(), 0777);
|
||||
chmod(conffile, 0777);
|
||||
chmod(nativeString, 0777);
|
||||
chmod((string(nativeString)+"/..").c_str(), 0777);
|
||||
|
|
|
@ -151,9 +151,9 @@ void showDemo() {
|
|||
dialog::addBreak(100);
|
||||
|
||||
dialog::addTitle("highlights", 0xC00000, 120);
|
||||
dialog::addItem(XLAT("Temple of Cthulhu"), 't');
|
||||
dialog::addItem(XLAT("Land of Storms"), 'l');
|
||||
dialog::addItem(XLAT("Burial Grounds"), 'b');
|
||||
dialog::addItem(XLAT1("Temple of Cthulhu"), 't');
|
||||
dialog::addItem(XLAT1("Land of Storms"), 'l');
|
||||
dialog::addItem(XLAT1("Burial Grounds"), 'b');
|
||||
|
||||
dialog::display();
|
||||
|
||||
|
|
454
hypgraph.cpp
454
hypgraph.cpp
File diff suppressed because it is too large
Load Diff
55
intra.cpp
55
intra.cpp
|
@ -163,7 +163,7 @@ EX portal_data make_portal(cellwalker cw, int spin) {
|
|||
#if CAP_BT
|
||||
if(bt::in()) {
|
||||
for(auto h: fac)
|
||||
println(hlog, PIU(deparabolic13(cgi.emb->normalize_flat(h))));
|
||||
println(hlog, PIU(deparabolic13(cgi.emb->flatten(h))));
|
||||
if(cw.spin == cw.at->type - 2)
|
||||
fac.pop_back();
|
||||
else
|
||||
|
@ -176,7 +176,7 @@ EX portal_data make_portal(cellwalker cw, int spin) {
|
|||
else {
|
||||
hyperpoint ctr = Hypc;
|
||||
for(auto p: fac) ctr += product_decompose(p).second;
|
||||
ctr = cgi.emb->normalize_flat(ctr);
|
||||
ctr = cgi.emb->flatten(ctr);
|
||||
id.T = gpushxto0(ctr);
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ EX portal_data make_portal(cellwalker cw, int spin) {
|
|||
id.v0 = Hypc;
|
||||
id.scale = cgi.plevel;
|
||||
for(auto p: fac) id.v0 += p;
|
||||
id.v0 = cgi.emb->normalize_flat(id.v0);
|
||||
hyperpoint h = cgi.emb->normalize_flat(fac[0]);
|
||||
id.v0 = cgi.emb->flatten(id.v0);
|
||||
hyperpoint h = cgi.emb->flatten(fac[0]);
|
||||
id.T = cspin90(1, 0) * spintox(gpushxto0(id.v0) * h) * gpushxto0(id.v0);
|
||||
if((id.T * C0)[0] > 0) id.T = spin180() * id.T;
|
||||
for(int i=0; i<3; i++) id.T[3][i] = id.T[i][3] = i==3;
|
||||
|
@ -527,21 +527,21 @@ EX void analyze_orthonormal(array<hyperpoint, 4> ds, ld sca) {
|
|||
}
|
||||
|
||||
EX void shift_view_portal(hyperpoint H) {
|
||||
shift_view(H);
|
||||
shift_view(H * scale);
|
||||
if(!through_portal()) return;
|
||||
shift_view(-H);
|
||||
shift_view(-H * scale);
|
||||
ld minv = 0, maxv = 1;
|
||||
for(int i=0; i<30; i++) {
|
||||
ld t = (minv + maxv) / 2;
|
||||
shift_view(H * t);
|
||||
shift_view(H * t * scale);
|
||||
bool b = through_portal();
|
||||
if(b) maxv = t; else minv = t;
|
||||
shift_view(H * -t);
|
||||
shift_view(H * -t * scale);
|
||||
}
|
||||
println(hlog, "maxv = ", maxv);
|
||||
shift_view(H * maxv);
|
||||
// println(hlog, "maxv = ", maxv);
|
||||
shift_view(H * maxv * scale);
|
||||
check_portal_movement();
|
||||
shift_view_portal(H * (1 - maxv));
|
||||
shift_view_portal(H * (1 - maxv) * scale);
|
||||
}
|
||||
|
||||
EX const connection_data* through_portal() {
|
||||
|
@ -552,6 +552,8 @@ EX const connection_data* through_portal() {
|
|||
return at_or_null(connections, cw1);
|
||||
}
|
||||
|
||||
EX ld scale = 1;
|
||||
|
||||
EX void check_portal_movement() {
|
||||
auto p = through_portal();
|
||||
|
||||
|
@ -620,20 +622,27 @@ EX void check_portal_movement() {
|
|||
#endif
|
||||
}
|
||||
|
||||
ld scale = p->id2.scale / p->id1.scale;
|
||||
|
||||
camera_speed *= scale;
|
||||
anims::cycle_length *= scale;
|
||||
#if CAP_VR
|
||||
vrhr::absolute_unit_in_meters *= scale;
|
||||
#endif
|
||||
if(walking::eye_level != -1) walking::eye_level *= scale;
|
||||
scale *= p->id2.scale / p->id1.scale;
|
||||
|
||||
walking::floor_dir = -1;
|
||||
walking::on_floor_of = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
EX void apply_scale() {
|
||||
if(scale != 1) {
|
||||
camera_speed *= scale;
|
||||
anims::cycle_length *= scale;
|
||||
vid.ipd *= scale;
|
||||
#if CAP_VR
|
||||
vrhr::absolute_unit_in_meters *= scale;
|
||||
#endif
|
||||
if(walking::eye_level != -1) walking::eye_level *= scale;
|
||||
scale = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vector<cellwalker> unconnected;
|
||||
|
||||
void erase_unconnected(cellwalker cw) {
|
||||
|
@ -659,7 +668,7 @@ EX string portal_help =
|
|||
EX void become_menu() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
dialog::init(XLAT("Become a portal map"));
|
||||
dialog::init(XLAT("become a portal map"));
|
||||
dialog::addHelp(XLAT(portal_help));
|
||||
dialog::addItem(XLAT("yes, that's what I want"), 'y');
|
||||
dialog::add_action([] {
|
||||
|
@ -779,7 +788,7 @@ EX void show_portals() {
|
|||
dialog::add_action([cw] { unconnected.push_back(cw); });
|
||||
dialog::start_list(500, 500, '1');
|
||||
for(auto p: unconnected) {
|
||||
dialog::addItem(XLAT("connect " + lalign(0, p)), dialog::list_fake_key++);
|
||||
dialog::addItem(XLAT("connect ") + lalign(0, p), dialog::list_fake_key++);
|
||||
dialog::add_action([p, cw] {
|
||||
connect_portal(cw, p, edit_spin);
|
||||
mapeditor::map_version++;
|
||||
|
@ -1162,7 +1171,7 @@ EX void add_options() {
|
|||
cell *c = centerover->move(point_direction);
|
||||
if(c && c->wall == waWaxWall) {
|
||||
color_t col = c->landparam;
|
||||
dialog::addBoolItem("we are facing floor (color " + format("%06X", col) + ")", colors_of_floors.count(col), 'n');
|
||||
dialog::addBoolItem("we are facing floor (color " + hr::format("%06X", col) + ")", colors_of_floors.count(col), 'n');
|
||||
dialog::add_action([col] {
|
||||
if(colors_of_floors.count(col)) colors_of_floors.erase(col);
|
||||
else colors_of_floors.insert(col);
|
||||
|
@ -1172,7 +1181,7 @@ EX void add_options() {
|
|||
}
|
||||
|
||||
auto a = addHook(hooks_configfile, 100, [] {
|
||||
param_b(auto_eyelevel, "auto_eyelevel")
|
||||
param_b(auto_eyelevel, "intra_eyelevel")
|
||||
-> editable("keep eye level when walking enabled", 'L');
|
||||
param_f(eye_level, "walk_eye_level")
|
||||
-> editable(0, 5, .1, "walking eye level",
|
||||
|
|
|
@ -36,8 +36,8 @@ EX namespace inv {
|
|||
for(int i=0; i<ittypes; i++) usedup[i] = 0;
|
||||
}
|
||||
|
||||
static const int MIRRORED = 1000;
|
||||
static const int TESTMIRRORED = 900;
|
||||
static constexpr int MIRRORED = 1000;
|
||||
static constexpr int TESTMIRRORED = 900;
|
||||
|
||||
struct lateextraorb {
|
||||
eItem treasure;
|
||||
|
|
133
irregular.cpp
133
irregular.cpp
|
@ -63,7 +63,7 @@ EX hrmap *base;
|
|||
|
||||
EX euc::torus_config_full base_config;
|
||||
|
||||
bool gridmaking;
|
||||
EX bool gridmaking;
|
||||
|
||||
int rearrange_index;
|
||||
|
||||
|
@ -402,10 +402,7 @@ bool step(int delta) {
|
|||
if(notfound) { status[4] = XLAT("cells badly paired: %1", its(notfound)); runlevel = 0; break; }
|
||||
|
||||
int heptas = 0;
|
||||
for(auto p: cells_of_heptagon) {
|
||||
printf("%p: %d\n", hr::voidp(p.first), isize(p.second));
|
||||
heptas++;
|
||||
}
|
||||
for(auto p: cells_of_heptagon) heptas++;
|
||||
|
||||
if(heptas != isize(all)) {
|
||||
status[4] = XLAT("cells not covered: %1", its(isize(all) - heptas));
|
||||
|
@ -607,7 +604,7 @@ int hdist(heptagon *h1, heptagon *h2) {
|
|||
// - compute celldists for all the cells in these three heptagons, by bfs, based on the 'parent' heptagons adjacent to h
|
||||
// - record the computed distances for h, but not for its siblings
|
||||
|
||||
static const int NODISTANCE = 2000000000;
|
||||
static constexpr int NODISTANCE = 2000000000;
|
||||
|
||||
map<heptagon*, heptagon*> last_on_horocycle;
|
||||
|
||||
|
@ -683,7 +680,7 @@ void compute_horocycle(heptagon *alt) {
|
|||
heptagon *master = last_on_horocycle[alt];
|
||||
// printf("computing horocycle, master distance = %d [M=%p, A=%p]\n", master->alt->distance, hr::voidp(master), hr::voidp(alt));
|
||||
|
||||
static const int LOOKUP = 16;
|
||||
static constexpr int LOOKUP = 16;
|
||||
set<heptagon*> hs[LOOKUP];
|
||||
hs[0].insert(master);
|
||||
set<heptagon*> region;
|
||||
|
@ -770,10 +767,9 @@ EX int celldist(cell *c, bool alts) {
|
|||
return hi.celldists[alts][cells[cellindex[c]].localindex];
|
||||
}
|
||||
|
||||
eGeometry orig_geometry;
|
||||
eGeometry orig_geometry, base_geometry;
|
||||
|
||||
void start_game_on_created_map() {
|
||||
popScreen();
|
||||
for(hrmap *& hm : allmaps) if(hm == base) hm = NULL;
|
||||
stop_game();
|
||||
geometry = orig_geometry;
|
||||
|
@ -807,6 +803,47 @@ bool save_map(const string& fname) {
|
|||
return true;
|
||||
}
|
||||
|
||||
vector<ld> float_order;
|
||||
|
||||
EX void save_map_bin(hstream& f) {
|
||||
if(!base) { f.write<short>(-1); return; }
|
||||
auto& all = base->allcells();
|
||||
int origcells = 0;
|
||||
for(cellinfo& ci: cells)
|
||||
if(ci.generation == 0)
|
||||
origcells++;
|
||||
f.write<short> (base_geometry);
|
||||
f.write<short> (isize(all));
|
||||
f.write<short> (origcells);
|
||||
int foi = 0;
|
||||
|
||||
auto check_float_order = [&] (ld x) {
|
||||
if(foi >= isize(float_order)) {
|
||||
float_order.push_back(x);
|
||||
f.write<ld>(x);
|
||||
}
|
||||
else if(abs(float_order[foi] - x) > 1e-6) {
|
||||
println(hlog, float_order[foi], " vs ", x, " : abs difference is ", abs(float_order[foi] - x));
|
||||
float_order[foi] = x;
|
||||
}
|
||||
f.write<ld>(float_order[foi++]);
|
||||
};
|
||||
|
||||
for(auto h: all) {
|
||||
origcells = 0;
|
||||
for(auto i: cells_of_heptagon[h->master])
|
||||
if(cells[i].generation == 0)
|
||||
origcells++;
|
||||
f.write<short> (origcells);
|
||||
for(auto i: cells_of_heptagon[h->master]) if(cells[i].generation == 0) {
|
||||
auto &ci = cells[i];
|
||||
check_float_order(ci.p[0]);
|
||||
check_float_order(ci.p[1]);
|
||||
check_float_order(ci.p[LDIM]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool load_map(const string &fname) {
|
||||
fhstream f(fname, "rt");
|
||||
if(!f.f) return false;
|
||||
|
@ -839,14 +876,64 @@ bool load_map(const string &fname) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void cancel_map_creation() {
|
||||
EX void load_map_bin(hstream& f) {
|
||||
auto& all = base->allcells();
|
||||
eGeometry g = (eGeometry) f.get<short>();
|
||||
if(int(g) == -1) return;
|
||||
int sa = f.get<short>();
|
||||
cellcount = f.get<short>();
|
||||
|
||||
if(g != geometry) throw hstream_exception("bad geometry");
|
||||
if(sa != isize(all)) throw hstream_exception("bad size of all");
|
||||
density = cellcount * 1. / isize(all);
|
||||
|
||||
cells.clear();
|
||||
float_order.clear();
|
||||
|
||||
for(auto h: all) {
|
||||
int q = f.get<short>();
|
||||
if(q < 0 || q > cellcount) throw hstream_exception("incorrect quantity");
|
||||
while(q--) {
|
||||
cells.emplace_back();
|
||||
cellinfo& s = cells.back();
|
||||
s.patterndir = -1;
|
||||
double a, b, c;
|
||||
a = f.get<ld>();
|
||||
b = f.get<ld>();
|
||||
c = f.get<ld>();
|
||||
float_order.push_back(a);
|
||||
float_order.push_back(b);
|
||||
float_order.push_back(c);
|
||||
s.p = hpxyz(a, b, c);
|
||||
s.p = normalize(s.p);
|
||||
for(auto c0: all) s.relmatrices[c0] = calc_relative_matrix(c0, h, s.p);
|
||||
s.owner = h;
|
||||
}
|
||||
}
|
||||
|
||||
make_cells_of_heptagon();
|
||||
runlevel = 2;
|
||||
}
|
||||
|
||||
EX void load_map_full(hstream& f) {
|
||||
init();
|
||||
try {
|
||||
load_map_bin(f);
|
||||
while(runlevel < 10) step(1000);
|
||||
start_game_on_created_map();
|
||||
}
|
||||
catch(hr_exception& e) {
|
||||
cancel_map_creation();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
EX void cancel_map_creation() {
|
||||
base = NULL;
|
||||
runlevel = 0;
|
||||
popScreen();
|
||||
gridmaking = false;
|
||||
stop_game();
|
||||
geometry = orig_geometry;
|
||||
start_game();
|
||||
}
|
||||
|
||||
string irrmapfile = "irregularmap.txt";
|
||||
|
@ -873,7 +960,7 @@ void show_gridmaker() {
|
|||
dialog::addSelItem(XLAT("density"), fts(density), 'd');
|
||||
dialog::add_action([] {
|
||||
dialog::editNumber(density, 1, 10, .1, 4, XLAT("density"), XLAT(irrhelp));
|
||||
dialog::reaction = [] () {
|
||||
dialog::get_di().reaction = [] () {
|
||||
int s = cellcount;
|
||||
if(density < 1) density = 1;
|
||||
cellcount = int(isize(currentmap->allcells()) * density + .5);
|
||||
|
@ -888,7 +975,7 @@ void show_gridmaker() {
|
|||
"The smallest allowed ratio of edge length to median edge length. "
|
||||
"Tilings with low values are easier to generate, but tend to be more ugly."
|
||||
));
|
||||
dialog::reaction = [] () {
|
||||
dialog::get_di().reaction = [] () {
|
||||
println(hlog, "quality = ", density);
|
||||
if(runlevel > 4) runlevel = 4;
|
||||
};
|
||||
|
@ -898,9 +985,9 @@ void show_gridmaker() {
|
|||
dialog::addInfo(status[i]);
|
||||
dialog::addBreak(100);
|
||||
dialog::addSelItem(XLAT("activate"), runlevel == 10 ? XLAT("ready") : XLAT("wait..."), 'f');
|
||||
if(runlevel == 10) dialog::add_action(start_game_on_created_map);
|
||||
if(runlevel == 10) dialog::add_action([] { popScreen(); start_game_on_created_map(); });
|
||||
dialog::addItem(XLAT("cancel"), 'c');
|
||||
dialog::add_action(cancel_map_creation);
|
||||
dialog::add_action([] { cancel_map_creation(); popScreen(); start_game(); });
|
||||
dialog::addItem(XLAT("save"), 's');
|
||||
dialog::add_action([] () {
|
||||
dialog::openFileDialog(irrmapfile, XLAT("irregular to save:"), ".txt", [] () {
|
||||
|
@ -931,7 +1018,7 @@ void show_gridmaker() {
|
|||
dialog::add_action([] () {
|
||||
dialog::editNumber(bitruncations_requested, 0, 5, 1, 1, XLAT("bitruncation const"),
|
||||
XLAT("Bitruncation introduces some regularity, allowing more sophisticated floor tilings and textures."));
|
||||
dialog::reaction = [] () {
|
||||
dialog::get_di().reaction = [] () {
|
||||
if(bitruncations_requested > bitruncations_performed && runlevel > 5) runlevel = 5;
|
||||
if(bitruncations_requested < bitruncations_performed) runlevel = 0;
|
||||
};
|
||||
|
@ -950,7 +1037,7 @@ void show_gridmaker() {
|
|||
};
|
||||
}
|
||||
|
||||
EX void visual_creator() {
|
||||
EX void init() {
|
||||
stop_game();
|
||||
orig_geometry = geometry;
|
||||
switch(geometry) {
|
||||
|
@ -966,13 +1053,19 @@ EX void visual_creator() {
|
|||
break;
|
||||
}
|
||||
|
||||
base_geometry = geometry;
|
||||
variation = eVariation::pure;
|
||||
start_game();
|
||||
if(base) delete base;
|
||||
base = currentmap;
|
||||
base_config = euc::eu;
|
||||
drawthemap();
|
||||
cellcount = int(isize(base->allcells()) * density + .5);
|
||||
gridmaking = true;
|
||||
drawthemap();
|
||||
}
|
||||
|
||||
EX void visual_creator() {
|
||||
init();
|
||||
pushScreen(show_gridmaker);
|
||||
runlevel = 0;
|
||||
gridmaking = true;
|
||||
|
@ -1015,7 +1108,7 @@ int readArgs() {
|
|||
else if(argis("-irrload")) {
|
||||
PHASE(3);
|
||||
restart_game();
|
||||
visual_creator();
|
||||
init();
|
||||
showstartmenu = false;
|
||||
shift();
|
||||
load_map(args());
|
||||
|
|
29
items.cpp
29
items.cpp
|
@ -16,8 +16,13 @@ EX array<int, ittypes> items;
|
|||
|
||||
EX map<modecode_t, array<int, ittypes> > hiitems;
|
||||
|
||||
EX bool pickable_from_water(eItem it) {
|
||||
return among(it, itOrbFish, itOrbAether);
|
||||
}
|
||||
|
||||
EX bool cannotPickupItem(cell *c, bool telekinesis) {
|
||||
return itemHidden(c) && !telekinesis && !(isWatery(c) && markOrb(itOrbFish));
|
||||
if(pickable_from_water(c->item) && isWatery(c)) return false;
|
||||
return itemHidden(c) && !telekinesis && !(isWatery(c) && (markOrb(itOrbFish) || markOrb(itOrbAether)));
|
||||
}
|
||||
|
||||
EX bool canPickupItemWithMagnetism(cell *c, cell *from) {
|
||||
|
@ -39,9 +44,9 @@ EX bool doPickupItemsWithMagnetism(cell *c) {
|
|||
if(!isNeighbor(c, c4) && c3->item && !c4->item && passable(c4, c3, ZERO)) {
|
||||
changes.ccell(c3);
|
||||
changes.ccell(c4);
|
||||
c4->item = c3->item;
|
||||
moveEffect(movei(c3, c4, (cw+j).spin), moDeadBird);
|
||||
c3->item = itNone;
|
||||
moveItem(c3, c4, false);
|
||||
animateMovement(match(c3, c4), LAYER_BOAT);
|
||||
moveEffect(movei(c4, c4, NODIR), moDeadBird);
|
||||
markOrb(itCurseRepulsion);
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +62,12 @@ EX bool doPickupItemsWithMagnetism(cell *c) {
|
|||
}
|
||||
else if(c3->item == itOrbSafety || c3->item == itBuggy || c3->item == itBuggy2)
|
||||
csaf = c3;
|
||||
else if(markOrb(itOrbMagnetism))
|
||||
else if(markOrb(itOrbMagnetism)) {
|
||||
eItem it = c3->item;
|
||||
collectItem(c3, c3, false);
|
||||
if(!c3->item)
|
||||
animate_item_throw(c3, c, it);
|
||||
}
|
||||
}
|
||||
if(csaf)
|
||||
return collectItem(csaf, csaf, false);
|
||||
|
@ -460,10 +469,10 @@ EX void countLocalTreasure() {
|
|||
}
|
||||
|
||||
#if HDR
|
||||
static const int NO_TREASURE = 1;
|
||||
static const int NO_YENDOR = 2;
|
||||
static const int NO_GRAIL = 4;
|
||||
static const int NO_LOVE = 8;
|
||||
static constexpr int NO_TREASURE = 1;
|
||||
static constexpr int NO_YENDOR = 2;
|
||||
static constexpr int NO_GRAIL = 4;
|
||||
static constexpr int NO_LOVE = 8;
|
||||
#endif
|
||||
|
||||
EX int gold(int no IS(0)) {
|
||||
|
@ -733,7 +742,7 @@ EX void collectMessage(cell *c2, eItem which) {
|
|||
|
||||
EX bool itemHiddenFromSight(cell *c) {
|
||||
return isWatery(c) && !items[itOrbInvis] && !(items[itOrbFish] && playerInWater())
|
||||
&& !(shmup::on && shmup::boatAt(c));
|
||||
&& !(shmup::on && shmup::boatAt(c)) && !(c->cpdist <= 1 && playerInWater());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
202
landgen.cpp
202
landgen.cpp
|
@ -171,8 +171,8 @@ EX void place_elemental_wall(cell *c) {
|
|||
else if(c->land == laEEarth) c->wall = waStone;
|
||||
}
|
||||
|
||||
// automatically adjust monster generation for 3D geometries
|
||||
EX int hrand_monster(int x) {
|
||||
// automatically adjust monster generation for 3D geometries and custom difficulty
|
||||
EX int hrand_monster_in(eLand l, int x) {
|
||||
// dual geometry mode is much harder, so generate less monsters to balance it
|
||||
if(dual::state) x *= 3;
|
||||
// in 3D monster generation depends on the sight range
|
||||
|
@ -180,9 +180,15 @@ EX int hrand_monster(int x) {
|
|||
int t = isize(gmatrix);
|
||||
if(t > 500) x = int(((long long)(x)) * t / 500);
|
||||
}
|
||||
if(use_custom_land_list) {
|
||||
x = x * 100 / custom_land_difficulty[l];
|
||||
if(x == 0) x = 1;
|
||||
}
|
||||
return hrand(x);
|
||||
}
|
||||
|
||||
#define hrand_monster(x) hrand_monster_in(c->land, x)
|
||||
|
||||
EX bool is_zebra_trapdoor(cell *c) {
|
||||
if(euclid && closed_or_bounded) return false;
|
||||
#if CAP_ARCM
|
||||
|
@ -195,7 +201,6 @@ EX bool is_zebra_trapdoor(cell *c) {
|
|||
else if(PURE && reg3::exact_rules()) switch(geometry) {
|
||||
case gSpace534: {
|
||||
if(c->master->fieldval == 0) return true;
|
||||
forCellCM(c1, c) if(c1->master->fieldval == 0) return true;
|
||||
return false;
|
||||
}
|
||||
case gSpace435: {
|
||||
|
@ -275,8 +280,30 @@ EX void place_random_gate_continuous(cell *c) {
|
|||
else toggleGates(c, waOpenPlate, 1);
|
||||
}
|
||||
|
||||
EX void gen_baby_tortoise(cell *c) {
|
||||
c->item = itBabyTortoise;
|
||||
tortoise::babymap[c] = tortoise::getb(c) ^ tortoise::getRandomBits();
|
||||
}
|
||||
|
||||
EX int rebalance_treasure(int x, int y, eLand l) {
|
||||
int res = ((tactic::on || quotient == 2 || daily::on) ? (y) : inv::on ? min(2*(y),x) : (x));
|
||||
if(use_custom_land_list) res = (res * custom_land_treasure[l] + 50) / 100;
|
||||
res *= ls::ls_mul();
|
||||
return res;
|
||||
}
|
||||
|
||||
EX eItem random_curse() {
|
||||
return pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony);
|
||||
}
|
||||
|
||||
EX void clear_item(cell *c) {
|
||||
if(c->item == itOrbWater && c->wall == waStrandedBoat)
|
||||
c->wall = waNone;
|
||||
c->item = itNone;
|
||||
}
|
||||
|
||||
EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
bool fargen = d == min(BARLEV, 9);
|
||||
bool fargen = d == 9;
|
||||
switch(c->land) {
|
||||
|
||||
case laPrairie: // -------------------------------------------------------------
|
||||
|
@ -453,7 +480,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
|
||||
// note: Princess Challenge brings back the normal Palace generation
|
||||
bool lookingForPrincess = !euclid && c->master->alt && !princess::challenge;
|
||||
bool lookingForPrincess = !euclid && c->master->alt && !princess::challenge && !ls::hv_structure();
|
||||
|
||||
bool pgate = false;
|
||||
if(PURE || GOLDBERG) {
|
||||
|
@ -531,7 +558,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
// no Plates or Trapdoors in the Princess cell
|
||||
if(d < 3 && (c->wall == waClosePlate || c->wall == waOpenPlate || c->wall == waTrapdoor))
|
||||
c->wall = waNone;
|
||||
if(d > 1) c->item = itNone;
|
||||
if(d > 1) clear_item(c);
|
||||
// the Princess herself
|
||||
if(d == 0) {
|
||||
c->monst = moPrincess;
|
||||
|
@ -551,7 +578,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
|
||||
ONEMPTY {
|
||||
bool lookingForPrincess0 = !euclid && c->master->alt;
|
||||
bool lookingForPrincess0 = !euclid && c->master->alt && !ls::hv_structure();
|
||||
bool lookingForPrincess = lookingForPrincess0 && !princess::challenge;
|
||||
int hardness = lookingForPrincess ? 5 : items[itPalace] + yendor::hardness();
|
||||
|
||||
|
@ -629,9 +656,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->wall = waCavewall;
|
||||
else c->wall = waCavefloor;
|
||||
}
|
||||
else if(a4 || arcm::in() || cryst)
|
||||
else if(a4 || arcm::in() || cryst || bt::in() || S3 >= OINF)
|
||||
c->wall = hrand(100) < 50 ? waCavefloor : waCavewall;
|
||||
else if(!BITRUNCATED) {
|
||||
else if(!BITRUNCATED && geometry != gOctagon) {
|
||||
if(polarb50(c))
|
||||
c->wall = waCavewall;
|
||||
else c->wall = waCavefloor;
|
||||
|
@ -738,7 +765,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
}
|
||||
// seal entrances to the Land of Power.
|
||||
if(d == 7 && ctof(c)) {
|
||||
if(d == 7 && ctof(c) && land_structure != lsLandscape) {
|
||||
bool onwall = false;
|
||||
for(int i=0; i<c->type; i++) if(c->move(i) && c->move(i)->land == laBarrier)
|
||||
onwall = true;
|
||||
|
@ -748,13 +775,16 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
cell *c3 = c2->modmove(c->c.spin(i) + 3);
|
||||
if(!c3) continue;
|
||||
if(c3->land != laPower && c3->land != laBarrier)
|
||||
if(c2->wall != waFire && c2->wall != waGlass) {
|
||||
if(c2->wall != waEternalFire && c2->wall != waGlass) {
|
||||
if(isFire(c)) c->monst = moWitchWinter;
|
||||
else if(c->wall == waGlass) c->monst = moWitchGhost;
|
||||
else c->monst = moEvilGolem;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(d == 7 && land_structure == lsLandscape) {
|
||||
forCellEx(c2, c) if(c2->land != laPower) c->wall = waEternalFire;
|
||||
}
|
||||
ONEMPTY {
|
||||
if(hrand(5000+50*items[itPower]) < 1200) {
|
||||
eItem powerorbs[6] = {
|
||||
|
@ -806,7 +836,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
else if(WDIM == 3 && hyperbolic && !bt::in())
|
||||
c->wall = (c->master->zebraval & 2) ? waVinePlant : waNone;
|
||||
else if(a4 || sphere || arcm::in())
|
||||
else if(a4 || sphere || arcm::in() || bt::in() || S3 >= OINF)
|
||||
c->wall = hrand(100) < 50 ? waNone : waVinePlant;
|
||||
else {
|
||||
int v = emeraldval(c);
|
||||
|
@ -827,6 +857,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
forCellCM(c2, c) if(emeraldval(c2) == (v^1))
|
||||
c->wall = waVinePlant;
|
||||
}
|
||||
if(weirdhyperbolic && cellHalfvine(c)) c->wall = waNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -880,7 +911,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(hrand(5000) < 25 && celldist(c) >= 5 && !safety) {
|
||||
bool goodland = true;
|
||||
cell *c2 = createMov(c, hrand(c->type));
|
||||
for(auto cx: {c, c2})
|
||||
if(!ls::any_chaos() && !ls::hv_structure()) for(auto cx: {c, c2})
|
||||
forCellCM(c3,cx) {
|
||||
if(c3->land != laNone && c3->land != laBurial)
|
||||
goodland = false;
|
||||
|
@ -919,11 +950,17 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
|
||||
case laTrollheim:
|
||||
if(fargen) {
|
||||
if(hrand(50000) < (ls::tame_chaos() ? 1000: ls::any_chaos() ?50:5) && c->wall != waBarrier && celldist(c) >= 7 && !safety && !peace::on) {
|
||||
int freq =
|
||||
land_structure == lsVineWalls ? 10000 :
|
||||
ls::wall_chaos() ? 2500 :
|
||||
ls::tame_chaos() ? 1000 :
|
||||
ls::any_chaos() ? 50 :
|
||||
5;
|
||||
if(hrand(50000) < freq && c->wall != waBarrier && celldist(c) >= 7 && !safety && !peace::on) {
|
||||
bool okay = true;
|
||||
forCellCM(c2, c) forCellCM(c3, c2) forCellCM(c4, c3) forCellCM(c5, c4) {
|
||||
cell *cx = ls::any_chaos() ? c3 : c5;
|
||||
if(cx->land != laTrollheim && cx->land != laNone)
|
||||
if(cx->land != laTrollheim && cx->land != laNone && !ls::hv_structure())
|
||||
okay = false;
|
||||
if(cx->bardir != NODIR) okay = false;
|
||||
}
|
||||
|
@ -1046,7 +1083,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
createMov(c2, i);
|
||||
int j = c2->c.spin(i);
|
||||
cell *c3 = c2->move(i);
|
||||
if(c3->monst || c3->bardir != NODIR || c3->wall || c3->mpdist <= 7) break;
|
||||
setdist(c3, 9, c2);
|
||||
if(c3->monst || (ls::hv_structure() ? c3->land != laDragon : c3->bardir != NODIR) || c3->wall || c3->mpdist <= 7) break;
|
||||
c2 = c3;
|
||||
c2->monst = moDragonTail;
|
||||
c2->hitpoints = 1;
|
||||
|
@ -1060,10 +1098,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
else c2->mondir = NODIR;
|
||||
}
|
||||
}
|
||||
if(!c->monst && !ls::single() && !racing::on && !yendor::on && !randomPatternsMode && !peace::on && !euclid && hrand(4000) < 10 && !safety) {
|
||||
c->item = itBabyTortoise;
|
||||
tortoise::babymap[c] = tortoise::getb(c) ^ tortoise::getRandomBits();
|
||||
}
|
||||
if(!c->monst && !ls::single() && !racing::on && !yendor::on && !randomPatternsMode && !peace::on && !euclid && hrand(4000) < 10 && !safety)
|
||||
gen_baby_tortoise(c);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1222,7 +1258,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(fargen) {
|
||||
if(hrand(500) < 15)
|
||||
createArrowTrapAt(c, laTerracotta);
|
||||
if(pseudohept(c) && hrand(100) < 40 && c->wall == waNone && !racing::on) {
|
||||
if(pseudohept_r(c) && hrand(100) < 40 && c->wall == waNone && !racing::on) {
|
||||
c->wall = waTerraWarrior;
|
||||
c->wparam = terracotta::randterra ? 0 : 3 + hrand(3);
|
||||
if(hrand(100) < items[itTerra]-10)
|
||||
|
@ -1264,7 +1300,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(d == 8) {
|
||||
bool ok = c->landparam == 0;
|
||||
forCellEx(c2, c) if(c2->landparam) ok = false;
|
||||
if(ok && hrand(doCross ?450:15000) < 20 + (2 * items[itMutant] + yendor::hardness()) && !safety) {
|
||||
if(ok && hrand(doCross ?450:15000) < (20 + (2 * items[itMutant] + yendor::hardness())) * ls::ls_mul_big() && !safety) {
|
||||
if(!peace::on) c->item = itMutant;
|
||||
c->landparam = items[itMutant] + 5 + hrand(11);
|
||||
c->wall = waNone;
|
||||
|
@ -1292,6 +1328,12 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
break;
|
||||
|
||||
case laHalloween:
|
||||
if(!closed_or_bounded) {
|
||||
ONEMPTY {
|
||||
if(hrand(1000) < PT(20, 20)) c->item = itTreat;
|
||||
if(hrand(1000) < 20) c->wall = waChasm;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case laWildWest:
|
||||
|
@ -1436,13 +1478,23 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->wall = waSandstone;
|
||||
}
|
||||
|
||||
if(ls::horodisk_structure()) {
|
||||
if(celldistAlt(c) >= horodisk_from) c->wall = waNone;
|
||||
}
|
||||
else if(!ls::voronoi_structure()) {
|
||||
for(int i=0; i<c->type; i++)
|
||||
if(c->move(i) && c->move(i)->land != laStorms && c->move(i)->land != laNone)
|
||||
c->wall = waNone;
|
||||
}
|
||||
}
|
||||
if(d == BARLEV && randstorm) {
|
||||
c->landparam = hrand(1000000);
|
||||
}
|
||||
if(d == 7 && ls::voronoi_structure()) {
|
||||
for(int i=0; i<c->type; i++)
|
||||
if(c->move(i) && c->move(i)->land != laStorms)
|
||||
c->wall = waNone;
|
||||
}
|
||||
if(d == BARLEV-1 && randstorm) {
|
||||
/* static int stormlevel, stormgroup;
|
||||
if(!stormlevel) stormgroup = 0;
|
||||
|
@ -1489,7 +1541,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(fargen) {
|
||||
if(randomPatternsMode)
|
||||
c->wall = RANDPAT ? ((RANDPATV(laCrossroads) || RANDPATV(laCrossroads2)) ? waAncientGrave : waFreshGrave) : waNone;
|
||||
else if(pseudohept(c))
|
||||
else if(pseudohept_r(c))
|
||||
c->wall = hrand(5) ? waAncientGrave : waFreshGrave;
|
||||
}
|
||||
ONEMPTY {
|
||||
|
@ -1522,7 +1574,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->move(i)->wall = waNone;
|
||||
}
|
||||
}
|
||||
if(pseudohept(c) && hrand(2)) c->wall = waColumn;
|
||||
if(pseudohept_r(c) && hrand(2)) c->wall = waColumn;
|
||||
}
|
||||
}
|
||||
ONEMPTY {
|
||||
|
@ -1640,8 +1692,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
|
||||
case laHive:
|
||||
if(fargen) {
|
||||
if(hrand(2000) < (ls::tame_chaos() ? 1000 : (PURE && !ls::any_chaos()) ?200: ls::any_chaos() ? 10 : 2) && !safety)
|
||||
if(hrand(2000) < (ls::tame_chaos() ? 1000 : (PURE && !ls::any_chaos()) ?200: ls::any_chaos() ? 10 : ls::horodisk_structure() ? 50 : ls::hv_structure() ? 10 : 2) && !safety)
|
||||
hive::createBugArmy(c);
|
||||
if(hrand_monster(20000) < 10 && ls::horodisk_structure()) c->monst = moPirate;
|
||||
if(hrand(2000) < 100 && !c->wall && !c->item && !c->monst) {
|
||||
int nww = 0;
|
||||
for(int i=0; i<c->type; i++) if(c->move(i) && c->move(i)->wall == waWaxWall)
|
||||
|
@ -1786,11 +1839,19 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
}
|
||||
ONEMPTY {
|
||||
if(hrand_monster(4000) < (peace::on ? 750 : 50 + items[itBabyTortoise]*2 + yendor::hardness() * 6) && !safety) {
|
||||
bool mk21tor = (tortoise::seek() && !((tortoise::getb(c) ^ tortoise::seekbits) & tortoise::mask) && (turncount > tortoise::last21tort + 100));
|
||||
if((mk21tor || hrand_monster(ls::hv_structure() ? 8000 : 4000) < (peace::on ? 750 : 50 + items[itBabyTortoise]*2 + yendor::hardness() * 6)) && !safety) {
|
||||
c->monst = moTortoise;
|
||||
c->hitpoints = 3;
|
||||
auto val = tortoise::getb(c);
|
||||
tortoise::emap[c] = val;
|
||||
if (mk21tor) tortoise::last21tort = turncount;
|
||||
}
|
||||
else if(ls::hv_structure() && hrand(10000) <= 250) {
|
||||
c->item = itCompass;
|
||||
}
|
||||
else if(ls::hv_structure() && hrand_monster(10000) <= 15) {
|
||||
c->monst = moPirate;
|
||||
}
|
||||
|
||||
int chance = 50 + items[itBabyTortoise]*2;
|
||||
|
@ -1934,6 +1995,10 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->wall = waBoat;
|
||||
c->item = itCoral;
|
||||
}
|
||||
else if(hrand(6000) < 1000 && ls::hv_structure()) {
|
||||
/* somehow there were not enough boats in hv_structure... */
|
||||
forCellEx(c1, c) if(c1->land == laWarpCoast) c->wall = waBoat;
|
||||
}
|
||||
}
|
||||
|
||||
ONEMPTY if(c->land == laWarpCoast) {
|
||||
|
@ -1982,7 +2047,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
for(int i=0; i<c->type; i++) {
|
||||
cell *c2 = c->move(i);
|
||||
if(c2 && c2->wall == waRose) nww++;
|
||||
if(c2 && !ls::any_chaos()) for(int j=0; j<c2->type; j++) {
|
||||
if(c2 && !ls::any_chaos() && !ls::hv_structure()) for(int j=0; j<c2->type; j++) {
|
||||
cell *c3 = c2->move(j);
|
||||
// note: c3->land is required for Android --
|
||||
// not strictly equivalent since another land there might be not yet generated
|
||||
|
@ -2020,7 +2085,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
|
||||
case laHunting:
|
||||
if(d == 7 && c->land == laHunting && !racing::on && !safety && !reptilecheat) {
|
||||
if(hrand(1000) < 20) {
|
||||
if(hrand(1000) < 20 * ls::ls_mul_big()) {
|
||||
if(openplains(c)) {
|
||||
if(hrand(2) == 0) {
|
||||
if(!items[itHunting]) {
|
||||
|
@ -2087,8 +2152,14 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
break;
|
||||
|
||||
case laOcean:
|
||||
if(d >= 8) c->wall = waSea;
|
||||
if(d >= 8 && d <= 9) c->wall = waSea;
|
||||
if(d == 7 && !safety) {
|
||||
|
||||
if(ls::hv_structure() && c->master->alt && hv_land[c->master->alt->alt] == laWhirlpool) {
|
||||
if(hrand(100) < 10) c->wall = waBoat;
|
||||
return;
|
||||
}
|
||||
|
||||
bool placecolumn = false;
|
||||
if(c->landparam % temple_layer_size() == 0 && c->landparam <= 24) {
|
||||
int q = 0;
|
||||
|
@ -2222,11 +2293,11 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->monst = moMonkey;
|
||||
else if(hrand_monster(80000) < 5 + items[itRuby] + yendor::hardness())
|
||||
c->monst = moEagle;
|
||||
else if(pseudohept(c) && c != currentmap->gamestart() && hrand_monster(4000) < 300 + items[itRuby] && !c->monst) {
|
||||
else if(pseudohept_r(c) && c != currentmap->gamestart() && hrand_monster(4000) < (300 + items[itRuby]) * ls::ls_mul_big() && !c->monst) {
|
||||
int hardchance = items[itRuby] + yendor::hardness();
|
||||
if(hardchance > 25) hardchance = 25;
|
||||
bool hardivy = hrand(100) < hardchance;
|
||||
if((cgflags & qFRACTAL) ? buildIvy(c, 0, 2) : hat::in() ? buildIvy(c, 0, 4) : (hardivy ? buildIvy(c, 1, 9) : buildIvy(c, 0, c->type)) && !peace::on)
|
||||
if(land_structure == lsVineWalls ? buildIvy(c, 0, 2) : (cgflags & qFRACTAL) ? buildIvy(c, 0, 2) : hat::in() ? buildIvy(c, 0, 4) : (hardivy ? buildIvy(c, 1, 9) : buildIvy(c, 0, c->type)) && !peace::on)
|
||||
c->item = itRuby;
|
||||
}
|
||||
}
|
||||
|
@ -2261,11 +2332,12 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
case laClearing:
|
||||
if(d == 7) {
|
||||
clearing::generate(c);
|
||||
if(ls::hv_structure() && celldistAlt(c) >= -1) c->monst = moNone;
|
||||
if(pseudohept(c)) {
|
||||
int d = -celldistAlt(c);
|
||||
if(hrand_monster(2500) < items[itMutant2] + yendor::hardness() - 10 && !reptilecheat)
|
||||
c->monst = moRedFox;
|
||||
else if(hrand(100 + d) < d && !reptilecheat)
|
||||
else if(d > 0 && hrand(100 + d) < d && !reptilecheat)
|
||||
c->item = itMutant2;
|
||||
}
|
||||
}
|
||||
|
@ -2344,7 +2416,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(hrand(1500) < PT(30 + kills[moHexDemon] + kills[moAltDemon] + kills[moMonk] + kills[moPair] + kills[moCrusher], 100) && notDippingFor(itRuins)) {
|
||||
c->item = itRuins;
|
||||
forCellEx(c2, c) if(c2->monst == moMonk)
|
||||
c->item = itNone;
|
||||
clear_item(c);
|
||||
}
|
||||
if(hrand_monster(7000) < kf && !c->monst) {
|
||||
c->monst = genRuinMonster(c);
|
||||
|
@ -2460,6 +2532,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
int freq = 4000;
|
||||
if(ls::single() && specialland == laCrossroads5 && !racing::on)
|
||||
freq = 250;
|
||||
if(ls::hv_structure() && hrand(10000) < 10 && !c->monst) { c->monst = moPirate; }
|
||||
if(ls::horodisk_structure() && !c->item && hrand(10000) < 10 && !safety)
|
||||
gen_baby_tortoise(c);
|
||||
if(hrand_monster(freq) < items[itHyperstone] && !c->monst) {
|
||||
// only interesting monsters here!
|
||||
eMonster cm = crossroadsMonster();
|
||||
|
@ -2479,7 +2554,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
if(d == 7) {
|
||||
c->wall = waNone;
|
||||
|
||||
c->item = itNone; c->monst = moNone;
|
||||
clear_item(c); c->monst = moNone;
|
||||
|
||||
if(hrand(100) < 25)
|
||||
c->wall = hrand(2) ? waBigTree : waSmallTree;
|
||||
|
@ -2520,7 +2595,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
treasure_rate += variant::features[i].rate_change;
|
||||
variant::features[i].build(c);
|
||||
}
|
||||
if(hrand(2000 - PT(kills[moVariantWarrior] * 5, 250)) < treasure_rate && !c->wall && !c->monst)
|
||||
if(hrand(max(100, 2000 - PT(kills[moVariantWarrior] * 5, 250))) < treasure_rate && !c->wall && !c->monst)
|
||||
c->item = itVarTreasure;
|
||||
}
|
||||
if(d == 7 && c->wall == waTrapdoor) {
|
||||
|
@ -2533,7 +2608,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
|
||||
case laEclectic: {
|
||||
|
||||
if(d >= 9) c->wall = waChasm;
|
||||
if(d == 9) c->wall = waChasm;
|
||||
|
||||
if(d == 8) wfc::schedule(c);
|
||||
|
||||
|
@ -2591,7 +2666,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
}
|
||||
|
||||
case laCursed: {
|
||||
if(fargen) {
|
||||
if(fargen && c->wall != waRubble) {
|
||||
c->wall = waStone;
|
||||
for(int i=0; i<3; i++) {
|
||||
auto ew = [i] (cell *c1) {
|
||||
|
@ -2627,7 +2702,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
c->wall = waStone;
|
||||
else {
|
||||
c->monst = moHexer;
|
||||
c->item = pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony);
|
||||
c->item = random_curse();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2700,7 +2775,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
break;
|
||||
|
||||
case laMemory:
|
||||
if(d >= 7) c->wall = waChasm;
|
||||
if(d >= 7 && d <= 9) c->wall = waChasm;
|
||||
if(d == 7 && !c->monst && hrand(2000) < 4)
|
||||
#if CAP_RACING
|
||||
if(!racing::on)
|
||||
|
@ -2709,7 +2784,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||
break;
|
||||
|
||||
case laAsteroids:
|
||||
if(d >= 7) c->wall = waInvisibleFloor;
|
||||
if(d >= 7 && d <= 9) c->wall = waInvisibleFloor;
|
||||
break;
|
||||
|
||||
case laWet:
|
||||
|
@ -2822,9 +2897,11 @@ EX void repairLandgen(cell *c) {
|
|||
}
|
||||
}
|
||||
|
||||
EX int randomwalk_size = 10;
|
||||
|
||||
EX void setland_randomwalk(cell *c) {
|
||||
if(c->land) return;
|
||||
if(hrand(10) == 0) setland(c, currentlands[hrand(isize(currentlands))]);
|
||||
if(hrand(randomwalk_size) == 0) setland(c, random_land());
|
||||
else {
|
||||
cell *c2 = nullptr;
|
||||
for(int i=0; i<10 && !(c2 && (!disksize || is_in_disk(c2)) && is_in_fractal(c2)); i++)
|
||||
|
@ -2843,13 +2920,37 @@ EX void share_land(cell *c, cell *c2) {
|
|||
c->land = c2->land;
|
||||
}
|
||||
|
||||
EX void set_land_for_geometry(cell *c) {
|
||||
// odd landscape_div are better
|
||||
EX int landscape_div = 25;
|
||||
|
||||
EX void set_land_for_geometry(cell *c) {
|
||||
if(!c->land && isize(currentlands)) {
|
||||
if(land_structure == lsTotalChaos) {
|
||||
setland(c, random_land());
|
||||
return;
|
||||
}
|
||||
if(land_structure == lsLandscape) {
|
||||
if(landscape_div <= 0) landscape_div = 1;
|
||||
array<int, 3> a;
|
||||
for(int i=0; i<3; i++) a[i] = getCdata(c, i);
|
||||
auto& ld = landscape_div;
|
||||
auto ld2 = ld * 2;
|
||||
int sh = 0;
|
||||
for(int i=0; i<3; i++) {
|
||||
int x = a[i];
|
||||
x = gmod(x, ld2);
|
||||
if(x >= ld) sh += x - ld;
|
||||
else sh += ld - 1 - x;
|
||||
}
|
||||
for(int i=0; i<3; i++) {
|
||||
if(sh * 2 < ld * 3) a[i] = gdiv(a[i], ld2)*2+1;
|
||||
else a[i] = gdiv(a[i]+ld, ld2)*2;
|
||||
}
|
||||
eLand& l = landscape_lands[make_array(a[0], a[1], a[2])];
|
||||
if(l == laNone) l = random_land();
|
||||
setland(c, l);
|
||||
return;
|
||||
}
|
||||
/* note: Nil patched chaos done in setLandNil */
|
||||
if(ls::patched_chaos() && (cgflags & qFRACTAL)) {
|
||||
share_land(c, fractal_rep(c));
|
||||
|
@ -2951,7 +3052,7 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if(!c->land && from && (WDIM == 3 || !among(from->land, laBarrier, laElementalWall, laHauntedWall, laOceanWall)) && !quotient && ls::chaoticity() < 60) {
|
||||
if(!c->land && from && (WDIM == 3 || !among(from->land, laBarrier, laElementalWall, laHauntedWall, laOceanWall)) && !quotient && ls::chaoticity() < 60 && land_structure != lsLandscape) {
|
||||
if(!hasbardir(c)) setland(c, from->land);
|
||||
}
|
||||
if(c->land == laTemple && ls::any_order()) setland(c, laRlyeh);
|
||||
|
@ -2974,18 +3075,18 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
}
|
||||
|
||||
if(d == BARLEV && c->land == laCanvas) {
|
||||
color_t col = patterns::generateCanvas(c);
|
||||
color_t col = ccolor::generateCanvas(c);
|
||||
c->landparam = col;
|
||||
c->wall = canvas_default_wall;
|
||||
if((GDIM == 3 || geom3::flipped) && (col & 0x1000000)) c->wall = waWaxWall;
|
||||
if(col & 0x1000000) c->wall = waWaxWall;
|
||||
}
|
||||
|
||||
#if CAP_FIELD
|
||||
if(d >= BARLEV-1 && c->land == laPrairie && !ls::any_chaos())
|
||||
if(d >= BARLEV-1 && c->land == laPrairie && !ls::any_chaos() && !ls::hv_structure())
|
||||
prairie::spread(c, from);
|
||||
#endif
|
||||
|
||||
if(d < BARLEV && c->land == laPrairie && !c->landparam && !ls::any_chaos()) {
|
||||
if(d < BARLEV && c->land == laPrairie && !c->landparam && !ls::any_chaos() && !ls::hv_structure()) {
|
||||
printf("d=%d/%d\n", d, BARLEV);
|
||||
raiseBuggyGeneration(c, "No landparam set");
|
||||
return;
|
||||
|
@ -3038,10 +3139,13 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
|
||||
if(!c->monst) c->stuntime = 0;
|
||||
|
||||
giantLandSwitch(c, d, from);
|
||||
bool big_first = ls::hv_structure();
|
||||
if(!big_first) giantLandSwitch(c, d, from);
|
||||
|
||||
if(d == min(reduced_barlev, 9)) moreBigStuff(c);
|
||||
|
||||
if(big_first) giantLandSwitch(c, d, from);
|
||||
|
||||
if(d == 7) repairLandgen(c);
|
||||
|
||||
// the number of tiles in the standard geometry has about 7553 digits!
|
||||
|
@ -3097,4 +3201,6 @@ EX void setdist(cell *c, int d, cell *from) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#undef hrand_monster
|
||||
|
||||
}
|
||||
|
|
324
landlock.cpp
324
landlock.cpp
|
@ -81,7 +81,7 @@ EX eLand firstland = laIce;
|
|||
EX eLand specialland = laIce;
|
||||
|
||||
#if HDR
|
||||
enum eLandStructure { lsNiceWalls, lsChaos, lsPatchedChaos, lsTotalChaos, lsChaosRW, lsWallChaos, lsSingle, lsNoWalls, lsGUARD };
|
||||
enum eLandStructure { lsNiceWalls, lsChaos, lsPatchedChaos, lsTotalChaos, lsChaosRW, lsWallChaos, lsSingle, lsNoWalls, lsHorodisks, lsVoronoi, lsLandscape, lsCrossWalls, lsVineWalls, lsCursedWalls, lsGUARD };
|
||||
#endif
|
||||
|
||||
EX eLandStructure land_structure;
|
||||
|
@ -90,14 +90,17 @@ EX namespace ls {
|
|||
|
||||
EX bool single() { return land_structure == lsSingle; }
|
||||
|
||||
EX bool any_chaos() { return among(land_structure, lsChaos, lsPatchedChaos, lsWallChaos, lsTotalChaos, lsChaosRW); }
|
||||
EX bool any_chaos() { return among(land_structure, lsChaos, lsPatchedChaos, lsWallChaos, lsTotalChaos, lsChaosRW, lsCrossWalls, lsVineWalls, lsCursedWalls, lsLandscape); }
|
||||
EX bool std_chaos() { return land_structure == lsChaos; }
|
||||
EX bool wall_chaos() { return land_structure == lsWallChaos; }
|
||||
EX bool wall_chaos() { return among(land_structure, lsWallChaos, lsCrossWalls, lsVineWalls, lsCursedWalls); }
|
||||
EX bool patched_chaos() { return land_structure == lsPatchedChaos; }
|
||||
|
||||
EX bool any_order() { return among(land_structure, lsNiceWalls, lsNoWalls); }
|
||||
EX bool any_order() { return among(land_structure, lsNiceWalls, lsNoWalls, lsHorodisks, lsVoronoi); }
|
||||
EX bool nice_walls() { return land_structure == lsNiceWalls; }
|
||||
EX bool no_walls() { return land_structure == lsNoWalls; }
|
||||
EX bool horodisk_structure() { return land_structure == lsHorodisks; }
|
||||
EX bool voronoi_structure() { return land_structure == lsVoronoi; }
|
||||
EX bool hv_structure() { return among(land_structure, lsHorodisks, lsVoronoi); }
|
||||
|
||||
EX bool any_nowall() { return no_walls() || std_chaos(); }
|
||||
EX bool any_wall() { return nice_walls() || wall_chaos(); }
|
||||
|
@ -107,11 +110,33 @@ EX int chaoticity() {
|
|||
if(land_structure == lsChaosRW) return 80;
|
||||
if(land_structure == lsPatchedChaos) return 60;
|
||||
if(land_structure == lsChaos) return 40;
|
||||
if(land_structure == lsLandscape) return 35;
|
||||
if(land_structure == lsWallChaos) return 30;
|
||||
if(land_structure == lsCrossWalls) return 32;
|
||||
if(land_structure == lsCursedWalls) return 34;
|
||||
if(land_structure == lsVoronoi) return 20;
|
||||
if(land_structure == lsSingle) return 0;
|
||||
return 10;
|
||||
}
|
||||
|
||||
/** a multiplier to make stuff more frequent in Wall Chaos and Cross Wall Chaos: treasure */
|
||||
EX int ls_mul() {
|
||||
if(land_structure == lsWallChaos) return 2;
|
||||
if(land_structure == lsCrossWalls) return 3;
|
||||
if(land_structure == lsVineWalls) return 3;
|
||||
if(land_structure == lsCursedWalls) return 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** a multiplier to make stuff more frequent in Wall Chaos and Cross Wall Chaos: even bigger */
|
||||
EX int ls_mul_big() {
|
||||
if(land_structure == lsWallChaos) return 5;
|
||||
if(land_structure == lsCrossWalls) return 10;
|
||||
if(land_structure == lsVineWalls) return 10;
|
||||
if(land_structure == lsCursedWalls) return 10;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EX bool tame_chaos() { return any_chaos() && chaoticity() < 35; }
|
||||
EX }
|
||||
|
||||
|
@ -131,8 +156,20 @@ EX string land_structure_name(bool which) {
|
|||
return XLAT("random-walk chaos");
|
||||
case lsSingle:
|
||||
return which ? XLAT("single land: ") + XLATN(linf[specialland].name) : XLAT("single land");
|
||||
case lsHorodisks:
|
||||
return XLAT("horodisks");
|
||||
case lsVoronoi:
|
||||
return XLAT("ideal Voronoi");
|
||||
case lsLandscape:
|
||||
return XLAT("landscape");
|
||||
case lsNoWalls:
|
||||
return XLAT("wall-less");
|
||||
case lsCrossWalls:
|
||||
return XLAT("excessive crossing walls");
|
||||
case lsVineWalls:
|
||||
return XLAT("regular walls");
|
||||
case lsCursedWalls:
|
||||
return XLAT("cursed walls");
|
||||
default:
|
||||
return "error structure";
|
||||
}
|
||||
|
@ -143,6 +180,8 @@ EX void fix_land_structure_choice() {
|
|||
if(land_structure != lsTotalChaos && land_structure != lsChaosRW)
|
||||
land_structure = lsSingle;
|
||||
}
|
||||
if(land_structure == lsLandscape && !geometry_supports_cdata())
|
||||
land_structure = lsChaosRW;
|
||||
if(tactic::on || princess::challenge)
|
||||
land_structure = lsSingle;
|
||||
if(yendor::on)
|
||||
|
@ -151,6 +190,14 @@ EX void fix_land_structure_choice() {
|
|||
land_structure = lsNoWalls;
|
||||
if(!nice_walls_available() && land_structure == lsWallChaos)
|
||||
land_structure = lsChaos;
|
||||
if(!nice_walls_available() && land_structure == lsCrossWalls)
|
||||
land_structure = lsChaos;
|
||||
if(land_structure == lsVineWalls && (geometry != gNormal || !BITRUNCATED))
|
||||
land_structure = lsNiceWalls;
|
||||
if(land_structure == lsCursedWalls && (geometry != gNormal || !BITRUNCATED))
|
||||
land_structure = lsNiceWalls;
|
||||
if(ls::hv_structure() && (!hyperbolic || bt::in() || quotient))
|
||||
land_structure = lsSingle;
|
||||
if(walls_not_implemented() && among(land_structure, lsChaos, lsNoWalls))
|
||||
land_structure = lsSingle;
|
||||
if(land_structure == lsPatchedChaos && !(stdeuc || nil || cryst || (euclid && WDIM == 3) || aperiodic))
|
||||
|
@ -174,6 +221,10 @@ EX int lands_for_hell() {
|
|||
return casual ? 40 : 9;
|
||||
}
|
||||
|
||||
EX int lands_for_cr3() {
|
||||
return casual ? 20 : 9;
|
||||
}
|
||||
|
||||
EX int variant_unlock_value() {
|
||||
return inv::on ? 75 : 30;
|
||||
}
|
||||
|
@ -191,6 +242,10 @@ EX bool landUnlocked(eLand l) {
|
|||
|
||||
if(princess::challenge) return among(l, laPalace, laPrincessQuest);
|
||||
|
||||
if(ls::any_chaos() && isCrossroads(l)) {
|
||||
return hyperstonesUnlocked();
|
||||
}
|
||||
|
||||
switch(l) {
|
||||
#define LAND(a,b,c,d,e,f,g) case c:
|
||||
#define REQ(x) x return true;
|
||||
|
@ -210,6 +265,8 @@ EX bool landUnlocked(eLand l) {
|
|||
#define ACCONLY2(x,y)
|
||||
#define ACCONLY3(x,y,z)
|
||||
#define ACCONLYF(x)
|
||||
#define IFINGAME(land, ok, fallback) if(isLandIngame(land)) { ok } else { fallback }
|
||||
#define INMODE(x) if(x) return true;
|
||||
#include "content.cpp"
|
||||
|
||||
case landtypes: return false;
|
||||
|
@ -231,6 +288,10 @@ EX void countHyperstoneQuest(int& i1, int& i2) {
|
|||
i1 = 0; i2 = 0;
|
||||
generateLandList(isLandIngame);
|
||||
for(eLand l: landlist) {
|
||||
// no treasure
|
||||
if(l == laCA) continue;
|
||||
// same treasure, so count only once
|
||||
if(l == laMirrorOld && isLandIngame(laMirror)) continue;
|
||||
eItem ttype = treasureType(l);
|
||||
if(!required_for_hyperstones(ttype)) continue;
|
||||
i2++; if(items[ttype] >= R10) i1++;
|
||||
|
@ -252,6 +313,20 @@ EX int isRandland(eLand l) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
EX int voronoi_sea_category(eLand l) {
|
||||
if(l == laRlyeh) return rlyehComplete() ? 0 : 2;
|
||||
if(among(l, laOcean, laWarpCoast, laLivefjord, laDocks)) return 1;
|
||||
if(among(l, laWhirlpool, laKraken, laWarpSea, laCaribbean)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EX bool voronoi_sea_incompatible(eLand l1, eLand l2) {
|
||||
int c1 = voronoi_sea_category(l1);
|
||||
int c2 = voronoi_sea_category(l2);
|
||||
if(c1+c2 == 2 && c1 != c2) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
EX bool incompatible1(eLand l1, eLand l2) {
|
||||
if(isCrossroads(l1) && isCrossroads(l2)) return true;
|
||||
if(l1 == laJungle && l2 == laMotion) return true;
|
||||
|
@ -348,7 +423,7 @@ EX eLand pickluck(eLand l1, eLand l2) {
|
|||
} */
|
||||
|
||||
EX eLand getNewSealand(eLand old) {
|
||||
while(true) {
|
||||
for(int it=0; it<100; it++) {
|
||||
eLand p = pick(laOcean, pick(laCaribbean, laLivefjord, laWarpSea, laKraken, laDocks));
|
||||
if(p == laKraken && !landUnlocked(p)) continue;
|
||||
if(p == laKraken && peace::on) continue;
|
||||
|
@ -357,6 +432,7 @@ EX eLand getNewSealand(eLand old) {
|
|||
if(!isLandIngame(p)) continue;
|
||||
return p;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
EX bool createOnSea(eLand old) {
|
||||
|
@ -523,7 +599,8 @@ EX eLand getNewLand(eLand old) {
|
|||
// the intermediate lands
|
||||
if(all_unlocked || gold() >= R30) {
|
||||
tab[cnt++] = laCrossroads;
|
||||
tab[cnt++] = geometry ? laMirrorOld : laMirror;
|
||||
tab[cnt++] = laMirrorOld;
|
||||
tab[cnt++] = laMirror;
|
||||
tab[cnt++] = laOcean;
|
||||
tab[cnt++] = laLivefjord;
|
||||
if(all_unlocked || kills[moVizier]) tab[cnt++] = laEmerald;
|
||||
|
@ -532,6 +609,11 @@ EX eLand getNewLand(eLand old) {
|
|||
tab[cnt++] = laDocks;
|
||||
}
|
||||
|
||||
tab[cnt++] = laHalloween;
|
||||
tab[cnt++] = laWildWest;
|
||||
tab[cnt++] = laAsteroids;
|
||||
tab[cnt++] = laCA;
|
||||
|
||||
// the advanced lands
|
||||
if(all_unlocked || gold() >= R60) {
|
||||
tab[cnt++] = laCrossroads;
|
||||
|
@ -539,7 +621,7 @@ EX eLand getNewLand(eLand old) {
|
|||
if(all_unlocked || rlyehComplete()) tab[cnt++] = laRlyeh;
|
||||
else if(ls::std_chaos() && (old == laWarpCoast || old == laLivefjord || old == laOcean))
|
||||
tab[cnt++] = laRlyeh;
|
||||
if((all_unlocked || items[itStatue] >= U5) && ls::std_chaos())
|
||||
if((all_unlocked || items[itStatue] >= U5) && (ls::std_chaos() || ls::horodisk_structure()))
|
||||
tab[cnt++] = laTemple;
|
||||
if(old == laCrossroads || old == laCrossroads2) tab[cnt++] = laOcean;
|
||||
if(old == laOcean) tab[cnt++] = laCrossroads;
|
||||
|
@ -555,11 +637,30 @@ EX eLand getNewLand(eLand old) {
|
|||
tab[cnt++] = laSnakeNest;
|
||||
}
|
||||
|
||||
if(ls::horodisk_structure()) {
|
||||
if(gold() >= R30) {
|
||||
tab[cnt++] = laCaribbean;
|
||||
tab[cnt++] = laKraken;
|
||||
tab[cnt++] = laWhirlpool;
|
||||
}
|
||||
if(gold() >= R60) {
|
||||
tab[cnt++] = laRlyeh;
|
||||
if(landUnlocked(laTemple)) tab[cnt++] = laTemple;
|
||||
}
|
||||
if(items[itBone] >= 10)
|
||||
tab[cnt++] = laHaunted;
|
||||
}
|
||||
|
||||
if(ls::hv_structure() && landUnlocked(laMountain)) tab[cnt++] = laMountain;
|
||||
if(ls::hv_structure() && landUnlocked(laClearing)) tab[cnt++] = laClearing;
|
||||
if(ls::voronoi_structure() && landUnlocked(laRlyeh) && !rlyehComplete()) LIKELY tab[cnt++] = laRlyeh;
|
||||
if(ls::hv_structure() && landUnlocked(laTemple)) tab[cnt++] = laTemple;
|
||||
|
||||
if(landUnlocked(laTrollheim)) {
|
||||
if(isTrollLand(old)) LIKELY tab[cnt++] = laTrollheim;
|
||||
if(old == laTrollheim) for(int i=0; i<landtypes; i++) {
|
||||
eLand l2 = eLand(i);
|
||||
if(isTrollLand(l2)) LIKELY tab[cnt++] = l2;
|
||||
if(isTrollLand(l2) && landUnlocked(l2)) LIKELY tab[cnt++] = l2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,16 +677,43 @@ EX eLand getNewLand(eLand old) {
|
|||
if(old == laOcean) tab[cnt++] = laCrossroads2;
|
||||
}
|
||||
|
||||
eLand n = old;
|
||||
while(incompatible(n, old) || !isLandIngame(n)) {
|
||||
n = tab[hrand(cnt)];
|
||||
if(weirdhyperbolic && specialland == laCrossroads4 && isCrossroads(n))
|
||||
n = laCrossroads4;
|
||||
if(ls::horodisk_structure() && tortoise::seek()) LIKELY tab[cnt++] = laTortoise;
|
||||
|
||||
int idx = 0;
|
||||
while (idx < cnt) {
|
||||
eLand n = tab[idx];
|
||||
if (incompatible(n, old) || !isLandIngame(n))
|
||||
tab[idx] = tab[--cnt];
|
||||
else
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (!cnt) {
|
||||
addMessage("No eligible land candidates!");
|
||||
return old;
|
||||
}
|
||||
|
||||
eLand n = tab[hrand(cnt)];
|
||||
if (weirdhyperbolic && specialland == laCrossroads4 && isCrossroads(n))
|
||||
n = laCrossroads4;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
EX eLand getNewLand2(vector<eLand> olds) {
|
||||
for(int i=0;; i++) {
|
||||
auto old = hrand_elt(olds);
|
||||
eLand l = getNewLand(old);
|
||||
// how bad it is
|
||||
int err = 0;
|
||||
for(auto o: olds) if(l == o) err += 2000;
|
||||
for(auto o: olds) if(incompatible(l, o)) err += 1000;
|
||||
for(auto o: olds) if(voronoi_sea_incompatible(l, o)) err += 100;
|
||||
// we still allow bad choices if we cannot obtain a good one
|
||||
if(err <= i) return l;
|
||||
}
|
||||
}
|
||||
|
||||
EX vector<eLand> land_over = {
|
||||
laIce, laCaves, laDesert, laHunting, laMotion, laJungle, laAlchemist,
|
||||
laCrossroads,
|
||||
|
@ -619,13 +747,13 @@ template<class T> void generateLandList(T t) {
|
|||
|
||||
#if HDR
|
||||
namespace lv {
|
||||
static const flagtype appears_in_geom_exp = 1;
|
||||
static const flagtype display_error_message = 2;
|
||||
static const flagtype appears_in_full = 4;
|
||||
static const flagtype appears_in_ptm = 8;
|
||||
static const flagtype display_in_help = 16;
|
||||
static const flagtype one_and_half = 32;
|
||||
static const flagtype switch_to_single = 64;
|
||||
static constexpr flagtype appears_in_geom_exp = 1;
|
||||
static constexpr flagtype display_error_message = 2;
|
||||
static constexpr flagtype appears_in_full = 4;
|
||||
static constexpr flagtype appears_in_ptm = 8;
|
||||
static constexpr flagtype display_in_help = 16;
|
||||
static constexpr flagtype one_and_half = 32;
|
||||
static constexpr flagtype switch_to_single = 64;
|
||||
}
|
||||
|
||||
struct land_validity_t {
|
||||
|
@ -648,14 +776,26 @@ EX eLand getLandForList(cell *c) {
|
|||
return l;
|
||||
}
|
||||
|
||||
EX bool use_custom_land_list;
|
||||
EX array<bool, landtypes> custom_land_list;
|
||||
EX array<int, landtypes> custom_land_treasure;
|
||||
EX array<int, landtypes> custom_land_difficulty;
|
||||
EX array<int, landtypes> custom_land_wandering;
|
||||
|
||||
EX bool isLandIngame(eLand l) {
|
||||
if(isElemental(l)) l = laElementalWall;
|
||||
if(use_custom_land_list) return custom_land_list[l];
|
||||
if(dual::state == 2 && !dual::check_side(l)) return false;
|
||||
if((eubinary || sol) && isCyclic(l) && l != specialland) return false;
|
||||
if(l == laCamelot && hyperbolic && WDIM == 3) return false;
|
||||
return land_validity(l).flags & lv::appears_in_full;
|
||||
}
|
||||
|
||||
EX bool landUnlockedIngame(eLand l) {
|
||||
if(!peace::on && !landUnlocked(l)) return false;
|
||||
return isLandIngame(l);
|
||||
}
|
||||
|
||||
namespace lv {
|
||||
|
||||
flagtype q0 = lv::display_error_message | lv::display_in_help | lv::appears_in_geom_exp;
|
||||
|
@ -681,6 +821,7 @@ namespace lv {
|
|||
land_validity_t out_of_theme = { 3, qm2 &~ lv::appears_in_full, "Out of theme for the full game."};
|
||||
land_validity_t no_game = { 2, q2 &~ lv::appears_in_full, "No game here."};
|
||||
land_validity_t not_in_chaos = { 0, q0, "Does not work in chaos mode."};
|
||||
land_validity_t not_in_landscape = { 0, q0, "Does not work in landscape mode."};
|
||||
land_validity_t not_in_full_game = {2, qm2 &~ lv::appears_in_full, "Not in the full game."};
|
||||
land_validity_t not_in_full_game3 = {3, qm2 &~ lv::appears_in_full, "Not in the full game."};
|
||||
land_validity_t special_chaos = { 2, qm2, "Special construction in the Chaos mode." };
|
||||
|
@ -722,6 +863,7 @@ namespace lv {
|
|||
land_validity_t not_in_shmup = {0, q0, "This land is not available in the shmup mode."};
|
||||
land_validity_t not_in_multi = {0, q0, "This land is not available in multiplayer."};
|
||||
land_validity_t single_only = {2, q0 | switch_to_single, "Available in single land mode only." };
|
||||
land_validity_t not_in_hv = { 0, q0, "Does not work in horodisk/Voronoi mode."};
|
||||
}
|
||||
|
||||
// old Daily Challenges should keep their validity forever
|
||||
|
@ -737,6 +879,132 @@ EX const int cursed_when = 386;
|
|||
|
||||
EX const int walls_when = 388;
|
||||
|
||||
EX void mark_tamper() { cheater++; }
|
||||
|
||||
EX void customize_land_in_list(eLand l) {
|
||||
cmode = sm::SIDE | sm::MAYDARK; gamescreen();
|
||||
|
||||
dialog::init(XLATN(linf[l].name), linf[l].color);
|
||||
|
||||
help = generateHelpForLand(l);
|
||||
addHelpWithTitle();
|
||||
|
||||
dialog::addBreak(100);
|
||||
|
||||
dialog::addBoolItem(XLAT("land in game"), custom_land_list[l], 'a');
|
||||
dialog::add_action([l] {
|
||||
custom_land_list[l] = !custom_land_list[l];
|
||||
cheater++;
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("treasure rate"), its(custom_land_treasure[l]), 't');
|
||||
dialog::add_action([l] {
|
||||
dialog::editNumber(custom_land_treasure[l], 0, 1000, 10, 100, XLAT("treasure rate in %the1", linf[l].name), "");
|
||||
dialog::get_ne().reaction = mark_tamper;
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("difficulty"), its(custom_land_difficulty[l]), 'd');
|
||||
dialog::add_action([l] {
|
||||
dialog::editNumber(custom_land_difficulty[l], 0, 1000, 10, 100, XLAT("difficulty of %the1", linf[l].name), "");
|
||||
dialog::get_ne().reaction = mark_tamper;
|
||||
});
|
||||
|
||||
dialog::addSelItem(XLAT("wandering"), its(custom_land_wandering[l]), 'w');
|
||||
dialog::add_action([l] {
|
||||
dialog::editNumber(custom_land_wandering[l], 0, 1000, 10, 100, XLAT("difficulty of %the1", linf[l].name), "");
|
||||
dialog::get_ne().reaction = mark_tamper;
|
||||
});
|
||||
|
||||
gen_landvisited();
|
||||
if(landvisited[l]) {
|
||||
dialog::addItem(XLAT("test"), 'T');
|
||||
dialog::add_action([l] {
|
||||
stop_game(); firstland = specialland = l; start_game();
|
||||
});
|
||||
}
|
||||
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
EX void customize_land_list() {
|
||||
cmode = sm::SIDE | sm::MAYDARK; gamescreen();
|
||||
dialog::init(XLAT("custom land list"));
|
||||
if(dialog::infix != "") mouseovers = dialog::infix;
|
||||
|
||||
generateLandList([] (eLand l) {
|
||||
if(!use_custom_land_list) {
|
||||
custom_land_list[l] = isLandIngame(l);
|
||||
custom_land_treasure[l] = 100;
|
||||
custom_land_difficulty[l] = 100;
|
||||
custom_land_wandering[l] = 100;
|
||||
}
|
||||
if(dialog::infix != "" && !dialog::hasInfix(linf[l].name)) return false;
|
||||
if(l == laCanvas) return true;
|
||||
return !!(land_validity(l).flags & lv::appears_in_geom_exp);
|
||||
});
|
||||
stable_sort(landlist.begin(), landlist.end(), [] (eLand l1, eLand l2) { return land_validity(l1).quality_level > land_validity(l2).quality_level; });
|
||||
|
||||
dialog::start_list(900, 900, '1');
|
||||
for(eLand l: landlist) {
|
||||
dialog::addBoolItem(XLAT1(linf[l].name), custom_land_list[l], dialog::list_fake_key++);
|
||||
string s;
|
||||
if(custom_land_treasure[l] != 100) s += "$" + its(custom_land_treasure[l]) + " ";
|
||||
if(custom_land_difficulty[l] != 100) s += "!" + its(custom_land_difficulty[l]) + " ";
|
||||
if(custom_land_wandering[l] != 100) s += "^" + its(custom_land_wandering[l]) + " ";
|
||||
if(s != "") dialog::lastItem().value = s;
|
||||
dialog::add_action_confirmed([l] {
|
||||
if(!use_custom_land_list) {
|
||||
stop_game();
|
||||
use_custom_land_list = true;
|
||||
start_game();
|
||||
}
|
||||
pushScreen([l] { customize_land_in_list(l); });
|
||||
});
|
||||
}
|
||||
dialog::end_list();
|
||||
|
||||
dialog::addInfo(XLAT("press letters to search"));
|
||||
dialog::addBoolItem("custom land list mode", use_custom_land_list, 'U');
|
||||
dialog::add_action_confirmed([] {
|
||||
stop_game();
|
||||
use_custom_land_list = !use_custom_land_list;
|
||||
start_game();
|
||||
});
|
||||
|
||||
if(use_custom_land_list) {
|
||||
dialog::addItem("disable/enable all", 'D');
|
||||
dialog::add_action([] {
|
||||
int qty = 0;
|
||||
for(int i=0; i<landtypes; i++) if(custom_land_list[i]) qty++;
|
||||
for(int i=0; i<landtypes; i++) custom_land_list[i] = !qty;
|
||||
});
|
||||
}
|
||||
else dialog::addBreak(100);
|
||||
|
||||
dialog::addHelp();
|
||||
dialog::add_action([] {
|
||||
gotoHelp(XLAT(
|
||||
"In this mode, you can choose the lands you want to be in game. You can also customize their treasure rate and difficulty.\n\n"
|
||||
"While the game automatically selects a list of lands by default, "
|
||||
"based on whether it thinks they work well in the currently selected tiling, "
|
||||
"you might not agree with this selection.\n\n"
|
||||
"Note that, often, lands are enabled or disabled for a GOOD reason! Use at your own risk.\n\n"
|
||||
"Just click on a land to configure it. If you are not in the custom land list mode, "
|
||||
"this will restart the game. You can change the settings during a custom game, but it counts as a cheat."
|
||||
));
|
||||
});
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(dialog::editInfix(uni)) dialog::list_skip = 0;
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
// check if the given land should appear in lists
|
||||
EX land_validity_t& land_validity(eLand l) {
|
||||
|
||||
|
@ -845,6 +1113,10 @@ EX land_validity_t& land_validity(eLand l) {
|
|||
if(l == laMirrorOld && !shmup::on) return not_implemented;
|
||||
}
|
||||
|
||||
if(ls::hv_structure() && among(l, laDungeon, laEndorian, laBrownian, laPrincessQuest)) return not_in_hv;
|
||||
if(ls::voronoi_structure() && among(l, laPrairie, laCamelot, laWhirlpool, laClearing, laHaunted, laWestWall)) return not_in_hv;
|
||||
if(ls::horodisk_structure() && l != laCrossroads && isCrossroads(l)) return not_in_hv;
|
||||
|
||||
if(l == laBrownian) {
|
||||
if(quotient || !hyperbolic || cryst) return dont_work;
|
||||
}
|
||||
|
@ -926,12 +1198,14 @@ EX land_validity_t& land_validity(eLand l) {
|
|||
if(l == laWhirlwind && hyperbolic_not37)
|
||||
return pattern_incompatibility;
|
||||
|
||||
bool better_mirror = !geometry && STDVAR && !ls::hv_structure() && !among(land_structure, lsTotalChaos, lsPatchedChaos, lsLandscape, lsVineWalls);
|
||||
|
||||
// available only in non-standard geometries
|
||||
if(l == laMirrorOld && !geometry && STDVAR)
|
||||
if(l == laMirrorOld && better_mirror)
|
||||
return better_version_exists;
|
||||
|
||||
// available only in standard geometry
|
||||
if(l == laMirror && (geometry || NONSTDVAR))
|
||||
if(l == laMirror && !better_mirror)
|
||||
return not_implemented;
|
||||
|
||||
// Halloween needs bounded world (can be big bounded)
|
||||
|
@ -945,6 +1219,9 @@ EX land_validity_t& land_validity(eLand l) {
|
|||
if(l == laHaunted && ls::std_chaos())
|
||||
return not_in_chaos;
|
||||
|
||||
if(among(l, laHaunted, laElementalWall) && land_structure == lsLandscape)
|
||||
return not_in_landscape;
|
||||
|
||||
// standard, non-PTM specific
|
||||
if(l == laCrossroads5 && old_daily_id < 999 && tactic::on)
|
||||
return not_in_ptm;
|
||||
|
@ -1061,9 +1338,6 @@ EX land_validity_t& land_validity(eLand l) {
|
|||
if(INVERSE) return not_implemented;
|
||||
}
|
||||
|
||||
if(ls::any_chaos() && isCrossroads(l))
|
||||
return not_in_chaos;
|
||||
|
||||
// this pattern does not work on elliptic and small spheres
|
||||
if((l == laBlizzard || l == laVolcano) && elliptic && S7 < 5 && !arcm::in())
|
||||
return not_enough_space;
|
||||
|
|
675
language-cz.cpp
675
language-cz.cpp
|
@ -2145,7 +2145,7 @@ S("Mighty warriors from the Fjord, who can use boats.",
|
|||
N("Water Elemental", GEN_M, "Elementál Vody", "Elementálové Vody", "Elementála Vody", "Elementálem Vody")
|
||||
S("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.",
|
||||
"Kamkoli se vydá tato mocná bytost, tam se Živoucí fjord potápí pod vodu, všechny čluny kromě magických "
|
||||
"jsou zničeny a veškerý oheň je uhašen.\n\n"
|
||||
"Na Elementála Vody můžeš zaútočit z vody, aniž by ses okamžitě utopil; to je speciální případ.")
|
||||
|
@ -7935,6 +7935,7 @@ Cell("{3,3,3} 5") Cell("{4,3,3} 8") Cell("{3,3,4} 16") Cell("{3,4,3} 24") Cell("
|
|||
S(x " field quotient space", x " prostor s tělesovým kvocientem")
|
||||
|
||||
Honeycomb("{5,3,4}") Honeycomb("{4,3,5}") Honeycomb("{3,3,6}") Honeycomb("{3,4,4}") Honeycomb("{5,3,5}") Honeycomb("{5,3,6}") Honeycomb("{4,3,6}") Honeycomb("{5,3,6}")
|
||||
Honeycomb("{3,4,5}") Honeycomb("{3,5,3}") Honeycomb("{3,5,4}") Honeycomb("{3,5,5}")
|
||||
#undef Honeycomb
|
||||
|
||||
// new or previously untranslated options
|
||||
|
@ -8425,7 +8426,7 @@ S("stretched hyperbolic", "natažené hyperbolické")
|
|||
S("stretched Solv", "natažený Solv")
|
||||
|
||||
S("{3,∞} (infinite triangles)", "{3,∞} (nekonečné trojúhelníky)")
|
||||
S("{4,∞} (infinite triangles)", "{4,∞} (nekonečné čtverce)")
|
||||
S("{4,∞} (infinite squares)", "{4,∞} (nekonečné čtverce)")
|
||||
S("{3/4,∞} (infinite triangles and squares)", "nekonečné trojúhelníky a čtverce")
|
||||
|
||||
S("4D crystal in H3", "4D krystal v H3")
|
||||
|
@ -9036,19 +9037,20 @@ S("display only chessboard white", "zobrazit pouze bílá políčka šachovnice"
|
|||
S("display only chessboard black", "zobrazit pouze černá políčka šachovnice")
|
||||
|
||||
S(
|
||||
"This lets you specify the color pattern as a function of the cell. "
|
||||
"This lets you specify the color pattern as a function of the cell.\n",
|
||||
|
||||
"Zde můžeš specifikovat barevný vzor jako funkci políčka.\n")
|
||||
|
||||
S(
|
||||
"Available parameters:\n\n"
|
||||
"x, y, z (hyperboloid/sphere/plane coordinates in non-crystal geometries)\n"
|
||||
"ex, ey, ez (in Euclidean geometries)\n"
|
||||
"x0, x1, x2... (crystal geometry only)\n"
|
||||
"0 is black, 1 is white, rgb(1,0,0) is red, ifp(p-2,1,0) is blue (p=1 for red, 2 for green, 3 for blue).",
|
||||
"x0, x1, x2... (crystal geometry only)\n",
|
||||
|
||||
"Zde můžeš specifikovat barevný vzor jako funkci políčka. "
|
||||
"Dostupné parametry:\n\n"
|
||||
"x, y, z (souřadnice hyperboloidu/koule/roviny v nekrystalových geometriích)\n"
|
||||
"ex, ey, ez (v eukleidovských geometriích)\n"
|
||||
"x0, x1, x2... (pouze v krystalové geometrii)\n"
|
||||
"0 je černá, 1 bílá, rbg(1,0,0) červená, ifp(p-2,1,0) modrá (p=1 pro červenou, 2 pro zelenou, 3 pro modrou)."
|
||||
)
|
||||
|
||||
S(
|
||||
|
@ -9692,3 +9694,662 @@ S(
|
|||
"* na Prérii poté, co ji odemkneš (%3 pokladů)\n\n"
|
||||
)
|
||||
|
||||
// 13.0
|
||||
|
||||
// gameplay
|
||||
//==========
|
||||
|
||||
// these were missing somehow
|
||||
|
||||
N("Palace Quest", GEN_F, "Palácová mise", "Palácové mise", "Palácovou misi", "na Palácové misi")
|
||||
N("Pike", GEN_F, "Štika", "Štiky", "Štiku", "Štikou")
|
||||
|
||||
// crossbow
|
||||
|
||||
S("The warped space distracts you from reloading while staying in place!",
|
||||
"Pokřivený prostor ti brání nabíjet na místě!")
|
||||
S("Fire!", "Hoří!")
|
||||
S("(shooting while unstable -- no turn passes)", "(střelba z nestabilní polohy -- bez spotřeby kola)")
|
||||
S("Stab them by shooting around them.", "(Bodni je tím, že střelíš kolem nich.)")
|
||||
S("You are too weakened to attack %the1!", "Jsi příliš slab%ý0 na útok proti %a2!")
|
||||
S("You cannot attack your own mount!", "Nemůžeš útočit na vlastní jízdní zvíře!")
|
||||
S("A magical shield protects %the1!", "%a1 chrání magický štít!")
|
||||
S("You have no melee weapon!", "Nemáš žádnou zbraň pro boj na blízko!")
|
||||
S("Your crossbow is still reloading!", "Tvá kuše se stále ještě nabíjí!")
|
||||
S("Trying to fire.", "Pokoušíš se vystřelit.")
|
||||
S(" (turns to reload: %1)", " (počet kol do nabití: %1)")
|
||||
S(" (fire mode on / turns to reload: %1)", " (palebný mód / počet kol do nabití: %1)")
|
||||
S(" (fire mode on)", " (palebný mód)")
|
||||
S(" (click to fire)", " (střílej kliknutím)")
|
||||
S("You fire an angry glance at your enemies.", "Věnuješ nepřátelům ošklivý pohled.")
|
||||
S("Note: cannot fire again yet. Turns to reload: %1.", "Poznámka: ještě nemůžeš střílet. Počet kol do nabití: %1")
|
||||
S("Fire crossbow! Click to aim, click again to confirm.", "Vystřel! Klikni pro zamíření, a znovu pro potvrzení.")
|
||||
S("Fire mode disabled.", "Palebný mód vypnut.")
|
||||
S("Firing cancelled.", "Střelba zrušena.")
|
||||
S("Cannot fire again yet. Turns to reload: %1.", "Ještě nemůžeš znovu střílet. Počet kol do nabití: %1")
|
||||
S("No way to hit this place.", "To se nedá zasáhnout.")
|
||||
S("Shooting impossible.", "Nemůžeš střílet.")
|
||||
S("%The1 is enraged!", "%1 se rozzuři%l1!")
|
||||
S("weapon selection", "výběr zbraně")
|
||||
S("Cannot hit anything by shooting this direction!", "Tímhle směrem nemůžeš nic trefit!")
|
||||
S("Welcome to HyperRanger!", "Vítej v HyperRanger!")
|
||||
S("bow color", "barva kuše")
|
||||
S("bowstring color", "barva tětivy")
|
||||
S("%The1 alarms other dogs as it dies!", "Umírající %1 burcuje ostatní!")
|
||||
S("crossbow straight line style", "styl střelných čar")
|
||||
S("bull line", "býčí čára")
|
||||
S("Can go in either direction on odd shapes. 3 turns to reload.", "Na lichých tvarech můžeš jít kterýmkoli směrem. Nabíjení trvá 3 kola.")
|
||||
S("Graph geodesic: any sequence of tiles is OK as long as there are no shortcuts. 4 turns to reload.", "Grafová geodetika: jakákoli sekvence políček je v pořáídku, pokud neexistují zkratky. Nabíjení trvá 4 kola.")
|
||||
S("geometric", "geometrické čáry")
|
||||
S("Approximations of geometric straight lines.", "Aproximace geometrických přímek")
|
||||
S("bump to shoot", "střílej naběhnutím")
|
||||
S("mouse auto-fire mode", "mód automatické střelby myší")
|
||||
S("explicit", "explicitní")
|
||||
S("You need to click crossbow or be close to fire.", "Na výstřel musíš kliknout na kuši nebo být blízko.")
|
||||
S("priority", "prioritní")
|
||||
S("Click on a faraway monster to fire if possible, or move if not.", "Klikni na vzdáleného netvora, abys vystřelil, je-li to možné, nebo se pohnul, pokud není.")
|
||||
S("Clicking on a faraway monster always means an attempt to fire.", "Kliknutí na vzdáleného netvora vždy znamená pokus o výstřel.")
|
||||
S("blade", "čepel")
|
||||
S("Standard Rogue weapon. Bump into a monster to hit. Most monsters attack you the same way.",
|
||||
"Standardní zbraň. Naběhni do netvora, abys na něj zaútočil. Většina netvorů na tebe útočí stejným způsobem.")
|
||||
S("crossbow", "kuše")
|
||||
S("Hits all monsters in a straight line, but slow to reload. Press 'f' or click the crossbow icon to target.",
|
||||
"Zasáhne všechny netvory v přímé linii, chvíli však trvá, než se znovu nabije. Cíluj klávesou 'f' nebo kliknutím na ikonu kuše.")
|
||||
|
||||
// 'click to use orb' errors
|
||||
|
||||
S("You have no ranged Orbs!", "Nemáš žádné dálkové Sféry!")
|
||||
S("Strong wind can only take you to a specific place!", "Silný vítr tě může odnést pouze na určité místo!")
|
||||
S("%The1 can only be used on items!", "%1 se dá použít pouze na předměty!")
|
||||
S("Nothing to blow here!", "Tady není co odfouknout!")
|
||||
S("Cannot be used in multiplayer", "Toto nelze použít v módu pro více hráčů")
|
||||
S("You cannot grow on yourself!", "Nemůžeš růst na sobě!")
|
||||
S("Cannot attack there!", "Tam nemůžeš útočit!")
|
||||
S("Cannot grow there!", "Tam nemůžeš růst!")
|
||||
S("Cannot grow against gravity!", "Nemůžeš růst proti gravitaci!")
|
||||
S("You cannot grow there from any adjacent cell!", "Tam nemůžeš vyrůst z žádného sousedního políčka!")
|
||||
S("Cannot vault that far!", "Tak daleko nedoskočíš!")
|
||||
S("ERROR: No common neighbor to vault through!", "CHYBA: Není žádný společné sousední políčko, přes které bys mohl přeskočit!")
|
||||
S("Can only vault in a roughly straight line!", "Skoky lze provádět pouze (zhruba) přímo!")
|
||||
S("Nothing to vault over!", "Není přes co přeskočit!")
|
||||
S("Cannot pass through %the1 while vaulting!", "Při přeskoku nemůžeš projít skrz %a1!")
|
||||
S("Cannot vault onto %the1!", "Nemůžeš skočit na %a1!")
|
||||
S("Cannot vault to %the1!", "Nemůžeš skočit do %a1!")
|
||||
S("Cannot attack %the1 while vaulting!", "Nemůžeš útočit během skoku!")
|
||||
S("Cannot jump that far!", "Tak daleko nedoskočíš!")
|
||||
S("Cannot jump onto %the1!", "Nemůžeš vyskočit na %a1!")
|
||||
S("Cannot phase that far!", "Nemůžeš fázovat tak daleko!")
|
||||
S("Cannot phase onto %the1!", "Nemůžeš fázovat na %a1!")
|
||||
S("Cannot phase to %the1!", "Nemůžeš fázovat do %a1!")
|
||||
S("Nothing to phase through!", "Není tu nic, skrz co by se dalo fázovat!")
|
||||
S("Can only use %the1 on a monster!", "%a1 můžeš použít pouze na netvory!")
|
||||
S("%The1 is immune to %the2!", "%1 je proti %a2 imunní!")
|
||||
S("%The1 can only be used on monsters.", "%1 se dá používat pouze na netvory.")
|
||||
S("%The1 cannot be used on big monsters.", "%1 se nedá používat na velké netvory.")
|
||||
S("%The1 cannot be used on %the2.", "%1 se nedá použít na %abl2.")
|
||||
S("%The1 is already stunned!", "%1 už je omráčen%ý1!")
|
||||
|
||||
// multiplayer settings
|
||||
|
||||
S("friendly fire", "přátelská palba")
|
||||
S("friendly fire off -- achievements disabled", "přátelská palba vypnutá -- achievementy také")
|
||||
|
||||
S("player vs player", "hráč proti hráči")
|
||||
S("PvP available only in shmup", "mód 'hráč proti hráči' je dostupný pouze ve střílečkovém módu")
|
||||
S("PvP grants infinite lives -- achievements disabled", "v módu 'hráč proti hráči' máš nekonečné životy -- achievementy jsou vypnuté")
|
||||
|
||||
S("split screen mode", "mód rozdělené obrazovky")
|
||||
S("achievements disabled in split screen", "mód rozdělené obrazovky -- achievementy jsou vypnuté")
|
||||
|
||||
S("auto-adjust dual-focus projections", "automatické přizpůsobení projekcí s dvojím zaostřením")
|
||||
S("autoscale dual focus", "automatické škálování dvojího zaostření")
|
||||
|
||||
S("self hits", "útoky do sebe")
|
||||
|
||||
S(" (%1 $$$, %2 kills, %3 deaths)", "(%1 $$$, zabitých nepřátel: %2, smrtí: %3)")
|
||||
S(" (%1 pkills)", " (%1 zabitých hráčů)")
|
||||
S(" (%1 self)", " (%1 sebe)")
|
||||
|
||||
// racing mode
|
||||
|
||||
S("play on an official track", "hraj na oficiální dráze")
|
||||
S("generate a random track", "vygeneruj náhodnou dráhu")
|
||||
S("Too many pauses!", "Příliš mnoho pauz!")
|
||||
S("Pauses: %1 of %2 allowed", "Pauzy: %1 z %2 povolených")
|
||||
|
||||
// new land structures
|
||||
|
||||
S("horodisks", "horodisky")
|
||||
S("land size in horodisk mode", "velikost krajů v horodiskovém módu")
|
||||
S("Set this to -2 to get perfect horodisks. Smaller values yield less dense horodisks, and larger values might produce horodisks with errors or crashing into each other.",
|
||||
"Dokonalé horodisky získáš na hodnotě -2. Nižší hodnoty vedou k menší hustotě horodisků; vyšší hodnoty mohou vést k horodiskům, které obsahují chyby nebo do sebe narážejí.")
|
||||
|
||||
S("ideal Voronoi", "ideální Voronoi")
|
||||
S("display Voronoi tie debug values", "zobrazit debugové hodnoty pro Voronoiova políčka")
|
||||
|
||||
S("land size in randomwalk mode", "velikost krajů v módu náhodné procházky")
|
||||
S("The average size of a land in randomwalk mode.", "Průměrná velikost kraje v módu náhodné procházky.")
|
||||
|
||||
S("this starting land is not eligible for achievements", "s tímto počátečním krajem není možné získat achievementy")
|
||||
S("eligible for most achievements", "lze získat většinu achievementů")
|
||||
S("eligible for Chaos mode achievements", "lze získat achievementy v chaotickém módu")
|
||||
S("eligible for special achievements", "lze získat speciální achievementy")
|
||||
S("not eligible for achievements", "nelze získat achievementy")
|
||||
S("(but the cheat mode is on)", "(ale je zapnutý cheat mód)")
|
||||
S("(but the casual mode is on)", "(ale je zapnutý neformální mód)")
|
||||
|
||||
// other gameplay
|
||||
|
||||
S("There should be a Palace somewhere nearby...", "Někde tady by měl být Palác...")
|
||||
S("The following Orbs act an extra lives in the shmup mode:", "Následující Sféry fungují ve střílečkovém módu jako životy navíc:")
|
||||
S("\n\nThis Orb is triggered on your first direct melee attack or illegal move.", /* 'direct melee' added to an earlier version of this message */
|
||||
"\n\nTato Sféra se spustí při tvém prvním přímém útoku nablízko nebo ilegálním tahu.")
|
||||
S("\n\nOrb unlocked: %1", "\n\nSféra odemčena: %1")
|
||||
S("toggle numerical display", "přepnutí číselného displeje") // in help
|
||||
S("display mine counts numerically", "zobrazuj počet min číslem")
|
||||
S("Accessible only from %the1, %2, or %3.\n", "Kraj je přístupný pouze z: %1, %2, %3.\n")
|
||||
S("Cannot switch places with %the1!", "Nemůžeš si vyměnit místo s %abl1!")
|
||||
S("d%1 rolled %2", "d%1 hodila %2")
|
||||
|
||||
S("orb display mode", "mód zobrazení Sfér")
|
||||
S("icons", "ikony")
|
||||
|
||||
// menu & configuration
|
||||
//======================
|
||||
|
||||
S("default: ", "standardní: ")
|
||||
S("use the default value", "použij standardní hodnotu")
|
||||
|
||||
S("pick scores", "vyber skóre")
|
||||
|
||||
S("Angle to rotate by.", "Úhel rotace")
|
||||
S("dxy(n) = rotate n degrees from x to y\n\nd-degree, r-radian, t-turn\n\nexample: dxy(30)*dyz(45)",
|
||||
"dxy(n) = otočení o n stupňů od x do y\n\nd-stupeň (degree), r-radián, t-otočka (turn)\n\například: dxy(30)*dyz(45)")
|
||||
|
||||
S("no filters", "bez filtrů")
|
||||
|
||||
S("yet another classic game", "další klasická hra") // hyperbolic Minesweeper
|
||||
|
||||
S("context help", "kontextová nápověda")
|
||||
S("all context help/welcome messages", "plná kontextová nápověda")
|
||||
S("no context help/welcome messages", "bez kontextové nápovědy")
|
||||
S("I know I can press F1 for help", "vím, že mohu získat nápovědu stisknutím klávesy F1")
|
||||
|
||||
S("menu map darkening", "ztmavování mapy v menu")
|
||||
S("A larger number means darker game map in the background. Set to 8 to disable the background.",
|
||||
"Vyšší číslo znamená tmavší herní mapu na pozadí. Hodnota 8 pozadí úplně vypne.")
|
||||
S("centered menus in widescreen", "vycentrované menu na širokých obrazovkách")
|
||||
|
||||
S("less items/kills in landscape", "méně předmětů/zabití v orientaci na šířku")
|
||||
S("less items/kills in portrait", "méně předmětů/zabití v orientaci na výšku")
|
||||
|
||||
S("forced center down", "vynucený střed níže")
|
||||
S("make the center not the actual screen center", "způsobí, že střed herní plochy není skutečným středem obrazovky")
|
||||
|
||||
// animations
|
||||
|
||||
S("idle animation speed", "rychlost nečinné animace")
|
||||
S("flashing effects", "bleskové efekty")
|
||||
S("Disable if you are photosensitive. Replaces flashing effects such as Orb of Storms lightning with slow, adjustable animations.",
|
||||
"Vypni, pokud máš citlivost na světlo. Nahrazuje blikající efekty, jako je Sféra Bouří, pomalými, konfigurovatelnými animacemi.")
|
||||
|
||||
S("start animations", "startovní animace")
|
||||
|
||||
S("movement animation", "animace pohybu")
|
||||
|
||||
S("animation rug angle", "úhel animace koberce")
|
||||
S("rug forward movement angle", "úhel pohybu koberce dopředu")
|
||||
S("rug_camera angle", "úhel kamery koberce")
|
||||
S("translation+rotation", "posunutí+otočení")
|
||||
|
||||
// save file selection
|
||||
|
||||
S("select the score/save file on startup", "vyber soubor se skóre/uloženou hrou při spuštění")
|
||||
S("choose your score/save file", "vyber soubor se skóre/uloženou hrou")
|
||||
S("Save the config and restart to select another score/save file.", "Ulož konfiguraci a restartuj hru pro vybrání jiného souboru se skóre/uloženou hrou.")
|
||||
S("Save the config to always play without recording your progress.", "Ulož konfiguraci, aby se vždy hrálo bez zaznamenávání postupu.")
|
||||
S("Save the config to always use %1.", "Ulož konfiguraci, aby se vždy používalo %1.")
|
||||
S("Your progress will not be saved.", "Tvůj postup nebude uložen.")
|
||||
|
||||
// online demo (not translated but just in case)
|
||||
|
||||
S("HyperRogue %1: online demo", "HyperRogue %1: online demo")
|
||||
S("play the game", "hraj")
|
||||
S("learn about hyperbolic geometry", "nauč se něco o hyperbolické geometrii")
|
||||
S("toggle high detail", "přepni vysokou úroveň detailů")
|
||||
|
||||
// other
|
||||
|
||||
S("wiki", "wiki")
|
||||
S("highlight faraway monsters", "zvýrazni vzdálené netvory")
|
||||
|
||||
// map editor, line patterns, etc.
|
||||
//=================================
|
||||
|
||||
S("hint: shift+A to enter the map editor", "nápověda: stiskem shift+A se dostaneš do mapového editoru")
|
||||
|
||||
S("z = set Shift+click", "z = nastav Shift+klik")
|
||||
S("B = build on walls ", "B = stavění na zdech")
|
||||
S("S = snap (%1)", "S = přicvaknutí (%1)")
|
||||
S("Z =", "Z = ")
|
||||
S("X =", "X = ")
|
||||
S("Y =", "Y = ")
|
||||
S("w: %1", "w: %1")
|
||||
S("λ: %1°", "λ: %1°")
|
||||
|
||||
S("edit cell values", "editace hodnot políček")
|
||||
S("canvas floor shape", "tvar podlahy Plátna")
|
||||
S("canvas darkness", "tmavost Plátna")
|
||||
|
||||
S("die shape", "tvar kostky")
|
||||
S("die face", "stěna kostky")
|
||||
S("die direction", "směr kostky")
|
||||
S("die mirror status", "zrcadlový status kostky")
|
||||
S("mirrored", "zrcadlená")
|
||||
|
||||
// line patterns
|
||||
|
||||
S("parallel/meridian orientation", "orientace rovnoběžek/poledníků")
|
||||
S("number of parallels drawn", "počet nakreslených rovnoběžek")
|
||||
S("last parallel drawn", "poslední nakreslená rovnoběžka")
|
||||
S("tree-drawing parameter", "parametr kreslení stromu")
|
||||
S("How much of edges to draw for tree patterns (to show how the tree edges are oriented).",
|
||||
"Jak velká část hran se má kreslit ve stromových vzorech (pro vyznačení jejich orientace).")
|
||||
|
||||
// debug tools
|
||||
|
||||
S("error", "chyba")
|
||||
|
||||
S("display tile debug values", "zobrazení debugových hodnot políček")
|
||||
S("Display cell type IDs, as well as vertex and edge identifiers.\n\n"
|
||||
"Setting 1 uses the internal shape IDs, while setting 2 in tes files uses the original IDs"
|
||||
" in case if extra tile types were added to separate mirror images or different football types.",
|
||||
|
||||
"Zobrazuje ID typu políčka a identifikátory vrcholů a hran.\n\n"
|
||||
"Hodnota 1 používá interní ID tvarů, zatímco hodnota 2 používá původní ID ze souborů *.tes "
|
||||
"pro případ, že se přidaly další typy políček, aby se oddělily zrcadlové obrazy nebo různé fotbalové typy.")
|
||||
|
||||
// tessellations / honeycombs / projections / embeddings
|
||||
//========================================================
|
||||
|
||||
// new geometry settings
|
||||
|
||||
S("projective Bring's Surface", "projektivní Bringův povrch")
|
||||
S("aperiodic hat", "aperiodický klobouk")
|
||||
S("Sierpiński triangle", "Sierpińského trojúhelník")
|
||||
S("Sierpiński carpet", "Sierpińského koberec")
|
||||
S("6-flake fractal", "6-vločkový fraktál")
|
||||
S("Menger sponge", "Mengerova houba")
|
||||
S("Sierpiński tetrahedron", "Sierpińského čtyřstěn")
|
||||
S("aperiodic spectre", "aperiodický přízrak")
|
||||
|
||||
// inter-geometric portals
|
||||
|
||||
S("Welcome to a portal map! Press 'o' to configure.", "Vítej v portálové mapě! Stiskni 'o' pro konfiguraci.")
|
||||
S("become a portal map", "změnit na portálovou mapu")
|
||||
S("yes, that's what I want", "ano, to je to, co chci")
|
||||
S("world list", "seznam světů")
|
||||
S("manage portals", "správa portálů")
|
||||
S("view another world", "podívat se na jiný svět")
|
||||
S("connect ", "spojit ")
|
||||
S("disconnect this portal", "odpojit tento portál")
|
||||
S("remove %1 from the list", "odstranit %1 ze seznamu")
|
||||
S("add to list", "přidat na seznam")
|
||||
S("portal orientation", "orientace portálu")
|
||||
S("mirror connection", "zrcadlové spojení")
|
||||
S("test portal here", "otestovat portál zde")
|
||||
S("set recommended settings", "zadat doporučené nastavení")
|
||||
S("height-to-width ratio", "poměr výšky a šířky")
|
||||
|
||||
S("keep eye level when walking enabled", "udržovat výši oka při zapnuté chůzi")
|
||||
S("walking eye angle", "úhel oka při chůzi")
|
||||
S("0 = looking forward, 90 = looking upward. In VR this is adjusted automatically.",
|
||||
"0 = dopředu, 90 = nahoru. Ve VR módu se upravuje automaticky.")
|
||||
S("eye angle scale", "škálování úhlu oka")
|
||||
S("1 = the angle can be changed with keyboard or mouse movements, 0 = the angle is fixed",
|
||||
"1 = úhel je možné měnit klávesnicí nebo pohybem myši, 0 = úhel je pevně daný")
|
||||
S("walking eye level", "výše oka při chůzi")
|
||||
S("Distance from the floor to the eye in the walking mode, in absolute units. In VR this is adjusted automatically.",
|
||||
"Vzdálenost oka od podlahy v módu chůze, vyjádřená v absolutních jednotkách. Ve VR módu se upravuje automaticky.")
|
||||
|
||||
S("move the camera with arrow keys and Home/End", "přesouvat kameru šipkami a klávesami home/End")
|
||||
S("the map is fixed (improves performance)", "fixní mapa (zlepšuje výkon)")
|
||||
|
||||
S("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",
|
||||
"Momentálně se nacházíš ve vizualizaci. Stiskni klávesy WASD pro pohyb, QE pro rotaci. Také můžeš používat šipky. ESC otvírá menu.\n\n")
|
||||
|
||||
S("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",
|
||||
"Momentálně se nacházíš ve vizualizaci. Stiskni klávesy WASDQE pro rotaci kamery, IJKLYH pro pohyb. Také můžeš používat šipky a klávesy Home/End a PgUp/PgDn. ESC otvírá menu.\n\n")
|
||||
|
||||
S("pure exploration (game keys scroll)", "čisté zkoumání světa (herní klávesy scrollují)")
|
||||
|
||||
// subdivisions of 3D honeycombs
|
||||
|
||||
S("sub-cubes", "podkrychle")
|
||||
S("dual sub-cubes", "duální podkrychle")
|
||||
S("bitruncated sub-cubes", "dvojseříznuté podkrychle")
|
||||
S("note: more choices in cubic honeycombs", "poznámka: v krychlových dlážděních je více voleb")
|
||||
S("subdivision", "poddělení")
|
||||
S("split by original faces", "rozdělit podle původních stran")
|
||||
S("split by vertex axes", "rozdělit podle vrcholových os")
|
||||
S("split by midedges", "rozdělit podle středů hran")
|
||||
S("Outside of the supported limits", "Mimo podporované hranice")
|
||||
// let's just not translate this
|
||||
S("subcubed", "subcubed")
|
||||
S("dual-subcubed", "dual-subcubed")
|
||||
S("bitruncated-subcubed", "bitruncated-subcubed")
|
||||
S("subdivided", "subdivided")
|
||||
|
||||
// restrict map to disk
|
||||
|
||||
S("disk size", "rozměr disku")
|
||||
S("Play on a disk. Enables the special game rules for small bounded spaces (especially relevant for e.g. Minefield and Halloween). "
|
||||
"The number given is the number of tiles to use; it is not used exactly, actually the smallest disk above this size is used. Set to 0 to disable.",
|
||||
"Hraj na disku. Aktivuje zvláštní herní pravidla pro malé, ohraničené prostory (zvláště relevantní pro např. Minové pole a Halloween). "
|
||||
"Udané číslo je počet políček; nepoužívá se však přesně tato hodnota, ale nejmenší disk, který ji převyšuje. Nastavením na 0 se tato možnost vypne.")
|
||||
|
||||
S("disk shape", "tvar disku")
|
||||
S("distance in tiles", "vzdálenost v políčkách")
|
||||
S("distance in vertices", "vzdálenost ve vrcholech")
|
||||
S("geometric distance", "geometrická vzdálenost")
|
||||
S("fraction of mine in bounded minefield", "podíl min v ohraničeném minovém poli")
|
||||
|
||||
// tessellation tree generation
|
||||
|
||||
S("strict tree maps", "striktní stromové mapy")
|
||||
S("display distances up to", "zobraz vzdálenosti až do")
|
||||
S("extend automatically", "automatické rozšíření tabulky") // the table of tile count by distances
|
||||
S("rules generated successfully: %1 states using %2-%3 cells", "pravidla úspěšně vygenerovaná: %1 stavů s využitím %2-%3 políček")
|
||||
S("too difficult: %1", "příliš obtížné: %1")
|
||||
S("bug: %1", "bug: %1")
|
||||
S(
|
||||
"Strict tree maps are generated using a more powerful algorithm.\n\nThis algorithm supports horocycles and knows the expansion rates of various "
|
||||
"tessellations (contrary to the basic implementation of Archimedean, tes, and unrectified/warped/untruncated tessellations).\n\nYou can convert mostly any "
|
||||
"non-spherical periodic 2D tessellation to strict tree based.\n\nSwitching the map format erases your map.",
|
||||
|
||||
"Striktní stromové mapy se vytvářejí pomocí silnějšího algoritmu.\n\nTento algoritmus podporuje horocykly a zná rychlost růstu různých "
|
||||
"dláždění (oproti základní implementaci archimédovských dláždění, *.tes a nerektifikovaných/pokřivených/neseříznutých dláždění).\n\nTéměř jakékoli "
|
||||
"nesférické periodické 2D dláždění je možné zkonvertovat na striktní stromovou mapu.\n\nZměna formátu mapy tvoji mapu vymaže."
|
||||
)
|
||||
|
||||
S("in tes internal format", "v interním formátu *.tes")
|
||||
S("converted successfully -- %1 cell types", "konverze úspěšná -- %1 typů políček")
|
||||
S("cannot be disabled for this tiling", "v tomto dláždění nelze vypnout")
|
||||
S("extended football colorability", "rozšířená obarvitelnost fotbalového míče")
|
||||
S("consider all symmetries when converting", "ber při konverzi v úvahu všechny symetrie")
|
||||
S("tes reverse order on convert", "obrácené pořadí *.tes při konverzi")
|
||||
S("maximum cellcount", "maximální počet políček")
|
||||
S("controls the max memory usage of conversion algorithm -- the algorithm fails if exceeded",
|
||||
"ovládá maximální využití paměti konverzním algoritmem -- pokud se toto množství překročí, algoritmus skončí neúspěšně")
|
||||
|
||||
// hat tiling
|
||||
|
||||
S("hat/spectre/turtle parameter", "parametr hat/spectre/turtle")
|
||||
S("Apeirodic hat tiling based on: https://arxiv.org/pdf/2303.10798.pdf\n\n"
|
||||
"This controls the parameter discussed in Section 6. Parameter p is Tile(p, (2-p)√3), "
|
||||
"scaled so that the area is the same for every p.\n\n"
|
||||
"Aperiodic spectre tiling based on: https://arxiv.org/abs/2305.17743\n\n"
|
||||
"In the spectre tiling, set the parameter to 'spectre' value to make all tiles have the same shape.",
|
||||
|
||||
"Aperiodické kloboukové (hat) dláždění založené na: https://arxiv.org/pdf/2303.10798.pdf\n\n"
|
||||
"Toto ovládá parametr diskutovaná v Sekci 6. Parametr p znamená Tile(p, (2-p)√3), "
|
||||
"škálovaný tak, aby měla pole pro všechna p stejný obsah.\n\n"
|
||||
"Aperiodické přízrakové (spectre) dláždění založené na: https://arxiv.org/abs/2305.17743\n\n"
|
||||
"Pokud v přízrakovém dláždění nastavíš parametr na hodnotu 'spectre', budou mít všechna políčka stejný tvar.")
|
||||
|
||||
S("Welcome to HatRogue!", "Vítej v HatRogue!")
|
||||
S("hat in cluster", "klobouk ve shluku")
|
||||
S("hat clusters", "shluky klobouků")
|
||||
S("hat superclusters", "supershluky klobouků")
|
||||
S("types (mark reverse)", "typy (označit převrácené)")
|
||||
S("display small floors", "zobrazit malé podlahy")
|
||||
S("chevron (periodic)", "chevron (periodický)")
|
||||
S("hat", "klobouk ('hat')")
|
||||
S("spectre", "přízrak ('spectre')")
|
||||
S("turtle", "želva ('turtle')")
|
||||
S("comma (periodic)", "čárka (periodická)")
|
||||
|
||||
S("hat parameter (imaginary)", "parametr 'hat' (imaginární)")
|
||||
S("Imaginary part of the hat parameter. This corresponds to the usual interpretation of complex numbers in Euclidean planar geometry: "
|
||||
"rather than shortened or lengthened, the edges are moved in the other dimension.",
|
||||
"Imaginární část parametru 'hat'. Odpovídá obvyklé interpretaci komplexních čísel v eukleidovské rovinné geometrii: "
|
||||
"místo aby se hrany zkracovaly nebo prodlužovaly, posouvají se ve druhém rozměru."
|
||||
)
|
||||
|
||||
// fake curvature setting in experiments in geometry (some texts were not translated)
|
||||
|
||||
S(
|
||||
"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",
|
||||
|
||||
"Zde můžeš sestavit stejné dláždění, ale "
|
||||
"z tvarů odlišné křivosti.\n\n"
|
||||
"Číslo, které se zde zadává, udává (2D) stupeň vrcholu nebo (3D) "
|
||||
"počet buněk kolem hrany.\n\n")
|
||||
|
||||
S("original", "originální")
|
||||
S("double original", "dvojitá originální")
|
||||
S("draw all if multiple of original", "vykresluj vše, je-li to násobkem originálu")
|
||||
S("draw copies (2D only)", "vykresluj kopie (pouze 2D)")
|
||||
S("unordered", "neuspořádané")
|
||||
S("pre-ordered", "uspořádané 'před'")
|
||||
S("post-ordered", "uspořádané 'po'")
|
||||
|
||||
// other tessellation-related
|
||||
|
||||
S("color by symmetries (reversed tiles marked)", "obarvi podle symetrií (s vyznačením převrácených dlaždic)")
|
||||
S("unreversed colors", "nepřevrácené barvy")
|
||||
S("symmetric subdivision", "symetrické poddělení")
|
||||
S("simplified display of apeirogons", "zjednodušené zobrazení apeirogonů")
|
||||
|
||||
S("Width of cell boundaries", "šířka hranic políček")
|
||||
S("How wide should the cell boundaries be.", "Jak široké by měly být hranice políček.")
|
||||
|
||||
S("the following sliders will restart the game", "následující slidery restartují hru")
|
||||
|
||||
// new projections and parameters
|
||||
|
||||
S("horocyclic equal-area", "horocyklická rovnoplochá")
|
||||
S("conformal square", "konformální čtverec")
|
||||
S("Lie perspective", "perspektiva v Lieově grupě")
|
||||
S("Lie orthogonal", "ortogonální projekce v Lieově grupě")
|
||||
S("relativistic perspective", "relativistická perspektiva")
|
||||
S("relativistic orthogonal", "relativistická ortogonální projekce")
|
||||
S("angle between the axes", "úhel mezi osami")
|
||||
S("In two-axe-based models, this parameter gives the angle between the two axes.", "V modelech založených na dvou osách tento parametr udává úhel mezi nimi.")
|
||||
S("model orientation 3D", "orientace modelu ve 3D")
|
||||
S("semidirect_rendering (perspective on GPU)", "polopřímé renderování (perspektiva v GPU)")
|
||||
S("this is not a Lie group", "toto není Lieova grupa")
|
||||
S("not implemented", "není implementováno")
|
||||
|
||||
S("auto rotation", "automatická rotace")
|
||||
S("auto rotation in 3D", "automatická rotace ve 3D")
|
||||
|
||||
// alternative screen projections
|
||||
|
||||
S("stereo/high-FOV mode", "mód stereo / velký zorný úhel")
|
||||
S("linear perspective", "lineární perspektiva")
|
||||
S("for red-cyan glasses", "pro červeno-tyrkysové 3D brýle")
|
||||
S("for mobile VR", "pro mobilní VR")
|
||||
S("ODS", "projekce ODS")
|
||||
S("for rendering 360° VR videos (implemented only in raycaster and some other parts)",
|
||||
"pro renderování 360° VR videí (implementováno pouze v raycasteru a některých jiných částech)")
|
||||
S("Panini", "Panini")
|
||||
S("Projection believed to be used by Italian painters. Allows very high FOV angles while rendering more straight lines as straight than the stereographic projection.",
|
||||
"Domníváme se, že tuto projekci používali italští malíři. Umožňuje opravdu velké zorné úhly, a přitom vykresluje více přímek jako přímky než stereografická projekce.")
|
||||
S("stereographic", "stereografická projekce")
|
||||
S("Stereographic projection allows very high FOV angles.", "Stereografická projekce umožňuje opravdu velké zorné úhly.")
|
||||
S("equirectangular", "rovnoobdélníková projekce")
|
||||
S("for rendering 360° videos (implemented only in raycaster)", "pro renderování 360° videí (implementováno pouze v raycasteru)")
|
||||
S("stereographic/Panini parameter", "parametr stereografické/Paniniho projekce")
|
||||
S("1 for full stereographic/Panini projection. Lower values reduce the effect.\n\n"
|
||||
"HyperRogue uses a quick implementation, so parameter values too close to 1 may be buggy (outside of raycasting); try e.g. 0.9 instead.",
|
||||
"1 pro plnou stereografickou/Paniniho projekci. Nižší hodnoty účinek oslabují.\n\n"
|
||||
"HyperRogue používá rychlou implementaci, takže hodnoty parametrů, které se příliš blíží jedné, mohou vést k chybám (s výjimkou raycastingu); zkus raději např. hodnotu 0.9."
|
||||
)
|
||||
|
||||
// embeddings
|
||||
//============
|
||||
|
||||
S("3D embedding method", "metoda vnoření do 3D")
|
||||
S("3D style", "3D styl")
|
||||
S("2D engine", "2D engine")
|
||||
S("Use HyperRogue's 2D engine to simulate same curvature. Works well in top-down and third-person perspective. The Hypersian Rug mode can be used to project this to a surface.",
|
||||
"Použij 2D engine HyperRogue k simulování stejné křivosti. Dobře to funguje v pohledu seshora nebo třetí osoby. Můžeš použít mód Hyperského koberce, abys výsledek promítl na nějaký povrch.")
|
||||
S("same curvature", "stejná křivost")
|
||||
S("Embed as an equidistant surface in the 3D version of the same geometry.",
|
||||
"Vnoř jako ekvidistantní povrch ve 3D verzi stejné geometrie.")
|
||||
S("lower curvature", "menší křivost")
|
||||
S("Embed as a surface in a space of lower curvature.", "Vnoř jako povrch v prostoru s menší křivostí.")
|
||||
S("much lower curvature", "mnohem menší křivost")
|
||||
S("Embed sphere as a sphere in hyperbolic space.", "Vnoř kouli jako kouli v hyperbolickém prostoru.")
|
||||
S("product", "součin")
|
||||
S("Add one extra dimension in the Euclidean way.", "Přidej jeden rozměr navíc eukleidovským způsobem.")
|
||||
S("Embed Euclidean plane into Nil.", "Vnoř eukleidovskou rovinu do Nil.")
|
||||
S("Embed Euclidean or hyperbolic plane into Sol.", "Vnoř eukleidovskou rovinu do Sol.")
|
||||
S("Embed Euclidean or hyperbolic plane into stretched hyperbolic geometry.", "Vnoř eukleidovskou nebo hyperbolickou rovinu do natažené hyperbolické geometrie.")
|
||||
S("stretched Sol", "natažený Sol.")
|
||||
S("Embed Euclidean or hyperbolic plane into stretched Sol geometry.", "Vnoř eukleidovskou nebo hyperbolickou rovinu do natažené geometrie Sol.")
|
||||
S("Clifford Torus", "Cliffordův torus")
|
||||
S("Embed Euclidean rectangular torus into S3.", "Vnoř eukleidovský obdélníkový torus do S3.")
|
||||
S("hyperbolic product", "hyperbolický součin")
|
||||
S("Embed Euclidean or hyperbolic plane in the H2xR product space.", "Vnoř eukleidovskou nebo hyperbolickou rovinu do součinového prostoru H2xR")
|
||||
S("spherical product", "sférický součin")
|
||||
S("Embed Euclidean cylinder or spherical plane in the H2xR product space.", "Vnoř eukleidovský válec nebo sférickou rovinu do součinového prostoru S2xR")
|
||||
S("Embed Euclidean plane in twisted product geometry.", "Vnoř eukleidovskou rovinu do zkroucené součinové geometrie.")
|
||||
S("Embed Euclidean cylinder in Euclidean space.", "Vnoř eukleidovský válec do eukleidovského prostoru.")
|
||||
S("hyperbolic cylinder", "hyperbolický válec")
|
||||
S("Embed Euclidean cylinder in hyperbolic space.", "Vnoř eukleidovský válec do hyperbolického prostoru.")
|
||||
S("product cylinder", "součinový válec")
|
||||
S("Embed Euclidean cylinder in H2xR space.", "Vnoř eukleidovský válec do prostoru H2xR.")
|
||||
S("Nil cylinder", "Nil válec")
|
||||
S("Embed Euclidean cylinder in Nil.", "Vnoř eukleidovský válec do Nil.")
|
||||
S("horocylinder", "horoválec")
|
||||
S("Embed Euclidean as a horocylinder in H2xR space.", "Vnoř eukleidovskou rovinu do prostoru H2xR jako horoválec.")
|
||||
S("SL2 cylinder", "SL2 válec")
|
||||
S("Embed Euclidean as a cylinder in twisted product geometry.", "Vnoř eukleidovský válec do zkroucené součinové geometrie.")
|
||||
|
||||
// embedding settings
|
||||
|
||||
S("flat, not equidistant", "ploché, nikoli ekvidistantní")
|
||||
S("invert convex/concave", "převrať konvexní/konkávní")
|
||||
|
||||
// embedding errors
|
||||
|
||||
S("set square tiling", "nastav čtvercové dláždění")
|
||||
S("set hex tiling", "nastav šestiúhelníkové dláždění")
|
||||
S("error: currently works only in PURE Euclidean regular square or hex tiling", "chyba: momentálně funguje pouze v ČISTÉM eukleidovském pravidelném čtvercovém nebo šestiúhelníkovém dláždění")
|
||||
S("error: currently works only in pure Euclidean, or binary tiling and similar", "chyba: momentálně funguje pouze v čistých eukleidovských dlážděních nebo v binárním dláždění a jemu podobným")
|
||||
S("set binary tiling variant", "nastav variantu binárního dláždění")
|
||||
S("set ternary tiling", "nastav ternární dláždění")
|
||||
S("set binary tiling", "nastav binární dláždění")
|
||||
S("error: this embedding does not work in shmup", "chyba: toto vnoření nefunguje ve střílečkovém módu")
|
||||
S("error: this method works only in rectangular torus", "chyba: tato metoda funguje pouze v obdélníkovém torusu")
|
||||
S("set 20x20 torus", "nastav torus 20x20")
|
||||
S("error: this method works only in cylinder", "chyba: tato metoda funguje pouze ve válci")
|
||||
S("set cylinder", "nastav válec")
|
||||
S("error: not supported", "chyba: není podporováno")
|
||||
S("error: this method does not work in spherical geometry", "chyba: tato metoda nefunguje ve sférické geometrii")
|
||||
S("error: this method does not work in hyperbolic geometry", "chyba: tato metoda nefunguje v hyperbolické geometrii")
|
||||
S("3D styles", "styly 3D")
|
||||
S("3D detailed settings", "detailní nastavení 3D")
|
||||
S("more options in 3D engine", "více možností v 3D enginu")
|
||||
S("configure Hypersian Rug", "konfiguruj Hyperský koberec")
|
||||
S("view shift for embedded planes", "změna pohledu pro vnořené roviny")
|
||||
S("always move on geodesics", "vždy se pohybuj po geodetikách")
|
||||
S("keep levels", "udržuj úrovně")
|
||||
S("keep the vertical angle of the camera", "udržuj vertikální úhel kamery")
|
||||
S("mixed", "smíšený mód")
|
||||
S("on geodesics when moving camera manually, keep level when auto-centering", "udržuj úroveň při automatickém centrování během ručního pohybu kamery po geodetikách")
|
||||
S("Euclidean embedding rotation", "rotace eukleidovského vnoření")
|
||||
S("How to rotate the Euclidean embedding, in degrees.", "O kolik stupňů otočit eukleidovské vnoření.")
|
||||
S("Euclidean embedding scale", "škála eukleidovského vnoření")
|
||||
S("How to scale the Euclidean map, relatively to the 3D absolute unit.", "Jak škálovat eukleidovskou mapu v poměru ke 3D absolutní jednotce.")
|
||||
S("Euclidean embedding scale Y/X", "škála eukleidovského vnoření Y/X")
|
||||
S("This scaling factor affects only the Y coordinate.", "Tento škálovací faktor ovlivňuje pouze souřadnici Y.")
|
||||
S("(fix errors)", "(oprav chyby)")
|
||||
S("reset view", "vyresetuj pohled")
|
||||
S("needs", "potřebuje: ")
|
||||
|
||||
// embeddings: detailed 3D parameters
|
||||
|
||||
S("set 3D settings automatically", "nastav 3D možnosti automaticky")
|
||||
|
||||
S("draw plain floors in 3D", "vykresluj v 3D módu prostou podlahu")
|
||||
S("floor alpha", "průhlednost podlahy")
|
||||
S("255 = opaque", "255 = neprůhledné")
|
||||
|
||||
S("altitude of the stars", "výška hvězd")
|
||||
S("star probability", "pravděpodobnost hvězdy")
|
||||
S("probability of star per tile", "pravděpodobnost hvězdy na jednu dlaždici")
|
||||
S("night star size (relative to item sizes)", "velikost nočních hvězd (v poměru k velikosti předmětů)")
|
||||
S("sun size (relative to item sizes)", "velikost slunce (v poměru k velikosti předmětů)")
|
||||
S("infinite sky", "nekonečná obloha")
|
||||
S("ratio of high walls to normal walls", "poměr vysokých a normálních stěn")
|
||||
S("ratio of very high walls to normal walls", "poměr velmi vysokých a normálních stěn")
|
||||
S("altitude of the sky", "výška oblohy")
|
||||
S("sky fake height", "falešná výška oblohy")
|
||||
S("Sky is rendered at the distance computed based on the sky height, "
|
||||
"which might be beyond the range visible in fog. To prevent this, "
|
||||
"the intensity of the fog effect depends on the value here rather than the actual distance. Stars are affected similarly.",
|
||||
|
||||
"Nebe se renderuje ve vzdálenosti vypočtené na základě výšky oblohy, "
|
||||
"což může být dál, než činí viditelnost v mlze. Aby se tomu zabránilo, "
|
||||
"závisí intenzita efektu mlhy na této hodnotě a ne na skutečné vzdálenosti. Hvězdy jsou ovlivněny podobným způsobem."
|
||||
)
|
||||
S("sky rendering", "renderování oblohy")
|
||||
S("do not draw sky", "nevykresluj oblohu")
|
||||
S("skybox", "skybox")
|
||||
S("infinite depth", "nekonečná hloubka")
|
||||
S("The unit this value is given in is wall height. "
|
||||
"Note that, in exponentially expanding spaces, too high values could cause rendering issues. "
|
||||
"So if you want infinity, values of 5 or similar should be used -- there is no visible difference from infinity and glitches are avoided.",
|
||||
"Tato hodnota je udávaná v jednotkách výšky stěny. "
|
||||
"Pozor -- v exponenciálně se zvětšujících prostorech by příliš vysoká hodnota mohla způsobit problémy při renderování. "
|
||||
"Chceš-li tedy nekonečno, použij hodnotu 5 nebo něco podobného -- vizuálně tam žádný rozdíl oproti nekonečnu není a vyhneš se chybám.")
|
||||
S("Level of shallow water", "Úroveň mělké vody")
|
||||
S("do not render higher levels if camera too high", "nerenderuj vyšší úrovně, je-li kamera příliš vysoko")
|
||||
S("works only in Euclidean", "toto funguje pouze v eukleidovském prostoru")
|
||||
S("always", "vždy")
|
||||
S("might be glitched in some settings", "s některými nastaveními může dělat chyby")
|
||||
S("prevent exceeding recommended altitudes", "nepřekračuj doporučenou výšku")
|
||||
|
||||
S("camera angle", "úhel kamery")
|
||||
S("render behind the camera", "renderuj za kamerou")
|
||||
|
||||
// embeddings: pseudohedral setting
|
||||
|
||||
S("make the tiles flat", "ploché dlaždice")
|
||||
S("the tiles are curved", "dlaždice jsou zakřivené")
|
||||
S("inscribed", "vepsané")
|
||||
S("the tiles are inscribed", "dlaždice jsou vepsané")
|
||||
S("circumscribed", "opsané")
|
||||
S("the tiles are circumscribed", "dlaždice jsou opsané")
|
||||
S("depth bonus in pseudohedral", "bonus na hloubku v pseudohedrálním módu")
|
||||
|
||||
// embeddings: geodesic movement in Solv etc
|
||||
|
||||
S("straight lines", "přímky")
|
||||
S("Lie group", "Lieova grupa")
|
||||
S("light, camera, and objects move in lines of constant direction, in the Lie group sense", "světlo, kamera a předměty se pohybují po čarách konstantního směru ve smyslu Lieovy grupy")
|
||||
S("geodesics", "geodetiky")
|
||||
S("light, camera, and objects always take the shortest path", "světlo, kamera a objekty se vždy pohybují po nejkratší dráze")
|
||||
|
||||
// achievement eligiblity
|
||||
S("achievement/leaderboard eligiblity:", "dostupnost achievementů/leaderboardů:")
|
||||
S("eligible for most", "většina achievementů/leaderboardů dostupná")
|
||||
S("eligible for most -- leaderboards separate", "většina achievementů dostupná -- leaderboardy oddělené")
|
||||
S("eligible for racing", "závodní achievementy/leaderboardy dostupné")
|
||||
S("eligible for shmup", "střílečkové achievementy/leaderboardy dostupné")
|
||||
S("eligible for multiplayer", "multiplayerové achievementy/leaderboardy dostupné")
|
||||
S("eligible for Chaos mode", "achievementy/leaderboardy chaotického módu dostupné")
|
||||
S("eligible for Princess Challenge", "achievementy/leaderboardy Mise: Princezna dostupné")
|
||||
S("eligible for heptagonal", "achievementy/leaderboardy sedmiúhelníkového módu dostupné")
|
||||
S("eligible for special geometry", "achievementy/leaderboardy speciální geometrie dostupné")
|
||||
S("eligible for Strange Challenge", "achievementy/leaderboardy Podivné mise dostupné")
|
||||
S("disabled in cheat mode", "v cheat módu jsou achievementy/leaderboardy nedostupné")
|
||||
S("disabled in casual mode", "v neformálním módu jsou achievementy/leaderboardy nedostupné")
|
||||
S("not eligible due to current mode settings", "achievementy/leaderboardy nejsou dostupné díky současnému nastavení módu")
|
||||
S("no achievements/leaderboards in this version", "v této verzi žádné achievementy/leaderboardy nejsou")
|
||||
|
|
|
@ -1991,7 +1991,7 @@ S("Mighty warriors from the Fjord, who can use boats.",
|
|||
N("Water Elemental", GEN_M, "Wasserelementar", "Wasserelementare", "Wasserelementar")
|
||||
S("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.",
|
||||
"Wohin auch immer sich dieses Wesen bewegt sinkt der lebende Fjord. "
|
||||
"Dadurch werden nicht magische Boote zerstört und Feuer gelöscht.\n\n"
|
||||
"Die Besonderheit ist: du kannst den Wasserelementar vom Wasser aus angreifen ohne sofort zu ertrinken.")
|
||||
|
|
|
@ -2010,7 +2010,7 @@ S("Mighty warriors from the Fjord, who can use boats.",
|
|||
N("Water Elemental", GEN_M | GENF_ELISION, "Élémental d'Eau", "Élémentaux d'Eau", "Élémental d'Eau")
|
||||
S("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.",
|
||||
"Là où cet être puissant va, le fjord vivant est submergé d'eau, les bateaux non-magiques détruits, "
|
||||
"et les feux éteints.\n\n"
|
||||
"Cas particulier : vous pouvez attaquer l'Élemental depuis l'eau sans vous noyer immédiatement.")
|
||||
|
@ -7540,6 +7540,7 @@ Cell("{3,3,3} 5") Cell("{4,3,3} 8") Cell("{3,3,4} 16") Cell("{3,4,3} 24") Cell("
|
|||
S(x " field quotient space", x " champ d'espace quotient")
|
||||
|
||||
Honeycomb("{5,3,4}") Honeycomb("{4,3,5}") Honeycomb("{3,3,6}") Honeycomb("{3,4,4}") Honeycomb("{5,3,5}") Honeycomb("{5,3,6}") Honeycomb("{4,3,6}") Honeycomb("{5,3,6}")
|
||||
Honeycomb("{3,4,5}") Honeycomb("{3,5,3}") Honeycomb("{3,5,4}") Honeycomb("{3,5,5}")
|
||||
|
||||
#undef Honeycomb
|
||||
|
||||
|
@ -8651,19 +8652,20 @@ S("display only chessboard white", "afficher seulement le plateau d'échec blanc
|
|||
S("display only chessboard black", "afficher seulement le plateau d'échec noir")
|
||||
|
||||
S(
|
||||
"This lets you specify the color pattern as a function of the cell. "
|
||||
"This lets you specify the color pattern as a function of the cell.\n",
|
||||
|
||||
"Vous laisse choisir le motif de couleur comme fonction de la case.\n")
|
||||
|
||||
S(
|
||||
"Available parameters:\n\n"
|
||||
"x, y, z (hyperboloid/sphere/plane coordinates in non-crystal geometries)\n"
|
||||
"ex, ey, ez (in Euclidean geometries)\n"
|
||||
"x0, x1, x2... (crystal geometry only)\n"
|
||||
"0 is black, 1 is white, rgb(1,0,0) is red, ifp(p-2,1,0) is blue (p=1 for red, 2 for green, 3 for blue).",
|
||||
"x0, x1, x2... (crystal geometry only)\n",
|
||||
|
||||
"Vous laisse choisir le motif de couleur comme fonction de la case. "
|
||||
"Paramètres disponibles : \n\n"
|
||||
"x, y, z (coordonnées hyperboloïde/sphère/plan dans des géométries non-cristallines)\n"
|
||||
"ex, ey, ez (dans une géométrie euclidienne)\n"
|
||||
"x0, x1, x2... (dans les géométries cristallines seulement)\n"
|
||||
"0 est noir, 1 est blanc, rgb(1,0,0) est rouge, ifp(p-2,1,0) est bleu (p=1 pour rouge, 2 pour vert, 3 pour bleu)."
|
||||
)
|
||||
|
||||
S(
|
||||
|
|
677
language-pl.cpp
677
language-pl.cpp
|
@ -2097,10 +2097,10 @@ S("Mighty warriors from the Fjord, who can use boats.",
|
|||
N("Water Elemental", GEN_M, "Wodny Żywiołak", "Wodne Żywiołaki", "Wodnego Żywiołaka", "Wodnym Żywiołakiem")
|
||||
S("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 with your blade from the water, without drowning immediately.",
|
||||
"Gdziekolwiek przejdzie ta potężna istota, żywy fiord tonie, niemagiczne łódki są niszczone, a "
|
||||
"ogień gaśnie.\n\n"
|
||||
"Jako szczególny przypadek, możesz atakować Wodnego Żywiołaka z wody, nie topiąc się.")
|
||||
"Jako szczególny przypadek, możesz atakować Wodnego Żywiołaka mieczem z wody, nie topiąc się.")
|
||||
|
||||
|
||||
N("Garnet", GEN_O, "Granat", "Granaty", "Granat", "Granatem")
|
||||
|
@ -7657,6 +7657,7 @@ Cell("{3,3,3} 5") Cell("{4,3,3} 8") Cell("{3,3,4} 16") Cell("{3,4,3} 24") Cell("
|
|||
S(x " field quotient space", x " przestrzeń ilorazowa ciała")
|
||||
|
||||
Honeycomb("{5,3,4}") Honeycomb("{4,3,5}") Honeycomb("{3,3,6}") Honeycomb("{3,4,4}") Honeycomb("{5,3,5}") Honeycomb("{5,3,6}") Honeycomb("{4,3,6}") Honeycomb("{5,3,6}")
|
||||
Honeycomb("{3,4,5}") Honeycomb("{3,5,3}") Honeycomb("{3,5,4}") Honeycomb("{3,5,5}")
|
||||
|
||||
#undef Honeycomb
|
||||
|
||||
|
@ -8144,7 +8145,7 @@ S("stretched hyperbolic", "rozciągnięta hiperboliczna")
|
|||
S("stretched Solv", "rozciągnięta geometria Solv")
|
||||
|
||||
S("{3,∞} (infinite triangles)", "{3,∞} (nieskończone trójkąty)")
|
||||
S("{4,∞} (infinite triangles)", "{4,∞} (nieskończone kwadraty)")
|
||||
S("{4,∞} (infinite squares)", "{4,∞} (nieskończone kwadraty)")
|
||||
S("{3/4,∞} (infinite triangles and squares)", "nieskończone trójkąty i kwadraty")
|
||||
|
||||
S("4D crystal in H3", "4D kryształ w H3")
|
||||
|
@ -8755,18 +8756,19 @@ S("display only chessboard white", "tylko białe pola szachownicy")
|
|||
S("display only chessboard black", "tylko czarne pola szachownicy")
|
||||
|
||||
S(
|
||||
"This lets you specify the color pattern as a function of the cell. "
|
||||
"This lets you specify the color pattern as a function of the cell.\n",
|
||||
"Tu możesz określić wzór jako funkcję komórki.\n")
|
||||
|
||||
S(
|
||||
"Available parameters:\n\n"
|
||||
"x, y, z (hyperboloid/sphere/plane coordinates in non-crystal geometries)\n"
|
||||
"ex, ey, ez (in Euclidean geometries)\n"
|
||||
"x0, x1, x2... (crystal geometry only)\n"
|
||||
"0 is black, 1 is white, rgb(1,0,0) is red, ifp(p-2,1,0) is blue (p=1 for red, 2 for green, 3 for blue).",
|
||||
"x0, x1, x2... (crystal geometry only)\n",
|
||||
|
||||
"Tu możesz określić wzór jako funkcję komórki. Dostępne parametry:\n\n"
|
||||
"Dostępne parametry:\n\n"
|
||||
"x, y, z (współrzędne hiperboloidy/sfery/powierczni, poza kryształami)\n"
|
||||
"ex, ey, ez (w geometriach euklidesowych)\n"
|
||||
"x0, x1, x2... (w kryształach)\n"
|
||||
"0 to czarny, 1 to biały, rgb(1,0,0) to czerwony, ifp(p-2,1,0) to niebieski (p=1 to czerwony, 2 to zielony, 3 to niebieski)."
|
||||
)
|
||||
|
||||
S(
|
||||
|
@ -9407,6 +9409,663 @@ S(
|
|||
"* na Prerii po jej odblokowaniu (%3 skarbów)\n\n"
|
||||
)
|
||||
|
||||
N("Palace Quest", GEN_O, "Misja w Pałacu", "Misje w Pałacu", "Misję w Pałacu", "na Misji w Pałacu")
|
||||
// 13.0
|
||||
|
||||
// gameplay
|
||||
//==========
|
||||
|
||||
// these were missing somehow
|
||||
|
||||
N("Palace Quest", GEN_O, "Misja w Pałacu", "Misje w Pałacu", "Misję w Pałacu", "na Misji w Pałacu")
|
||||
N("Pike", GEN_F, "Szczupak", "Szczupaki", "Szczupaka", "Szczupakiem")
|
||||
|
||||
// crossbow
|
||||
|
||||
S("The warped space distracts you from reloading while staying in place!",
|
||||
"Zakrzywiona przestrzeń nie pozwala Ci ładować broni bez ruszania się!")
|
||||
S("Fire!", "Ognia!")
|
||||
S("(shooting while unstable -- no turn passes)", "(Strzał z niestabilnej pozycji -- tura nie mija)")
|
||||
S("Stab them by shooting around them.", "(Dźgnij ich poprzez strzelanie wokół nich.)")
|
||||
S("You are too weakened to attack %the1!", "Jesteś za słab%y0, by zaatakować %a2!")
|
||||
S("You cannot attack your own mount!", "Nie można atakować swojego własnego wierzchowca!")
|
||||
S("A magical shield protects %the1!", "Magiczna tarcza chroni %a1!")
|
||||
S("You have no melee weapon!", "Nie masz broni do walki wręcz!")
|
||||
S("Your crossbow is still reloading!", "Twoja kusza wciąż się ładuje!")
|
||||
S("Trying to fire.", "Próbujesz strzelać.")
|
||||
S(" (turns to reload: %1)", " (kolejki do naładowania: %1)")
|
||||
S(" (fire mode on / turns to reload: %1)", " (tryb strzału / kolejki do naładowania: %1)")
|
||||
S(" (fire mode on)", " (tryb strzału)")
|
||||
S(" (click to fire)", " (kliknij by strzelać)")
|
||||
S("You fire an angry glance at your enemies.", "Strzelasz focha.")
|
||||
S("Note: cannot fire again yet. Turns to reload: %1.", "Uwaga: jeszcze za wcześnie, by strzelać. Liczba kolejek do naładowania: %1")
|
||||
S("Fire crossbow! Click to aim, click again to confirm.", "Strzał! Kliknij cel, a następnie jeszcze raz, by potwierdzić.")
|
||||
S("Fire mode disabled.", "Tryb strzału wyłączony.")
|
||||
S("Firing cancelled.", "Strzał anulowany.")
|
||||
S("Cannot fire again yet. Turns to reload: %1.", "Wciąż nie możesz strzelać. Liczba kolejek do naładowania: %1")
|
||||
S("No way to hit this place.", "Nie da się tam trafić.")
|
||||
S("Shooting impossible.", "Strzał niemożliwy.")
|
||||
S("%The1 is enraged!", "%1 jest wściekł%y1!")
|
||||
S("weapon selection", "wybór broni")
|
||||
S("Cannot hit anything by shooting this direction!", "Nic nie trafisz strzelając w tym kierunku!")
|
||||
S("Welcome to HyperRanger!", "Witaj w HyperRanger!")
|
||||
S("bow color", "kolor kuszy")
|
||||
S("bowstring color", "kolor cięciwy")
|
||||
S("%The1 alarms other dogs as it dies!", "Umierając%y1 %1 podnosi alarm!")
|
||||
S("crossbow straight line style", "styl linii strzału")
|
||||
S("bull line", "linie byka")
|
||||
S("Can go in either direction on odd shapes. 3 turns to reload.", "Na polach nieparzystych może lekko skręcić w lewo lub prawo. 3 kolejki do przeładowania.")
|
||||
S("Graph geodesic: any sequence of tiles is OK as long as there are no shortcuts. 4 turns to reload.", "Geodezyjna grafowa: każdy ciąg pól dobry o ile nie ma skrótów. 4 kolejki do przeładowania.")
|
||||
S("geometric", "linie geometryczne")
|
||||
S("Approximations of geometric straight lines.", "Przybliżenia geometrycznych linii prostych")
|
||||
S("bump to shoot", "uderz by strzelać")
|
||||
S("mouse auto-fire mode", "tryb auto-strzału dla myszy")
|
||||
S("explicit", "kategoryczny")
|
||||
S("You need to click crossbow or be close to fire.", "By strzelać, musisz nacisnąć kuszę, albo być blisko.")
|
||||
S("priority", "priorytetowy")
|
||||
S("Click on a faraway monster to fire if possible, or move if not.", "Klikając odległego przeciwnika strzelasz jeśli to możliwe, ruszasz się jeśli nie.")
|
||||
S("Clicking on a faraway monster always means an attempt to fire.", "Kliknięcie przeciwnika zawsze jest rozumiane jako próba strzału.")
|
||||
S("blade", "broń biała")
|
||||
S("Standard Rogue weapon. Bump into a monster to hit. Most monsters attack you the same way.",
|
||||
"Standardowa broń. Uderz potwora, by go zaatakować. Większość potworów atakuję Cię w ten sposób.")
|
||||
S("crossbow", "kusza")
|
||||
S("Hits all monsters in a straight line, but slow to reload. Press 'f' or click the crossbow icon to target.",
|
||||
"Rani wszystkich przeciwników w linii prostej, ale przeładowanie zajmuje dużo czasu. Naciśnij 'f' lub kliknij ikonę kuszy, by celować.")
|
||||
|
||||
// 'click to use orb' errors
|
||||
|
||||
S("You have no ranged Orbs!", "Nie masz Sfer działających na odległość!")
|
||||
S("Strong wind can only take you to a specific place!", "Silny wiatr może przenieść Cię tylko w konkretne miejsce!")
|
||||
S("%The1 can only be used on items!", "%1 może być używan%y1 tylko na przedmiotach!")
|
||||
S("Nothing to blow here!", "Tu nic nie można zdmuchnąć!")
|
||||
S("Cannot be used in multiplayer", "Nie można używać w grze na wielu graczy")
|
||||
S("You cannot grow on yourself!", "Nie możesz rosnąć na sobie!")
|
||||
S("Cannot attack there!", "Nie można tam zaatakować!")
|
||||
S("Cannot grow there!", "Nie można tam rosnąć!")
|
||||
S("Cannot grow against gravity!", "Nie można rosnąć wbrew grawitacji!")
|
||||
S("You cannot grow there from any adjacent cell!", "Nie można tam wyrosnąć z żadnego sąsiedniego pola!")
|
||||
S("Cannot vault that far!", "Nie można przeskoczyć tak daleko!")
|
||||
S("ERROR: No common neighbor to vault through!", "BŁĄD: brak wspólnego sąsiada do przeskoku!")
|
||||
S("Can only vault in a roughly straight line!", "Przeskok można wykonać tylko w (mniej więcej) prostej linii!")
|
||||
S("Nothing to vault over!", "Nie ma przez co przeskoczyć!")
|
||||
S("Cannot pass through %the1 while vaulting!", "Nie można przejść przez %a1 podczas przeskoku!")
|
||||
S("Cannot vault onto %the1!", "Nie można przeskoczyć na %a1!")
|
||||
S("Cannot vault to %the1!", "Nie można przeskoczyć do %a1!")
|
||||
S("Cannot attack %the1 while vaulting!", "Nie można zaatakować %a1 podczas przeskoku!")
|
||||
S("Cannot jump that far!", "Nie można skoczyć tak daleko!")
|
||||
S("Cannot jump onto %the1!", "Nie można wskoczyć na %a1!")
|
||||
S("Cannot phase that far!", "Nie można fazować tak daleko!")
|
||||
S("Cannot phase onto %the1!", "Nie można fazować na %a1!")
|
||||
S("Cannot phase to %the1!", "Nie można fazować do %a1!")
|
||||
S("Nothing to phase through!", "Nie ma nic przez co można fazować!")
|
||||
S("Can only use %the1 on a monster!", "Można użyć %a1 tylko na potworze!")
|
||||
S("%The1 is immune to %the2!", "%1 jest odporn%y1 na %a2!")
|
||||
S("%The1 can only be used on monsters.", "%1 może być użyt%y1 tylko na potworach.")
|
||||
S("%The1 cannot be used on big monsters.", "%1 nie może być użyt%y1 na dużych potworach.")
|
||||
S("%The1 cannot be used on %the2.", "%1 nie może być użyt%y1 na %abl2.")
|
||||
S("%The1 is already stunned!", "%1 już jest ogłuszon%y1!")
|
||||
|
||||
// multiplayer settings
|
||||
|
||||
S("friendly fire", "bratobójczy ogień")
|
||||
S("friendly fire off -- achievements disabled", "bratobójczy ogień wyłączony -- osiągnięcia wyłączone")
|
||||
|
||||
S("player vs player", "gracz vs gracz")
|
||||
S("PvP available only in shmup", "tryb gracz vs gracz dostępny tylko w trybie strzelanki")
|
||||
S("PvP grants infinite lives -- achievements disabled", "gracz vs gracz daje nieskończenie wiele żyć -- osiągnięcia wyłączone")
|
||||
|
||||
S("split screen mode", "tryb podzielonego ekranu")
|
||||
S("achievements disabled in split screen", "podzielony ekran -- osiągnięcia wyłączone")
|
||||
|
||||
S("auto-adjust dual-focus projections", "automatycznie dostosuj projekcje podwójnie zogniskowane")
|
||||
S("autoscale dual focus", "automatyczne skalowanie przy podwójnym ogniskowaniu")
|
||||
|
||||
S("self hits", "atakowanie siebie")
|
||||
|
||||
S(" (%1 $$$, %2 kills, %3 deaths)", "(%1 $$$, pokonanych: %2, śmierci: %3)")
|
||||
S(" (%1 pkills)", " (%1 pokonanych graczy)")
|
||||
S(" (%1 self)", " (%1 siebie)")
|
||||
|
||||
// racing mode
|
||||
|
||||
S("play on an official track", "graj na torze oficjalnym")
|
||||
S("generate a random track", "generuj tor losowy")
|
||||
S("Too many pauses!", "za dużo pauz!")
|
||||
S("Pauses: %1 of %2 allowed", "Pauzy: %1 dozwolone: %2")
|
||||
|
||||
// new land structures
|
||||
|
||||
S("horodisks", "horodyski")
|
||||
S("land size in horodisk mode", "wielkość krainy w trybie horodysków")
|
||||
S("Set this to -2 to get perfect horodisks. Smaller values yield less dense horodisks, and larger values might produce horodisks with errors or crashing into each other.",
|
||||
"Ustaw -2 by horodyski były dokładne. Mniejsze wartości to rzadsze horodyski; większe wartości mogą powodować, że horodyski się zderzają, i inne błędy.")
|
||||
|
||||
S("ideal Voronoi", "idealne Voronoi")
|
||||
S("display Voronoi tie debug values", "wartości do debugowania Voronoi")
|
||||
|
||||
S("land size in randomwalk mode", "wielkość krainy w trybie błądzenia losowego")
|
||||
S("The average size of a land in randomwalk mode.", "Średnia wielkość krainy w trybie błądzenia losowego.")
|
||||
|
||||
S("this starting land is not eligible for achievements", "ta kraina startu wyłącza osiągnięcia")
|
||||
S("eligible for most achievements", "większość osiągnięć legalna")
|
||||
S("eligible for Chaos mode achievements", "osiągnięcia trybu Chaosu legalne")
|
||||
S("eligible for special achievements", "osiągnięcia spejalne legalne")
|
||||
S("not eligible for achievements", "osiągnięcia nielegalne")
|
||||
S("(but the cheat mode is on)", "(ale włączono tryb oszusta)")
|
||||
S("(but the casual mode is on)", "(ale włączono tryb niezobowiązujący)")
|
||||
|
||||
// other gameplay
|
||||
|
||||
S("There should be a Palace somewhere nearby...", "Gdzieś tu powinien być Pałac...")
|
||||
S("The following Orbs act an extra lives in the shmup mode:", "Następujące sfery w trybie strzelanki dają dodatkowe życie:")
|
||||
S("\n\nThis Orb is triggered on your first direct melee attack or illegal move.", /* 'direct melee' added to an earlier version of this message */
|
||||
"\n\nTa Sfera się aktywuje automatycznie, gdy wykonasz bezpośredni atak wręcz lub nielegalny ruch.")
|
||||
S("\n\nOrb unlocked: %1", "\n\nSfera odblokowana: %1")
|
||||
S("toggle numerical display", "przestaw tryb numeryczny") // in help
|
||||
S("display mine counts numerically", "pokazuj liczby min cyframi")
|
||||
S("Accessible only from %the1, %2, or %3.\n", "Kraina dostępna jedynie z: %1, %2, %3.\n")
|
||||
S("Cannot switch places with %the1!", "Nie można się zamienić miejscami z %abl1!")
|
||||
S("d%1 rolled %2", "d%1 wyrzuciła %2")
|
||||
|
||||
S("orb display mode", "tryb pokazywania sfer")
|
||||
S("icons", "ikony")
|
||||
|
||||
// menu & configuration
|
||||
//======================
|
||||
|
||||
S("default: ", "domyślne: ")
|
||||
S("use the default value", "użyj wartości domyślnych")
|
||||
|
||||
S("pick scores", "wybór wyników")
|
||||
|
||||
S("Angle to rotate by.", "O jaki kąt obrócić")
|
||||
S("dxy(n) = rotate n degrees from x to y\n\nd-degree, r-radian, t-turn\n\nexample: dxy(30)*dyz(45)",
|
||||
"dxy(n) = obróć n stopni od x do y\n\nd-stopeń (degree), r-radian, t-obrót (turn)\n\nprzykład: dxy(30)*dyz(45)")
|
||||
|
||||
S("no filters", "bez filtrów")
|
||||
|
||||
S("yet another classic game", "kolejna klasyczna gra") // hyperbolic Minesweeper
|
||||
|
||||
S("context help", "pomoc kontekstowa")
|
||||
S("all context help/welcome messages", "pełna pomoc kontekstowa")
|
||||
S("no context help/welcome messages", "bez pomocy kontekstowej")
|
||||
S("I know I can press F1 for help", "wiem, że mogę nacisnąć F1 by dostać pomoc")
|
||||
|
||||
S("menu map darkening", "przyciemnianie mapy w menu")
|
||||
S("A larger number means darker game map in the background. Set to 8 to disable the background.",
|
||||
"Większa liczba to ciemniejsze tło z mapą gry. Ustaw 8, by całkowicie wyłączyć tło.")
|
||||
S("centered menus in widescreen", "wycentrowane menu przy szerokim ekranie")
|
||||
|
||||
S("less items/kills in landscape", "mniej przedmiotów/zabić w trybie pejzażu")
|
||||
S("less items/kills in portrait", "mniej przedmiotów/zabić w trybie portretu")
|
||||
|
||||
S("forced center down", "centrum niżej")
|
||||
S("make the center not the actual screen center", "umieść centrum mapy poniżej centrum ekranu")
|
||||
|
||||
// animations
|
||||
|
||||
S("idle animation speed", "prędkość animacji własnej")
|
||||
S("flashing effects", "efekty rozbłysku")
|
||||
S("Disable if you are photosensitive. Replaces flashing effects such as Orb of Storms lightning with slow, adjustable animations.",
|
||||
"Wyłącz jeśli jesteś czuł%y0 na światło. Zamienia rozbłyski takie, jak efekt błyskawicy, na powolne, konfigurowalne animacje.")
|
||||
|
||||
S("start animations", "animacje podczas startu gry")
|
||||
|
||||
S("movement animation", "animacja ruchu")
|
||||
|
||||
S("animation rug angle", "kąt animacji dywanu")
|
||||
S("rug forward movement angle", "kąt ruchu wprost dywanu")
|
||||
S("rug_camera angle", "kąt kamery dywanu")
|
||||
S("translation+rotation", "translacja+rotacja")
|
||||
|
||||
// save file selection
|
||||
|
||||
S("select the score/save file on startup", "wybierz plik postępów podczas uruchamiania")
|
||||
S("choose your score/save file", "Wybierz plik z zapisanymi stanami gry i wynikami")
|
||||
S("Save the config and restart to select another score/save file.", "Zapisz konfigurację i zrestartuj, by użyć innego pliku postępów.")
|
||||
S("Save the config to always play without recording your progress.", "Zapisz konfigurację, by zawsze grać bez zapisu postępów.")
|
||||
S("Save the config to always use %1.", "Zapisz konfigurację by zawsze używać pliku postępów %1.")
|
||||
S("Your progress will not be saved.", "Twoje postępy nie będą zapisywane.")
|
||||
|
||||
// online demo (not translated but just in case)
|
||||
|
||||
S("HyperRogue %1: online demo", "HyperRogue %1: demo online")
|
||||
S("play the game", "gramy")
|
||||
S("learn about hyperbolic geometry", "nauka o geometrii hiperbolicznej")
|
||||
S("toggle high detail", "przestaw wysoki poziom szczegółów")
|
||||
|
||||
// other
|
||||
|
||||
S("wiki", "wiki")
|
||||
S("highlight faraway monsters", "podświetlaj odległe potwory")
|
||||
|
||||
// map editor, line patterns, etc.
|
||||
//=================================
|
||||
|
||||
S("hint: shift+A to enter the map editor", "wskazówka: shift+A uruchamia edytor map")
|
||||
|
||||
S("z = set Shift+click", "z = ustaw Shift+klik")
|
||||
S("B = build on walls ", "B = budowa na ścianie")
|
||||
S("S = snap (%1)", "S = przyciąganie (%1)")
|
||||
S("Z =", "Z = ")
|
||||
S("X =", "X = ")
|
||||
S("Y =", "Y = ")
|
||||
S("w: %1", "w: %1")
|
||||
S("λ: %1°", "λ: %1°")
|
||||
|
||||
S("edit cell values", "edytuj zmienne w polach")
|
||||
S("canvas floor shape", "kształt podłogi płotna")
|
||||
S("canvas darkness", "przyciemnianie płótna")
|
||||
|
||||
S("die shape", "kształt kostki")
|
||||
S("die face", "ścianka kostki")
|
||||
S("die direction", "kierunek kostki")
|
||||
S("die mirror status", "stan lustrzanego odbicia kostki")
|
||||
S("mirrored", "lustrzane")
|
||||
|
||||
// line patterns
|
||||
|
||||
S("parallel/meridian orientation", "orientacja równoleżników i południków")
|
||||
S("number of parallels drawn", "liczba rysowanych równoleżników")
|
||||
S("last parallel drawn", "ostatni równoleżnik rysowany")
|
||||
S("tree-drawing parameter", "parametr rysowania drzew")
|
||||
S("How much of edges to draw for tree patterns (to show how the tree edges are oriented).",
|
||||
"Jaką część krawędzi rysować (by pokazać, w którą stronę zorientowane są krawędzie drzewa).")
|
||||
|
||||
// debug tools
|
||||
|
||||
S("error", "błąd")
|
||||
|
||||
S("display tile debug values", "pokaż wartości do debugowania kafelków")
|
||||
S("Display cell type IDs, as well as vertex and edge identifiers.\n\n"
|
||||
"Setting 1 uses the internal shape IDs, while setting 2 in tes files uses the original IDs"
|
||||
" in case if extra tile types were added to separate mirror images or different football types.",
|
||||
|
||||
"Typy komórek, numery krawędzi i wierzchołków. Ustaw 1 = wewnętrzne IDy kształtów, 2 = oryginalne IDy, "
|
||||
"o ile dodatkowe typy zostały dodane, by odseparować odbicia lustrzane lub dodatkowe typy wprowadzone w celu uzyskania kolorowalności piłki nożnej.")
|
||||
|
||||
// tessellations / honeycombs / projections / embeddings
|
||||
//========================================================
|
||||
|
||||
// new geometry settings
|
||||
|
||||
S("projective Bring's Surface", "rzutowa powierzchnia Bringa")
|
||||
S("aperiodic hat", "aperiodyczny kapelusz (hat)")
|
||||
S("Sierpiński triangle", "trójkąt Sierpińskiego")
|
||||
S("Sierpiński carpet", "dywan Sierpińskiego")
|
||||
S("6-flake fractal", "fraktal 6-płatek")
|
||||
S("Menger sponge", "gąbka Mengera")
|
||||
S("Sierpiński tetrahedron", "czworościan Sierpińskiego")
|
||||
S("aperiodic spectre", "aperiodyczny spektr (spectre)")
|
||||
|
||||
// inter-geometric portals
|
||||
|
||||
S("Welcome to a portal map! Press 'o' to configure.", "Witaj w mapie portalowej! Naciśnij 'o', by skonfigurować.")
|
||||
S("become a portal map", "Przekształć na mapę portalową")
|
||||
S("yes, that's what I want", "Tak, tego chcę")
|
||||
S("world list", "lista światów")
|
||||
S("manage portals", "zarządzanie portalami")
|
||||
S("view another world", "pokaż inny świat")
|
||||
S("connect ", "połącz ")
|
||||
S("disconnect this portal", "rozłącz ten portal")
|
||||
S("remove %1 from the list", "usuń %1 z listy")
|
||||
S("add to list", "dodaj do listy")
|
||||
S("portal orientation", "orientacja portalu")
|
||||
S("mirror connection", "połączenie lustrzane")
|
||||
S("test portal here", "testuj portal tutaj")
|
||||
S("set recommended settings", "ustaw zalecane ustawienia")
|
||||
S("height-to-width ratio", "stosunek wysokości do szerokości")
|
||||
|
||||
S("keep eye level when walking enabled", "trzymaj poziom oka podczas chodzenia")
|
||||
S("walking eye angle", "chodzenie: kąt widzenia")
|
||||
S("0 = looking forward, 90 = looking upward. In VR this is adjusted automatically.",
|
||||
"0 = wprost, 90 = do góry. W VR to jest dostosowywane automatycznie.")
|
||||
S("eye angle scale", "skalowanie kąta widzenia")
|
||||
S("1 = the angle can be changed with keyboard or mouse movements, 0 = the angle is fixed",
|
||||
"1 = kąt widzenia można zmieniać klawiaturą lub myszą, 0 = kąt jest sztywno ustalony")
|
||||
S("walking eye level", "chodzenie: poziom oka")
|
||||
S("Distance from the floor to the eye in the walking mode, in absolute units. In VR this is adjusted automatically.",
|
||||
"Odległość od podłogi do oka w trybie chodzenia, w jednostkach bezwzględnych. W trybie VR jest to dobierane automatycznie.")
|
||||
|
||||
S("move the camera with arrow keys and Home/End", "strzałki i Home/End by ruszać kamerą")
|
||||
S("the map is fixed (improves performance)", "stała mapa (lepsza wydajność)")
|
||||
|
||||
S("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",
|
||||
"Jesteś w wizualizacji. Klawisze: wasd by przesuwać, qe by obracać. Można też używać strzałek. ESC by wyjść do menu.\n\n")
|
||||
|
||||
S("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",
|
||||
"Jesteś w wizualizacji. Klawisze: wasdqe by obracać kamerę, ijklyh by poruszać. Można też używać strzałek, Home/End, i PgUp/PgDn. ESC by wyjść do menu.\n\n")
|
||||
|
||||
S("pure exploration (game keys scroll)", "czysta eksploracja (klawisze gry przewijają)")
|
||||
|
||||
// subdivisions of 3D honeycombs
|
||||
|
||||
S("sub-cubes", "pod-kostki")
|
||||
S("dual sub-cubes", "dualne pod-kostki")
|
||||
S("bitruncated sub-cubes", "przycięte pod-kostki")
|
||||
S("note: more choices in cubic honeycombs", "uwaga: w teselacjach 3D kubicznych jest więcej możliwości")
|
||||
S("subdivision", "podział")
|
||||
S("split by original faces", "podziel według ścian oryginalnych komórek")
|
||||
S("split by vertex axes", "podziel według osi wierzchołków")
|
||||
S("split by midedges", "podziel według środków krawędzi")
|
||||
S("Outside of the supported limits", "przekraczasz dozwolone limity")
|
||||
// let's just not translate this
|
||||
S("subcubed", "subcubed")
|
||||
S("dual-subcubed", "dual-subcubed")
|
||||
S("bitruncated-subcubed", "bitruncated-subcubed")
|
||||
S("subdivided", "subdivided")
|
||||
|
||||
// restrict map to disk
|
||||
|
||||
S("disk size", "rozmiar dysku")
|
||||
S("Play on a disk. Enables the special game rules for small bounded spaces (especially relevant for e.g. Minefield and Halloween). "
|
||||
"The number given is the number of tiles to use; it is not used exactly, actually the smallest disk above this size is used. Set to 0 to disable.",
|
||||
"Graj na dysku. Uruchamia specjalne reguły gry dla małych, ograniczonych przestrzeni, które są szczególnie ważne dla Pola Minowego i Halloween. "
|
||||
"Podaj, ile ma być pól; zwykle nie będzie dokładnie tyle, najmniejszy dysk ponad ten rozmiar będzie użyty. Ustaw 0 by wyłączyć.")
|
||||
|
||||
S("disk shape", "kształt dysku")
|
||||
S("distance in tiles", "odległość w polach")
|
||||
S("distance in vertices", "odległość w wierzchołkach")
|
||||
S("geometric distance", "odległość geometryczna")
|
||||
S("fraction of mine in bounded minefield", "frakcja min w ograniczonym polu minowym")
|
||||
|
||||
// tessellation tree generation
|
||||
|
||||
S("strict tree maps", "ściśle drzewiaste mapy")
|
||||
S("display distances up to", "pokazuj odległości aż do")
|
||||
S("extend automatically", "automatycznie rozszerzaj tablicę") // the table of tile count by distances
|
||||
S("rules generated successfully: %1 states using %2-%3 cells", "reguły wygenerowane, liczba stanów: %1, liczba pól: %2-%3")
|
||||
S("too difficult: %1", "za trudne: %1")
|
||||
S("bug: %1", "bug: %1")
|
||||
S(
|
||||
"Strict tree maps are generated using a more powerful algorithm.\n\nThis algorithm supports horocycles and knows the expansion rates of various "
|
||||
"tessellations (contrary to the basic implementation of Archimedean, tes, and unrectified/warped/untruncated tessellations).\n\nYou can convert mostly any "
|
||||
"non-spherical periodic 2D tessellation to strict tree based.\n\nSwitching the map format erases your map.",
|
||||
|
||||
"Ściśle drzewiaste mapy używają mocniejsego algorytmu.\n\n"
|
||||
"W tym algorytmie działają horocykle i obliczanie stopnia ekspansji dla różnych teselacji (w przeciwieństwie do podstawowej implementacji map archimedesowych, "
|
||||
".tes, i teselacji unrectified/warped/untruncated).\n\n"
|
||||
"Można skonwertować prawie dowolną niesferyczną okresową teselację 2D do ściśle drzewiastej mapy.\n\n"
|
||||
"Ta konwersja powoduje wykasowanie Twojej obecnej mapy gry."
|
||||
)
|
||||
|
||||
S("in tes internal format", "w formacie wewnętrznym .tes")
|
||||
S("converted successfully -- %1 cell types", "konwersja udana -- liczba typów pól: %1")
|
||||
S("cannot be disabled for this tiling", "nie da się wyłączyć dla tej teselacji")
|
||||
S("extended football colorability", "rozszerzona kolorowalność w stylu piłki nożnej")
|
||||
S("consider all symmetries when converting", "przy konwersji uwzględniaj wszystkie symetrie")
|
||||
S("tes reverse order on convert", "odwrócona kolejność tes przy konwersji")
|
||||
S("maximum cellcount", "max liczba pól")
|
||||
S("controls the max memory usage of conversion algorithm -- the algorithm fails if exceeded",
|
||||
"steruje maksymalnym zużyciem pamięci algorytmu konwersji -- jeśli przekroczymy podaną wartość, algorytm jest przerywany")
|
||||
|
||||
// hat tiling
|
||||
|
||||
S("hat/spectre/turtle parameter", "parametr hat/spectre/turtle")
|
||||
S("Apeirodic hat tiling based on: https://arxiv.org/pdf/2303.10798.pdf\n\n"
|
||||
"This controls the parameter discussed in Section 6. Parameter p is Tile(p, (2-p)√3), "
|
||||
"scaled so that the area is the same for every p.\n\n"
|
||||
"Aperiodic spectre tiling based on: https://arxiv.org/abs/2305.17743\n\n"
|
||||
"In the spectre tiling, set the parameter to 'spectre' value to make all tiles have the same shape.",
|
||||
|
||||
"Hat: aperiodyczny parkietaż oparty na: https://arxiv.org/pdf/2303.10798.pdf\n\n"
|
||||
"Tu możemy sterować parametrem opisanym w Sekcji 6. Parametr p to Tile(p, (2-p)√3), "
|
||||
"przeskalowany tak, by pole było takie samo dla każdego p.\n\n"
|
||||
"Spectre: aperiodyczny parkietaż oparty na: https://arxiv.org/abs/2305.17743\n\n"
|
||||
"W tym parkietażu ustaw parametr na 'spectre' by wszystkie kafelki miały ten sam kształt.")
|
||||
|
||||
S("Welcome to HatRogue!", "Witaj w HatRogue!")
|
||||
S("hat in cluster", "kapelusz w klastrze")
|
||||
S("hat clusters", "klastry kapeluszy")
|
||||
S("hat superclusters", "superklastry")
|
||||
S("types (mark reverse)", "typy (zaznacz odwrócone)")
|
||||
S("display small floors", "małe podłogi")
|
||||
S("chevron (periodic)", "szewron")
|
||||
S("hat", "kapelusz ('hat')")
|
||||
S("spectre", "spektr ('spectre')")
|
||||
S("turtle", "żółw ('turtle')")
|
||||
S("comma (periodic)", "przecinek")
|
||||
|
||||
S("hat parameter (imaginary)", "parametr hat (część urojona)")
|
||||
S("Imaginary part of the hat parameter. This corresponds to the usual interpretation of complex numbers in Euclidean planar geometry: "
|
||||
"rather than shortened or lengthened, the edges are moved in the other dimension.",
|
||||
"Część urojona parametru hat. Odpowiada ona standardowej interpretacji liczb zespolonych w geometrii płaskiej: "
|
||||
"zamiast skracać czy wydłużać, krawędzie są przemieszczane w drugim wymiarze."
|
||||
)
|
||||
|
||||
// fake curvature setting in experiments in geometry (some texts were not translated)
|
||||
|
||||
S(
|
||||
"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",
|
||||
|
||||
"Ta funkcja pozwala skonstruować ten sam parkietaż, ale z kształów pochodzących z geometrii o innej krzywiźnie.\n\n"
|
||||
"Podana liczba to (w 2D) stopień wierczhołka lub (w 3D) liczba komórek wokół krawędzi.\n\n")
|
||||
|
||||
S("original", "oryginalna")
|
||||
S("double original", "podwójna oryginalna")
|
||||
S("draw all if multiple of original", "rysuj wszystkie jeśli wielokrotność oryginalnej")
|
||||
S("draw copies (2D only)", "rysuj kopie (tylko 2D)")
|
||||
S("unordered", "nieuporządkowane")
|
||||
S("pre-ordered", "uporządkowane przed")
|
||||
S("post-ordered", "uporządkowane po")
|
||||
|
||||
// other tessellation-related
|
||||
|
||||
S("color by symmetries (reversed tiles marked)", "koloruj po symetriach (zaznacz odwrócone kafelki)")
|
||||
S("unreversed colors", "kolory nie odwrócone")
|
||||
S("symmetric subdivision", "symetryczny podział")
|
||||
S("simplified display of apeirogons", "uproszczone pokazywanie apeirogonów")
|
||||
|
||||
S("Width of cell boundaries", "szerokość brzegów pól")
|
||||
S("How wide should the cell boundaries be.", "Jak szerokie powinny być brzegi pól.")
|
||||
|
||||
S("the following sliders will restart the game", "te suwaki restartują grę")
|
||||
|
||||
// new projections and parameters
|
||||
|
||||
S("horocyclic equal-area", "horocykliczny, równe pola")
|
||||
S("conformal square", "kwadrat konforemny")
|
||||
S("Lie perspective", "perspektywa w grupie Liego")
|
||||
S("Lie orthogonal", "rzut ortogonalny w grupie Liego")
|
||||
S("relativistic perspective", "perspektywa relatywistyczna")
|
||||
S("relativistic orthogonal", "rzut ortogonalny relatywistyczny")
|
||||
S("angle between the axes", "kąt między osiami")
|
||||
S("In two-axe-based models, this parameter gives the angle between the two axes.", "W modelach opartych na dwóch osiach ten parametr określa kąt między osiami.")
|
||||
S("model orientation 3D", "orientacja modelu w 3D")
|
||||
S("semidirect_rendering (perspective on GPU)", "półbezpośrednie (perspektywa na GPU)")
|
||||
S("this is not a Lie group", "to nie grupa Liego")
|
||||
S("not implemented", "nie zaimplementowane")
|
||||
|
||||
S("auto rotation", "automatyczne obracanie")
|
||||
S("auto rotation in 3D", "automatyczne obracanie w 3D")
|
||||
|
||||
// alternative screen projections
|
||||
|
||||
S("stereo/high-FOV mode", "tryb stereo / duże pole widzenia")
|
||||
S("linear perspective", "perspektywa liniowa")
|
||||
S("for red-cyan glasses", "do użycia z czerowno-turkusowymi okularami 3D")
|
||||
S("for mobile VR", "do mobilnego VR")
|
||||
S("ODS", "rzut ODS")
|
||||
S("for rendering 360° VR videos (implemented only in raycaster and some other parts)",
|
||||
"do renderowania filmów VR w 360° stopniach (zaimplementowane jedynie w raycasterze i innych szczególnych przypadkach)")
|
||||
S("Panini", "Panini")
|
||||
S("Projection believed to be used by Italian painters. Allows very high FOV angles while rendering more straight lines as straight than the stereographic projection.",
|
||||
"Rekonstrukcja rzutu używanego przez włoskich malarzy. Bardzo duże pole widzenia, ale więcej linii prostych niż w rzucie stereograficznym.")
|
||||
S("stereographic", "rzut stereograficzny")
|
||||
S("Stereographic projection allows very high FOV angles.", "Rzut stereograficzny pozwala na bardzo duże pole widzenia.")
|
||||
S("equirectangular", "rzut równoprostokątny")
|
||||
S("for rendering 360° videos (implemented only in raycaster)", "do filmów w 360° (zaimplementowany tylko w raycasterze)")
|
||||
S("stereographic/Panini parameter", "parametr rzutu stereograficznego/Paniniego")
|
||||
S("1 for full stereographic/Panini projection. Lower values reduce the effect.\n\n"
|
||||
"HyperRogue uses a quick implementation, so parameter values too close to 1 may be buggy (outside of raycasting); try e.g. 0.9 instead.",
|
||||
"1 to pełny rzut stereograficzny/Paniniego; mniejsze wartości to efekt pośredni.\n\n"
|
||||
"Obecna implementacja jest uproszczona, także wartości parametru zbytnio bliskie 1 mogą powodować błędy graficzne (poza trybem raycastingu), "
|
||||
"także zaleca się używać mniejszych wartości, przykładowo 0.9."
|
||||
)
|
||||
|
||||
// embeddings
|
||||
//============
|
||||
|
||||
S("3D embedding method", "metoda zanurzenia w 3D")
|
||||
S("3D style", "styl 3D")
|
||||
S("2D engine", "silnik 2D")
|
||||
S("Use HyperRogue's 2D engine to simulate same curvature. Works well in top-down and third-person perspective. The Hypersian Rug mode can be used to project this to a surface.",
|
||||
"Używamy silnika 2D by symulować tą samą krzywiznę w trzecim wymiarze. Działa dobrze przy widoku z góry i z perspektywy trzeciej osoby. Tryb Hiperskiego Dywanu "
|
||||
"może być użyty, by zrobić rzut na powierzchnię w trzech wymiarach.")
|
||||
S("same curvature", "ta sama krzywizna")
|
||||
S("Embed as an equidistant surface in the 3D version of the same geometry.",
|
||||
"Zanurz jako powierzchnia ekwidystantna w trójwymiarowej wersji tej samej geometrii.")
|
||||
S("lower curvature", "niższa krzywizna")
|
||||
S("Embed as a surface in a space of lower curvature.", "Zanurz jako powierzchnia w przestrzeni o niższej krzywiźnie.")
|
||||
S("much lower curvature", "o wiele niższa krzywizna")
|
||||
S("Embed sphere as a sphere in hyperbolic space.", "Zanurz sferę w przestrzeni hiperbolicznej.")
|
||||
S("product", "produkt")
|
||||
S("Add one extra dimension in the Euclidean way.", "Dodaje dodatkowy wymiar w sposób Euklidesowy.")
|
||||
S("Embed Euclidean plane into Nil.", "Zanurz płaszczyznę euklidesową w geometrię Nil.")
|
||||
S("Embed Euclidean or hyperbolic plane into Sol.", "Zanurz płaszczyznę euklidesową w geometrię Sol.")
|
||||
S("Embed Euclidean or hyperbolic plane into stretched hyperbolic geometry.", "Zanurz płaszczyznę euklidesową lub hiperboliczną w rozciągniętą geometrię hiperboliczną.")
|
||||
S("stretched Sol", "rozciągnięte Sol.")
|
||||
S("Embed Euclidean or hyperbolic plane into stretched Sol geometry.", "Zanurz płaszczyznę euklidesową lub hiperboliczną w rozciągniętą geometrię Sol.")
|
||||
S("Clifford Torus", "torus Clifforda")
|
||||
S("Embed Euclidean rectangular torus into S3.", "Zanurz prostokątny torus w geometrię sferyczną.")
|
||||
S("hyperbolic product", "produkt hiperboliczny")
|
||||
S("Embed Euclidean or hyperbolic plane in the H2xR product space.", "Zanurz płaszczyznę euklidesową lub hiperboliczną w przestrzeń produktową H2xR")
|
||||
S("spherical product", "produkt sferyczny")
|
||||
S("Embed Euclidean cylinder or spherical plane in the H2xR product space.", "Zanurz płaszczyznę euklidesową lub sferę w przestrzeń produktową H2xR")
|
||||
S("Embed Euclidean plane in twisted product geometry.", "Zanurz płaszczyznę euklidesową w skręconą geometrię produktową.")
|
||||
S("Embed Euclidean cylinder in Euclidean space.", "Zanurz walec euklidesowy w przestrzeń euklidesową.")
|
||||
S("hyperbolic cylinder", "walec hiperboliczny")
|
||||
S("Embed Euclidean cylinder in hyperbolic space.", "Zanurz walec euklidesowy w przestrzeń hiperboliczną.")
|
||||
S("product cylinder", "walec produktowy")
|
||||
S("Embed Euclidean cylinder in H2xR space.", "Zanurz walec euklidesowy w przestrzeń produktową H2xR.")
|
||||
S("Nil cylinder", "walec Nil")
|
||||
S("Embed Euclidean cylinder in Nil.", "Zanurz walec euklidesowy w Nil.")
|
||||
S("horocylinder", "horowalec")
|
||||
S("Embed Euclidean as a horocylinder in H2xR space.", "Zanurz płaszczyznę euklidesową jako horowalec w H2xR.")
|
||||
S("SL2 cylinder", "walec SL2")
|
||||
S("Embed Euclidean as a cylinder in twisted product geometry.", "Zanurz walec euklidesowy w poskręcaną przestrzeń produktową.")
|
||||
|
||||
// embedding settings
|
||||
|
||||
S("flat, not equidistant", "płaskie, a nie ekwidystantny")
|
||||
S("invert convex/concave", "odwróć wypukły/wklęsły")
|
||||
|
||||
// embedding errors
|
||||
|
||||
S("set square tiling", "ustaw parkietaż kwadratowy")
|
||||
S("set hex tiling", "ustaw parkietaż sześciokątny")
|
||||
S("error: currently works only in PURE Euclidean regular square or hex tiling", "błąd: obecnie działa tylko w CZYSTYM parkietażu euklidesowym kwadratowym lub sześciokątnym")
|
||||
S("error: currently works only in pure Euclidean, or binary tiling and similar", "błąd: obecnie działa tylko w czystym parkietażu euklidesowym, lub podobnym do parkietażu binarnego")
|
||||
S("set binary tiling variant", "ustaw wariant parkietażu binarnego")
|
||||
S("set ternary tiling", "ustaw parkietaż ternarny")
|
||||
S("set binary tiling", "ustaw parkietaż binarny")
|
||||
S("error: this embedding does not work in shmup", "błąd: to zanurzenie nie działa w trybie strzelanki")
|
||||
S("error: this method works only in rectangular torus", "błąd: ta metoda działa tylko dla torusu prostokątnego")
|
||||
S("set 20x20 torus", "ustaw torus 20x20")
|
||||
S("error: this method works only in cylinder", "błąd: ta metoda działa tylko dla walcowej mapy")
|
||||
S("set cylinder", "ustaw walec")
|
||||
S("error: not supported", "błąd: nie działa")
|
||||
S("error: this method does not work in spherical geometry", "błąd: ta metoda nie działa w geometrii sferycznej")
|
||||
S("error: this method does not work in hyperbolic geometry", "błąd: ta metoda nie działa w geometrii hiperbolicznej")
|
||||
S("3D styles", "style 3D")
|
||||
S("3D detailed settings", "szczegółowe ustawienia 3D")
|
||||
S("more options in 3D engine", "więcej opcji przy użyciu silnika 3D")
|
||||
S("configure Hypersian Rug", "konfiguruj Hiperski Dywan")
|
||||
S("view shift for embedded planes", "zmiana kamery dla zanurzonych płaszczyzn")
|
||||
S("always move on geodesics", "ruch zawsze po geodezyjnych")
|
||||
S("keep levels", "trzymaj poziom")
|
||||
S("keep the vertical angle of the camera", "trzymaj pionowy kąt kamery")
|
||||
S("mixed", "tryb mieszany")
|
||||
S("on geodesics when moving camera manually, keep level when auto-centering", "geodezyjne przy ręcznym ruchu kamerą, trzymaj poziom przy auto-centrowaniu")
|
||||
S("Euclidean embedding rotation", "obrót zanurzenia euklidesowego")
|
||||
S("How to rotate the Euclidean embedding, in degrees.", "O ile obrócić zanurzoną płaszczyznę euklidesową, w stopniach.")
|
||||
S("Euclidean embedding scale", "skala zanurzenia euklidesowego")
|
||||
S("How to scale the Euclidean map, relatively to the 3D absolute unit.", "Jak przeskalować mapę euklidesową, w stosunku do jednostki absolutnej 3D.")
|
||||
S("Euclidean embedding scale Y/X", "skala Y/X zanurzenia euklidesowego")
|
||||
S("This scaling factor affects only the Y coordinate.", "Ten współczynnik skali wpływa jedynie na współrzędną Y.")
|
||||
S("(fix errors)", "(popraw błędy)")
|
||||
S("reset view", "zresetuj obraz")
|
||||
S("needs", "potrzeba: ")
|
||||
|
||||
// embeddings: detailed 3D parameters
|
||||
|
||||
S("set 3D settings automatically", "ustaw 3D automatycznie")
|
||||
|
||||
S("draw plain floors in 3D", "w trybie 3D rysuj zwykłe podłogi")
|
||||
S("floor alpha", "przezroczystość podłóg")
|
||||
S("255 = opaque", "255 = nieprzejrzyste")
|
||||
|
||||
S("altitude of the stars", "wysokość gwiazd")
|
||||
S("star probability", "prawdopodobieństwo gwiazdy")
|
||||
S("probability of star per tile", "prawdopodobieństwo gwiazdy na kafelek")
|
||||
S("night star size (relative to item sizes)", "rozmiar gwiazd nocnych (w stosunku do wielkości przedmiotów)")
|
||||
S("sun size (relative to item sizes)", "rozmiar słońca (w stosunku do wielkości przedmiotów)")
|
||||
S("infinite sky", "nieskończone niebo")
|
||||
S("ratio of high walls to normal walls", "stosunek wysokich ścian do normalnych")
|
||||
S("ratio of very high walls to normal walls", "stosunek bardzo wysokich ścian do normalnych")
|
||||
S("altitude of the sky", "wysokość nieba")
|
||||
S("sky fake height", "fałszywa wysokość nieba")
|
||||
S("Sky is rendered at the distance computed based on the sky height, "
|
||||
"which might be beyond the range visible in fog. To prevent this, "
|
||||
"the intensity of the fog effect depends on the value here rather than the actual distance. Stars are affected similarly.",
|
||||
|
||||
"Niebo jest renderowane w odległości obliczanej na podstawie parametru, "
|
||||
"co może być dalej, niż zasięg widoczny we mgle. By tego uniknąć, "
|
||||
"intensywność mgły zależy od tej wartości zamiast faktycznej odległości. Ten sam efekt wpływa na gwiazdy."
|
||||
)
|
||||
S("sky rendering", "renderowanie powietrza")
|
||||
S("do not draw sky", "nie rysuj powietrza")
|
||||
S("skybox", "skybox")
|
||||
S("infinite depth", "nieskończona głębokość")
|
||||
S("The unit this value is given in is wall height. "
|
||||
"Note that, in exponentially expanding spaces, too high values could cause rendering issues. "
|
||||
"So if you want infinity, values of 5 or similar should be used -- there is no visible difference from infinity and glitches are avoided.",
|
||||
"Ta wartość jest podawana w jednostkach wysokości ściany. "
|
||||
"W przestrzeniach rosnących wykładniczo, zbyt wysokie wartości mogą powodować błędy. "
|
||||
"Także sugerujemy użycie wartości około 5 dla nieskończoności -- nie ma widocznych różnic i te błędy nie wystąpią.")
|
||||
S("Level of shallow water", "poziom płytkiej wody")
|
||||
S("do not render higher levels if camera too high", "nie renderuj wyższych poziomów jeśli kamera jest ponad nimi")
|
||||
S("works only in Euclidean", "działa tylko w przestrzeni euklidesowej")
|
||||
S("always", "zawsze")
|
||||
S("might be glitched in some settings", "w niektórych ustawieniach źle działa")
|
||||
S("prevent exceeding recommended altitudes", "nie przekraczaj rekomendowanych wysokości")
|
||||
|
||||
S("camera angle", "kąt kamery")
|
||||
S("render behind the camera", "renderuj za kamerą")
|
||||
|
||||
// embeddings: pseudohedral setting
|
||||
|
||||
S("make the tiles flat", "płaskie kafelki")
|
||||
S("the tiles are curved", "kafelki są zakrzywione")
|
||||
S("inscribed", "wpisane")
|
||||
S("the tiles are inscribed", "kafelki są wpisane")
|
||||
S("circumscribed", "opisane")
|
||||
S("the tiles are circumscribed", "kafelki są opisane")
|
||||
S("depth bonus in pseudohedral", "bonus do głębokości")
|
||||
|
||||
// embeddings: geodesic movement in Solv etc
|
||||
|
||||
S("straight lines", "linie proste")
|
||||
S("Lie group", "grupy Liego")
|
||||
S("light, camera, and objects move in lines of constant direction, in the Lie group sense", "światło, kamera, i obiekty ruszają się w liniach o stałym kierunku w sensie group Liego")
|
||||
S("geodesics", "geodezyjne")
|
||||
S("light, camera, and objects always take the shortest path", "światło, kamera, i obiekty ruszają się po najkrótszej ścieżce")
|
||||
|
||||
// achievement eligiblity
|
||||
S("achievement/leaderboard eligiblity:", "legalność osiągnięć i rankingów:")
|
||||
S("eligible for most", "większość legalna")
|
||||
S("eligible for most -- leaderboards separate", "większość legalna -- osobne rankingi")
|
||||
S("eligible for racing", "legalne dla wyścigu")
|
||||
S("eligible for shmup", "legalne dla strzelanki")
|
||||
S("eligible for multiplayer", "legalne dla wielu graczy")
|
||||
S("eligible for Chaos mode", "legalne dla trybu Chaosu")
|
||||
S("eligible for Princess Challenge", "legalne dla misji Księżniczka")
|
||||
S("eligible for heptagonal", "legalne dla trybu siedmiokątów")
|
||||
S("eligible for special geometry", "legalne dla geometrii specjalnych")
|
||||
S("eligible for Strange Challenge", "legalne dla Dziwnej Misji")
|
||||
S("disabled in cheat mode", "wyłączone w trybie oszusta")
|
||||
S("disabled in casual mode", "wyłączone w trybie niezobowiązującym")
|
||||
S("not eligible due to current mode settings", "nielegalne w obecnych trybach")
|
||||
S("no achievements/leaderboards in this version", "brak osiągnięć i rankingów w tej wersji")
|
||||
|
|
|
@ -2083,7 +2083,7 @@ S("Mighty warriors from the Fjord, who can use boats.",
|
|||
N("Water Elemental", GEN_M, "Водный элементаль", "Водные элементали", "Водного элементаля", "Водным элементалем")
|
||||
S("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.",
|
||||
"Где бы ни шло это могущественное существо, фьорды расступаются перед ним, "
|
||||
"обычные лодки уничтожаются, огонь гаснет.\n\n"
|
||||
"Однако, если Вы атакуете его, находясь в воде, Вас не затянет сразу в воду.")
|
||||
|
|
|
@ -1994,7 +1994,7 @@ S("Mighty warriors from the Fjord, who can use boats.",
|
|||
N("Water Elemental", GEN_M, "Su Özütü", "Su Özütleri", "Su Özütünü", "Su Özütüyle")
|
||||
S("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.",
|
||||
"Bu güçlü yaratığın geçtiği her yerde Yaşayan Fiyort su altına gömülür, sihirli olmayan kayıklar yok olur ve ateşler söner. \n\n "
|
||||
"İstisna bir durum olarak Su Özütüne suyun içerisinden hemen boğulmadan vurursan onu öldürebilirsin. ")
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
#include "hyper.h"
|
||||
namespace hr {
|
||||
|
||||
EX const string dnameof(eMonster m) { return m >= 0 && m < motypes ? minf[m].name : format("[MONSTER %d]", m); }
|
||||
EX const string dnameof(eLand l) { return l >= 0 && l < landtypes ? linf[l].name : format("[LAND %d]", l); }
|
||||
EX const string dnameof(eWall w) { return w >= 0 && w < walltypes ? winf[w].name : format("[WALL %d]", w); }
|
||||
EX const string dnameof(eItem i) { return i >= 0 && i < ittypes ? iinf[i].name : format("[ITEM %d]", i); }
|
||||
EX const string dnameof(eMonster m) { return m >= 0 && m < motypes ? minf[m].name : hr::format("[MONSTER %d]", m); }
|
||||
EX const string dnameof(eLand l) { return l >= 0 && l < landtypes ? linf[l].name : hr::format("[LAND %d]", l); }
|
||||
EX const string dnameof(eWall w) { return w >= 0 && w < walltypes ? winf[w].name : hr::format("[WALL %d]", w); }
|
||||
EX const string dnameof(eItem i) { return i >= 0 && i < ittypes ? iinf[i].name : hr::format("[ITEM %d]", i); }
|
||||
|
||||
#if HDR
|
||||
#define NUMLAN 8
|
||||
|
|
201
legacy.cpp
201
legacy.cpp
|
@ -204,12 +204,11 @@ int modecodetable[42][6] = {
|
|||
|
||||
EX modecode_t legacy_modecode() {
|
||||
if(int(geometry) > 3 || int(variation) > 1) return UNKNOWN;
|
||||
if(casual) return UNKNOWN;
|
||||
if(bow::weapon) return UNKNOWN;
|
||||
if(use_custom_land_list) return UNKNOWN;
|
||||
|
||||
bool is_default_land_structure =
|
||||
(princess::challenge || tactic::on) ? ls::single() :
|
||||
racing::on ? (land_structure == lsSingle) :
|
||||
yendor::on ? (land_structure == yendor::get_land_structure()) :
|
||||
ls::nice_walls();
|
||||
bool is_default_land_structure = land_structure == get_default_land_structure();
|
||||
|
||||
if(!is_default_land_structure && !ls::std_chaos()) return UNKNOWN;
|
||||
|
||||
|
@ -246,6 +245,41 @@ EX modecode_t legacy_modecode() {
|
|||
return mct;
|
||||
}
|
||||
|
||||
EX void legacy_modecode_read(modecode_t mc) {
|
||||
if(mc >= FIRST_MODECODE) throw hr_exception("not a legacy modecode");
|
||||
|
||||
inv::on = (mc & (1<<11));
|
||||
peace::on = (mc & (1<<12));
|
||||
tour::on = (mc & (1<<13));
|
||||
bool seven = (mc & (1<<14));
|
||||
mc &= (1<<11)-1;
|
||||
|
||||
for(int xcode=0; xcode<42;xcode++) for(int pl=0; pl<6; pl++) if(modecodetable[xcode][pl] == mc) {
|
||||
if(seven) pl = 7; else pl++;
|
||||
multi::players = pl;
|
||||
land_structure = xcode >= 21 ? lsChaos : get_default_land_structure();
|
||||
xcode %= 21;
|
||||
shmup::on = 0; hardcore = false;
|
||||
if(xcode % 3 == 2) shmup::on = true;
|
||||
if(xcode % 3 == 1) hardcore = true;
|
||||
xcode /= 3;
|
||||
geometry = gNormal; variation = eVariation::bitruncated;
|
||||
if(xcode == 1) variation = eVariation::pure;
|
||||
if(xcode == 2) geometry = gEuclid;
|
||||
if(xcode == 3) geometry = gSphere;
|
||||
if(xcode == 4) geometry = gSphere, variation = eVariation::pure;
|
||||
if(xcode == 5) geometry = gElliptic;
|
||||
if(xcode == 6) geometry = gElliptic, variation = eVariation::pure;
|
||||
|
||||
use_custom_land_list = false;
|
||||
bow::weapon = bow::wBlade;
|
||||
casual = false;
|
||||
return;
|
||||
}
|
||||
|
||||
throw hr_exception("legacy code not recognized");
|
||||
}
|
||||
|
||||
#if CAP_RACING
|
||||
EX bool legacy_racing() {
|
||||
return racing::on && geometry == gNormal && BITRUNCATED;
|
||||
|
@ -326,11 +360,166 @@ int read_legacy_args() {
|
|||
stop_game();
|
||||
land_structure = lsNiceWalls;
|
||||
}
|
||||
else if(argis("-grotate")) {
|
||||
PHASE(3); start_game();
|
||||
shift(); int i = argi();
|
||||
shift(); int j = argi();
|
||||
shift(); View = View * cspin(i, j, argf());
|
||||
playermoved = false;
|
||||
}
|
||||
else if(argis("-grotatei")) {
|
||||
PHASE(3); start_game();
|
||||
shift(); int i = argi();
|
||||
shift(); int j = argi();
|
||||
shift(); rotate_view(cspin(i, j, argf()));
|
||||
playermoved = false;
|
||||
}
|
||||
else if(argis("-rotate")) {
|
||||
PHASE(3); start_game();
|
||||
shift(); ld a = argf();
|
||||
shift(); ld b = argf();
|
||||
View = View * spin(TAU * a / b);
|
||||
playermoved = false;
|
||||
}
|
||||
else if(argis("-rotate3")) {
|
||||
PHASE(3); start_game();
|
||||
shift(); ld a = argf();
|
||||
shift(); ld b = argf();
|
||||
View = View * cspin(1, 2, TAU * a / b);
|
||||
playermoved = false;
|
||||
}
|
||||
else if(argis("-cview")) {
|
||||
PHASE(3); start_game();
|
||||
View = Id; playermoved = false;
|
||||
}
|
||||
else if(argis("-ballangle")) {
|
||||
PHASEFROM(2);
|
||||
shift(); println(hlog, "-ballangle not implemented");
|
||||
// shift_arg_formula(vpconf.ballangle);
|
||||
}
|
||||
else if(argis("-crot")) {
|
||||
PHASEFROM(2);
|
||||
shift(); shift(); shift(); println(hlog, "-crot not implemented");
|
||||
/* shift_arg_formula(models::rotation);
|
||||
if(GDIM == 3) shift_arg_formula(models::rotation_xz);
|
||||
if(GDIM == 3) shift_arg_formula(models::rotation_xy2); */
|
||||
}
|
||||
else if(argis("-yca")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vid.yshift);
|
||||
shift(); ld angle = argf();
|
||||
pconf.cam() = cspin(0, 2, angle);
|
||||
}
|
||||
else return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto ah_legacy = addHook(hooks_args, 0, read_legacy_args);
|
||||
int read_legacy_args_anim() {
|
||||
using namespace anims;
|
||||
using namespace arg;
|
||||
ld movement_angle, shift_angle, rug_angle; /* TODO link to anims::angle's */
|
||||
if(0);
|
||||
else if(argis("-animperiod")) {
|
||||
PHASEFROM(2); shift_arg_formula(period);
|
||||
}
|
||||
else if(argis("-animcircle")) {
|
||||
PHASE(3); start_game();
|
||||
ma = maCircle; ma_reaction();
|
||||
shift_arg_formula(circle_spins);
|
||||
shift_arg_formula(circle_radius);
|
||||
shift(); circle_display_color = argcolor(24);
|
||||
}
|
||||
else if(argis("-animmove")) {
|
||||
ma = maTranslation;
|
||||
shift_arg_formula(cycle_length);
|
||||
shift_arg_formula(shift_angle);
|
||||
shift_arg_formula(movement_angle);
|
||||
}
|
||||
else if(argis("-animmoverot")) {
|
||||
ma = maTranslationRotation;
|
||||
shift_arg_formula(cycle_length);
|
||||
shift_arg_formula(shift_angle);
|
||||
shift_arg_formula(movement_angle);
|
||||
}
|
||||
else if(argis("-wallopt")) {
|
||||
wallopt = true;
|
||||
}
|
||||
else if(argis("-animpar")) {
|
||||
ma = maParabolic;
|
||||
shift_arg_formula(parabolic_length);
|
||||
shift_arg_formula(shift_angle);
|
||||
shift_arg_formula(movement_angle);
|
||||
}
|
||||
else if(argis("-animclear")) { clearup = true; }
|
||||
else if(argis("-animrot")) {
|
||||
ma = maRotation;
|
||||
if(GDIM == 3) {
|
||||
shift_arg_formula(movement_angle);
|
||||
shift_arg_formula(normal_angle);
|
||||
}
|
||||
}
|
||||
else if(argis("-innerwall")) {
|
||||
PHASEFROM(2);
|
||||
patterns::innerwalls = true;
|
||||
}
|
||||
else if(argis("-noinnerwall")) {
|
||||
PHASEFROM(2);
|
||||
patterns::innerwalls = false;
|
||||
}
|
||||
else if(argis("-animrotd")) {
|
||||
start_game();
|
||||
ma = maRotation;
|
||||
shift_arg_formula(rotation_distance);
|
||||
}
|
||||
else if(argis("-animrug")) {
|
||||
shift_arg_formula(rug_rotation1);
|
||||
shift_arg_formula(rug_angle);
|
||||
shift_arg_formula(rug_rotation2);
|
||||
}
|
||||
else if(argis("-animenv")) {
|
||||
shift_arg_formula(env_ocean);
|
||||
shift_arg_formula(env_volcano);
|
||||
}
|
||||
else if(argis("-animball")) {
|
||||
shift(); println(hlog, "-animball removed");
|
||||
}
|
||||
else if(argis("-animj")) {
|
||||
shift(); println(hlog, "-animj removed");
|
||||
/* to recreate: if(joukowsky_anim) {
|
||||
ld t = ticks / period;
|
||||
t = t - floor(t);
|
||||
if(pmodel == mdBand) {
|
||||
vpconf.model_transition = t * 4 - 1;
|
||||
}
|
||||
else {
|
||||
vpconf.model_transition = t / 1.1;
|
||||
vpconf.scale = (1 - vpconf.model_transition) / 2.;
|
||||
} */
|
||||
/* skiprope:legacy.cpp pconf.skiprope += skiprope_rotation * t * TAU / period; */
|
||||
}
|
||||
else if(argis("-palpha")) {
|
||||
PHASEFROM(2);
|
||||
#if CAP_GL
|
||||
shift_arg_formula(vid.stereo_param, reset_all_shaders);
|
||||
#else
|
||||
shift_arg_formula(vid.stereo_param);
|
||||
#endif
|
||||
vid.stereo_mode = sPanini;
|
||||
}
|
||||
else if(argis("-salpha")) {
|
||||
PHASEFROM(2);
|
||||
#if CAP_GL
|
||||
shift_arg_formula(vid.stereo_param, reset_all_shaders);
|
||||
#else
|
||||
shift_arg_formula(vid.stereo_param);
|
||||
#endif
|
||||
vid.stereo_mode = sStereographic;
|
||||
}
|
||||
else return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto ah_legacy = addHook(hooks_args, 0, read_legacy_args) + addHook(hooks_args, 0, read_legacy_args_anim);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ extern int cellcount, heptacount;
|
|||
|
||||
#define NODIR 126
|
||||
#define NOBARRIERS 127
|
||||
#define NOBARRIERS2 125
|
||||
|
||||
/** \brief Cell information for the game. struct cell builds on this */
|
||||
struct gcell {
|
||||
|
@ -197,10 +198,10 @@ template<class T> void tailored_delete(T* x) {
|
|||
delete[] ((char*) (x));
|
||||
}
|
||||
|
||||
static const struct wstep_t { wstep_t() {} } wstep;
|
||||
static const struct wmirror_t { wmirror_t() {}} wmirror;
|
||||
static const struct rev_t { rev_t() {} } rev;
|
||||
static const struct revstep_t { revstep_t() {}} revstep;
|
||||
static constexpr struct wstep_t {} wstep = {};
|
||||
static constexpr struct wmirror_t {} wmirror = {};
|
||||
static constexpr struct rev_t {} rev = {};
|
||||
static constexpr struct revstep_t {} revstep = {};
|
||||
|
||||
extern int hrand(int);
|
||||
|
||||
|
@ -212,7 +213,7 @@ template<class T> struct walker {
|
|||
int spin;
|
||||
/** \brief are we mirrored */
|
||||
bool mirrored;
|
||||
walker<T> (T *at = NULL, int s = 0, bool m = false) : at(at), spin(s), mirrored(m) { if(at) s = at->c.fix(s); }
|
||||
walker(T *at = NULL, int s = 0, bool m = false) : at(at), spin(s), mirrored(m) { if(at) s = at->c.fix(s); }
|
||||
/** \brief spin by i to the left (or right, when mirrored */
|
||||
walker<T>& operator += (int i) {
|
||||
spin = at->c.fix(spin+(mirrored?-i:i));
|
||||
|
@ -286,7 +287,7 @@ enum hstate { hsOrigin, hsA, hsB, hsError, hsA0, hsA1, hsB0, hsB1, hsC };
|
|||
struct cell *createMov(struct cell *c, int d);
|
||||
struct heptagon *createStep(struct heptagon *c, int d);
|
||||
|
||||
struct cdata_or_heptagon { virtual ~cdata_or_heptagon() {} };
|
||||
struct cdata_or_heptagon { virtual ~cdata_or_heptagon() = default; };
|
||||
|
||||
struct cdata : cdata_or_heptagon {
|
||||
int val[4];
|
||||
|
@ -452,7 +453,7 @@ struct celllister : manual_celllister {
|
|||
};
|
||||
|
||||
/** \brief translate heptspins to cellwalkers and vice versa */
|
||||
static const struct cth_t { cth_t() {}} cth;
|
||||
static constexpr struct cth_t {} cth = {};
|
||||
inline heptspin operator+ (cellwalker cw, cth_t) { return heptspin(cw.at->master, cw.spin * DUALMUL, cw.mirrored); }
|
||||
inline cellwalker operator+ (heptspin hs, cth_t) { return cellwalker(hs.at->c7, hs.spin / DUALMUL, hs.mirrored); }
|
||||
|
||||
|
@ -468,6 +469,7 @@ constexpr int NO_SPACE = 197;
|
|||
constexpr int TELEPORT = 196;
|
||||
constexpr int JUMP = 195;
|
||||
constexpr int STAY = 194;
|
||||
constexpr int NOMOVEI = 193;
|
||||
|
||||
namespace whirlwind { cell *jumpDestination(cell*); }
|
||||
|
||||
|
|
101
mapeditor.cpp
101
mapeditor.cpp
|
@ -20,7 +20,7 @@ EX namespace mapeditor {
|
|||
|
||||
#if HDR
|
||||
enum eShapegroup { sgPlayer, sgMonster, sgItem, sgFloor, sgWall };
|
||||
static const int USERSHAPEGROUPS = 5;
|
||||
static constexpr int USERSHAPEGROUPS = 5;
|
||||
#endif
|
||||
|
||||
EX color_t dtfill = 0;
|
||||
|
@ -184,10 +184,14 @@ EX namespace mapeditor {
|
|||
if(drawing_tool && (cmode & sm::DRAW)) {
|
||||
shiftpoint moh = full_mouseh();
|
||||
dynamicval<ld> lw(vid.linewidth, vid.linewidth * dtwidth * 100);
|
||||
if(holdmouse && mousekey == 'c')
|
||||
if(holdmouse && mousekey == 'c') {
|
||||
torus_rug_jump(moh, lstart);
|
||||
queue_hcircle(rgpushxto0(lstart), hdist(lstart, moh));
|
||||
else if(holdmouse && mousekey == 'l')
|
||||
}
|
||||
else if(holdmouse && mousekey == 'l') {
|
||||
torus_rug_jump(moh, lstart);
|
||||
queueline(lstart, moh, dtcolor, 4 + vid.linequality, PPR::LINE);
|
||||
}
|
||||
else if(!holdmouse) {
|
||||
shiftmatrix T = rgpushxto0(moh);
|
||||
queueline(T * xpush0(-.1), T * xpush0(.1), dtcolor);
|
||||
|
@ -208,6 +212,9 @@ EX namespace mapeditor {
|
|||
}
|
||||
|
||||
EX void dt_add_line(shiftpoint h1, shiftpoint h2, int maxl) {
|
||||
|
||||
torus_rug_jump(h2, h1);
|
||||
|
||||
if(hdist(h1, h2) > 1 && maxl > 0) {
|
||||
shiftpoint h3 = mid(h1, h2);
|
||||
dt_add_line(h1, h3, maxl-1);
|
||||
|
@ -216,18 +223,21 @@ EX namespace mapeditor {
|
|||
}
|
||||
cell *b = centerover;
|
||||
|
||||
auto xh1 = inverse_shift(ggmatrix(b), h1);
|
||||
virtualRebase(b, xh1);
|
||||
shiftmatrix T = rgpushxto0(h1);
|
||||
auto T1 = inverse_shift(ggmatrix(b), T);
|
||||
virtualRebase(b, T1);
|
||||
hyperpoint xh1 = tC0(T1);
|
||||
|
||||
auto l = new dtline;
|
||||
l->s = xh1;
|
||||
l->e = inverse_shift(ggmatrix(b), h2);
|
||||
l->e = inverse_shift(T*inverse(T1), h2);
|
||||
dt_add(b, l);
|
||||
}
|
||||
|
||||
EX void dt_add_circle(shiftpoint h1, shiftpoint h2) {
|
||||
cell *b = centerover;
|
||||
|
||||
torus_rug_jump(h2, h1);
|
||||
auto d = hdist(h1, h2);
|
||||
|
||||
auto xh1 = inverse_shift(ggmatrix(b), h1);
|
||||
|
@ -271,27 +281,46 @@ EX namespace mapeditor {
|
|||
|
||||
dtfree *cfree;
|
||||
cell *cfree_at;
|
||||
shiftmatrix cfree_old;
|
||||
|
||||
EX void dt_finish() {
|
||||
cfree = nullptr;
|
||||
cfree_at = nullptr;
|
||||
}
|
||||
|
||||
EX void torus_rug_jump(shiftpoint& h, shiftpoint last) {
|
||||
if(!rug::rugged) return;
|
||||
again:
|
||||
|
||||
auto C = ggmatrix(centerover);
|
||||
auto T1 = inverse_shift(C, rgpushxto0(h));
|
||||
|
||||
for(int a=0; a<2; a++) for(int s: {-1, 1}) {
|
||||
transmatrix T = eumove(s * euc::eu.optimal_axes[a]);
|
||||
shiftpoint h1 = C * T * tC0(T1);
|
||||
if(hdist(h1, last) < hdist(h, last) - 1e-6) { h = h1; goto again; }
|
||||
}
|
||||
}
|
||||
|
||||
EX void dt_add_free(shiftpoint h) {
|
||||
|
||||
if(cfree) torus_rug_jump(h, cfree_old * cfree->lh.back());
|
||||
|
||||
cell *b = centerover;
|
||||
shiftmatrix T = rgpushxto0(h);
|
||||
auto T1 = inverse_shift(ggmatrix(b), T);
|
||||
virtualRebase(b, T1);
|
||||
|
||||
if(cfree)
|
||||
cfree->lh.push_back(inverse_shift(ggmatrix(cfree_at), tC0(T)));
|
||||
if(cfree) {
|
||||
cfree->lh.push_back(inverse_shift(cfree_old, tC0(T)));
|
||||
}
|
||||
|
||||
if(b != cfree_at && !(dtfill && cfree_at)) {
|
||||
cfree = new dtfree;
|
||||
dt_add(b, cfree);
|
||||
cfree->lh.push_back(tC0(T1));
|
||||
cfree_at = b;
|
||||
cfree_old = T * inverse(T1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,6 +491,9 @@ EX namespace mapstream {
|
|||
f.write(gp::param.second);
|
||||
}
|
||||
#endif
|
||||
#if CAP_IRR
|
||||
if(IRREGULAR) irr::save_map_bin(f);
|
||||
#endif
|
||||
#if MAXMDIM >= 4
|
||||
if(variation == eVariation::coxeter) {
|
||||
f.write(reg3::coxeter_param);
|
||||
|
@ -541,6 +573,8 @@ EX namespace mapstream {
|
|||
f.write(euc::eu_input.twisted);
|
||||
}
|
||||
f.write(mine_adjacency_rule);
|
||||
f.write(req_disksize);
|
||||
f.write(diskshape);
|
||||
}
|
||||
|
||||
EX void load_geometry(hstream& f) {
|
||||
|
@ -556,6 +590,9 @@ EX namespace mapstream {
|
|||
f.read(gp::param.second);
|
||||
}
|
||||
#endif
|
||||
#if CAP_IRR
|
||||
if(IRREGULAR) { irr::load_map_full(f); stop_game(); }
|
||||
#endif
|
||||
#if MAXMDIM >= 4
|
||||
if(variation == eVariation::coxeter && vernum >= 0xA908) {
|
||||
f.read(reg3::coxeter_param);
|
||||
|
@ -625,7 +662,7 @@ EX namespace mapstream {
|
|||
else {
|
||||
string s;
|
||||
f.read(s);
|
||||
arb::run(s);
|
||||
arb::run_raw(s);
|
||||
stop_game();
|
||||
}
|
||||
if(rk) rulegen::prepare_rules();
|
||||
|
@ -681,6 +718,10 @@ EX namespace mapstream {
|
|||
}
|
||||
if(vernum >= 0xA810)
|
||||
f.read(mine_adjacency_rule);
|
||||
if(vernum >= 0xA933) {
|
||||
f.read(req_disksize);
|
||||
f.read(diskshape);
|
||||
}
|
||||
geometry_settings(was_default);
|
||||
}
|
||||
|
||||
|
@ -705,14 +746,16 @@ EX namespace mapstream {
|
|||
f.write(gen_wandering);
|
||||
f.write(reptilecheat);
|
||||
f.write(timerghost);
|
||||
f.write(patterns::canvasback);
|
||||
f.write(ccolor::plain.ctab[0]);
|
||||
f.write(patterns::whichShape);
|
||||
f.write(patterns::subpattern_flags);
|
||||
f.write(patterns::whichCanvas);
|
||||
char wc = '*';
|
||||
f.write(wc);
|
||||
f.write(ccolor::which->name);
|
||||
f.write(patterns::displaycodes);
|
||||
f.write(canvas_default_wall);
|
||||
f.write(mapeditor::drawplayer);
|
||||
if(patterns::whichCanvas == 'f') f.write(patterns::color_formula);
|
||||
if(ccolor::which == &ccolor::formula) f.write(ccolor::color_formula);
|
||||
f.write(canvasfloor);
|
||||
f.write(canvasdark);
|
||||
|
||||
|
@ -905,15 +948,21 @@ EX namespace mapstream {
|
|||
f.read(gen_wandering);
|
||||
f.read(reptilecheat);
|
||||
f.read(timerghost);
|
||||
f.read(patterns::canvasback);
|
||||
f.read(ccolor::plain.ctab[0]);
|
||||
f.read(patterns::whichShape);
|
||||
f.read(patterns::subpattern_flags);
|
||||
f.read(patterns::whichCanvas);
|
||||
char wc;
|
||||
f.read(wc);
|
||||
if(wc == '*') {
|
||||
string name;
|
||||
f.read(name);
|
||||
for(auto& p: ccolor::all) if(p->name == name) ccolor::which = p;
|
||||
}
|
||||
f.read(patterns::displaycodes);
|
||||
if(f.vernum >= 0xA816)
|
||||
f.read(canvas_default_wall);
|
||||
f.read(mapeditor::drawplayer);
|
||||
if(patterns::whichCanvas == 'f') f.read(patterns::color_formula);
|
||||
if(wc == 'f') f.read(ccolor::color_formula);
|
||||
if(f.vernum >= 0xA90D) {
|
||||
f.read(canvasfloor);
|
||||
f.read(canvasdark);
|
||||
|
@ -1867,7 +1916,7 @@ EX namespace mapeditor {
|
|||
bool coloring;
|
||||
color_t colortouse = 0xC0C0C0FFu;
|
||||
// fake key sent to change the color
|
||||
static const int COLORKEY = (-10000);
|
||||
static constexpr int COLORKEY = (-10000);
|
||||
|
||||
EX shiftmatrix drawtrans, drawtransnew;
|
||||
|
||||
|
@ -2553,16 +2602,16 @@ EX namespace mapeditor {
|
|||
bool onelayeronly;
|
||||
|
||||
bool loadPicFile(const string& s) {
|
||||
fhstream f(picfile, "rt");
|
||||
fhstream f(s, "rt");
|
||||
if(!f.f) {
|
||||
addMessage(XLAT("Failed to load pictures from %1", picfile));
|
||||
addMessage(XLAT("Failed to load pictures from %1", s));
|
||||
return false;
|
||||
}
|
||||
scanline(f);
|
||||
scan(f, f.vernum);
|
||||
printf("vernum = %x\n", f.vernum);
|
||||
if(f.vernum == 0) {
|
||||
addMessage(XLAT("Failed to load pictures from %1", picfile));
|
||||
addMessage(XLAT("Failed to load pictures from %1", s));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2590,6 +2639,7 @@ EX namespace mapeditor {
|
|||
}
|
||||
|
||||
initShape(i, j);
|
||||
println(hlog, "shape ", tie(i, j), " layer ", l);
|
||||
usershapelayer& ds(usershapes[i][j]->d[l]);
|
||||
if(f.vernum >= 0xA608) scan(f, ds.zlevel);
|
||||
ds.shift = readHyperpoint(f);
|
||||
|
@ -2703,8 +2753,7 @@ EX namespace mapeditor {
|
|||
stop_game();
|
||||
enable_canvas();
|
||||
canvas_default_wall = waInvisibleFloor;
|
||||
patterns::whichCanvas = 'g';
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
dtcolor = (forecolor << 8) | 255;
|
||||
drawplayer = false;
|
||||
vid.use_smart_range = 2;
|
||||
|
@ -2725,7 +2774,7 @@ EX namespace mapeditor {
|
|||
|
||||
if(uni == 'z' && GDIM == 3) {
|
||||
dialog::editNumber(front_edit, 0, 5, 0.1, 0.5, XLAT("z-level"), "");
|
||||
dialog::extra_options = [] () {
|
||||
dialog::get_di().extra_options = [] () {
|
||||
dialog::addBoolItem(XLAT("The distance from the camera to added points."), front_config == eFront::sphere_camera, 'A');
|
||||
dialog::add_action([] { front_config = eFront::sphere_camera; });
|
||||
dialog::addBoolItem(XLAT("place points at fixed radius"), front_config == eFront::sphere_center, 'B');
|
||||
|
@ -2740,25 +2789,21 @@ EX namespace mapeditor {
|
|||
}
|
||||
dialog::addSelItem(XLAT("mousewheel step"), fts(front_step), 'S');
|
||||
dialog::add_action([] {
|
||||
popScreen();
|
||||
dialog::editNumber(front_step, -10, 10, 0.1, 0.1, XLAT("mousewheel step"), "hint: shift for finer steps");
|
||||
});
|
||||
if(front_config == eFront::sphere_center) {
|
||||
dialog::addSelItem(XLAT("parallels to draw"), its(parallels), 'P');
|
||||
dialog::add_action([] {
|
||||
popScreen();
|
||||
dialog::editNumber(parallels, 0, 72, 1, 12, XLAT("parallels to draw"), "");
|
||||
});
|
||||
dialog::addSelItem(XLAT("meridians to draw"), its(meridians), 'M');
|
||||
dialog::add_action([] {
|
||||
popScreen();
|
||||
dialog::editNumber(meridians, 0, 72, 1, 12, XLAT("meridians to draw"), "");
|
||||
});
|
||||
}
|
||||
else if(front_config != eFront::sphere_camera) {
|
||||
dialog::addSelItem(XLAT("range of grid to draw"), fts(equi_range), 'R');
|
||||
dialog::add_action([] {
|
||||
popScreen();
|
||||
dialog::editNumber(equi_range, 0, 5, 0.1, 1, XLAT("range of grid to draw"), "");
|
||||
});
|
||||
}
|
||||
|
@ -2854,7 +2899,7 @@ EX namespace mapeditor {
|
|||
static string text = "";
|
||||
dialog::edit_string(text, "", "");
|
||||
shiftpoint h = mh;
|
||||
dialog::reaction_final = [h] {
|
||||
dialog::get_di().reaction_final = [h] {
|
||||
if(text != "")
|
||||
dt_add_text(h, dtwidth * 50, text);
|
||||
};
|
||||
|
@ -2956,7 +3001,7 @@ EX namespace mapeditor {
|
|||
|
||||
if(uni == 'p') {
|
||||
dialog::openColorDialog(colortouse);
|
||||
dialog::reaction = [] () {
|
||||
dialog::get_di().reaction = [] () {
|
||||
drawHandleKey(COLORKEY, COLORKEY);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -575,8 +575,13 @@ EX bool destroyHalfvine(cell *c, eWall newwall IS(waNone), int tval IS(6)) {
|
|||
}
|
||||
|
||||
EX int coastvalEdge(cell *c) { return coastval(c, laIvoryTower); }
|
||||
EX int coastvalWest(cell *c) { return coastval(c, laWestWall); }
|
||||
|
||||
EX int gravityLevel(cell *c) {
|
||||
if(c->land == laIvoryTower && ls::hv_structure())
|
||||
return celldistAlt(c);
|
||||
if(c->land == laDungeon && ls::hv_structure())
|
||||
return -celldistAlt(c);
|
||||
if(c->land == laIvoryTower || c->land == laEndorian)
|
||||
return coastval(c, laIvoryTower);
|
||||
if(c->land == laDungeon)
|
||||
|
@ -597,10 +602,10 @@ EX int gravityLevelDiff(cell *c, cell *d) {
|
|||
if(shmup::on) return 0;
|
||||
|
||||
int nid = neighborId(c, d);
|
||||
int id1 = parent_id(c, 1, coastvalEdge) + 1;
|
||||
int id1 = parent_id(c, 1, coastvalWest) + 1;
|
||||
int di1 = angledist(c->type, id1, nid);
|
||||
|
||||
int id2 = parent_id(c, -1, coastvalEdge) - 1;
|
||||
int id2 = parent_id(c, -1, coastvalWest) - 1;
|
||||
int di2 = angledist(c->type, id2, nid);
|
||||
|
||||
if(di1 < di2) return 1;
|
||||
|
@ -636,7 +641,7 @@ EX bool cellEdgeUnstable(cell *c, flagtype flags IS(0)) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int tidalphase;
|
||||
EX int tidalphase;
|
||||
|
||||
EX int tidalsize, tide[200];
|
||||
|
||||
|
@ -704,8 +709,8 @@ EX void checkTide(cell *c) {
|
|||
if(!c2) continue;
|
||||
if(c2->land == laBarrier || c2->land == laOceanWall) ;
|
||||
else if(c2->land == laOcean)
|
||||
seadist = min(seadist, c2->SEADIST ? c2->SEADIST+1 : 7),
|
||||
landdist = min(landdist, c2->LANDDIST ? c2->LANDDIST+1 : 7);
|
||||
seadist = min(seadist, c2->SEADIST >= 1 ? c2->SEADIST+1 : 7),
|
||||
landdist = min(landdist, c2->LANDDIST >= 1 ? c2->LANDDIST+1 : 7);
|
||||
else if(isSealand(c2->land)) seadist = 1;
|
||||
else landdist = 1;
|
||||
}
|
||||
|
@ -739,20 +744,35 @@ EX void checkTide(cell *c) {
|
|||
else if(c->wall == waMagma) c->wall = waNone;
|
||||
}
|
||||
#endif
|
||||
if(c->land == laCanvas && ccolor::live_canvas) {
|
||||
color_t col = ccolor::generateCanvas(c);
|
||||
c->landparam = col;
|
||||
c->wall = canvas_default_wall;
|
||||
if(col & 0x1000000) c->wall = waWaxWall;
|
||||
}
|
||||
}
|
||||
|
||||
EX bool makeEmpty(cell *c) {
|
||||
|
||||
if(c->monst != moPrincess) {
|
||||
EX bool makeNoMonster(cell *c) {
|
||||
changes.ccell(c);
|
||||
if(isAnyIvy(c->monst)) killMonster(c, moPlayer, 0);
|
||||
else if(c->monst == moPair) {
|
||||
changes.ccell(c->move(c->mondir));
|
||||
if(c->move(c->mondir)->monst == moPair)
|
||||
c->move(c->mondir)->monst = moNone;
|
||||
}
|
||||
else if(isWorm(c->monst)) {
|
||||
if(!items[itOrbDomination]) return false;
|
||||
}
|
||||
else if(isMultitile(c->monst)) {
|
||||
return false;
|
||||
}
|
||||
else c->monst = moNone;
|
||||
return true;
|
||||
}
|
||||
|
||||
EX bool makeEmpty(cell *c) {
|
||||
if(c->monst != moPrincess) {
|
||||
if(!makeNoMonster(c)) return false;
|
||||
}
|
||||
|
||||
if(c->land == laCanvas) ;
|
||||
|
@ -810,10 +830,12 @@ EX bool makeEmpty(cell *c) {
|
|||
}
|
||||
|
||||
if(c->land == laWildWest) {
|
||||
forCellEx(c2, c)
|
||||
forCellEx(c3, c2)
|
||||
if(c3->wall != waBarrier)
|
||||
c3->wall = waNone;
|
||||
celllister cl(cwt.at, 100, 1000000, NULL);
|
||||
for(cell *c: cl.lst) {
|
||||
if(c == cwt.at) continue;
|
||||
if(c->wall != waSaloon) break;
|
||||
c->wall = waNone;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
177
menus.cpp
177
menus.cpp
|
@ -50,6 +50,8 @@ EX void showOverview() {
|
|||
|
||||
bool not_in_game = false;
|
||||
|
||||
auto displayed_landlist = landlist;
|
||||
|
||||
if(dialog::infix != "") {
|
||||
auto land_matches = [] (eLand l) {
|
||||
string s = dnameof(l);
|
||||
|
@ -63,14 +65,14 @@ EX void showOverview() {
|
|||
vector<eLand> filtered;
|
||||
for(eLand l: landlist) if(land_matches(l)) filtered.push_back(l);
|
||||
if(filtered.size())
|
||||
landlist = filtered;
|
||||
displayed_landlist = filtered;
|
||||
else {
|
||||
for(int i=0; i<landtypes; i++) if(land_matches(eLand(i))) filtered.push_back(eLand(i));
|
||||
if(filtered.size()) landlist = filtered, not_in_game = true;
|
||||
if(filtered.size()) displayed_landlist = filtered, not_in_game = true;
|
||||
}
|
||||
}
|
||||
|
||||
int nl = isize(landlist), nlm;
|
||||
int nl = isize(displayed_landlist), nlm;
|
||||
|
||||
int lstart = 0;
|
||||
|
||||
|
@ -92,7 +94,7 @@ EX void showOverview() {
|
|||
}
|
||||
|
||||
for(int i=0; i<nl; i++) {
|
||||
eLand l = landlist[lstart + i];
|
||||
eLand l = displayed_landlist[lstart + i];
|
||||
int xr = vid.xres / 64;
|
||||
int i0 = 56 + vid.fsize + i * vf;
|
||||
color_t col;
|
||||
|
@ -181,7 +183,7 @@ EX void showOverview() {
|
|||
gotoHelp(generateHelpForItem(eItem(umod)));
|
||||
if(cheater) {
|
||||
dialog::helpToEdit(items[umod], 0, 200, 10, 10);
|
||||
dialog::reaction = [] () {
|
||||
dialog::get_ne().reaction = [] () {
|
||||
if(hardcore) canmove = true;
|
||||
else checkmove();
|
||||
cheater++;
|
||||
|
@ -276,13 +278,17 @@ EX void enable_cheat() {
|
|||
|
||||
// -- game modes --
|
||||
|
||||
EX void switchHardcore() {
|
||||
EX void switchHardcore_quiet() {
|
||||
if(hardcore && !canmove) {
|
||||
restart_game();
|
||||
if(delayed_start) stop_game(); else restart_game();
|
||||
hardcore = false;
|
||||
}
|
||||
else if(hardcore && canmove) { hardcore = false; }
|
||||
else { hardcore = true; canmove = true; hardcoreAt = turncount; }
|
||||
}
|
||||
|
||||
EX void switchHardcore() {
|
||||
switchHardcore_quiet();
|
||||
if(hardcore)
|
||||
addMessage(XLAT("One wrong move and it is game over!"));
|
||||
else
|
||||
|
@ -374,6 +380,9 @@ EX void showCreative() {
|
|||
}
|
||||
#endif
|
||||
|
||||
dialog::addItem(XLAT("line patterns"), 'l');
|
||||
dialog::add_action_push(linepatterns::showMenu);
|
||||
|
||||
// dialog::addBoolItem(XLAT("expansion"), viewdists, 'x');
|
||||
|
||||
dialog::addBreak(50);
|
||||
|
@ -381,6 +390,43 @@ EX void showCreative() {
|
|||
dialog::display();
|
||||
}
|
||||
|
||||
EX void show_achievement_eligibility() {
|
||||
#if CAP_ACHIEVE
|
||||
dialog::addBreak(100);
|
||||
dialog::addInfo(XLAT("achievement/leaderboard eligiblity:"), 0xFF8000);
|
||||
if(!wrongMode(0)) {
|
||||
if(inv::on || bow::crossbow_mode()) dialog::addInfo(XLAT("eligible for most -- leaderboards separate"), 0x80FF00);
|
||||
else dialog::addInfo(XLAT("eligible for most"), 0x00FF00);
|
||||
}
|
||||
else if(!wrongMode(rg::racing))
|
||||
dialog::addInfo(XLAT("eligible for racing"), 0xFFFF00);
|
||||
else if(!wrongMode(rg::shmup))
|
||||
dialog::addInfo(XLAT("eligible for shmup"), 0xFFFF00);
|
||||
else if(!wrongMode(rg::multi))
|
||||
dialog::addInfo(XLAT("eligible for multiplayer"), 0xFFFF00);
|
||||
else if(!wrongMode(rg::chaos))
|
||||
dialog::addInfo(XLAT("eligible for Chaos mode"), 0xFFFF00);
|
||||
else if(!wrongMode(rg::princess))
|
||||
dialog::addInfo(XLAT("eligible for Princess Challenge"), 0xFFFF00);
|
||||
else if(!wrongMode(specgeom_heptagonal()))
|
||||
dialog::addInfo(XLAT("eligible for heptagonal"), 0xFFFF00);
|
||||
else if(!wrongMode(any_specgeom())) /* the player probably knows what they are aiming at */
|
||||
dialog::addInfo(XLAT("eligible for special geometry"), 0xFFFF00);
|
||||
#if CAP_DAILY
|
||||
else if(daily::on && !daily::historical)
|
||||
dialog::addInfo(XLAT("eligible for Strange Challenge"), 0xFFFF00);
|
||||
#endif
|
||||
else if(cheater) dialog::addInfo(XLAT("disabled in cheat mode"), 0xC00000);
|
||||
else if(casual) dialog::addInfo(XLAT("disabled in casual mode"), 0xC00000);
|
||||
else if(ineligible_starting_land)
|
||||
dialog::addInfo(XLAT("this starting land is not eligible for achievements"), 0xC00000);
|
||||
else
|
||||
dialog::addInfo(XLAT("not eligible due to current mode settings"), 0XC00000);
|
||||
#else
|
||||
dialog::addInfo(XLAT("no achievements/leaderboards in this version"), 0XFF8000);
|
||||
#endif
|
||||
}
|
||||
|
||||
EX void show_chaos() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
|
@ -388,10 +434,10 @@ EX void show_chaos() {
|
|||
chaosUnlocked = chaosUnlocked || autocheat;
|
||||
|
||||
dialog::addHelp(
|
||||
"In the Chaos mode, lands change very often, and "
|
||||
XLAT("In the Chaos mode, lands change very often, and "
|
||||
"there are no walls between them. "
|
||||
"Some lands are incompatible with this."
|
||||
"\n\nYou need to reach Crossroads IV to unlock the Chaos mode."
|
||||
"\n\nYou need to reach Crossroads IV to unlock the Chaos mode.")
|
||||
);
|
||||
|
||||
dialog::addBreak(100);
|
||||
|
@ -420,21 +466,84 @@ EX void show_chaos() {
|
|||
dialog::addSelItem(XLAT("land"), XLAT1(linf[specialland].name), 'l');
|
||||
dialog::add_action(activate_ge_land_selection);
|
||||
|
||||
dialog::addBreak(100);
|
||||
if(ineligible_starting_land)
|
||||
dialog::addInfo("this starting land is not eligible for achievements");
|
||||
else if(land_structure == lsNiceWalls)
|
||||
dialog::addInfo("eligible for most achievements");
|
||||
else if(land_structure == lsChaos)
|
||||
dialog::addInfo("eligible for Chaos mode achievements");
|
||||
else if(land_structure == lsSingle)
|
||||
dialog::addInfo("eligible for special achievements");
|
||||
else
|
||||
dialog::addInfo("not eligible for achievements");
|
||||
if(cheater) dialog::addInfo("(but the cheat mode is on)");
|
||||
if(casual) dialog::addInfo("(but the casual mode is on)");
|
||||
show_achievement_eligibility();
|
||||
|
||||
dialog::addBreak(100);
|
||||
if(ls::horodisk_structure())
|
||||
add_edit(horodisk_from);
|
||||
else if(land_structure == lsChaosRW)
|
||||
add_edit(randomwalk_size);
|
||||
else if(land_structure == lsLandscape)
|
||||
add_edit(landscape_div);
|
||||
else if(land_structure == lsCursedWalls)
|
||||
add_edit(curse_percentage);
|
||||
else
|
||||
dialog::addBreak(100);
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
EX string custom_welcome;
|
||||
|
||||
string customfile = "custom.hrm";
|
||||
|
||||
string name_to_edit;
|
||||
|
||||
EX void show_custom() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
gamescreen();
|
||||
dialog::init(XLAT("custom mode"));
|
||||
|
||||
list_saved_custom_modes();
|
||||
dialog::addBreak(100);
|
||||
if(custom_welcome != "") {
|
||||
dialog::addInfo("custom welcome message:");
|
||||
dialog::addInfo(custom_welcome);
|
||||
dialog::addItem("edit", '/');
|
||||
}
|
||||
else {
|
||||
dialog::addItem("custom welcome message", '/');
|
||||
}
|
||||
dialog::add_action([] () {
|
||||
dialog::edit_string(custom_welcome, "custom welcome message", "");
|
||||
});
|
||||
dialog::addBreak(100);
|
||||
auto m = at_or_null(modename, current_modecode);
|
||||
dialog::addSelItem("name custom mode", m ? *m : "", 'N');
|
||||
dialog::add_action([] {
|
||||
name_to_edit = modename[current_modecode];
|
||||
dialog::edit_string(name_to_edit, "name custom mode", "");
|
||||
dialog::get_di().reaction_final = [] { update_modename(name_to_edit); };
|
||||
});
|
||||
|
||||
dialog::addItem("save custom mode", 'S');
|
||||
dialog::add_action([] {
|
||||
dialog::openFileDialog(customfile, XLAT("file to save:"), ".hrm", [] () {
|
||||
try {
|
||||
save_mode_to_file(customfile);
|
||||
addMessage(XLAT("Mode saved to %1", customfile));
|
||||
return true;
|
||||
}
|
||||
catch(hstream_exception& e) {
|
||||
addMessage(XLAT("Failed to save mode to %1", customfile));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
dialog::addItem("load custom mode", 'L');
|
||||
dialog::add_action([] {
|
||||
dialog::openFileDialog(customfile, XLAT("file to load:"), ".hrm", [] () {
|
||||
try {
|
||||
load_mode_from_file(customfile);
|
||||
addMessage(XLAT("Loaded mode from %1", customfile));
|
||||
return true;
|
||||
}
|
||||
catch(hstream_exception& e) {
|
||||
addMessage(XLAT("Failed to load mode from %1", customfile));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
@ -654,6 +763,12 @@ EX void showChangeMode() {
|
|||
multi::cpid = 0;
|
||||
menuitem_land_structure('l');
|
||||
|
||||
dialog::addBoolItem(XLAT("custom land list"), use_custom_land_list, 'L');
|
||||
dialog::add_action_push(customize_land_list);
|
||||
|
||||
dialog::addBoolItem(XLAT("weapon selection"), bow::weapon, 'b');
|
||||
dialog::add_action_push(bow::showMenu);
|
||||
|
||||
dialog::addBoolItem(XLAT("puzzle/exploration mode"), peace::on, 'p');
|
||||
dialog::add_action_push(peace::showMenu);
|
||||
|
||||
|
@ -688,7 +803,7 @@ EX void showChangeMode() {
|
|||
#endif
|
||||
dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'P');
|
||||
dialog::add_action_confirmed([] {
|
||||
if(!princess::everSaved)
|
||||
if(!princess::everSaved && !autocheat)
|
||||
addMessage(XLAT("Save %the1 first to unlock this challenge!", moPrincess));
|
||||
else restart_game(rg::princess);
|
||||
});
|
||||
|
@ -707,11 +822,13 @@ EX void showChangeMode() {
|
|||
dialog::add_action(racing::configure_race);
|
||||
#endif
|
||||
|
||||
dialog::addBreak(50);
|
||||
show_achievement_eligibility();
|
||||
|
||||
dialog::addBreak(50);
|
||||
dialog::addItem(XLAT("highlights & achievements"), 'h');
|
||||
dialog::add_action_push(mode_higlights);
|
||||
|
||||
dialog::addItem(XLAT("custom mode manager"), 'm');
|
||||
dialog::add_action(prepare_custom);
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
@ -912,7 +1029,7 @@ EX void showStartMenu() {
|
|||
stop_game();
|
||||
enable_canvas();
|
||||
cheater = true;
|
||||
patterns::canvasback = 0xFFFFFF;
|
||||
ccolor::set_plain(0xFFFFFF);
|
||||
mapeditor::drawplayer = false;
|
||||
start_game();
|
||||
clearMessages();
|
||||
|
@ -953,10 +1070,10 @@ EX void showStartMenu() {
|
|||
specialland = racing::race_lands[rand() % isize(racing::race_lands)];
|
||||
start_game();
|
||||
pmodel = mdBand;
|
||||
pconf.model_orientation = racing::race_angle;
|
||||
pconf.mori() = racing::race_angle;
|
||||
racing::race_advance = 1;
|
||||
vid.yshift = 0;
|
||||
pconf.camera_angle = 0;
|
||||
pconf.cam() = Id;
|
||||
pconf.xposition = 0;
|
||||
pconf.yposition = 0;
|
||||
pconf.scale = 1;
|
||||
|
@ -1155,6 +1272,10 @@ int read_menu_args() {
|
|||
else if(argis("-d:mode")) {
|
||||
PHASEFROM(2); launch_dialog(showChangeMode);
|
||||
}
|
||||
else if(argis("-d:custom")) {
|
||||
PHASEFROM(3);
|
||||
prepare_custom();
|
||||
}
|
||||
else if(argis("-d:history")) {
|
||||
PHASEFROM(2); launch_dialog(history::history_menu);
|
||||
}
|
||||
|
|
16
mobile.cpp
16
mobile.cpp
|
@ -14,27 +14,23 @@ string buildScoreDescription() {
|
|||
time_t timer;
|
||||
timer = time(NULL);
|
||||
char buf[128]; strftime(buf, 128, "%c", localtime(&timer));
|
||||
char buf2[128];
|
||||
|
||||
s += XLAT("HyperRogue for Android");
|
||||
s += " ( " VER "), http://www.roguetemple.com/z/hyper/\n";
|
||||
s += XLAT("Date: %1 time: %2 s ", buf, getgametime_s());
|
||||
s += XLAT("distance: %1\n", its(celldist(cwt.at)));
|
||||
// s += buf2;
|
||||
if(cheater) s += XLAT("Cheats: ") + its(cheater) + "\n";
|
||||
s += XLAT("Score: ") + its(gold());
|
||||
|
||||
for(int i=0; i<ittypes; i++) if(items[i]) {
|
||||
string t = XLATN(iinf[i].name);
|
||||
sprintf(buf2, " %s (%d)", t.c_str(), items[i]);
|
||||
s += buf2;
|
||||
s += hr::format(" %s (%d)", t.c_str(), items[i]);
|
||||
}
|
||||
s += "\n";
|
||||
s += XLAT("Kills: ") + its(tkills());
|
||||
for(int i=1; i<motypes; i++) if(kills[i]) {
|
||||
string t = XLATN(minf[i].name);
|
||||
sprintf(buf2, " %s (%d)", t.c_str(), kills[i]);
|
||||
s += buf2;
|
||||
s += hr::format(" %s (%d)", t.c_str(), kills[i]);
|
||||
}
|
||||
s += "\n";
|
||||
|
||||
|
@ -96,6 +92,11 @@ void handleclick(MOBPAR_FORMAL) {
|
|||
getcstat = 0;
|
||||
}
|
||||
|
||||
else if(statkeys && getcstat == 'f') {
|
||||
bow::switch_fire_mode();
|
||||
getcstat = 0;
|
||||
}
|
||||
|
||||
else if(getcstat != SDLK_F1 && getcstat != 'i' && getcstat != 't') {
|
||||
int px = mousex < current_display->xcenter ? 0 : 1;
|
||||
int py = mousey < current_display->ycenter ? 0 : 1;
|
||||
|
@ -294,6 +295,8 @@ EX void mobile_draw(MOBPAR_FORMAL) {
|
|||
|
||||
if(inmenu && !clicked && !lclicked) inmenu = false;
|
||||
|
||||
if(!clicked && !lclicked) invslider = false;
|
||||
|
||||
bool keyreact = lclicked && !clicked;
|
||||
|
||||
#if CAP_MENUSCALING
|
||||
|
@ -306,6 +309,7 @@ EX void mobile_draw(MOBPAR_FORMAL) {
|
|||
#endif
|
||||
|
||||
if(inslider) keyreact = true;
|
||||
if(invslider || getcstat == PSEUDOKEY_LIST_SLIDER) keyreact = true;
|
||||
|
||||
#if CAP_ANDROIDSHARE
|
||||
if(getcstat == 's'-96 && keyreact) {
|
||||
|
|
296
models.cpp
296
models.cpp
|
@ -20,7 +20,7 @@ EX namespace polygonal {
|
|||
#endif
|
||||
|
||||
#if HDR
|
||||
static const int MSI = 120;
|
||||
static constexpr int MSI = 120;
|
||||
#endif
|
||||
|
||||
typedef long double xld;
|
||||
|
@ -113,30 +113,52 @@ inline bool mdBandAny() { return mdinf[pmodel].flags & mf::pseudocylindrical; }
|
|||
inline bool mdPseudocylindrical() { return mdBandAny() && !(mdinf[pmodel].flags & mf::cylindrical); }
|
||||
#endif
|
||||
|
||||
projection_configuration::projection_configuration() {
|
||||
formula = "z^2"; top_z = 5; model_transition = 1; spiral_angle = 70; spiral_x = 10; spiral_y = 7;
|
||||
rotational_nil = 1;
|
||||
right_spiral_multiplier = 1;
|
||||
any_spiral_multiplier = 1;
|
||||
sphere_spiral_multiplier = 2;
|
||||
spiral_cone = 360;
|
||||
use_atan = false;
|
||||
product_z_scale = 1;
|
||||
aitoff_parameter = .5;
|
||||
miller_parameter = .8;
|
||||
loximuthal_parameter = 0;
|
||||
winkel_parameter = .5;
|
||||
show_hyperboloid_flat = true;
|
||||
depth_scaling = 1;
|
||||
vr_angle = 0;
|
||||
hyperboloid_scaling = 1;
|
||||
vr_zshift = 0;
|
||||
vr_scale_factor = 1;
|
||||
back_and_front = 0;
|
||||
dualfocus_autoscale = false;
|
||||
axial_angle = 90;
|
||||
ptr_model_orientation = new trans23;
|
||||
ptr_ball = new transmatrix;
|
||||
*ptr_ball = cspin(1, 2, 20._deg);
|
||||
ptr_camera = new transmatrix; *ptr_camera = Id;
|
||||
offside = 0; offside2 = M_PI;
|
||||
}
|
||||
|
||||
EX namespace models {
|
||||
|
||||
EX ld rotation = 0;
|
||||
EX ld rotation_xz = 90;
|
||||
EX ld rotation_xy2 = 90;
|
||||
EX trans23 rotation;
|
||||
EX int do_rotate = 1;
|
||||
EX ld ocos, osin, ocos_yz, osin_yz;
|
||||
EX ld cos_ball, sin_ball;
|
||||
EX bool model_straight, model_straight_yz;
|
||||
EX bool model_straight, model_straight_yz, camera_straight;
|
||||
|
||||
#if HDR
|
||||
// screen coordinates to logical coordinates: apply_orientation(x,y)
|
||||
// logical coordinates back to screen coordinates: apply_orientation(y,x)
|
||||
template<class A>
|
||||
void apply_orientation(A& x, A& y) { if(!model_straight) tie(x,y) = make_pair(x*ocos + y*osin, y*ocos - x*osin); }
|
||||
template<class A>
|
||||
void apply_orientation_yz(A& x, A& y) { if(!model_straight_yz) tie(x,y) = make_pair(x*ocos_yz + y*osin_yz, y*ocos_yz - x*osin_yz); }
|
||||
template<class A>
|
||||
void apply_ball(A& x, A& y) { tie(x,y) = make_pair(x*cos_ball + y*sin_ball, y*cos_ball - x*sin_ball); }
|
||||
#endif
|
||||
/** screen coordinates to orientation logical coordinates */
|
||||
EX void ori_to_scr(hyperpoint& h) { if(!model_straight) h = pconf.mori().get() * h; }
|
||||
EX void ori_to_scr(transmatrix& h) { if(!model_straight) h = pconf.mori().get() * h; }
|
||||
|
||||
/** orientation logical coordinates to screen coordinates */
|
||||
EX void scr_to_ori(hyperpoint& h) { if(!model_straight) h = iso_inverse(pconf.mori().get()) * h; }
|
||||
EX void scr_to_ori(transmatrix& h) { if(!model_straight) h = iso_inverse(pconf.mori().get()) * h; }
|
||||
|
||||
EX transmatrix rotmatrix() {
|
||||
if(GDIM == 2 || gproduct) return spin(rotation * degree);
|
||||
return spin(rotation_xy2 * degree) * cspin(0, 2, -rotation_xz * degree) * spin(rotation * degree);
|
||||
if(gproduct) return rotation.v2;
|
||||
return rotation.get();
|
||||
}
|
||||
|
||||
int spiral_id = 7;
|
||||
|
@ -149,14 +171,9 @@ EX namespace models {
|
|||
EX transmatrix euclidean_spin;
|
||||
|
||||
EX void configure() {
|
||||
ld ball = -pconf.ballangle * degree;
|
||||
cos_ball = cos(ball), sin_ball = sin(ball);
|
||||
ocos = cos(pconf.model_orientation * degree);
|
||||
osin = sin(pconf.model_orientation * degree);
|
||||
ocos_yz = cos(pconf.model_orientation_yz * degree);
|
||||
osin_yz = sin(pconf.model_orientation_yz * degree);
|
||||
model_straight = (ocos > 1 - 1e-9);
|
||||
model_straight_yz = GDIM == 2 || (ocos_yz > 1-1e-9);
|
||||
model_straight = (pconf.mori().get()[0][0] > 1 - 1e-9);
|
||||
model_straight_yz = GDIM == 2 || (pconf.mori().get()[2][2] > 1-1e-9);
|
||||
camera_straight = eqmatrix(pconf.cam(), Id);
|
||||
if(history::on) history::apply();
|
||||
|
||||
if(!euclid) {
|
||||
|
@ -218,7 +235,7 @@ EX namespace models {
|
|||
}
|
||||
|
||||
EX bool has_orientation(eModel m) {
|
||||
if(is_perspective(m) && panini_alpha) return true;
|
||||
if(is_perspective(m) && vid.stereo_mode == sPanini) return true;
|
||||
if(nonisotropic) return false;
|
||||
return (mdinf[m].flags & mf::orientation);
|
||||
}
|
||||
|
@ -300,7 +317,7 @@ EX namespace models {
|
|||
});
|
||||
if(spiral_id > isize(torus_zeros)) spiral_id = 0;
|
||||
dialog::editNumber(spiral_id, 0, isize(torus_zeros)-1, 1, 10, XLAT("match the period of the torus"), "");
|
||||
dialog::reaction = [] () {
|
||||
dialog::get_di().reaction = [] () {
|
||||
auto& co = torus_zeros[spiral_id];
|
||||
vpconf.spiral_x = co.first;
|
||||
vpconf.spiral_y = co.second;
|
||||
|
@ -319,7 +336,7 @@ EX namespace models {
|
|||
)
|
||||
);
|
||||
#if CAP_QUEUE && CAP_CURVE
|
||||
dialog::extra_options = [] () {
|
||||
dialog::get_di().extra_options = [] () {
|
||||
dialog::parser_help();
|
||||
initquickqueue();
|
||||
queuereset(mdPixel, PPR::LINE);
|
||||
|
@ -335,35 +352,11 @@ EX namespace models {
|
|||
quickqueue();
|
||||
};
|
||||
#endif
|
||||
dialog::reaction_final = [] () {
|
||||
dialog::get_di().reaction_final = [] () {
|
||||
vpconf.model = mdFormula;
|
||||
};
|
||||
}
|
||||
|
||||
EX void edit_rotation(ld& which) {
|
||||
dialog::editNumber(which, 0, 360, 90, 0, XLAT("rotation"),
|
||||
"This controls the automatic rotation of the world. "
|
||||
"It affects the line animation in the history mode, and "
|
||||
"lands which have a special direction. Note that if finding this special direction is a part of the puzzle, "
|
||||
"it works only in the cheat mode.");
|
||||
dialog::dialogflags |= sm::CENTER;
|
||||
dialog::extra_options = [] () {
|
||||
dialog::addBreak(100);
|
||||
dialog::addBoolItem_choice("line animation only", models::do_rotate, 0, 'N');
|
||||
dialog::addBoolItem_choice("gravity lands", models::do_rotate, 1, 'G');
|
||||
dialog::addBoolItem_choice("all directional lands", models::do_rotate, 2, 'D');
|
||||
if(GDIM == 3) {
|
||||
dialog::addBreak(100);
|
||||
dialog::addSelItem(XLAT("XY plane"), fts(models::rotation) + "°", 'A');
|
||||
dialog::add_action([] { popScreen(); edit_rotation(models::rotation); });
|
||||
dialog::addSelItem(XLAT("XZ plane"), fts(models::rotation_xz) + "°", 'B');
|
||||
dialog::add_action([] { popScreen(); edit_rotation(models::rotation_xz); });
|
||||
dialog::addSelItem(XLAT("XY plane #2"), fts(models::rotation_xy2) + "°", 'C');
|
||||
dialog::add_action([] { popScreen(); edit_rotation(models::rotation_xy2); });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
EX void model_list() {
|
||||
cmode = sm::SIDE | sm::MAYDARK | sm::CENTER;
|
||||
gamescreen();
|
||||
|
@ -405,7 +398,7 @@ EX namespace models {
|
|||
dialog::addBreak(100);
|
||||
if(sphere && pmodel == mdBandEquiarea) {
|
||||
dialog::addBoolItem("Gall-Peters", vpconf.stretch == 2, 'O');
|
||||
dialog::add_action([] { vpconf.stretch = 2; dialog::ne.s = "2"; });
|
||||
dialog::add_action([] { vpconf.stretch = 2; dialog::get_ne().s = "2"; });
|
||||
}
|
||||
if(pmodel == mdBandEquiarea) {
|
||||
// y = K * sin(phi)
|
||||
|
@ -440,13 +433,9 @@ EX namespace models {
|
|||
if(nonisotropic && !sl2)
|
||||
dialog::addBoolItem_action(XLAT("geodesic movement in Sol/Nil"), nisot::geodesic_movement, 'G');
|
||||
|
||||
dialog::addBoolItem(XLAT("rotation"), do_rotate == 2, 'r');
|
||||
if(do_rotate == 0) dialog::lastItem().value = XLAT("NEVER");
|
||||
if(GDIM == 2)
|
||||
dialog::lastItem().value += " " + its(rotation) + "°";
|
||||
else
|
||||
dialog::lastItem().value += " " + its(rotation) + "°" + its(rotation_xz) + "°" + its(rotation_xy2) + "°";
|
||||
dialog::add_action([] { edit_rotation(rotation); });
|
||||
add_edit((GDIM == 2 || gproduct) ? rotation.v2 : rotation.v3);
|
||||
if(do_rotate == 0) { dialog::lastItem().value = XLAT("NEVER"); dialog::lastItem().type = dialog::diItem; }
|
||||
else { dialog::lastItem().value = ONOFF(do_rotate == 2); }
|
||||
|
||||
bool vr_settings = vrhr::active() && set_vr_settings;
|
||||
|
||||
|
@ -475,22 +464,16 @@ EX namespace models {
|
|||
}
|
||||
|
||||
if(has_orientation(vpmodel)) {
|
||||
dialog::addSelItem(XLAT("model orientation"), fts(vpconf.model_orientation) + "°", 'l');
|
||||
dialog::addMatrixItem(XLAT("model orientation"), vpconf.mori().get(), 'l');
|
||||
dialog::add_action([] () {
|
||||
dialog::editNumber(vpconf.model_orientation, 0, 360, 90, 0, XLAT("model orientation"), "");
|
||||
dialog::editMatrix(vpconf.mori().get(), XLAT("model orientation"), "", GDIM);
|
||||
});
|
||||
if(GDIM == 3) {
|
||||
dialog::addSelItem(XLAT("model orientation (y/z plane)"), fts(vpconf.model_orientation_yz) + "°", 'L');
|
||||
dialog::add_action([] () {
|
||||
dialog::editNumber(vpconf.model_orientation_yz, 0, 360, 90, 0, XLAT("model orientation (y/z plane)"), "");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(among(vpmodel, mdPerspective, mdHorocyclic) && nil) {
|
||||
dialog::addSelItem(XLAT("model orientation"), fts(vpconf.model_orientation) + "°", 'l');
|
||||
dialog::addMatrixItem(XLAT("model orientation"), vpconf.mori().get(), 'l');
|
||||
dialog::add_action([] () {
|
||||
dialog::editNumber(vpconf.model_orientation, 0, 360, 90, 0, XLAT("model orientation"), "");
|
||||
dialog::editMatrix(vpconf.mori().get(), XLAT("model orientation"), "", GDIM);
|
||||
});
|
||||
dialog::addSelItem(XLAT("rotational or Heisenberg"), fts(vpconf.rotational_nil), 'L');
|
||||
dialog::add_action([] () {
|
||||
|
@ -571,23 +554,23 @@ EX namespace models {
|
|||
dialog::addSelItem(XLAT("polygon sides"), its(polygonal::SI), 'x');
|
||||
dialog::add_action([] () {
|
||||
dialog::editNumber(polygonal::SI, 3, 10, 1, 4, XLAT("polygon sides"), "");
|
||||
dialog::reaction = polygonal::solve;
|
||||
dialog::get_di().reaction = polygonal::solve;
|
||||
});
|
||||
dialog::addSelItem(XLAT("star factor"), fts(polygonal::STAR), 'y');
|
||||
dialog::add_action([]() {
|
||||
dialog::editNumber(polygonal::STAR, -1, 1, .1, 0, XLAT("star factor"), "");
|
||||
dialog::reaction = polygonal::solve;
|
||||
dialog::get_di().reaction = polygonal::solve;
|
||||
});
|
||||
dialog::addSelItem(XLAT("degree of the approximation"), its(polygonal::deg), 'n');
|
||||
dialog::add_action([](){
|
||||
dialog::editNumber(polygonal::deg, 2, polygonal::MSI-1, 1, 2, XLAT("degree of the approximation"), "");
|
||||
dialog::reaction = polygonal::solve;
|
||||
dialog::get_di().reaction = polygonal::solve;
|
||||
dialog::bound_low(0); dialog::bound_up(polygonal::MSI-1);
|
||||
});
|
||||
}
|
||||
|
||||
if(is_3d(vpconf) && GDIM == 2 && !vr_settings)
|
||||
add_edit(vpconf.ballangle);
|
||||
add_edit(vpconf.ball());
|
||||
|
||||
if(vr_settings) {
|
||||
dialog::addSelItem(XLAT("VR: rotate the 3D model"), fts(vpconf.vr_angle) + "°", 'B');
|
||||
|
@ -637,6 +620,11 @@ EX namespace models {
|
|||
if(vpmodel == mdFisheye)
|
||||
add_edit(vpconf.fisheye_param);
|
||||
|
||||
if(vpmodel == mdFisheye2) {
|
||||
add_edit(vpconf.fisheye_param);
|
||||
add_edit(vpconf.fisheye_alpha);
|
||||
}
|
||||
|
||||
if(is_hyperboloid(vpmodel))
|
||||
add_edit(pconf.show_hyperboloid_flat);
|
||||
|
||||
|
@ -656,6 +644,11 @@ EX namespace models {
|
|||
if(among(vpmodel, mdLoximuthal, mdRetroHammer, mdRetroCraig))
|
||||
add_edit(vpconf.loximuthal_parameter);
|
||||
|
||||
if(among(vpmodel, mdPolar)) {
|
||||
add_edit(vpconf.offside);
|
||||
add_edit(vpconf.offside2);
|
||||
}
|
||||
|
||||
if(among(vpmodel, mdAitoff, mdHammer, mdWinkelTripel))
|
||||
add_edit(vpconf.aitoff_parameter);
|
||||
|
||||
|
@ -832,10 +825,6 @@ EX namespace models {
|
|||
shift(); vpconf.formula = args();
|
||||
}
|
||||
}
|
||||
else if(argis("-ballangle")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.ballangle);
|
||||
}
|
||||
else if(argis("-topz")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.top_z);
|
||||
|
@ -848,10 +837,6 @@ EX namespace models {
|
|||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.halfplane_scale);
|
||||
}
|
||||
else if(argis("-mori")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.model_orientation);
|
||||
}
|
||||
else if(argis("-mets")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.euclid_to_sphere);
|
||||
|
@ -868,17 +853,6 @@ EX namespace models {
|
|||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.rotational_nil);
|
||||
}
|
||||
else if(argis("-mori2")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.model_orientation);
|
||||
shift_arg_formula(vpconf.model_orientation_yz);
|
||||
}
|
||||
else if(argis("-crot")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(models::rotation);
|
||||
if(GDIM == 3) shift_arg_formula(models::rotation_xz);
|
||||
if(GDIM == 3) shift_arg_formula(models::rotation_xy2);
|
||||
}
|
||||
else if(argis("-clip")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.clip_min);
|
||||
|
@ -921,22 +895,6 @@ EX namespace models {
|
|||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.skiprope);
|
||||
}
|
||||
else if(argis("-palpha")) {
|
||||
PHASEFROM(2);
|
||||
#if CAP_GL
|
||||
shift_arg_formula(panini_alpha, reset_all_shaders);
|
||||
#else
|
||||
shift_arg_formula(panini_alpha);
|
||||
#endif
|
||||
}
|
||||
else if(argis("-salpha")) {
|
||||
PHASEFROM(2);
|
||||
#if CAP_GL
|
||||
shift_arg_formula(stereo_alpha, reset_all_shaders);
|
||||
#else
|
||||
shift_arg_formula(stereo_alpha);
|
||||
#endif
|
||||
}
|
||||
else if(argis("-zoom")) {
|
||||
PHASEFROM(2); shift_arg_formula(vpconf.scale);
|
||||
}
|
||||
|
@ -961,22 +919,29 @@ EX namespace models {
|
|||
#endif
|
||||
|
||||
void add_model_config() {
|
||||
addsaver(polygonal::SI, "polygon sides");
|
||||
param_f(polygonal::STAR, "star", "polygon star factor");
|
||||
addsaver(polygonal::deg, "polygonal degree");
|
||||
param_i(polygonal::SI, "polygon sides");
|
||||
param_f(polygonal::STAR, parameter_names("star", "polygon star factor"));
|
||||
param_i(polygonal::deg, "polygonal degree");
|
||||
|
||||
addsaver(polygonal::maxcoef, "polynomial degree");
|
||||
param_i(polygonal::maxcoef, "polynomial degree");
|
||||
for(int i=0; i<polygonal::MSI; i++) {
|
||||
addsaver(polygonal::coefr[i], "polynomial "+its(i)+".real");
|
||||
addsaver(polygonal::coefi[i], "polynomial "+its(i)+".imag");
|
||||
param_f(polygonal::coefr[i], "polynomial "+its(i)+".real");
|
||||
param_f(polygonal::coefi[i], "polynomial "+its(i)+".imag");
|
||||
}
|
||||
|
||||
param_f(models::rotation, "rotation", "conformal rotation");
|
||||
addsaver(models::rotation_xz, "conformal rotation_xz");
|
||||
addsaver(models::rotation_xy2, "conformal rotation_2");
|
||||
addsaver(models::do_rotate, "conformal rotation mode", 1);
|
||||
auto setrot = [] {
|
||||
dialog::get_di().dialogflags |= sm::CENTER;
|
||||
dialog::addBreak(100);
|
||||
dialog::addBoolItem_choice("line animation only", models::do_rotate, 0, 'N');
|
||||
dialog::addBoolItem_choice("gravity lands", models::do_rotate, 1, 'G');
|
||||
dialog::addBoolItem_choice("all directional lands", models::do_rotate, 2, 'D');
|
||||
};
|
||||
|
||||
param_f(pconf.halfplane_scale, "hp", "halfplane scale", 1);
|
||||
param_matrix(models::rotation.v2, "rotation", 2)->editable("auto rotation", "", 'r')->set_extra(setrot);
|
||||
param_matrix(models::rotation.v3, "rotation3", 3)->editable("auto rotation in 3D", "", 'r')->set_extra(setrot);
|
||||
param_i(models::do_rotate, "auto_rotation_mode", 1);
|
||||
|
||||
param_f(pconf.halfplane_scale, parameter_names("hp", "halfplane scale"), 1);
|
||||
|
||||
auto add_all = [&] (projection_configuration& p, string pp, string sp) {
|
||||
|
||||
|
@ -984,40 +949,52 @@ EX namespace models {
|
|||
dynamicval<function<bool()>> ds(auto_restrict);
|
||||
auto_restrict = [&p] { return &vpconf == &p; };
|
||||
|
||||
addsaverenum(p.model, pp+"used model", mdDisk);
|
||||
param_custom(pmodel, "projection|Poincare|Klein|half-plane|perspective", menuitem_projection, '1');
|
||||
if(&p.model == &pmodel) {
|
||||
auto par = param_custom_int(pmodel, parameter_names(pp+"used_model", "used model"), menuitem_projection, '1');
|
||||
par->help_text = "projection|Poincare|Klein|half-plane|perspective";
|
||||
}
|
||||
else param_enum(p.model, parameter_names(pp+"used_model", sp+"used model"), mdDisk);
|
||||
|
||||
param_f(p.model_orientation, pp+"mori", sp+"model orientation", 0);
|
||||
param_f(p.model_orientation_yz, pp+"mori_yz", sp+"model orientation-yz", 0);
|
||||
param_matrix(p.mori().v2, pp+"mori", 2)
|
||||
-> editable("model orientation", "", 'o');
|
||||
param_matrix(p.mori().v3, pp+"mori3", 3)
|
||||
-> editable("model orientation 3D", "", 'o');
|
||||
|
||||
param_f(p.top_z, sp+"topz", 5)
|
||||
-> editable(1, 20, .25, "maximum z coordinate to show", "maximum z coordinate to show", 'l');
|
||||
|
||||
param_f(p.model_transition, pp+"mtrans", sp+"model transition", 1)
|
||||
param_f(p.model_transition, parameter_names(pp+"mtrans", sp+"model transition"), 1)
|
||||
-> editable(0, 1, .1, "model transition",
|
||||
"You can change this parameter for a transition from another model to this one.", 't');
|
||||
|
||||
param_f(p.rotational_nil, sp+"rotnil", 1);
|
||||
|
||||
param_f(p.clip_min, pp+"clipmin", sp+"clip-min", rug ? -100 : -1);
|
||||
param_f(p.clip_max, pp+"clipmax", sp+"clip-max", rug ? +10 : +1);
|
||||
param_f(p.clip_min, parameter_names(pp+"clipmin", sp+"clip-min"), rug ? -100 : -1);
|
||||
param_f(p.clip_max, parameter_names(pp+"clipmax", sp+"clip-max"), rug ? +10 : +1);
|
||||
|
||||
param_f(p.euclid_to_sphere, pp+"ets", sp+"euclid to sphere projection", 1.5)
|
||||
param_f(p.euclid_to_sphere, parameter_names(pp+"ets", sp+"euclid to sphere projection"), 1.5)
|
||||
-> editable(1e-1, 10, .1, "ETS parameter", "Stereographic projection to a sphere. Choose the radius of the sphere.", 'l')
|
||||
-> set_sets(dialog::scaleLog);
|
||||
|
||||
param_f(p.twopoint_param, pp+"twopoint", sp+"twopoint parameter", 1)
|
||||
param_f(p.twopoint_param, parameter_names(pp+"twopoint", sp+"twopoint parameter"), 1)
|
||||
-> editable(1e-3, 10, .1, "two-point parameter", "In two-point-based models, this parameter gives the distance from each of the two points to the center.", 'b')
|
||||
-> set_sets(dialog::scaleLog);
|
||||
|
||||
param_f(p.axial_angle, pp+"axial", sp+"axial angle", 90)
|
||||
param_f(p.axial_angle, parameter_names(pp+"axial", sp+"axial angle"), 90)
|
||||
-> editable(1e-3, 10, .1, "angle between the axes", "In two-axe-based models, this parameter gives the angle between the two axes.", 'x')
|
||||
-> set_sets(dialog::scaleLog);
|
||||
|
||||
param_f(p.fisheye_param, pp+"fisheye", sp+"fisheye parameter", 1)
|
||||
param_f(p.fisheye_param, parameter_names(pp+"fisheye", sp+"fisheye parameter"), 1)
|
||||
-> editable(1e-3, 10, .1, "fisheye parameter", "Size of the fish eye.", 'b')
|
||||
-> set_sets(dialog::scaleLog);
|
||||
|
||||
param_f(p.fisheye_alpha, parameter_names(pp+"fishalpha", sp+"off-center parameter"), 0)
|
||||
-> editable(1e-1, 10, .1, "off-center parameter",
|
||||
"This projection is obtained by composing gnomonic projection and inverse stereographic projection. "
|
||||
"This parameter changes the center of the first projection (0 = gnomonic, 1 = stereographic). Use a value closer to 1 "
|
||||
"to make the projection more conformal.",
|
||||
'o');
|
||||
|
||||
param_f(p.stretch, pp+"stretch", 1)
|
||||
-> editable(0, 10, .1, "vertical stretch", "Vertical stretch factor.", 's')
|
||||
-> set_extra(stretch_extra);
|
||||
|
@ -1025,9 +1002,9 @@ EX namespace models {
|
|||
param_f(p.product_z_scale, pp+"zstretch")
|
||||
-> editable(0.1, 10, 0.1, "product Z stretch", "", 'Z');
|
||||
|
||||
param_f(p.collignon_parameter, pp+"collignon", sp+"collignon-parameter", 1)
|
||||
param_f(p.collignon_parameter, parameter_names(pp+"collignon", sp+"collignon-parameter"), 1)
|
||||
-> editable(-1, 1, .1, "Collignon parameter", "", 'b')
|
||||
-> modif([] (float_setting* f) {
|
||||
-> modif([] (float_parameter* f) {
|
||||
f->unit = vpconf.collignon_reflected ? " (r)" : "";
|
||||
})
|
||||
-> set_extra([&p] {
|
||||
|
@ -1041,6 +1018,12 @@ EX namespace models {
|
|||
"The Aitoff projection is obtained by multiplying the longitude by 1/2, using azimuthal equidistant projection, and then dividing X by 1/2. "
|
||||
"Hammer projection is similar but equi-area projection is used instead. "
|
||||
"Here you can change this parameter.", 'b');
|
||||
param_f(p.offside, sp+"offside")
|
||||
-> editable(0, TAU, TAU/10, "offside parameter",
|
||||
"Do not center the projection on the player -- move the center offside. Useful in polar, where the value equal to offside2 can be used to center the projection on the player.", 'o');
|
||||
param_f(p.offside2, sp+"offside2")
|
||||
-> editable(0, TAU, TAU/10, "offside parameter II",
|
||||
"In polar projection, what distance to display in the center. Use asinh(1) (in hyperbolic) to make it conformal in the center, and pi to have the projection extend the same distance to the left, right, and upwards.", 'O');
|
||||
param_f(p.miller_parameter, sp+"miller");
|
||||
param_f(p.loximuthal_parameter, sp+"loximuthal")
|
||||
-> editable(-90._deg, 90._deg, .1, "loximuthal parameter",
|
||||
|
@ -1064,9 +1047,9 @@ EX namespace models {
|
|||
param_b(p.dualfocus_autoscale, sp+"dualfocus_autoscale", 0)
|
||||
-> editable("autoscale dual focus", 'A');
|
||||
|
||||
addsaver(p.formula, sp+"formula");
|
||||
addsaverenum(p.basic_model, sp+"basic model");
|
||||
addsaver(p.use_atan, sp+"use_atan");
|
||||
param_str(p.formula, sp+"formula");
|
||||
param_enum(p.basic_model, sp+"basic model");
|
||||
param_b(p.use_atan, sp+"use_atan");
|
||||
|
||||
param_f(p.spiral_angle, sp+"sang")
|
||||
-> editable(0, 360, 15, "spiral angle", "set to 90° for the ring projection", 'x')
|
||||
|
@ -1082,23 +1065,32 @@ EX namespace models {
|
|||
|
||||
param_i(p.back_and_front, sp+"backandfront", 0);
|
||||
|
||||
addsaver(p.alpha, sp+"projection", 1);
|
||||
param_custom(p.alpha, sp+"projection", menuitem_projection_distance, 'p')
|
||||
->help_text = "projection distance|Gans Klein Poincare orthographic stereographic";
|
||||
if(&p.model == &pmodel) {
|
||||
p.alpha = 1;
|
||||
auto proj = param_custom_ld(p.alpha, sp+"projection", menuitem_projection_distance, 'p');
|
||||
proj->help_text = "projection distance|Gans Klein Poincare orthographic stereographic";
|
||||
}
|
||||
else {
|
||||
param_f(p.alpha, sp+"projection", 1);
|
||||
}
|
||||
|
||||
param_f(p.camera_angle, pp+"cameraangle", sp+"camera angle", 0);
|
||||
addsaver(p.ballproj, sp+"ballproj", 1);
|
||||
param_matrix(p.cam(), pp+"cameraangle", 3)
|
||||
-> editable(pp+"camera angle", "Rotate the camera. Can be used to obtain a first person perspective, "
|
||||
"or third person perspective when combined with Y shift.", 'S')
|
||||
-> set_extra([] {
|
||||
dialog::addBoolItem(XLAT("render behind the camera"), vpconf.back_and_front, 'R');
|
||||
dialog::add_action([] { vpconf.back_and_front = !vpconf.back_and_front; });
|
||||
});
|
||||
|
||||
param_f(p.ballangle, pp+"ballangle", sp+"ball angle", 20)
|
||||
-> editable(0, 90, 5, "camera rotation in 3D models",
|
||||
param_matrix(p.ball(), pp+"ballangle", 3)
|
||||
-> editable("camera rotation in 3D models",
|
||||
"Rotate the camera in 3D models (ball model, hyperboloid, and hemisphere). "
|
||||
"Note that hyperboloid and hemisphere models are also available in the "
|
||||
"Hypersian Rug surfaces menu, but they are rendered differently there -- "
|
||||
"by making a flat picture first, then mapping it to a surface. "
|
||||
"This makes the output better in some ways, but 3D effects are lost. "
|
||||
"Hypersian Rug model also allows more camera freedom.",
|
||||
'b')
|
||||
-> unit = "°";
|
||||
'b');
|
||||
|
||||
string help =
|
||||
"This parameter has a bit different scale depending on the settings:\n"
|
||||
|
@ -1106,16 +1098,16 @@ EX namespace models {
|
|||
"(2) in hyperbolic geometry, with spiral angle being +90° or -90°\n"
|
||||
"(3) in hyperbolic geometry, with other spiral angles (1 makes the bands fit exactly)";
|
||||
|
||||
param_f(p.sphere_spiral_multiplier, "sphere_spiral_multiplier")
|
||||
param_f(p.sphere_spiral_multiplier, pp+"sphere_spiral_multiplier")
|
||||
-> editable(0, 10, .1, "sphere spiral multiplier", help, 'M')->unit = "°";
|
||||
|
||||
param_f(p.right_spiral_multiplier, "right_spiral_multiplier")
|
||||
param_f(p.right_spiral_multiplier, pp+"right_spiral_multiplier")
|
||||
-> editable(0, 10, .1, "right spiral multiplier", help, 'M')->unit = "°";
|
||||
|
||||
param_f(p.any_spiral_multiplier, "any_spiral_multiplier")
|
||||
param_f(p.any_spiral_multiplier, pp+"any_spiral_multiplier")
|
||||
-> editable(0, 10, .1, "any spiral multiplier", help, 'M')->unit = "°";
|
||||
|
||||
param_f(p.spiral_cone, "spiral_cone")
|
||||
param_f(p.spiral_cone, pp+"spiral_cone")
|
||||
-> editable(0, 360, -45, "spiral cone", "", 'C')->unit = "°";
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "hyper.h"
|
||||
namespace hr {
|
||||
|
||||
EX int avengers, mirrorspirits, wandering_jiangshi, jiangshi_on_screen;
|
||||
EX int avengers, mirrorspirits, wandering_jiangshi, jiangshi_on_screen, splitrocks;
|
||||
|
||||
EX bool timerghost = true;
|
||||
EX bool gen_wandering = true;
|
||||
|
@ -192,7 +192,7 @@ EX int reptilemax() {
|
|||
return r;
|
||||
}
|
||||
|
||||
bool wchance(int a, int of, int reduction = 0) {
|
||||
bool wchance_in(eLand l, int a, int of, int reduction = 0) {
|
||||
of *= 10;
|
||||
a += yendor::hardness() + 1;
|
||||
if(isCrossroads(cwt.at->land))
|
||||
|
@ -206,6 +206,11 @@ bool wchance(int a, int of, int reduction = 0) {
|
|||
a -= reduction;
|
||||
if(a < 0) return false;
|
||||
|
||||
if(use_custom_land_list) {
|
||||
of *= 100;
|
||||
a *= custom_land_wandering[l];
|
||||
}
|
||||
|
||||
return hrand(a+of) < a;
|
||||
}
|
||||
|
||||
|
@ -337,7 +342,7 @@ EX void wandering() {
|
|||
if(closed_or_bounded && specialland == laClearing)
|
||||
clearing::new_root();
|
||||
|
||||
if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance(items[itZebra], 20))
|
||||
if(cwt.at->land == laZebra && cwt.at->wall == waNone && wchance_in(laZebra, items[itZebra], 20))
|
||||
wanderingZebra(cwt.at);
|
||||
|
||||
bool smallbounded_generation = smallbounded || (closed_manifold && specialland == laClearing);
|
||||
|
@ -371,6 +376,8 @@ EX void wandering() {
|
|||
if(!valid(c)) continue;
|
||||
if(isPlayerOn(c)) break;
|
||||
|
||||
auto wchance = [c] (int a, int of, int reduction = 0) { return wchance_in(c->land, a, of, reduction); };
|
||||
|
||||
if(specialland == laStorms) {
|
||||
// place the sandstone wall completely randomly (but not on the player)
|
||||
vector<cell*>& ac = currentmap->allcells();
|
||||
|
@ -555,6 +562,12 @@ EX void wandering() {
|
|||
|
||||
else if(c->monst || c->pathdist == PINFD) break;
|
||||
|
||||
else if(c->land == laAsteroids && splitrocks && canReachPlayer(c, moYeti)) {
|
||||
c->monst = moAsteroid;
|
||||
splitrocks--;
|
||||
continue;
|
||||
}
|
||||
|
||||
else if(c->land == laAsteroids) {
|
||||
int gen = 0;
|
||||
if(asteroids_generated * 12 <= items[itAsteroid]) gen = 2;
|
||||
|
|
|
@ -887,8 +887,7 @@ EX void moveWorm(cell *c) {
|
|||
else
|
||||
addMessage(XLAT("The sandworm explodes!"));
|
||||
playSound(NULL, "explosion");
|
||||
if(geometry == gZebraQuotient)
|
||||
achievement_gain_once("ZEBRAWORM", rg::special_geometry);
|
||||
achievement_gain_once("ZEBRAWORM", specgeom_zebra());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
133
multi.cpp
133
multi.cpp
|
@ -11,21 +11,22 @@ namespace hr {
|
|||
EX namespace multi {
|
||||
|
||||
#if HDR
|
||||
static const int MAXJOY = 8;
|
||||
static const int MAXBUTTON = 64;
|
||||
static const int MAXAXE = 16;
|
||||
static const int MAXHAT = 4;
|
||||
static constexpr int SCANCODES = 512;
|
||||
static constexpr int MAXJOY = 8;
|
||||
static constexpr int MAXBUTTON = 64;
|
||||
static constexpr int MAXAXE = 16;
|
||||
static constexpr int MAXHAT = 4;
|
||||
|
||||
struct config {
|
||||
char keyaction[512];
|
||||
char joyaction[MAXJOY][MAXBUTTON];
|
||||
char axeaction[MAXJOY][MAXAXE];
|
||||
char hataction[MAXJOY][MAXHAT][4];
|
||||
int keyaction[SCANCODES];
|
||||
int joyaction[MAXJOY][MAXBUTTON];
|
||||
int axeaction[MAXJOY][MAXAXE];
|
||||
int hataction[MAXJOY][MAXHAT][4];
|
||||
int deadzoneval[MAXJOY][MAXAXE];
|
||||
};
|
||||
#endif
|
||||
|
||||
EX config scfg;
|
||||
EX config scfg_default;
|
||||
EX charstyle scs[MAXPLAYER];
|
||||
|
||||
EX bool split_screen;
|
||||
|
@ -75,8 +76,8 @@ EX namespace multi {
|
|||
|
||||
EX double mdx[MAXPLAYER], mdy[MAXPLAYER]; // movement vector for the next move
|
||||
|
||||
static const int CMDS = 15;
|
||||
static const int CMDS_PAN = 11;
|
||||
static constexpr int CMDS = 15;
|
||||
static constexpr int CMDS_PAN = 11;
|
||||
|
||||
vector<string> playercmds_shmup = {
|
||||
"forward", "backward", "turn left", "turn right",
|
||||
|
@ -165,13 +166,13 @@ EX const char* axemodes3[4] = {
|
|||
|
||||
EX int centerplayer = -1;
|
||||
|
||||
char* axeconfigs[24]; int numaxeconfigs;
|
||||
int* axeconfigs[24]; int numaxeconfigs;
|
||||
int* dzconfigs[24];
|
||||
|
||||
string listkeys(int id) {
|
||||
string listkeys(config& scfg, int id) {
|
||||
#if CAP_SDL
|
||||
string lk = "";
|
||||
for(int i=0; i<512; i++)
|
||||
for(int i=0; i<SCANCODES; i++)
|
||||
if(scfg.keyaction[i] == id)
|
||||
#if CAP_SDL2
|
||||
lk = lk + " " + SDL_GetScancodeName(SDL_Scancode(i));
|
||||
|
@ -236,8 +237,9 @@ struct key_configurer {
|
|||
vector<string>& shmupcmdtable;
|
||||
string caption;
|
||||
int setwhat;
|
||||
config *which_config;
|
||||
|
||||
key_configurer(int sc, vector<string>& sct, const string& caption) : sc(sc), shmupcmdtable(sct), caption(caption), setwhat(0) {
|
||||
key_configurer(int sc, vector<string>& sct, const string& caption, config& w) : sc(sc), shmupcmdtable(sct), caption(caption), setwhat(0), which_config(&w) {
|
||||
}
|
||||
|
||||
void operator() () {
|
||||
|
@ -247,7 +249,7 @@ struct key_configurer {
|
|||
getcstat = ' ';
|
||||
|
||||
for(int i=0; i<isize(shmupcmdtable); i++) if(shmupcmdtable[i][0])
|
||||
dialog::addSelItem(XLAT(shmupcmdtable[i]), listkeys(16*sc+i),
|
||||
dialog::addSelItem(XLAT(shmupcmdtable[i]), listkeys(*which_config, 16*sc+i),
|
||||
setwhat ? (setwhat>1 && i == (setwhat&15) ? '?' : 0) : 'a'+i);
|
||||
else dialog::addBreak(100);
|
||||
|
||||
|
@ -264,7 +266,8 @@ struct key_configurer {
|
|||
if(!setwhat) dialog::handleNavigation(sym, uni);
|
||||
if(sym) {
|
||||
if(setwhat) {
|
||||
scfg.keyaction[sym] = setwhat;
|
||||
int scan = key_to_scan(sym);
|
||||
if(scan >= 0 && scan < SCANCODES) which_config->keyaction[scan] = setwhat;
|
||||
setwhat = 0;
|
||||
}
|
||||
else if(uni >= 'a' && uni < 'a' + isize(shmupcmdtable) && shmupcmdtable[uni-'a'][0])
|
||||
|
@ -282,7 +285,7 @@ struct key_configurer {
|
|||
int joyid = ev.jbutton.which;
|
||||
int button = ev.jbutton.button;
|
||||
if(joyid < 8 && button < 32)
|
||||
scfg.joyaction[joyid][button] = setwhat;
|
||||
which_config->joyaction[joyid][button] = setwhat;
|
||||
setwhat = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -297,7 +300,7 @@ struct key_configurer {
|
|||
if(ev.jhat.value == SDL_HAT_LEFT) dir = 3;
|
||||
printf("%d %d %d\n", joyid, hat, dir);
|
||||
if(joyid < 8 && hat < 4 && dir < 4) {
|
||||
scfg.hataction[joyid][hat][dir] = setwhat;
|
||||
which_config->hataction[joyid][hat][dir] = setwhat;
|
||||
setwhat = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -309,7 +312,11 @@ struct key_configurer {
|
|||
};
|
||||
|
||||
EX reaction_t get_key_configurer(int sc, vector<string>& sct, string caption) {
|
||||
return key_configurer(sc, sct, caption);
|
||||
return key_configurer(sc, sct, caption, scfg_default);
|
||||
}
|
||||
|
||||
EX reaction_t get_key_configurer(int sc, vector<string>& sct, string caption, config &cfg) {
|
||||
return key_configurer(sc, sct, caption, cfg);
|
||||
}
|
||||
|
||||
EX reaction_t get_key_configurer(int sc, vector<string>& sct) {
|
||||
|
@ -320,7 +327,8 @@ EX reaction_t get_key_configurer(int sc, vector<string>& sct) {
|
|||
sc == 5 ? XLAT("configure player 4") :
|
||||
sc == 6 ? XLAT("configure player 5") :
|
||||
sc == 7 ? XLAT("configure player 6") :
|
||||
sc == 8 ? XLAT("configure player 7") : ""
|
||||
sc == 8 ? XLAT("configure player 7") : "",
|
||||
scfg_default
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -329,7 +337,8 @@ struct joy_configurer {
|
|||
|
||||
bool shmupcfg, racecfg;
|
||||
int playercfg;
|
||||
joy_configurer(int playercfg) : playercfg(playercfg) {}
|
||||
config& scfg;
|
||||
joy_configurer(int playercfg, config& scfg) : playercfg(playercfg), scfg(scfg) {}
|
||||
|
||||
void operator() () {
|
||||
dialog::init();
|
||||
|
@ -486,7 +495,7 @@ struct shmup_configurer {
|
|||
else if(uni == '6') pushScreen(get_key_configurer(7, cmdlist));
|
||||
else if(uni == '7') pushScreen(get_key_configurer(8, cmdlist));
|
||||
#if CAP_SDLJOY
|
||||
else if(uni == 'j') pushScreen(joy_configurer(players));
|
||||
else if(uni == 'j') pushScreen(joy_configurer(players, scfg_default));
|
||||
#endif
|
||||
else if(uni == 'a') multi::alwaysuse = !multi::alwaysuse;
|
||||
#if CAP_SDLJOY
|
||||
|
@ -515,6 +524,7 @@ EX void showConfigureMultiplayer() {
|
|||
dialog::do_if_confirmed([i] {
|
||||
stop_game();
|
||||
players = i;
|
||||
if(multi::players > 1 && !shmup::on) bow::weapon = bow::wBlade;
|
||||
start_game();
|
||||
});
|
||||
});
|
||||
|
@ -576,17 +586,52 @@ void pressaction(int id) {
|
|||
actionspressed[id]++;
|
||||
}
|
||||
|
||||
EX int key_to_scan(int sym) {
|
||||
#if CAP_SDL2
|
||||
return SDL_GetScancodeFromKey(sym);
|
||||
#else
|
||||
return sym;
|
||||
#endif
|
||||
}
|
||||
|
||||
EX bool notremapped(int sym) {
|
||||
int k = scfg.keyaction[sym];
|
||||
auto& scfg = scfg_default;
|
||||
int sc = key_to_scan(sym);
|
||||
if(sc < 0 || sc >= SCANCODES) return true;
|
||||
int k = scfg.keyaction[sc];
|
||||
if(k == 0) return true;
|
||||
k /= 16;
|
||||
if(k > 3) k--; else if(k==3) k = 0;
|
||||
return k > multi::players;
|
||||
}
|
||||
|
||||
EX void initConfig() {
|
||||
EX void sconfig_savers(config& scfg, string prefix) {
|
||||
// unfortunately we cannot use key names here because SDL is not yet initialized
|
||||
for(int i=0; i<SCANCODES; i++)
|
||||
param_i(scfg.keyaction[i], prefix + string("key:")+its(i));
|
||||
|
||||
char* t = scfg.keyaction;
|
||||
for(int i=0; i<MAXJOY; i++) {
|
||||
string pre = prefix + "joystick "+cts('A'+i);
|
||||
for(int j=0; j<MAXBUTTON; j++)
|
||||
param_i(scfg.joyaction[i][j], pre+"-B"+its(j));
|
||||
for(int j=0; j<MAXAXE; j++) {
|
||||
param_i(scfg.axeaction[i][j], pre+" axis "+its(j));
|
||||
param_i(scfg.deadzoneval[i][j], pre+" deadzone "+its(j));
|
||||
}
|
||||
for(int j=0; j<MAXHAT; j++) for(int k=0; k<4; k++) {
|
||||
param_i(scfg.hataction[i][j][k], pre+" hat "+its(j)+" "+"URDL"[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EX void clear_config(config& scfg) {
|
||||
for(int i=0; i<SCANCODES; i++) scfg.keyaction[i] = 0;
|
||||
}
|
||||
|
||||
EX void initConfig() {
|
||||
auto& scfg = scfg_default;
|
||||
|
||||
int* t = scfg.keyaction;
|
||||
|
||||
#if CAP_SDL2
|
||||
|
||||
|
@ -721,7 +766,7 @@ EX void initConfig() {
|
|||
multi::scs[6].uicolor = 0xC0C0C0FF;
|
||||
|
||||
#if CAP_CONFIG
|
||||
addsaver(multi::players, "mode-number of players");
|
||||
param_i(multi::players, "mode-number of players")->be_non_editable();
|
||||
param_b(multi::split_screen, "splitscreen", false)
|
||||
->editable("split screen mode", 's');
|
||||
param_b(multi::pvp_mode, "pvp_mode", false)
|
||||
|
@ -732,27 +777,16 @@ EX void initConfig() {
|
|||
->editable("self hits", 'h');
|
||||
param_b(multi::two_focus, "two_focus", false)
|
||||
->editable("auto-adjust dual-focus projections", 'f');
|
||||
addsaver(alwaysuse, "use configured keys");
|
||||
// unfortunately we cannot use key names here because SDL is not yet initialized
|
||||
for(int i=0; i<512; i++)
|
||||
addsaver(scfg.keyaction[i], string("key:")+its(i));
|
||||
for(int i=0; i<MAXJOY; i++) {
|
||||
string pre = "joystick "+cts('A'+i);
|
||||
for(int j=0; j<MAXBUTTON; j++)
|
||||
addsaver(scfg.joyaction[i][j], pre+"-B"+its(j));
|
||||
for(int j=0; j<MAXAXE; j++) {
|
||||
addsaver(scfg.axeaction[i][j], pre+" axis "+its(j));
|
||||
addsaver(scfg.deadzoneval[i][j], pre+" deadzone "+its(j));
|
||||
}
|
||||
for(int j=0; j<MAXHAT; j++) for(int k=0; k<4; k++) {
|
||||
addsaver(scfg.hataction[i][j][k], pre+" hat "+its(j)+" "+"URDL"[k]);
|
||||
}
|
||||
}
|
||||
for(int i=0; i<7; i++) addsaver(multi::scs[i], "player"+its(i));
|
||||
param_b(alwaysuse, "use configured keys");
|
||||
|
||||
for(int i=0; i<7; i++) paramset(multi::scs[i], "player"+its(i));
|
||||
|
||||
sconfig_savers(scfg, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
EX void get_actions() {
|
||||
EX void get_actions(config& scfg) {
|
||||
|
||||
#if !ISMOBILE
|
||||
const Uint8 *keystate = SDL12_GetKeyState(NULL);
|
||||
|
||||
|
@ -792,14 +826,15 @@ EX void get_actions() {
|
|||
#endif
|
||||
}
|
||||
|
||||
EX void handleInput(int delta) {
|
||||
EX void handleInput(int delta, config &scfg) {
|
||||
#if CAP_SDL
|
||||
double d = delta / 500.;
|
||||
|
||||
get_actions();
|
||||
get_actions(scfg);
|
||||
|
||||
const Uint8 *keystate = SDL12_GetKeyState(NULL);
|
||||
if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5;
|
||||
|
||||
if(keystate[SDL12(SDLK_LCTRL, SDL_SCANCODE_LCTRL)] || keystate[SDL12(SDLK_RCTRL, SDL_SCANCODE_RCTRL)]) d /= 5;
|
||||
|
||||
double panx =
|
||||
actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0;
|
||||
|
@ -857,6 +892,8 @@ EX void handleInput(int delta) {
|
|||
#endif
|
||||
}
|
||||
|
||||
EX void handleInput(int delta) { handleInput(delta, scfg_default); }
|
||||
|
||||
EX int tableid[7] = {1, 2, 4, 5, 6, 7, 8};
|
||||
|
||||
EX void leaveGame(int i) {
|
||||
|
|
|
@ -29,7 +29,7 @@ struct gamedata {
|
|||
::new (&record[index]) T(std::move(x));
|
||||
}
|
||||
else {
|
||||
T& at = (T&) record[index];
|
||||
T& at = *((T*) (void*) &(record[index]));
|
||||
x = std::move(at);
|
||||
at.~T();
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void gamedata_all(gamedata& gd) {
|
|||
gd.store(genrange_bonus);
|
||||
gd.store(gamerange_bonus);
|
||||
gd.store(targets);
|
||||
gd.store(patterns::rwalls);
|
||||
gd.store(ccolor::rwalls);
|
||||
if(GOLDBERG) gd.store(gp::param);
|
||||
callhooks(hooks_gamedata, &gd);
|
||||
}
|
||||
|
|
|
@ -439,9 +439,7 @@ EX namespace netgen {
|
|||
for(int ix=0; ix<PX; ix++) {
|
||||
for(int y=0; y<qy; y++) for(int x=0; x<qx; x++)
|
||||
qpixel(quarter,x,y) = qpixel(net, x+qx*ix, y+qy*iy);
|
||||
char buf[64];
|
||||
sprintf(buf, "papermodel-page%d%d" IMAGEEXT, iy, ix);
|
||||
IMAGESAVE(quarter, buf);
|
||||
IMAGESAVE(quarter, hr::format("papermodel-page%d%d" IMAGEEXT, iy, ix).c_str());
|
||||
}
|
||||
|
||||
SDL_FreeSurface(net);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue