diff --git a/classes.cpp b/classes.cpp index 1345ee55..813532da 100644 --- a/classes.cpp +++ b/classes.cpp @@ -739,7 +739,7 @@ enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProdu enum class eVariation { bitruncated, pure, goldberg, irregular, dual, untruncated, warped, unrectified }; -typedef flagtype modecode_t; +typedef int modecode_t; /** only the actual geometry */ struct geometryinfo1 { @@ -764,7 +764,6 @@ struct geometryinfo { int vertex; flagtype flags; geometryinfo1 g; - modecode_t xcode; std::array distlimit; // bitrunc, non-bitrunc eVariation default_variation; }; @@ -844,85 +843,85 @@ EX modecode_t no_code = 0x1; /** list of available geometries */ EX vector ginf = { - {"{7,3}", "none", "{7,3} (standard HyperRogue map)", "HR", 7, 3, 0, giHyperb2, 0, {{7, 5}}, eVariation::bitruncated}, - {"{6,3}", "none", "{6,3} (euclidean Hex grid)", "euclid", 6, 3, qOPTQ, giEuclid2, 0, {{7, 7}}, eVariation::bitruncated}, - {"{5,3}", "none", "{5,3} (dodecahedron)", "sphere", 5, 3, qsSMALLB, giSphere2, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"{5,3}", "elliptic", "elliptic geometry in {5,3}", "elliptic", 5, 3, qsNONORE, giSphere2, 0, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"{7,3}", "Zebra", "Zebra quotient", "Zebra", 7, 3, qsZEBRA, giHyperb2, 0x00400, {{7, 5}}, eVariation::bitruncated}, - {"{7,3}", "field", "field quotient", "field", 7, 3, qsFIELD, giHyperb2, 0x00200, {{7, 5}}, eVariation::bitruncated}, - {"{6,3}", "torus", "torus/Klein bottle/...", "torus", 6, 3, qsBQ|qDEPRECATED, giEuclid2, 0x00600, {{7, 7}}, eVariation::bitruncated}, - {"{8,3}", "none", "{8,3} (like standard but with octagons)", "oct", 8, 3, 0, giHyperb2, 0x08000, {{6, 4}}, eVariation::bitruncated}, - {"{5,4}", "none", "{5,4} (four pentagons)", "4x5", 5, 4, 0, giHyperb2, 0x08200, {{6, 4}}, eVariation::bitruncated}, - {"{6,4}", "none", "{6,4} (four hexagons)", "4x6", 6, 4, 0, giHyperb2, 0x08400, {{5, 3}}, eVariation::bitruncated}, - {"{7,4}", "none", "{7,4} (four heptagons)", "4x7", 7, 4, 0, giHyperb2, 0x08600, {{4, 3}}, eVariation::bitruncated}, - {"{4,3}", "none", "{4,3} (cube)", "3x4", 4, 3, qsSMALLB, giSphere2, 0x10000, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"{3,3}", "none", "{3,3} (tetrahedron)", "3x3", 3, 3, qsSMALLB, giSphere2, 0x10200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"{4,4}", "none", "{4,4} (Euclidean square grid)", "4x4", 4, 4, qOPTQ, giEuclid2, 0x10400, {{7, 7}}, eVariation::bitruncated}, - {"{4,3}", "elliptic", "elliptic geometry in {4,3}", "e3x4", 4, 3, qsNONORE, giSphere2, 0x10600, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"{7,3}", "Klein", "Klein Quartic", "Klein", 7, 3, qsSMALL, giHyperb2, 0x18000, {{7, 5}}, eVariation::bitruncated}, - {"{8,3}", "Bolza", "Bolza Surface", "Bolza", 8, 3, qsDOCKS, giHyperb2, 0x18200, {{6, 4}}, eVariation::bitruncated}, - {"{8,3}", "Bolza2", "Bolza Surface x2", "Bolza2", 8, 3, qsDOCKS, giHyperb2, 0x18400, {{6, 4}}, eVariation::bitruncated}, - {"{7,3}", "minimal", "minimal quotient", "minimal", 7, 3, qsSMALLN, giHyperb2, 0x18600, {{7, 5}}, eVariation::bitruncated}, - {"binary","none", "variant of the binary tiling", "binary", 7, 3, qBINARY, giHyperb2, 0x48400, {{7, 5}}, eVariation::pure}, - {"Arch", "none", "Archimedean", "A", 7, 3, qARCHI, giHyperb2, 0, {{7, 5}}, eVariation::pure}, - {"{7,3}", "Macbeath", "Macbeath Surface", "Macbeath", 7, 3, qsSMALL, giHyperb2, 0x20000, {{7, 5}}, eVariation::bitruncated}, - {"{5,4}", "Bring", "Bring's Surface", "Bring", 5, 4, qsSMALL, giHyperb2, 0x20200, {{6, 4}}, eVariation::bitruncated}, - {"{12,3}","M3", "Schmutz's M(3)", "M3", 12, 3, qsSMALL, giHyperb2, 0x20400, {{4, 2}}, eVariation::bitruncated}, - {"{12,3}","M4", "Schmutz's M(4)", "M4", 12, 3, qsSMALL, giHyperb2, 0x20600, {{4, 2}}, eVariation::bitruncated}, - {"{6,4}", "Crystal", "dimensional crystal", "Crystal", 6, 4, qANYQ|qCRYSTAL, giHyperb2, 0x28000, {{5, 3}}, eVariation::pure}, - {"{3,4}", "none", "{3,4} (octahedron)", "4x3", 3, 4, qsSMALLB, giSphere2, 0x28200, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, - {"bin{4,4}", "none", "{4,4} on horospheres", "bin44", 9, 3, qBINARY, giHyperb3, 0x30000, {{7, 3}}, eVariation::pure}, - {"{4,3,4}","none", "{4,3,4} cube tiling", "434", 6, 4, qOPTQ, giEuclid3, 0x30200, {{7, 5}}, eVariation::pure}, - {"{5,3,3}","none", "{5,3,3} 120-cell", "533", 12, 3, qsSMALLB, giSphere3, 0x30400, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{5,3,3}", "elliptic","{5,3,3} 120-cell (elliptic space)", "e533", 12, 3, qsSMALLBE, giSphere3, 0x30600, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"rh{4,3,4}","none", "rhombic dodecahedral honeycomb", "rh434", 12, 3, qOPTQ, giEuclid3, 0x31000, {{7, 5}}, eVariation::pure}, - {"2t{4,3,4}","none", "bitruncated cubic honeycomb", "2t434", 14, 3, qOPTQ, giEuclid3, 0x31200, {{7, 5}}, eVariation::pure}, - {"{5,3,4}","none", "{5,3,4} hyperbolic honeycomb", "534", 12, 4, 0, giHyperb3, 0x31400, {{7, 2}}, eVariation::pure}, - {"{4,3,5}","none", "{4,3,5} hyperbolic honeycomb", "435", 6, 5, 0, giHyperb3, 0x31600, {{7, 2}}, eVariation::pure}, - {"{3,3,3}","none", "{3,3,3} 5-cell", "333", 4, 3, qsSMALLB, giSphere3, 0x38000, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{3,3,4}","none", "{3,3,4} 16-cell", "334", 4, 4, qsSMALLB, giSphere3, 0x38200, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{3,3,4}","elliptic","{3,3,4} 16-cell (elliptic space)", "e334", 4, 4, qsSMALLBE, giSphere3, 0x39200, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{4,3,3}","none", "{4,3,3} 8-cell", "433", 6, 4, qsSMALLB, giSphere3, 0x38400, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{4,3,3}","elliptic","{4,3,3} 8-cell (elliptic space)", "e433", 6, 4, qsSMALLBE, giSphere3, 0x39400, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{3,4,3}","none", "{3,4,3} 24-cell", "343", 8, 3, qsSMALLB, giSphere3, 0x38600, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{3,4,3}","elliptic","{3,4,3} 24-cell (elliptic space)", "e343", 8, 3, qsSMALLBE, giSphere3, 0x39600, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{3,3,5}","none", "{3,3,5} 600-cell", "335", 4, 3, qsSMALLB, giSphere3, 0x41000, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{3,3,5}","elliptic","{3,3,5} 600-cell (elliptic space)", "e335", 4, 3, qsSMALLBE, giSphere3, 0x41200, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"bin{3,6}", "none", "{3,6} on horospheres", "bin36", 8, 3, qBINARY, giHyperb3, 0x40000, {{7, 3}}, eVariation::pure}, - {"bin-rect", "none", "rectangles on horospheres", "bin44/2", 7, 3, qBINARY, giHyperb3, 0x40200, {{7, 3}}, eVariation::pure}, - {"bin{6,3}", "none", "{6,3} on horospheres", "bin63", 14, 3, qBINARY, giHyperb3, 0x40400, {{7, 3}}, eVariation::pure}, - {"{4,3,5}","field", "{4,3,5} field quotient space", "f435", 6, 5, qsSMALLBF | qDEPRECATED, giHyperb3, 0x40600, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"{5,3,4}","field", "{5,3,4} field quotient space", "f435", 12, 4, qsSMALLBF | qDEPRECATED, giHyperb3, 0x40800, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, - {"binary4","none", "standard binary tiling", "binary4", 5, 3, qBINARY, giHyperb2, 0x41400, {{7, 5}}, eVariation::pure}, - {"sol", "none", "Solv geometry", "sol", 8, 3, qBINARY|qSOL, giSolNIH, 0x41600, {{7, 5}}, eVariation::pure}, - {"kd2", "none", "kite-and-dart", "kd2", 4, 3, qKITE, giEuclid2, 0x48000, {{7, 7}}, eVariation::pure}, - {"kd3", "none", "kite-and-dart on horospheres", "kd3", 12, 3, qsBP, giHyperb3, 0x48200, {{7, 3}}, eVariation::pure}, - {"nil", "none", "Nil geometry", "nil", 6, 3, qOPTQ, giNil, 0x48600, {{7, 5}}, eVariation::pure}, - {"product","none", "product space", "product", 7, 3, qHYBRID, giProduct, 0x00000, {{7, 3}}, eVariation::pure}, - {"twisted","none", "rotation space", "twisted", 7, 3, qHYBRID, giSL2, 0x00000, {{6, 4}}, eVariation::pure}, - {"ternary","none", "standard ternary tiling", "ternary", 6, 3, qBINARY, giHyperb2, 0x48400, {{6, 4}}, eVariation::pure}, - {"3x2", "none", "stretched hyperbolic", "3:2", 11, 3, qBINARY|qNIH, giSolNIH, 0x49000, {{6, 3}}, eVariation::pure}, - {"3x1/2", "none", "stretched Solv", "3:1/2", 9, 3, (qBINARY|qSOL|qNIH), giSolNIH, 0x49200, {{7, 3}}, eVariation::pure}, - {"{3,oo}", "none", "{3,∞} (infinite triangles)", "oox3", 3, OINF, qIDEAL, giHyperb2, 0x49400, {{7, 7}}, eVariation::pure}, - {"{3,3,6}","none", "{3,3,6} hyperbolic honeycomb", "336", 4, 6, qIDEAL, giHyperb3, 0x49600, {{7, 2}}, eVariation::pure}, - {"{3,4,4}","none", "{3,4,4} hyperbolic honeycomb", "344", 8, 4, qIDEAL, giHyperb3, 0x50000, {{7, 2}}, eVariation::pure}, - {"{3,4,4}","Crystal", "4D crystal in H3", "Cryst3" , 8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, 0x52000, {{7, 3}}, eVariation::pure}, - {"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ, giSolNIH, 0x52200, {{6, 4}}, eVariation::pure}, - {"file", "none", "load from file", "file", 7, 3, qEXPERIMENTAL, giEuclid2, 0, {{7, 5}}, eVariation::pure}, - {"{4,oo}", "none", "{4,∞} (infinite squares)", "oox4", 4, OINF, qIDEAL, giHyperb2, 0x49400, {{5, 5}}, eVariation::pure}, - {"{5,3,4}","Crystal", "6D crystal in H3", "Cryst6" , 12, 4, qANYQ | qCRYSTAL, giHyperb3, 0x52000, {{7, 3}}, eVariation::pure}, - {"{5,3,5}","none", "{5,3,5} hyperbolic honeycomb", "535", 12, 5, 0, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{5,3,6}","none", "{5,3,6} hyperbolic honeycomb", "536", 12, 6, qIDEAL, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{5,3,5}","SWh", "{5,3,5} quotient", "535c", 12, 5, qsSMALLB | qANYQ, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{5,3,5}","SW", "Seifert-Weber space", "535s", 12, 5, qsSINGLE, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{5,3,3}","SW", "Poincaré homology sphere", "533s", 12, 3, qsSINGLE, giSphere3, no_code, {{7, 2}}, eVariation::pure}, - {"{?,oo}", "none", "{3/4,∞} (infinite triangles and squares)", "ooxm", 3, OINF, qIDEAL | qINFMIXED, giHyperb2, no_code, {{6, 6}}, eVariation::pure}, - {"{4,3,6}","none", "{4,3,6} hyperbolic honeycomb", "436", 6, 6, qIDEAL, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"?", "none", "fake", "", 0, 0, qRAYONLY, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{3,4,5}","none", "{3,4,5} hyperbolic honeycomb", "345", 8, 5, qIDEAL | qULTRA, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{3,5,3}","none", "{3,5,3} hyperbolic honeycomb", "353", 20, 5, 0, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{3,5,4}","none", "{3,5,4} hyperbolic honeycomb", "354", 20, 5, qIDEAL | qULTRA, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, - {"{3,5,5}","none", "{3,5,5} hyperbolic honeycomb", "355", 20, 5, qIDEAL | qULTRA, giHyperb3, no_code, {{7, 2}}, eVariation::pure}, + {"{7,3}", "none", "{7,3} (standard HyperRogue map)", "HR", 7, 3, 0, giHyperb2, {{7, 5}}, eVariation::bitruncated}, + {"{6,3}", "none", "{6,3} (euclidean Hex grid)", "euclid", 6, 3, qOPTQ, giEuclid2, {{7, 7}}, eVariation::bitruncated}, + {"{5,3}", "none", "{5,3} (dodecahedron)", "sphere", 5, 3, qsSMALLB, giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{5,3}", "elliptic", "elliptic geometry in {5,3}", "elliptic", 5, 3, qsNONORE, giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{7,3}", "Zebra", "Zebra quotient", "Zebra", 7, 3, qsZEBRA, giHyperb2, {{7, 5}}, eVariation::bitruncated}, + {"{7,3}", "field", "field quotient", "field", 7, 3, qsFIELD, giHyperb2, {{7, 5}}, eVariation::bitruncated}, + {"{6,3}", "torus", "torus/Klein bottle/...", "torus", 6, 3, qsBQ|qDEPRECATED, giEuclid2, {{7, 7}}, eVariation::bitruncated}, + {"{8,3}", "none", "{8,3} (like standard but with octagons)", "oct", 8, 3, 0, giHyperb2, {{6, 4}}, eVariation::bitruncated}, + {"{5,4}", "none", "{5,4} (four pentagons)", "4x5", 5, 4, 0, giHyperb2, {{6, 4}}, eVariation::bitruncated}, + {"{6,4}", "none", "{6,4} (four hexagons)", "4x6", 6, 4, 0, giHyperb2, {{5, 3}}, eVariation::bitruncated}, + {"{7,4}", "none", "{7,4} (four heptagons)", "4x7", 7, 4, 0, giHyperb2, {{4, 3}}, eVariation::bitruncated}, + {"{4,3}", "none", "{4,3} (cube)", "3x4", 4, 3, qsSMALLB, giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{3,3}", "none", "{3,3} (tetrahedron)", "3x3", 3, 3, qsSMALLB, giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{4,4}", "none", "{4,4} (Euclidean square grid)", "4x4", 4, 4, qOPTQ, giEuclid2, {{7, 7}}, eVariation::bitruncated}, + {"{4,3}", "elliptic", "elliptic geometry in {4,3}", "e3x4", 4, 3, qsNONORE, giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"{7,3}", "Klein", "Klein Quartic", "Klein", 7, 3, qsSMALL, giHyperb2, {{7, 5}}, eVariation::bitruncated}, + {"{8,3}", "Bolza", "Bolza Surface", "Bolza", 8, 3, qsDOCKS, giHyperb2, {{6, 4}}, eVariation::bitruncated}, + {"{8,3}", "Bolza2", "Bolza Surface x2", "Bolza2", 8, 3, qsDOCKS, giHyperb2, {{6, 4}}, eVariation::bitruncated}, + {"{7,3}", "minimal", "minimal quotient", "minimal", 7, 3, qsSMALLN, giHyperb2, {{7, 5}}, eVariation::bitruncated}, + {"binary","none", "variant of the binary tiling", "binary", 7, 3, qBINARY, giHyperb2, {{7, 5}}, eVariation::pure}, + {"Arch", "none", "Archimedean", "A", 7, 3, qARCHI, giHyperb2, {{7, 5}}, eVariation::pure}, + {"{7,3}", "Macbeath", "Macbeath Surface", "Macbeath", 7, 3, qsSMALL, giHyperb2, {{7, 5}}, eVariation::bitruncated}, + {"{5,4}", "Bring", "Bring's Surface", "Bring", 5, 4, qsSMALL, giHyperb2, {{6, 4}}, eVariation::bitruncated}, + {"{12,3}","M3", "Schmutz's M(3)", "M3", 12, 3, qsSMALL, giHyperb2, {{4, 2}}, eVariation::bitruncated}, + {"{12,3}","M4", "Schmutz's M(4)", "M4", 12, 3, qsSMALL, giHyperb2, {{4, 2}}, eVariation::bitruncated}, + {"{6,4}", "Crystal", "dimensional crystal", "Crystal", 6, 4, qANYQ|qCRYSTAL, giHyperb2, {{5, 3}}, eVariation::pure}, + {"{3,4}", "none", "{3,4} (octahedron)", "4x3", 3, 4, qsSMALLB, giSphere2, {{SEE_ALL, SEE_ALL}}, eVariation::bitruncated}, + {"bin{4,4}", "none", "{4,4} on horospheres", "bin44", 9, 3, qBINARY, giHyperb3, {{7, 3}}, eVariation::pure}, + {"{4,3,4}","none", "{4,3,4} cube tiling", "434", 6, 4, qOPTQ, giEuclid3, {{7, 5}}, eVariation::pure}, + {"{5,3,3}","none", "{5,3,3} 120-cell", "533", 12, 3, qsSMALLB, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{5,3,3}", "elliptic","{5,3,3} 120-cell (elliptic space)", "e533", 12, 3, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"rh{4,3,4}","none", "rhombic dodecahedral honeycomb", "rh434", 12, 3, qOPTQ, giEuclid3, {{7, 5}}, eVariation::pure}, + {"2t{4,3,4}","none", "bitruncated cubic honeycomb", "2t434", 14, 3, qOPTQ, giEuclid3, {{7, 5}}, eVariation::pure}, + {"{5,3,4}","none", "{5,3,4} hyperbolic honeycomb", "534", 12, 4, 0, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{4,3,5}","none", "{4,3,5} hyperbolic honeycomb", "435", 6, 5, 0, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,3,3}","none", "{3,3,3} 5-cell", "333", 4, 3, qsSMALLB, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{3,3,4}","none", "{3,3,4} 16-cell", "334", 4, 4, qsSMALLB, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{3,3,4}","elliptic","{3,3,4} 16-cell (elliptic space)", "e334", 4, 4, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{4,3,3}","none", "{4,3,3} 8-cell", "433", 6, 4, qsSMALLB, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{4,3,3}","elliptic","{4,3,3} 8-cell (elliptic space)", "e433", 6, 4, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{3,4,3}","none", "{3,4,3} 24-cell", "343", 8, 3, qsSMALLB, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{3,4,3}","elliptic","{3,4,3} 24-cell (elliptic space)", "e343", 8, 3, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{3,3,5}","none", "{3,3,5} 600-cell", "335", 4, 3, qsSMALLB, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{3,3,5}","elliptic","{3,3,5} 600-cell (elliptic space)", "e335", 4, 3, qsSMALLBE, giSphere3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"bin{3,6}", "none", "{3,6} on horospheres", "bin36", 8, 3, qBINARY, giHyperb3, {{7, 3}}, eVariation::pure}, + {"bin-rect", "none", "rectangles on horospheres", "bin44/2", 7, 3, qBINARY, giHyperb3, {{7, 3}}, eVariation::pure}, + {"bin{6,3}", "none", "{6,3} on horospheres", "bin63", 14, 3, qBINARY, giHyperb3, {{7, 3}}, eVariation::pure}, + {"{4,3,5}","field", "{4,3,5} field quotient space", "f435", 6, 5, qsSMALLBF | qDEPRECATED, giHyperb3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"{5,3,4}","field", "{5,3,4} field quotient space", "f435", 12, 4, qsSMALLBF | qDEPRECATED, giHyperb3, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, + {"binary4","none", "standard binary tiling", "binary4", 5, 3, qBINARY, giHyperb2, {{7, 5}}, eVariation::pure}, + {"sol", "none", "Solv geometry", "sol", 8, 3, qBINARY|qSOL, giSolNIH, {{7, 5}}, eVariation::pure}, + {"kd2", "none", "kite-and-dart", "kd2", 4, 3, qKITE, giEuclid2, {{7, 7}}, eVariation::pure}, + {"kd3", "none", "kite-and-dart on horospheres", "kd3", 12, 3, qsBP, giHyperb3, {{7, 3}}, eVariation::pure}, + {"nil", "none", "Nil geometry", "nil", 6, 3, qOPTQ, giNil, {{7, 5}}, eVariation::pure}, + {"product","none", "product space", "product", 7, 3, qHYBRID, giProduct, {{7, 3}}, eVariation::pure}, + {"twisted","none", "rotation space", "twisted", 7, 3, qHYBRID, giSL2, {{6, 4}}, eVariation::pure}, + {"ternary","none", "standard ternary tiling", "ternary", 6, 3, qBINARY, giHyperb2, {{6, 4}}, eVariation::pure}, + {"3x2", "none", "stretched hyperbolic", "3:2", 11, 3, qBINARY|qNIH, giSolNIH, {{6, 3}}, eVariation::pure}, + {"3x1/2", "none", "stretched Solv", "3:1/2", 9, 3, (qBINARY|qSOL|qNIH), giSolNIH, {{7, 3}}, eVariation::pure}, + {"{3,oo}", "none", "{3,∞} (infinite triangles)", "oox3", 3, OINF, qIDEAL, giHyperb2, {{7, 7}}, eVariation::pure}, + {"{3,3,6}","none", "{3,3,6} hyperbolic honeycomb", "336", 4, 6, qIDEAL, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,4,4}","none", "{3,4,4} hyperbolic honeycomb", "344", 8, 4, qIDEAL, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,4,4}","Crystal", "4D crystal in H3", "Cryst3" , 8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, {{7, 3}}, eVariation::pure}, + {"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ, giSolNIH, {{6, 4}}, eVariation::pure}, + {"file", "none", "load from file", "file", 7, 3, qEXPERIMENTAL, giEuclid2, {{7, 5}}, eVariation::pure}, + {"{4,oo}", "none", "{4,∞} (infinite squares)", "oox4", 4, OINF, qIDEAL, giHyperb2, {{5, 5}}, eVariation::pure}, + {"{5,3,4}","Crystal", "6D crystal in H3", "Cryst6" , 12, 4, qANYQ | qCRYSTAL, giHyperb3, {{7, 3}}, eVariation::pure}, + {"{5,3,5}","none", "{5,3,5} hyperbolic honeycomb", "535", 12, 5, 0, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{5,3,6}","none", "{5,3,6} hyperbolic honeycomb", "536", 12, 6, qIDEAL, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{5,3,5}","SWh", "{5,3,5} quotient", "535c", 12, 5, qsSMALLB | qANYQ, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{5,3,5}","SW", "Seifert-Weber space", "535s", 12, 5, qsSINGLE, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{5,3,3}","SW", "Poincaré homology sphere", "533s", 12, 3, qsSINGLE, giSphere3, {{7, 2}}, eVariation::pure}, + {"{?,oo}", "none", "{3/4,∞} (infinite triangles and squares)", "ooxm", 3, OINF, qIDEAL | qINFMIXED, giHyperb2, {{6, 6}}, eVariation::pure}, + {"{4,3,6}","none", "{4,3,6} hyperbolic honeycomb", "436", 6, 6, qIDEAL, giHyperb3, {{7, 2}}, eVariation::pure}, + {"?", "none", "fake", "", 0, 0, qRAYONLY, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,4,5}","none", "{3,4,5} hyperbolic honeycomb", "345", 8, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,5,3}","none", "{3,5,3} hyperbolic honeycomb", "353", 20, 5, 0, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,5,4}","none", "{3,5,4} hyperbolic honeycomb", "354", 20, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure}, + {"{3,5,5}","none", "{3,5,5} hyperbolic honeycomb", "355", 20, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure}, }; // bits: 9, 10, 15, 16, (reserved for later) 17, 18 diff --git a/fake.cpp b/fake.cpp index 00850350..336a66f9 100644 --- a/fake.cpp +++ b/fake.cpp @@ -518,8 +518,6 @@ void set_gfake(ld _around) { check_cgi(); cgi.require_basics(); - ginf[gFake].xcode = no_code; - if(currentmap) new hrmap_fake(currentmap); } diff --git a/hprint.cpp b/hprint.cpp index bedcbf28..194aa67d 100644 --- a/hprint.cpp +++ b/hprint.cpp @@ -134,9 +134,11 @@ struct fhstream : hstream { }; struct shstream : hstream { + color_t vernum; + virtual color_t get_vernum() override { return vernum; } string s; int pos; - shstream(const string& t = "") : s(t) { pos = 0; } + shstream(const string& t = "") : s(t) { pos = 0; vernum = VERNUM_HEX; } virtual void write_char(char c) { s += c; } virtual char read_char() { if(pos == isize(s)) throw hstream_exception(); return s[pos++]; } }; @@ -402,6 +404,30 @@ template T deserialize(const string& s) { } #endif +EX string as_hexstring(string o) { + string res; + for(char x: o) { + char buf[4]; + sprintf(buf, "%02X", (unsigned char)(x)); + res += buf; + } + return res; + } + +EX string from_hexstring(string o) { + string res; + for(int i=0; i hiitems[modecode()][it]) - changes.value_set(hiitems[modecode()][it], v); + if(v > hiitems[xcode][it]) + changes.value_set(hiitems[xcode][it], v); + } + +EX void updateHi(eItem it, int v) { + updateHi_for_code(it, v, modecode()); } EX void gainItem(eItem it) { diff --git a/legacy.cpp b/legacy.cpp index f9aa5efa..b9f1f005 100644 --- a/legacy.cpp +++ b/legacy.cpp @@ -2,9 +2,9 @@ // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details #include "hyper.h" -#if CAP_LEGACY namespace hr { +#if CAP_LEGACY namespace shmup { void scanchar(FILE *f, char& c) { @@ -143,6 +143,100 @@ void loadOldConfig(FILE *f) { err=fscanf(f, "%d%d%d%d%lf\n", &vid.mobilecompasssize, &vid.aurastr, &vid.aurasmoothen, &vid.graphglyph, &jps); vid.linewidth = jps; } +#endif + +// Identifiers for the current combinations of game modes +// These are recorded in the save file, so it is somewhat +// important that they do not change for already existing +// modes, as otherwise the scores would be lost. +// Unfortunately, the codes assigned when HyperRogue had +// just a few special modes did not really follow a specific +// rule, so this system has grown rather ugly as the +// number of special modes kept growing... + +// mode codes for 'old' modes, from 0 to 255 + +int modecodetable[42][6] = { + { 0, 38, 39, 40, 41, 42}, // softcore hyperbolic + { 7, 43, 44, 45, 46, 47}, // hardcore hyperbolic + { 2, 4, 9, 11, 48, 49}, // shmup hyperbolic + { 13, 50, 51, 52, 53, 54}, // softcore heptagonal hyperbolic + { 16, 55, 56, 57, 58, 59}, // hardcore heptagonal hyperbolic + { 14, 15, 17, 18, 60, 61}, // shmup heptagonal hyperbolic + { 1, 62, 63, 64, 65, 66}, // softcore euclidean + { 8, 67, 68, 69, 70, 71}, // hardcore euclidean + { 3, 5, 10, 12, 72, 73}, // shmup euclidean + {110,111,112,113,114,115}, // softcore spherical + {116,117,118,119,120,121}, // hardcore spherical + {122,123,124,125,126,127}, // shmup spherical + {128,129,130,131,132,133}, // softcore heptagonal spherical + {134,135,136,137,138,139}, // hardcore heptagonal spherical + {140,141,142,143,144,145}, // shmup heptagonal spherical + {146,147,148,149,150,151}, // softcore elliptic + {152,153,154,155,156,157}, // hardcore elliptic + {158,159,160,161,162,163}, // shmup elliptic + {164,165,166,167,168,169}, // softcore heptagonal elliptic + {170,171,172,173,174,175}, // hardcore heptagonal elliptic + {176,177,178,179,180,181}, // shmup heptagonal elliptic + { 19, 74, 75, 76, 77, 78}, // softcore hyperbolic chaosmode + { 26, 79, 80, 81, 82, 83}, // hardcore hyperbolic chaosmode + { 21, 23, 28, 30, 84, 85}, // shmup hyperbolic chaosmode + { 32, 86, 87, 88, 89, 90}, // softcore heptagonal hyperbolic chaosmode + { 35, 91, 92, 93, 94, 95}, // hardcore heptagonal hyperbolic chaosmode + { 33, 34, 36, 37, 96, 97}, // shmup heptagonal hyperbolic chaosmode + { 20, 98, 99,100,101,102}, // softcore euclidean chaosmode + { 27,103,104,105,106,107}, // hardcore euclidean chaosmode + { 22, 24, 29, 31,108,109}, // shmup euclidean chaosmode + {182,183,184,185,186,187}, // softcore spherical chaosmode + {188,189,190,191,192,193}, // hardcore spherical chaosmode + {194,195,196,197,198,199}, // shmup spherical chaosmode + {200,201,202,203,204,205}, // softcore heptagonal spherical chaosmode + {206,207,208,209,210,211}, // hardcore heptagonal spherical chaosmode + {212,213,214,215,216,217}, // shmup heptagonal spherical chaosmode + {218,219,220,221,222,223}, // softcore elliptic chaosmode + {224,225,226,227,228,229}, // hardcore elliptic chaosmode + {230,231,232,233,234,235}, // shmup elliptic chaosmode + {236,237,238,239,240,241}, // softcore heptagonal elliptic chaosmode + {242,243,244,245,246,247}, // hardcore heptagonal elliptic chaosmode + {248,249,250,251,252,253}, // shmup heptagonal elliptic chaosmode + }; +// unused codes: 6 (cheat/tampered), 25, 254, 255 + +EX modecode_t legacy_modecode() { + if(int(geometry) > 3 || int(variation) > 1) return UNKNOWN; + if(chaosmode > 1) return UNKNOWN; + // compute the old code + int xcode = 0; + + if(shmup::on) xcode += 2; + else if(pureHardcore()) xcode ++; + + if(euclid) xcode += 6; + else if(!BITRUNCATED) xcode += 3; + + if(sphere) { + xcode += 9; + if(elliptic) xcode += 6; + } + + if(chaosmode) xcode += 21; + + int np = numplayers()-1; if(np<0 || np>5) np=5; + + // bits: 0 to 7 + modecode_t mct = modecodetable[xcode][np]; + +#if CAP_INV + if(inv::on) mct += (1<<11); +#endif + if(peace::on) mct += (1<<12); +#if CAP_TOUR + if(tour::on) mct += (1<<13); +#endif + if(numplayers() == 7) mct += (1<<14); + + return mct; + } + } -#endif diff --git a/mapeditor.cpp b/mapeditor.cpp index 5e3d418c..e22a2e44 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -366,9 +366,13 @@ EX namespace mapeditor { } } #endif - } +EX } -namespace mapstream { +#if HDR +struct hstream; +#endif + +EX namespace mapstream { #if CAP_EDIT std::map cellids; @@ -427,7 +431,7 @@ namespace mapstream { return dir; } - void save_geometry(fhstream& f) { + EX void save_geometry(hstream& f) { f.write(geometry); char nbtype = char(variation); f.write(nbtype); @@ -476,6 +480,10 @@ namespace mapstream { if(hybri) { hybrid::in_underlying_geometry([&] { save_geometry(f); }); } + if(fake::in()) { + f.write(fake::around); + fake::in_underlying_geometry([&] { save_geometry(f); }); + } if(bt::in()) f.write(vid.binary_width); if(euc::in()) { @@ -485,7 +493,8 @@ namespace mapstream { f.write(mine_adjacency_rule); } - void load_geometry(fhstream& f) { + EX void load_geometry(hstream& f) { + auto vernum = f.get_vernum(); f.read(geometry); char nbtype; f.read(nbtype); @@ -497,7 +506,7 @@ namespace mapstream { } #endif #if CAP_CRYSTAL - if(cryst && f.vernum >= 10504) { + if(cryst && vernum >= 10504) { int sides; f.read(sides); #if CAP_CRYSTAL @@ -523,7 +532,7 @@ namespace mapstream { auto& ge = fgeomextras[current_extra]; auto& id = ge.current_prime_id; f.read(id); - if(f.vernum < 0xA80C) switch(ge.base) { + if(vernum < 0xA80C) switch(ge.base) { case gNormal: id++; break; case g45: id++; break; case g46: id+=2; break; @@ -544,36 +553,43 @@ namespace mapstream { } } #endif - if(geometry == gNil && f.vernum >= 0xA80C) { + if(geometry == gNil && vernum >= 0xA80C) { f.read(S7); f.read(nilv::nilperiod); nilv::set_flags(); } - if(geometry == gArnoldCat && f.vernum >= 0xA80C) { + if(geometry == gArnoldCat && vernum >= 0xA80C) { f.read(asonov::period_xy); f.read(asonov::period_z); asonov::set_flags(); } - if(geometry == gProduct && f.vernum >= 0xA80C) { + if(geometry == gProduct && vernum >= 0xA80C) { f.read(hybrid::csteps); - if(f.vernum >= 0xA80D) f.read(product::cspin); - if(f.vernum >= 0xA833) f.read(product::cmirror); + if(vernum >= 0xA80D) f.read(product::cspin); + if(vernum >= 0xA833) f.read(product::cmirror); } - if(geometry == gRotSpace && f.vernum >= 0xA833) { + if(geometry == gRotSpace && vernum >= 0xA833) { f.read(hybrid::csteps); } - if(hybri && f.vernum >= 0xA80C) { + if(hybri && vernum >= 0xA80C) { auto g = geometry; load_geometry(f); set_geometry(g); } - if(bt::in() && f.vernum >= 0xA80C) + if(fake::in()) { + ld ar; + f.read(ar); + fake::around = ar; + load_geometry(f); + fake::change_around(); + } + if(bt::in() && vernum >= 0xA80C) f.read(vid.binary_width); - if(euc::in() && f.vernum >= 0xA80D) { + if(euc::in() && vernum >= 0xA80D) { f.read(euc::eu_input.user_axes); f.read(euc::eu_input.twisted); } - if(f.vernum >= 0xA810) + if(vernum >= 0xA810) f.read(mine_adjacency_rule); } @@ -917,9 +933,9 @@ namespace mapstream { } #endif - } +EX } -namespace mapeditor { +EX namespace mapeditor { EX bool drawplayer = true; diff --git a/nonisotropic.cpp b/nonisotropic.cpp index b445318c..5bccb794 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -1043,7 +1043,6 @@ EX namespace hybrid { auto keep = ginf[g].menu_displayed_name; ginf[g] = ginf[underlying]; ginf[g].menu_displayed_name = keep; - ginf[g].xcode = no_code; if(g == gRotSpace) { ginf[g].g = sph ? giSphere3 : giSL2; ginf[g].tiling_name = "Iso(" + ginf[g].tiling_name + ")"; diff --git a/system.cpp b/system.cpp index b97b73c4..c9d68f4c 100644 --- a/system.cpp +++ b/system.cpp @@ -411,7 +411,7 @@ EX namespace scores { /** \brief the amount of boxes reserved for each hr::score item */ #define MAXBOX 500 /** \brief currently used boxes in hr::score */ -#define POSSCORE 387 +#define POSSCORE 388 /** \brief a struct to keep local score from an earlier game */ struct score { /** \brief version used */ @@ -491,7 +491,7 @@ void applyBoxI(eItem it, bool f = false) { fakebox[boxid] = f; monsbox[boxid] = false; if(loadingHi) { - updateHi(it, save.box[boxid++]); + updateHi_for_code(it, save.box[boxid++], saved_modecode); } else applyBox(items[it]); } @@ -531,6 +531,8 @@ void applyBoxM(eMonster m, bool f = false) { applyBox(kills[m]); } +EX modecode_t saved_modecode; + /** \brief Call applyBox for all the required values. This will save the values if hr::scores::saving==true, load if hr::scores::loading==true, load into highscores if hr::scores::loadingHi==true */ EX void applyBoxes() { invorb.clear(); @@ -879,6 +881,8 @@ EX void applyBoxes() { applyBoxM(moRusalka); list_invorb(); + applyBoxNum(saved_modecode, "modecode"); + if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid); if(isize(invorb)) { println(hlog, "ERROR: Orbs not taken into account"); exit(1); } } @@ -894,11 +898,13 @@ void loadBox() { boxid = 0; loading = true; applyBoxes(); loading = false; } -/** \brief load the current game values from save into the highscore tables */ -void loadBoxHigh() { +const int MODECODE_BOX = 387; +modecode_t fill_modecode() { dynamicval sp1(multi::players, save.box[197]); dynamicval sp2(geometry, (eGeometry) save.box[116]); + if(among(geometry, gArchimedean, gProduct, gRotSpace, gArbitrary)) + return 6; /* these would not be saved nor loaded correctly */ dynamicval sp3(shmup::on, save.box[119]); dynamicval sp4(chaosmode, save.box[196]); dynamicval sp5(variation, (eVariation) save.box[186]); @@ -911,14 +917,22 @@ void loadBoxHigh() { if(save.box[341]) variation = eVariation::goldberg; if(save.box[344]) variation = eVariation::irregular; - if(multi::players < 1 || multi::players > MAXPLAYER) + if(multi::players < 0 || multi::players > MAXPLAYER) + return 6; + + if(multi::players == 0) multi::players = 1; - if(shmup::on && multi::players == 1) ; - else { - // have boxid - boxid = 0; loadingHi = true; applyBoxes(); loadingHi = false; - } + if(shmup::on && multi::players == 1 && boxid <= 258) + return 6; /* not sure why */ + + return modecode(2); + } + +/** \brief load the current game values from save into the highscore tables */ +void loadBoxHigh() { + saved_modecode = save.box[MODECODE_BOX]; + boxid = 0; loadingHi = true; applyBoxes(); loadingHi = false; } EX } @@ -964,20 +978,18 @@ EX void saveStats(bool emergency IS(false)) { if(tour::on) return; #endif if(randomPatternsMode) return; - if(dual::state) return; - if(arcm::in()) return; - if(arb::in()) return; - if(hybri) return; if(daily::on) return; if(peace::on) return; if(dpgen::in) return; if(experimental) return; - if(ginf[geometry].xcode == no_code) return; - if(INVERSE) return; if(!gold()) return; remove_emergency_save(); + + auto& xcode = scores::saved_modecode; + xcode = modecode(); + FILE *f = fopen(scorefile, "at"); if(!f) { @@ -999,15 +1011,13 @@ EX void saveStats(bool emergency IS(false)) { if((tactic::on || yendor::on) && !items[itOrbSafety] && !cheater) { int t = (int) (timer - timerstart); - modecode_t xcode = modecode(); - if(tactic::on) { int score = items[treasureType(specialland)]; if(score) { int c = anticheat::certify(dnameof(specialland), turncount, t, (int) timerstart, - int(xcode)*999 + tactic::id + 256 * score + (xcode>>32)*7); + unsigned(xcode)*999 + tactic::id + 256 * score); fprintf(f, "TACTICS %s %d %d %d %d %d %d %d %d date: %s\n", VER, tactic::id, specialland, score, turncount, t, int(timerstart), c, int(xcode), buf); @@ -1020,7 +1030,7 @@ EX void saveStats(bool emergency IS(false)) { fprintf(f, "YENDOR %s %d %d %d %d %d %d %d %d date: %s\n", VER, yendor::lastchallenge, items[itOrbYendor], yendor::won, turncount, t, int(timerstart), anticheat::certify(yendor::won ? "WON" : "LOST", turncount, t, (int) timerstart, - int(xcode)*999 + yendor::lastchallenge + 256 * items[itOrbYendor] + (xcode>>32)*7), + unsigned(xcode)*999 + yendor::lastchallenge + 256 * items[itOrbYendor]), int(xcode), buf); @@ -1098,8 +1108,13 @@ EX void loadsave() { bool tamper = false; int coh = counthints(); while(!feof(f)) { - char buf[120]; - if(fgets(buf, 120, f) == NULL) break; + char buf[12000]; + if(fgets(buf, 12000, f) == NULL) break; + if(buf[0] == 'M' && buf[1] == 'O') { + string s = buf; + while(s != "" && s.back() < 32) s.pop_back(); + load_modecode_line(s); + } if(buf[0] == 'H' && buf[1] == 'y') { if(fscanf(f, "%s", buf) <= 0) break; sc.ver = buf; @@ -1115,6 +1130,8 @@ EX void loadsave() { using namespace scores; for(int i=0; i= 0 && save.box[258] < coh) { hints[save.box[258]].last = save.box[1]; @@ -1209,6 +1226,11 @@ EX void loadsave() { randomPatternsMode = false; yendor::on = false; tour::on = false; + + shstream ss; + ss.s = meaning[sc.box[MODECODE_BOX]]; + ss.read(ss.vernum); + mapstream::load_geometry(ss); } } #endif diff --git a/yendor.cpp b/yendor.cpp index 50b5bc33..49a5786e 100644 --- a/yendor.cpp +++ b/yendor.cpp @@ -16,7 +16,8 @@ EX int hiitemsMax(eItem it) { return mx; } -EX modecode_t modecode(); +/** 1 - just return UNKNOWN if id not assigned; 2 - assign without writing to file; 3 - assign with writing to file */ +EX modecode_t modecode(int mode IS(3)); typedef vector > subscoreboard; @@ -788,7 +789,6 @@ EX namespace yendor { if(yendor::on) { changes.value_set(yendor::won, true); if(!cheater) { - dynamicval c(chaosmode, 0); yendor::bestscore[modecode()][yendor::challenge] = max(yendor::bestscore[modecode()][yendor::challenge], items[itOrbYendor]); yendor::uploadScore(); @@ -830,8 +830,8 @@ EX namespace tactic { }; map> scoreboard; - int chances(eLand l) { - if(modecode() != 0 && l != laCamelot) return 3; + EX int chances(eLand l, modecode_t xc IS(modecode())) { + if(xc != 0 && l != laCamelot) return 3; for(auto& ti: land_tac) if(ti.l == l) return ti.tries; @@ -853,12 +853,12 @@ EX namespace tactic { return hiitemsMax(treasureType(l)) * landMultiplier(l) >= 20; } - EX void record(eLand land, int score, flagtype xc IS(modecode())) { + EX void record(eLand land, int score, modecode_t xc IS(modecode())) { if(land >=0 && land < landtypes) { for(int i=MAXTAC-1; i; i--) lsc[xc][land][i] = lsc[xc][land][i-1]; tactic::lsc[xc][land][0] = score; } - int t = chances(land); + int t = chances(land, xc); int csum = 0; for(int i=0; i 0) csum += lsc[xc][land][i]; if(csum > recordsum[xc][land]) recordsum[xc][land] = csum; @@ -1029,160 +1029,66 @@ EX namespace tactic { EX } -// Identifiers for the current combinations of game modes -// These are recorded in the save file, so it is somewhat -// important that they do not change for already existing -// modes, as otherwise the scores would be lost. -// Unfortunately, the codes assigned when HyperRogue had -// just a few special modes did not really follow a specific -// rule, so this system has grown rather ugly as the -// number of special modes kept growing... +map code_for; +EX map meaning; -// mode codes for 'old' modes, from 0 to 255 +char xcheat; -int modecodetable[42][6] = { - { 0, 38, 39, 40, 41, 42}, // softcore hyperbolic - { 7, 43, 44, 45, 46, 47}, // hardcore hyperbolic - { 2, 4, 9, 11, 48, 49}, // shmup hyperbolic - { 13, 50, 51, 52, 53, 54}, // softcore heptagonal hyperbolic - { 16, 55, 56, 57, 58, 59}, // hardcore heptagonal hyperbolic - { 14, 15, 17, 18, 60, 61}, // shmup heptagonal hyperbolic - { 1, 62, 63, 64, 65, 66}, // softcore euclidean - { 8, 67, 68, 69, 70, 71}, // hardcore euclidean - { 3, 5, 10, 12, 72, 73}, // shmup euclidean - {110,111,112,113,114,115}, // softcore spherical - {116,117,118,119,120,121}, // hardcore spherical - {122,123,124,125,126,127}, // shmup spherical - {128,129,130,131,132,133}, // softcore heptagonal spherical - {134,135,136,137,138,139}, // hardcore heptagonal spherical - {140,141,142,143,144,145}, // shmup heptagonal spherical - {146,147,148,149,150,151}, // softcore elliptic - {152,153,154,155,156,157}, // hardcore elliptic - {158,159,160,161,162,163}, // shmup elliptic - {164,165,166,167,168,169}, // softcore heptagonal elliptic - {170,171,172,173,174,175}, // hardcore heptagonal elliptic - {176,177,178,179,180,181}, // shmup heptagonal elliptic - { 19, 74, 75, 76, 77, 78}, // softcore hyperbolic chaosmode - { 26, 79, 80, 81, 82, 83}, // hardcore hyperbolic chaosmode - { 21, 23, 28, 30, 84, 85}, // shmup hyperbolic chaosmode - { 32, 86, 87, 88, 89, 90}, // softcore heptagonal hyperbolic chaosmode - { 35, 91, 92, 93, 94, 95}, // hardcore heptagonal hyperbolic chaosmode - { 33, 34, 36, 37, 96, 97}, // shmup heptagonal hyperbolic chaosmode - { 20, 98, 99,100,101,102}, // softcore euclidean chaosmode - { 27,103,104,105,106,107}, // hardcore euclidean chaosmode - { 22, 24, 29, 31,108,109}, // shmup euclidean chaosmode - {182,183,184,185,186,187}, // softcore spherical chaosmode - {188,189,190,191,192,193}, // hardcore spherical chaosmode - {194,195,196,197,198,199}, // shmup spherical chaosmode - {200,201,202,203,204,205}, // softcore heptagonal spherical chaosmode - {206,207,208,209,210,211}, // hardcore heptagonal spherical chaosmode - {212,213,214,215,216,217}, // shmup heptagonal spherical chaosmode - {218,219,220,221,222,223}, // softcore elliptic chaosmode - {224,225,226,227,228,229}, // hardcore elliptic chaosmode - {230,231,232,233,234,235}, // shmup elliptic chaosmode - {236,237,238,239,240,241}, // softcore heptagonal elliptic chaosmode - {242,243,244,245,246,247}, // hardcore heptagonal elliptic chaosmode - {248,249,250,251,252,253}, // shmup heptagonal elliptic chaosmode - }; -// unused codes: 6 (cheat/tampered), 25, 254, 255 +void save_mode_data(hstream& f) { + mapstream::save_geometry(f); + + if(yendor::on) + f.write(0); + else + f.write(chaosmode); + f.write(shmup::on); + f.write(inv::on); + f.write(tour::on); + f.write(peace::on); + f.write(peace::otherpuzzles); + f.write(peace::explore_other); + f.write(multi::players); + f.write(xcheat); + } -modecode_t modecode() { - // bit 61: product; 62: rotspace - if(hybri) return PIU(modecode()) | (1ll << (prod ? 61 : 62)); -#if CAP_SAVE - if(anticheat::tampered || cheater || geometry >= gGUARD) return 6; -#endif +EX modecode_t modecode(int mode) { + modecode_t x = legacy_modecode(); + if(x != UNKNOWN) return x; - // compute the old code - int xcode = 0; + xcheat = (cheater ? 1 : 0); + shstream ss; + ss.write(ss.vernum); + save_mode_data(ss); + + if(code_for.count(ss.s)) return code_for[ss.s]; - if(shmup::on) xcode += 2; - else if(pureHardcore()) xcode ++; + if(mode == 1) return UNKNOWN; - if(euclid) xcode += 6; - else if(!BITRUNCATED) xcode += 3; + modecode_t next = 100000; + while(meaning.count(next)) next++; - if(sphere) { - xcode += 9; - if(elliptic) xcode += 6; - } + meaning[next] = ss.s; + code_for[ss.s] = next; - if(chaosmode) xcode += 21; + if(mode == 2) return next; - int np = numplayers()-1; if(np<0 || np>5) np=5; - - // bits: 0 to 7 - modecode_t mct = modecodetable[xcode][np]; + FILE *f = fopen(scorefile, "at"); + string s = as_hexstring(ss.s); + fprintf(f, "MODE %d %s\n", next, s.c_str()); + fclose(f); - // bits: 9, 10, 15, 16, 17, 18 - mct += ginf[geometry].xcode; - -#if CAP_INV - if(inv::on) mct += (1<<11); -#endif - if(peace::on) mct += (1<<12); -#if CAP_TOUR - if(tour::on) mct += (1<<13); -#endif - if(numplayers() == 7) mct += (1<<14); + return next; + } - // daily/Yendor/Tactics/standard are saved separately, but are using the same codes (Daily uses no code) - // randompattern never records its scores - // no specifics of the advanced configuration of torus/fieldquotient currently recorded - - #if CAP_GP - if(GOLDBERG) { - mct += (1 << 19); - auto loc = gp::human_representation(gp::param); - mct += loc.first << 21; // 4 bits - mct += loc.second << 25; // 4 bits - } - #endif - - #if CAP_IRR - if(IRREGULAR) { - mct += (1 << 20); - mct += irr::density_code() << 21; // 8 bits - } - #endif - - if(DUAL) { - mct += (1 << 19); - mct += (1 << 20); - } - - typedef long long ll; - - // 32 bits [29..61) for geometry specifics - if(euclid && quotient) { - /* todo */ - } - - #if CAP_FIELD - if(geometry == gFieldQuotient) { - using namespace fieldpattern; - mct += ll(current_extra) << 29; - mct += ll(fgeomextras[current_extra].current_prime_id) << 37; - } - #endif - - #if CAP_CRYSTAL - if(cryst) { - mct += ll(ginf[geometry].sides) << 29; - mct += ll(ginf[geometry].vertex) << 37; - } - #endif - - #if CAP_ARCM - if(geometry == gArchimedean) { - unsigned res = 7; - for(char c: arcm::current.symbol) res = res * 157 + c; - mct += ll(res) << 29; - if(PURE) mct ^= (1<<29); - } - #endif - - return mct; +EX void load_modecode_line(string s) { + int code = atoi(&s[5]); + int pos = 5; + while(s[pos] != ' ' && s[pos]) pos++; + if(!s[pos]) return; + pos++; + string t = from_hexstring(s.substr(pos)); + code_for[t] = code; + meaning[code] = t; } EX namespace peace {