// Die 5 Wegkarten: je ein vorgerendertes 3D-Diorama (assets/maps/*.png, // 1536×1024) mit handvermessenen Routen-Polylinien (Bild-Pixel), festen // Bauplatz-Slots und optionalem Lift (Seilbahn zum Berg mit Rundweg oben). // Zonen: standard · road (Parkplatz/Bus) · lake (Badesteg) · hang (Skilift) // · berg (Almhütte/Aussicht, erst mit Lift erreichbar). export const TILE2PX = 36; // 1 „Feld" Reichweite = 36 Bild-Pixel export const MAPS = { talschleife: { id: 'talschleife', name: 'Talschleife', icon: '🏞️', desc: 'Der Klassiker: ein Weg vom Westrand durchs Dorf zum Talausgang – See und Berg locken abseits.', image: 'assets/maps/talschleife.png', w: 1536, h: 1024, routes: { westost: { entry: 'W', exit: 'SE', points: [[304, 340], [301, 354], [302, 370], [312, 379], [330, 382], [346, 390], [359, 398], [347, 383], [344, 364], [353, 350], [368, 338], [384, 333], [400, 335], [419, 347], [430, 357], [440, 367], [447, 376], [455, 396], [461, 414], [471, 435], [477, 455], [477, 473], [485, 488], [502, 502], [515, 516], [532, 532], [549, 541], [564, 544], [572, 531], [579, 544], [594, 551], [611, 555], [624, 567], [626, 581], [624, 565], [610, 554], [595, 550], [577, 554], [563, 564], [557, 576], [549, 591], [552, 611], [562, 627], [568, 640], [576, 658], [578, 677], [578, 695], [588, 711], [600, 726], [606, 742], [616, 754], [626, 766], [640, 773], [652, 784], [666, 786], [686, 784], [705, 788], [716, 800], [715, 816], [728, 816], [741, 826], [754, 836], [768, 840], [779, 851], [795, 860], [814, 865], [829, 874], [836, 886], [838, 889]], }, gegenzug: { entry: 'S', exit: 'E', reverseOf: 'westost', }, }, entryRoutes: { W: ['westost'], N: ['westost'], S: ['gegenzug'] }, slots: [ { x: 300, y: 292, zone: 'road' }, { x: 245, y: 425, zone: 'road' }, { x: 430, y: 378, zone: 'standard' }, { x: 588, y: 298, zone: 'standard' }, { x: 634, y: 372, zone: 'standard' }, { x: 697, y: 397, zone: 'standard' }, { x: 485, y: 595, zone: 'standard' }, { x: 700, y: 713, zone: 'standard' }, { x: 776, y: 742, zone: 'standard' }, { x: 357, y: 619, zone: 'standard' }, { x: 1235, y: 546, zone: 'standard' }, { x: 545, y: 655, zone: 'standard' }, { x: 900, y: 788, zone: 'standard' }, { x: 261, y: 520, zone: 'standard' }, { x: 885, y: 615, zone: 'lake' }, { x: 1005, y: 782, zone: 'lake' }, { x: 987, y: 381, zone: 'hang' }, { x: 888, y: 218, zone: 'berg' }, { x: 1049, y: 296, zone: 'berg' }, ], lift: { topX: 952, topY: 168, loop: [[1000, 212], [935, 242]] }, }, seerunde: { id: 'seerunde', name: 'Seerunde', icon: '🏖️', desc: 'Ein Rundweg um den großen Bergsee – Nord- oder Südufer? Beide Ströme wollen versorgt sein.', image: 'assets/maps/seerunde.png', w: 1536, h: 1024, routes: { nordufer: { entry: 'W', exit: 'E', points: [[274, 784], [290, 768], [300, 756], [311, 746], [323, 733], [336, 718], [348, 706], [359, 695], [368, 686], [378, 672], [371, 658], [358, 646], [348, 636], [336, 629], [325, 622], [308, 608], [302, 590], [310, 570], [322, 555], [336, 542], [350, 532], [368, 523], [384, 519], [396, 509], [407, 499], [420, 493], [436, 480], [445, 467], [451, 452], [454, 433], [456, 411], [459, 389], [466, 370], [477, 353], [490, 338], [510, 326], [522, 322], [535, 318], [550, 315], [566, 313], [584, 312], [603, 311], [620, 311], [636, 311], [648, 311], [668, 312], [683, 315], [698, 318], [714, 315], [734, 322], [748, 328], [760, 332], [780, 338], [792, 340], [804, 343], [818, 346], [830, 348], [850, 353], [866, 358], [882, 366], [902, 372], [921, 374], [942, 377], [960, 380], [976, 384], [991, 391], [1010, 406], [1020, 414], [1028, 424], [1035, 435], [1040, 446], [1044, 459], [1045, 471], [1046, 484], [1050, 502], [1063, 514], [1082, 522], [1100, 531], [1118, 543], [1130, 554], [1144, 555], [1158, 562], [1167, 574], [1170, 588], [1170, 604], [1163, 618], [1151, 633], [1137, 642], [1116, 652], [1100, 662], [1086, 670], [1068, 676], [1052, 678], [1032, 684], [1014, 691], [1000, 697], [977, 700], [965, 701], [942, 702], [930, 705], [914, 712], [897, 720], [880, 723], [866, 728], [852, 738], [837, 746], [822, 751], [814, 762], [808, 780], [796, 798], [780, 813], [763, 821], [744, 824], [728, 831], [702, 837], [689, 838], [664, 837], [649, 836], [636, 834], [624, 834], [605, 831], [588, 826], [576, 816], [588, 812], [606, 814], [588, 812], [572, 802], [563, 793], [563, 808], [550, 807], [536, 799], [522, 785], [506, 770], [488, 756], [474, 746], [457, 736], [449, 728], [440, 715], [429, 701], [415, 686], [401, 678], [384, 679], [369, 690], [360, 699], [348, 710], [336, 722], [323, 735], [311, 747], [300, 758], [292, 766], [279, 779], [274, 784]], }, suedufer: { entry: 'S', exit: 'SE', lake: true, points: [[274, 784], [290, 768], [300, 756], [311, 746], [323, 733], [336, 718], [349, 706], [360, 696], [370, 688], [387, 680], [403, 686], [416, 696], [427, 702], [443, 715], [462, 732], [473, 743], [486, 756], [497, 766], [506, 776], [521, 789], [534, 796], [552, 805], [568, 808], [588, 812], [604, 815], [589, 809], [579, 817], [596, 828], [614, 832], [636, 834], [649, 836], [664, 837], [677, 838], [700, 838], [718, 834], [735, 826], [750, 822], [770, 818], [788, 807], [797, 798], [808, 780], [812, 763], [830, 753], [845, 745], [860, 735], [874, 725], [892, 717], [910, 713], [927, 706], [947, 700], [959, 699], [973, 699], [991, 698], [1014, 693], [1026, 688], [1038, 684], [1055, 678], [1070, 676], [1086, 664], [1105, 654], [1120, 650], [1140, 641], [1157, 626], [1167, 610], [1170, 593], [1169, 576], [1158, 565], [1144, 561], [1131, 550], [1114, 538], [1104, 532], [1090, 528], [1079, 522], [1060, 513], [1050, 502], [1044, 481], [1042, 467], [1039, 450], [1031, 430], [1018, 412], [1000, 398], [990, 391], [978, 386], [960, 380], [942, 377], [921, 374], [902, 372], [882, 366], [866, 359], [840, 351], [827, 348], [806, 345], [785, 340], [766, 334], [748, 327], [732, 320], [716, 316], [698, 315], [681, 316], [664, 312], [647, 311], [626, 310], [612, 310], [600, 310], [580, 311], [562, 312], [545, 315], [534, 318], [518, 325], [503, 334], [488, 344], [474, 355], [464, 366], [456, 385], [452, 408], [452, 421], [453, 435], [452, 448], [448, 460], [443, 471], [436, 481], [420, 494], [402, 502], [388, 512], [372, 522], [356, 527], [337, 538], [324, 548], [310, 566], [303, 588], [308, 607], [326, 622], [336, 629], [348, 636], [358, 645], [368, 655], [381, 669], [368, 687], [357, 697], [347, 708], [335, 720], [321, 734], [309, 746], [299, 758], [291, 766], [279, 779], [274, 784]], }, }, entryRoutes: { W: ['nordufer'], N: ['nordufer'], S: ['suedufer'] }, slots: [ { x: 255, y: 641, zone: 'road' }, { x: 330, y: 800, zone: 'road' }, { x: 395, y: 330, zone: 'standard' }, { x: 520, y: 285, zone: 'standard' }, { x: 700, y: 245, zone: 'standard' }, { x: 966, y: 300, zone: 'standard' }, { x: 1075, y: 385, zone: 'standard' }, { x: 1230, y: 651, zone: 'standard' }, { x: 620, y: 772, zone: 'standard' }, { x: 900, y: 792, zone: 'standard' }, { x: 1080, y: 720, zone: 'standard' }, { x: 598, y: 346, zone: 'lake' }, { x: 700, y: 655, zone: 'lake' }, { x: 880, y: 635, zone: 'lake' }, ], }, serpentinen: { id: 'serpentinen', name: 'Serpentinen', icon: '⛰️', desc: 'Über den Berg ins Tal: langer Abstieg in Kehren – die Seilbahn verbindet Dorf und Gipfelterrasse.', image: 'assets/maps/serpentinen.png', w: 1536, h: 1024, routes: { kehren: { entry: 'W', exit: 'SE', points: [[355, 229], [357, 244], [362, 268], [367, 280], [379, 299], [388, 308], [396, 318], [403, 329], [411, 340], [419, 351], [432, 364], [446, 372], [463, 379], [480, 385], [498, 389], [515, 392], [532, 394], [546, 396], [564, 401], [584, 406], [601, 408], [619, 407], [640, 404], [664, 398], [677, 394], [690, 390], [704, 384], [720, 377], [734, 372], [748, 367], [761, 364], [774, 361], [786, 360], [798, 358], [819, 360], [838, 362], [858, 362], [879, 363], [900, 370], [918, 378], [936, 380], [945, 370], [952, 356], [950, 373], [939, 383], [923, 385], [904, 375], [920, 378], [936, 378], [926, 393], [916, 408], [895, 416], [881, 423], [869, 430], [858, 436], [840, 446], [822, 455], [806, 462], [791, 467], [777, 472], [757, 484], [747, 491], [732, 506], [724, 520], [716, 532], [704, 542], [691, 557], [678, 569], [664, 583], [650, 593], [635, 601], [614, 607], [602, 608], [584, 607], [566, 605], [550, 604], [536, 604], [515, 608], [499, 617], [494, 630], [503, 643], [513, 656], [526, 669], [542, 676], [557, 688], [572, 704], [586, 712], [580, 731], [570, 740], [560, 752], [549, 770], [544, 787], [548, 802], [561, 819], [558, 833], [544, 848], [542, 868], [551, 884], [568, 898], [584, 911], [598, 922], [601, 925]], }, talwaerts: { entry: 'S', exit: 'E', reverseOf: 'kehren' }, }, entryRoutes: { W: ['kehren'], N: ['kehren'], S: ['talwaerts'] }, slots: [ { x: 548, y: 901, zone: 'road' }, { x: 725, y: 890, zone: 'road' }, { x: 538, y: 325, zone: 'standard' }, { x: 665, y: 436, zone: 'standard' }, { x: 835, y: 428, zone: 'standard' }, { x: 1006, y: 480, zone: 'standard' }, { x: 415, y: 646, zone: 'standard' }, { x: 303, y: 578, zone: 'standard' }, { x: 695, y: 616, zone: 'standard' }, { x: 855, y: 636, zone: 'standard' }, { x: 1090, y: 780, zone: 'standard' }, { x: 1087, y: 627, zone: 'hang' }, { x: 845, y: 292, zone: 'berg' }, { x: 951, y: 312, zone: 'berg' }, ], lift: { topX: 898, topY: 292, loop: [[858, 300], [938, 315]] }, }, kreuzung: { id: 'kreuzung', name: 'Kreuzung', icon: '🛣️', desc: 'Zwei Täler kreuzen sich am Dorfplatz: vier Ströme, ein Zentrum – wer deckt alle Richtungen ab?', image: 'assets/maps/kreuzung.png', w: 1536, h: 1024, routes: { nordsued: { entry: 'N', exit: 'SE', points: [[487, 255], [498, 264], [511, 276], [528, 292], [538, 300], [546, 308], [556, 316], [565, 325], [575, 333], [585, 342], [595, 350], [605, 360], [615, 368], [624, 376], [642, 391], [658, 406], [674, 418], [687, 430], [698, 440], [712, 456], [716, 477], [712, 494], [705, 510], [695, 528], [682, 546], [668, 565], [660, 575], [650, 585], [642, 595], [633, 604], [624, 614], [616, 623], [607, 632], [598, 642], [590, 650], [580, 660], [572, 668], [563, 677], [547, 694], [532, 710], [516, 727], [504, 740], [493, 752], [490, 755]], }, westost: { entry: 'W', exit: 'E', points: [[135, 472], [158, 472], [174, 472], [189, 472], [207, 472], [228, 472], [248, 472], [270, 472], [290, 472], [312, 472], [332, 472], [354, 472], [374, 472], [396, 472], [416, 472], [436, 472], [456, 472], [474, 472], [493, 472], [510, 471], [527, 471], [543, 471], [559, 471], [575, 470], [591, 470], [607, 470], [623, 470], [638, 471], [654, 471], [670, 471], [686, 472], [701, 472], [717, 474], [732, 476], [748, 478], [763, 481], [779, 484], [795, 488], [811, 492], [828, 495], [844, 499], [862, 502], [879, 506], [897, 509], [916, 513], [934, 517], [953, 521], [972, 524], [990, 528], [1010, 532], [1028, 536], [1047, 539], [1066, 543], [1084, 547], [1103, 551], [1122, 554], [1140, 558], [1160, 561], [1178, 564], [1197, 568], [1216, 571], [1234, 574], [1253, 577], [1271, 580], [1289, 582], [1306, 585], [1324, 587], [1340, 590], [1357, 592], [1373, 593], [1387, 595], [1400, 596], [1418, 598], [1430, 600]], }, }, entryRoutes: { W: ['westost'], N: ['nordsued'], S: ['nordsued'] }, slots: [ { x: 425, y: 285, zone: 'road' }, { x: 300, y: 694, zone: 'road' }, { x: 645, y: 218, zone: 'standard' }, { x: 330, y: 380, zone: 'standard' }, { x: 545, y: 435, zone: 'standard' }, { x: 933, y: 546, zone: 'standard' }, { x: 760, y: 665, zone: 'standard' }, { x: 610, y: 782, zone: 'standard' }, { x: 890, y: 795, zone: 'standard' }, { x: 1140, y: 640, zone: 'standard' }, { x: 1180, y: 478, zone: 'standard' }, { x: 1405, y: 465, zone: 'standard' }, { x: 391, y: 512, zone: 'lake' }, { x: 310, y: 611, zone: 'lake' }, ], }, passstrasse: { id: 'passstrasse', name: 'Passstraße', icon: '🛤️', desc: 'Ein langer Anstieg zum Pass, kaum Bauplätze: Hier zählt jede Standortentscheidung doppelt.', image: 'assets/maps/passstrasse.png', w: 1536, h: 1024, routes: { bergauf: { entry: 'W', exit: 'E', points: [[700, 859], [687, 855], [684, 840], [692, 824], [705, 814], [707, 798], [697, 789], [686, 774], [670, 758], [656, 748], [643, 740], [629, 733], [614, 725], [600, 718], [582, 705], [570, 690], [564, 675], [564, 660], [572, 643], [592, 626], [603, 619], [624, 606], [638, 599], [649, 592], [669, 582], [686, 574], [702, 569], [710, 584], [695, 593], [672, 603], [656, 611], [642, 620], [658, 612], [669, 606], [688, 598], [710, 590], [723, 585], [743, 578], [757, 571], [766, 559], [779, 548], [794, 541], [811, 537], [828, 532], [843, 527], [863, 517], [880, 510], [897, 514], [913, 511], [925, 498], [928, 479], [927, 460], [922, 444], [910, 432], [888, 418], [870, 408], [856, 400], [842, 388], [837, 374], [847, 356], [859, 345], [870, 336], [890, 324], [909, 315], [926, 311], [937, 304]], }, bergab: { entry: 'S', exit: 'SE', reverseOf: 'bergauf' }, }, entryRoutes: { W: ['bergauf'], N: ['bergauf'], S: ['bergab'] }, slots: [ { x: 562, y: 815, zone: 'road' }, { x: 760, y: 875, zone: 'road' }, { x: 300, y: 565, zone: 'standard' }, { x: 415, y: 660, zone: 'standard' }, { x: 560, y: 600, zone: 'standard' }, { x: 850, y: 548, zone: 'standard' }, { x: 905, y: 400, zone: 'standard' }, { x: 1016, y: 330, zone: 'standard' }, ], }, }; // Editor-Overrides (js/maps-custom.json) über die eingebauten Daten legen: // routes ersetzt die Punktlisten (entry/exit/lake-Flags bleiben erhalten, // unbekannte Routen-IDs werden neu angelegt), slots ersetzt die Slot-Liste. export function applyMapOverrides(overrides) { if (!overrides) return; for (const [mid, o] of Object.entries(overrides)) { const def = MAPS[mid]; if (!def) continue; if (o.routes) { for (const [rk, pts] of Object.entries(o.routes)) { if (!Array.isArray(pts) || pts.length < 2) continue; if (def.routes[rk]) { def.routes[rk] = { ...def.routes[rk], points: pts, reverseOf: undefined }; } else { def.routes[rk] = { entry: 'W', exit: 'E', points: pts }; } } // reverseOf-Varianten zeigen ggf. auf ersetzte Routen – bleibt gültig, // solange die Basisroute existiert (prepMap löst sie auf) } if (Array.isArray(o.slots) && o.slots.length) { def.slots = o.slots.map(s => ({ x: s.x, y: s.y, zone: s.zone || 'standard' })); } if (o.lift) def.lift = o.lift; } } // Zubringer-Reihenfolge im Startbildschirm export const MAP_ORDER = ['talschleife', 'seerunde', 'serpentinen', 'kreuzung', 'passstrasse'];