about summary refs log tree commit diff stats
path: root/WitnessRandomizer/WitnessRandomizer.cpp
blob: 9178888b7c0af59985fe66e164d91fe45704678e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
/*
 * BUGS:
 * Something is wrong with bunker
 * FEATURES:
 * Randomize audio logs
 * Compile panel lists in a more reasonable way
 * Separate panels out by "square", which can probably be anywhere
 * List of panels which can be valid "Burn" (aka desert) substitutes: Prevent (or limit) panel counting
*/
#include "Memory.h"
#include "WitnessRandomizer.h"
#include <string>
#include <iostream>

int main(int argc, char** argv)
{
	WitnessRandomizer randomizer = WitnessRandomizer();

	//*

	std::vector<int> lasers = {
		0x0360D, // Symmetry
		0x03615, // Swamp
		0x09DE0, // Bunker
		0x17CA4, // Monastery
		0x032F5, // Town
		0x03613, // Treehouse
//		0x03608, // Desert
		0x03612, // Quarry
		0x03616, // Jungle
	};
	randomizer.Randomize(lasers, SWAP_TARGETS);


	if (argc == 2) {
		srand(atoi(argv[1])); // Seed with RNG from command line
	}

	std::vector<int> tutorialPanels = {
		// 0x0A3B5, // Back Left
		0x0A3B2, // Back Right
		0x00295, // Center Left
		0x00293, // Front Center
		0x002C2, // Front Left
		0x0C335, // Pillar
		0x0C373, // Patio floor
	};

	randomizer.Randomize(tutorialPanels, SWAP_TARGETS);

	std::vector<int> outsidetutorialPanels = {
		0x0005D, //Outside Tutorial Dots Tutorial 1
		0x0005E, //Outside Tutorial Dots Tutorial 2
		0x0005F, //Outside Tutorial Dots Tutorial 3
		0x00060, //Outside Tutorial Dots Tutorial 4
		0x00061, //Outside Tutorial Dots Tutorial 5
		0x018AF, //Outside Tutorial Stones Tutorial 1
		0x0001B, //Outside Tutorial Stones Tutorial 2
		0x012C9, //Outside Tutorial Stones Tutorial 3
		0x0001C, //Outside Tutorial Stones Tutorial 4
		0x0001D, //Outside Tutorial Stones Tutorial 5
		0x0001E, //Outside Tutorial Stones Tutorial 6
		0x0001F, //Outside Tutorial Stones Tutorial 7
		0x00020, //Outside Tutorial Stones Tutorial 8
		0x00021, //Outside Tutorial Stones Tutorial 9
		0x033D4, //Outside Tutorial Vault
//		0x03481, //Outside Tutorial Vault Box
		0x0A171, //Tutorial Optional Door 1
		0x04CA4, //Tutorial Optional Door 2
		0x17CFB, //Outside Tutorial Discard
//		0x00143. //Orchard Apple Tree 1
//		0x0003B. //Orchard Apple Tree 2
//		0x00055. //Orchard Apple Tree 3
//		0x032F7. //Orchard Apple Tree 4
//		0x032FF. //Orchard Apple Tree 5
	};
	randomizer.Randomize(outsidetutorialPanels, SWAP_LINES | SWAP_COLORS);

	
	std::vector<int> symmetryPanels = {
//		0x3C12B, // Glass Factory Discard
		0x01A54, // Glass Factory Entry
		0x00086, // Glass Factory Vertical Symmetry 1
		0x00087, // Glass Factory Vertical Symmetry 2
		0x00059, // Glass Factory Vertical Symmetry 3
		0x00062, // Glass Factory Vertical Symmetry 4
		0x0005C, // Glass Factory Vertical Symmetry 5
		// 0x17CC8, // Glass Factory Summon Boat
		0x0008D, // Glass Factory Rotational Symmetry 1
		0x00081, // Glass Factory Rotational Symmetry 2
		0x00083, // Glass Factory Rotational Symmetry 3
		0x00084, // Glass Factory Melting 1
		0x00082, // Glass Factory Melting 2
		0x0343A, // Glass Factory Melting 3

		0x000B0, // Symmetry Island Door 1
		0x00022, // Symmetry Island Black Dots 1
		0x00023, // Symmetry Island Black Dots 2
		0x00024, // Symmetry Island Black Dots 3
		0x00025, // Symmetry Island Black Dots 4
		0x00026, // Symmetry Island Black Dots 5
		0x0007C, // Symmetry Island Colored Dots 1
		0x0007E, // Symmetry Island Colored Dots 2
		0x00075, // Symmetry Island Colored Dots 3
		0x00073, // Symmetry Island Colored Dots 4
		0x00077, // Symmetry Island Colored Dots 5
		0x00079, // Symmetry Island Colored Dots 6
		0x00065, // Symmetry Island Fading Lines 1
		0x0006D, // Symmetry Island Fading Lines 2
		0x00072, // Symmetry Island Fading Lines 3
		0x0006F, // Symmetry Island Fading Lines 4
		0x00070, // Symmetry Island Fading Lines 5
		0x00071, // Symmetry Island Fading Lines 6
		0x00076, // Symmetry Island Fading Lines 7
		// 0x009B8, // Symmetry Island Transparent 1 // Too mean for right now
		// 0x003E8, // Symmetry Island Transparent 2 // Too mean for right now
		// 0x00A15, // Symmetry Island Transparent 3 // Too mean for right now
		// 0x00B53, // Symmetry Island Transparent 4 // Too mean for right now
		// 0x00B8D, // Symmetry Island Transparent 5 // Too mean for right now
		// 0x1C349, // Symmetry Island Door 2 - Collision fails here, sadly
		0x00A52, // Symmetry Island Laser Yellow 1
		0x00A57, // Symmetry Island Laser Yellow 2
		0x00A5B, // Symmetry Island Laser Yellow 3
		0x00A61, // Symmetry Island Laser Blue 1
		0x00A64, // Symmetry Island Laser Blue 2
		0x00A68, // Symmetry Island Laser Blue 3
	};
	randomizer.Randomize(symmetryPanels, SWAP_LINES | SWAP_COLORS);



	std::vector<int> desertPanels = {
//		0x17CE7, // Desert Discard
//		0x0CC7B, // Desert Vault
//		0x0339E, // Desert Vault Box
		0x00698, // Desert Surface 1
		0x0048F, // Desert Surface 2
		0x09F92, // Desert Surface 3
//		0x09FA0, // Desert Surface 3 Control
		0x0A036, // Desert Surface 4
		0x09DA6, // Desert Surface 5
		0x0A049, // Desert Surface 6
		0x0A053, // Desert Surface 7
		0x09F94, // Desert Surface 8
//		0x09F86, // Desert Surface 8 Control
//		0x0C339, // Desert Surface Door
//		0x09FAA, // Desert Lightswitch
		0x00422, // Desert Light 1
		0x006E3, // Desert Light 2
//		0x0A02D, // Desert Light 3
		0x00C72, // Desert Pond 1
		0x0129D, // Desert Pond 2
		0x008BB, // Desert Pond 3
		0x0078D, // Desert Pond 4
		0x18313, // Desert Pond 5
//		0x0A249, // Desert Pond Exit Door
//		0x1C2DF, // Desert Flood Control Lower Far Left
//		0x1831E, // Desert Flood Control Lower Far Right
//		0x1C260, // Desert Flood Control Lower Near Left
//		0x1831C, // Desert Flood Control Lower Near Right
//		0x1C2F3, // Desert Flood Control Raise Far Left
//		0x1831D, // Desert Flood Control Raise Far Right
//		0x1C2B1, // Desert Flood Control Raise Near Left
//		0x1831B, // Desert Flood Control Raise Near Right
		0x04D18, // Desert Flood 1
		0x01205, // Desert Flood 2
		0x181AB, // Desert Flood 3
		0x0117A, // Desert Flood 4
		0x17ECA, // Desert Flood 5
//		0x18076, // Desert Flood Exit
//		0x0A15C, // Desert Final Left Convex
//		0x09FFF, // Desert Final Left Concave
//		0x0A15F, // Desert Final Near
//		0x17C31, // Desert Final Transparent
		0x012D7, // Desert Final Far
//		0x0A015, // Desert Final Far Control
	};

	randomizer.Randomize(desertPanels, SWAP_LINES);

	std::vector<int> quarryPanels = {
		0x01E5A, // Mill Entry Door Left
		0x01E59, // Mill Entry Door Right
//		0x03678, // Mill Lower Ramp Contol
		0x00E0C, // Mill Lower Row 1
		0x01489, // Mill Lower Row 2
		0x0148A, // Mill Lower Row 3
		0x014D9, // Mill Lower Row 4
		0x014E7, // Mill Lower Row 5
		0x014E8, // Mill Lower Row 6
//		0x03679, // Mill Lower Lift Control
		0x00557, // Mill Upper Row 1
		0x005F1, // Mill Upper Row 2
		0x00620, // Mill Upper Row 3
		0x009F5, // Mill Upper Row 4
		0x0146C, // Mill Upper Row 5
		0x3C12D, // Mill Upper Row 6
		0x03686, // Mill Upper Row 7
		0x014E9, // Mill Upper Row 8
		0x0367C, // Mill Control Room 1
//		0x03675, // Mill Upper Lift Control
//		0x03676, // Mill Upper Ramp Control
		0x3C125, // Mill Control Room 2
//		0x275ED, // Mill EP Door
//		0x17CAC, // Mill Stairs Shortcut Door
		0x03677, // Mill Stairs Control
//		0x17CF0, // Mill Discard
//		0x17CC4, // Mill Elevator Control
		0x021D5, // Boathouse Ramp Activation Shapers
		0x034D4, // Boathouse Ramp Activation Stars
//		0x03852, // Boathouse Ramp Angle Control
		0x021B3, // Boathouse Erasers and Shapers 1
		0x021B4, // Boathouse Erasers and Shapers 2
		0x021B0, // Boathouse Erasers and Shapers 3
		0x021AF, // Boathouse Erasers and Shapers 4
		0x021AE, // Boathouse Erasers and Shapers 5
//		0x17CA6, // Boathouse Summon Boat
//		0x03858, // Boathouse Ramp Position Control
//		0x38663, // Boathouse Shortcut
		0x021B5, // Boathouse Erasers and Stars 1
		0x021B6, // Boathouse Erasers and Stars 2
		0x021B7, // Boathouse Erasers and Stars 3
		0x021BB, // Boathouse Erasers and Stars 4
		0x09DB5, // Boathouse Erasers and Stars 5
		0x09DB1, // Boathouse Erasers and Stars 6
		0x3C124, // Boathouse Erasers and Stars 7
		0x09DB3, // Boathouse Erasers Shapers and Stars 1
		0x09DB4, // Boathouse Erasers Shapers and Stars 2
		0x0A3CB, // Boathouse Erasers Shapers and Stars 3
		0x0A3CC, // Boathouse Erasers Shapers and Stars 4
		0x0A3D0, // Boathouse Erasers Shapers and Stars 5
//		0x275FA, // Boathouse Hook Control
		0x09E57, // Quarry Entry Gate 1
		0x17C09, // Quarry Entry Gate 2
	};
	randomizer.Randomize(quarryPanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> treehousePanels = { //worked fine until I commented out pivoting panels, puzzles solve fine if you know solution but star and dot colors are all messed up
//		0x17C95, // Treehouse Summon Boat
		0x0288C, // Treehouse Door 1
		0x02886, // Treehouse Door 2
		0x17D72, // Treehouse Yellow 1
		0x17D8F, // Treehouse Yellow 2
		0x17D74, // Treehouse Yellow 3
		0x17DAC, // Treehouse Yellow 4
		0x17D9E, // Treehouse Yellow 5
		0x17DB9, // Treehouse Yellow 6
		0x17D9C, // Treehouse Yellow 7
		0x17DC2, // Treehouse Yellow 8
		0x17DC4, // Treehouse Yellow 9
		0x0A182, // Treehouse Door 3
		0x17DC8, // Treehouse First Purple 1
		0x17DC7, // Treehouse First Purple 2
		0x17CE4, // Treehouse First Purple 3
		0x17D2D, // Treehouse First Purple 4
		0x17D6C, // Treehouse First Purple 5
		0x17D9B, // Treehouse Second Purple 1
		0x17D99, // Treehouse Second Purple 2
		0x17DAA, // Treehouse Second Purple 3
		0x17D97, // Treehouse Second Purple 4
		0x17BDF, // Treehouse Second Purple 5
		0x17D91, // Treehouse Second Purple 6
		0x17DC6, // Treehouse Second Purple 7
		0x17DB3, // Treehouse Left Orange 1
		0x17DB5, // Treehouse Left Orange 2
		0x17DB6, // Treehouse Left Orange 3
		0x17DC0, // Treehouse Left Orange 4
		0x17DD7, // Treehouse Left Orange 5
		0x17DD9, // Treehouse Left Orange 6
		0x17DB8, // Treehouse Left Orange 7
		0x17DDC, // Treehouse Left Orange 8
//		0x17DD1, // Treehouse Left Orange 9 has to pivot
		0x17DDE, // Treehouse Left Orange 10
		0x17DE3, // Treehouse Left Orange 11
		0x17DEC, // Treehouse Left Orange 12
		0x17DAE, // Treehouse Left Orange 13
		0x17DB0, // Treehouse Left Orange 14
		0x17DDB, // Treehouse Left Orange 15
		0x17D88, // Treehouse Right Orange 1
		0x17DB4, // Treehouse Right Orange 2
		0x17D8C, // Treehouse Right Orange 3
		0x17CE3, // Treehouse Right Orange 4
//		0x17DCD, // Treehouse Right Orange 5 has to pivot
		0x17DB2, // Treehouse Right Orange 6
		0x17DCC, // Treehouse Right Orange 7
		0x17DCA, // Treehouse Right Orange 8
		0x17D8E, // Treehouse Right Orange 9
//		0x17DB7, // Treehouse Right Orange 10 has to pivot
		0x17DB1, // Treehouse Right Orange 11
		0x17DA2, // Treehouse Right Orange 12
		0x17E3C, // Treehouse Green 1
		0x17E4D, // Treehouse Green 2
		0x17E4F, // Treehouse Green 3
		0x17E52, // Treehouse Green 4
		0x17E5B, // Treehouse Green 5
		0x17E5F, // Treehouse Green 6
		0x17E61, // Treehouse Green 7
		0x17FA9, // Treehouse Green Bridge Discard
		0x17FA0, // Treehouse Laser Discard
//		0x2700B, // Treehouse Exterior Door Control
//		0x17CBC, // Treehouse Interior Door Control
//		0x037FF, // Treehouse Drawbridge Control
	};
	randomizer.Randomize(treehousePanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> keepPanels = {
		0x00139, // Keep Hedges 1
		0x019DC, // Keep Hedges 2
		0x019E7, // Keep Hedges 3
		0x01A0F, // Keep Hedges 4
//		0x033EA, // Keep Yellow Pressure Plates
//		0x0A3A8, // Keep Yellow Reset
//		0x01BE9, // Keep Purple Pressure Plates
//		0x0A3B9, // Keep Purple Reset
//		0x01CD3, // Keep Green Pressure Plates
//		0x0A3BB, // Keep Green Reset
//		0x01D3F, // Keep Blue Pressure Plates
//		0x0A3AD, // Keep Blue Reset
		0x0360E, // Keep Front Laser
		0x03317, // Keep Back Laser
//		0x09E49, // Keep Shadows Shortcut
//		0x0361B, // Keep Tower Shortcut
		0x17D27, // Keep Discard
		0x17D28, // Shipwreck Discard
		0x00AFB, // Shipwreck Vault
//		0x03535, // Shipwreck Vault Box
	};
	randomizer.Randomize(keepPanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> shadowsPanels = { //works beautifully, can solve based on panel color and where start/end points are if your memory is good
		0x386FA, //Shadows Avoid 1
		0x1C33F, //Shadows Avoid 2
		0x196E2, //Shadows Avoid 3
		0x1972A, //Shadows Avoid 4
		0x19809, //Shadows Avoid 5
		0x19806, //Shadows Avoid 6
		0x196F8, //Shadows Avoid 7
		0x1972F, //Shadows Avoid 8
		0x19797, //Shadows Follow 1
		0x1979A, //Shadows Follow 2
		0x197E0, //Shadows Follow 3
		0x197E8, //Shadows Follow 4
		0x197E5, //Shadows Follow 5
//		0x334DC, //Shadows Inner Door Control
		0x19650, //Shadows Laser
//		0x334DB, //Shadows Outer Door Control
		0x198B5, //Shadows Tutorial 1
		0x198BD, //Shadows Tutorial 2
		0x198BF, //Shadows Tutorial 3
		0x19771, //Shadows Tutorial 4
		0x0A8DC, //Shadows Tutorial 5
		0x0AC74, //Shadows Tutorial 6
		0x0AC7A, //Shadows Tutorial 7
		0x0A8E0, //Shadows Tutorial 8
	};
	randomizer.Randomize(shadowsPanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> townPanels = { //appears to be ok but keeps crashing game?
		0x2899C, //Town 25 Dots 1
		0x28A33, //Town 25 Dots 2
		0x28ABF, //Town 25 Dots 3
		0x28AC0, //Town 25 Dots 4
		0x28AC1, //Town 25 Dots 5
		0x28938, //Town Apple Tree
		0x28AC7, //Town Blue 1
		0x28AC8, //Town Blue 2
		0x28ACA, //Town Blue 3
		0x28ACB, //Town Blue 4
		0x28ACC, //Town Blue 5
//		0x0A054, //Town Summon Boat
//		0x2896A, //Town Bridge
		0x28A0D, //Town Church Stars
		0x28AD9, //Town Eraser
		0x28998, //Town Green Door
//		0x09F98, //Town Laser Redirect Control
//		0x1C344, //Town Laser Redirect Panel 1
//		0x1C343, //Town Laser Redirect Panel 2
//		0x28A69, //Town Lattice
		0x28A79, //Town Maze
		0x0A0C8, //Town Orange Crate
		0x17D01, //Town Orange Crate Discard
//		0x28B39, //Town Red Hexagonal
//		0x334D8, //Town RGB Light Control
		0x03C08, //Town RGB Stars
		0x03C0C, //Town RGB Stones
		0x17C71, //Town Rooftop Discard
//		0x034E3, //Town Soundproof Dots panels in their locations must match so can't swap unless that is fixed
//		0x034E4, //Town Soundproof Waves
		0x18590, //Town Transparent
//		0x079DF, //Town Triple
		0x17D02, //Town Windmill Control
		0x17F5F, //Town Windmill Door
		0x28AE3, //Town Wire
		0x17F89, //Theater Entrance
//		0x00815, //Theater Video Input
//		0x03553, //Theater Tutorial Video
//		0x03552, //Theater Desert Video
//		0x0354E, //Theater Jungle Video
//		0x03549, //Theater Challenge Video
//		0x0354F, //Theater Shipwreck Video
//		0x03545, //Theater Mountain Video
		0x17CF7, //Theater Discard
		0x33AB2, //Theater Corona Exit
		0x0A168, //Theater Sun Exit
	};
	randomizer.Randomize(townPanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> monasteryPanels = {
//		0x00B10, //Monastery Left Door
//		0x00C92, //Monastery Right Door
		0x00290, //Monastery Exterior 1
		0x00038, //Monastery Exterior 2
		0x00037, //Monastery Exterior 3
//		0x09D9B, //Monastery Bonsai
		0x193A7, //Monastery Interior 1
		0x193AA, //Monastery Interior 2
		0x193AB, //Monastery Interior 3
		0x193A6, //Monastery Interior 4
		0x03713, //Monastery Shortcut
	};
	randomizer.Randomize(monasteryPanels, SWAP_TARGETS);

	std::vector<int> junglePanels = {
//		0x17CDF, //Jungle Summon Boat
		0x17F9B, //Jungle Discard
		0x002C4, //Jungle Waves 1
		0x00767, //Jungle Waves 2
		0x002C6, //Jungle Waves 3
		0x0070E, //Jungle Waves 4
		0x0070F, //Jungle Waves 5
		0x0087D, //Jungle Waves 6
		0x002C7, //Jungle Waves 7
//		0x15ADD, //Jungle Vault
//		0x03702, //Jungle Vault Box
//		0x17CAA, //Jungle Courtyard Gate
		0x0026D, //Jungle Dots 1
		0x0026E, //Jungle Dots 2
		0x0026F, //Jungle Dots 3
		0x00C3F, //Jungle Dots 4
		0x00C41, //Jungle Dots 5
		0x014B2, //Jungle Dots 6
//		0x17CAB, //Jungle Pop - up Wall
//		0x337FA, //Jungle Shortcut
	};
	randomizer.Randomize(junglePanels, SWAP_LINES | SWAP_COLORS);

//		std::vector<int> bunkerPanels = { this doesn't want to behave, I have no idea
//			0x17C2E, //Bunker Entry Door
//			0x09F7D, //Bunker Tutorial 1
//			0x09FDC, //Bunker Tutorial 2
//			0x09FF7, //Bunker Tutorial 3
//			0x09F82, //Bunker Tutorial 4
//			0x09FF8, //Bunker Tutorial 5
//			0x09D9F, //Bunker Advanced 1
//			0x09DA1, //Bunker Advanced 2
//			0x09DA2, //Bunker Advanced 3
//			0x09DAF, //Bunker Advanced 4
//	//		0x0A099, //Bunker Glass Door
//	//		0x0A010, //Bunker Glass 1
//	//		0x0A01B, //Bunker Glass 2
//	//		0x0A01F, //Bunker Glass 3
//			0x34BC5, //Bunker Open Ultraviolet
//			0x34BC6, //Bunker Close Ultraviolet
//			0x17E63, //Bunker Ultraviolet 1
//			0x17E67, //Bunker Ultraviolet 2
//			0x0A079, //Bunker Elevator
//		};
//		randomizer.Randomize(bunkerPanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> swampPanels = { //appears to work ok swapping panels but keeps crashing game?
		0x0056E, //Swamp Entry
		0x00469, //Swamp Tutorial 1
		0x00472, //Swamp Tutorial 2
		0x00262, //Swamp Tutorial 3
		0x00474, //Swamp Tutorial 4
		0x00553, //Swamp Tutorial 5
		0x0056F, //Swamp Tutorial 6
		0x00390, //Swamp Tutorial 7
		0x010CA, //Swamp Tutorial 8
		0x00983, //Swamp Tutorial 9
		0x00984, //Swamp Tutorial 10
		0x00986, //Swamp Tutorial 11
		0x00985, //Swamp Tutorial 12
		0x00987, //Swamp Tutorial 13
		0x181A9, //Swamp Tutorial 14
//		0x00609, //Swamp Surface Sliding Bridge Control
		0x00982, //Swamp Red 1
		0x0097F, //Swamp Red 2
		0x0098F, //Swamp Red 3
		0x00990, //Swamp Red 4
		0x17C0D, //Swamp Red Shortcut 1
		0x17C0E, //Swamp Red Shortcut 2
		0x00999, //Swamp Discontinuous 1
		0x0099D, //Swamp Discontinuous 2
		0x009A0, //Swamp Discontinuous 3
		0x009A1, //Swamp Discontinuous 4
		0x00007, //Swamp Rotation Tutorial 1
		0x00008, //Swamp Rotation Tutorial 2
		0x00009, //Swamp Rotation Tutorial 3
		0x0000A, //Swamp Rotation Tutorial 4
		0x181F5, //Swamp Rotating Bridge Control
		0x009AB, //Swamp Blue Underwater 1
		0x009AD, //Swamp Blue Underwater 2
		0x009AE, //Swamp Blue Underwater 3
		0x009AF, //Swamp Blue Underwater 4
		0x00006, //Swamp Blue Underwater 5
		0x003B2, //Swamp Rotation Advanced 1
		0x00A1E, //Swamp Rotation Advanced 2
		0x00C2E, //Swamp Rotation Advanced 3
		0x00E3A, //Swamp Rotation Advanced 4
//		0x17E2B, //Swamp Flood Gate Control
//		0x09DB8, //Swamp Summon Boat
		0x009A6, //Swamp Purple Tetris
//		0x18488, //Swamp Underwater Sliding Bridge Control
		0x00002, //Swamp Teal Underwater 1
		0x00004, //Swamp Teal Underwater 2
		0x00005, //Swamp Teal Underwater 3
		0x013E6, //Swamp Teal Underwater 4
		0x00596, //Swamp Teal Underwater 5
		0x00001, //Swamp Red Underwater 1
		0x014D2, //Swamp Red Underwater 2
		0x014D4, //Swamp Red Underwater 3
		0x014D1, //Swamp Red Underwater 4
		0x17C0A, //Swamp Island Control 1
		0x17E07, //Swamp Island Control 2
		0x17C05, //Swamp Laser Shortcut 1
		0x17C02, //Swamp Laser Shortcut 2
	};
	randomizer.Randomize(swampPanels, SWAP_LINES | SWAP_COLORS);

	std::vector<int> mountainPanels = {
//		0x09E39, //Mountain 1 Purple Pathway
		0x09E73, //Mountain 1 Orange 1
		0x09E75, //Mountain 1 Orange 2
		0x09E78, //Mountain 1 Orange 3
		0x09E79, //Mountain 1 Orange 4
		0x09E6C, //Mountain 1 Orange 5
		0x09E6F, //Mountain 1 Orange 6
		0x09E6B, //Mountain 1 Orange 7
//		0x33AF5, //Mountain 1 Blue 1
//		0x33AF7, //Mountain 1 Blue 2
//		0x09F6E, //Mountain 1 Blue 3
		0x09EAD, //Mountain 1 Purple 1
		0x09EAF, //Mountain 1 Purple 2
		0x09E7A, //Mountain 1 Green 1
		0x09E71, //Mountain 1 Green 2
		0x09E72, //Mountain 1 Green 3
		0x09E69, //Mountain 1 Green 4
		0x09E7B, //Mountain 1 Green 5
		0x09FD3, //Mountain 2 Rainbow 1
		0x09FD4, //Mountain 2 Rainbow 2
		0x09FD6, //Mountain 2 Rainbow 3
		0x09FD7, //Mountain 2 Rainbow 4
		0x09FD8, //Mountain 2 Rainbow 5
//		0x09E86, //Mountain 2 Blue Pathway
//		0x09FCC, //Mountain 2 Multipanel 1  panels work fine other places but the actual location isn't on - I think maybe it needs all the panels the same
//		0x09FCE, //Mountain 2 Multipanel 2
//		0x09FCF, //Mountain 2 Multipanel 3
//		0x09FD0, //Mountain 2 Multipanel 4
//		0x09FD1, //Mountain 2 Multipanel 5
//		0x09FD2, //Mountain 2 Multipanel 6
//		0x09ED8, //Mountain 2 Orange Pathway
//		0x09EEB, //Mountain 2 Elevator
		0x17F93, //Mountain 2 Discard
		0x09F8E, //Mountain 3 Near Right Floor
		0x09FC1, //Mountain 3 Near Left Floor
		0x09F01, //Mountain 3 Far Right Floor
		0x09EFF, //Mountain 3 Far Left Floor
		0x09FDA, //Mountain 3 Giant Floor
		0x17FA2, //Mountain 3 Secret Door
//		0x01983, //Mountain 3 Left Peekaboo
//		0x01987, //Mountain 3 Right Peekaboo
//		0x0383D, //Mountain 3 Left Pillar 1
//		0x0383F, //Mountain 3 Left Pillar 2
//		0x03859, //Mountain 3 Left Pillar 3
//		0x339BB, //Mountain 3 Left Pillar 4
//		0x0383A, //Mountain 3 Right Pillar 1
//		0x09E56, //Mountain 3 Right Pillar 2
//		0x09E5A, //Mountain 3 Right Pillar 3
//		0x33961, //Mountain 3 Right Pillar 4
//		0x3D9A6, //Mountain 3 Left Close Door
//		0x3D9A7, //Mountain 3 Right Close Door
//		0x3D9AA, //Mountain 3 Left Activate Elevator
//		0x3D9A8, //Mountain 3 Right Activate Elevator
//		0x3D9A9, //Mountain 3 Launch Elevator
//		0x3C113, //Mountain 3 Left Open Door
//		0x3C114, //Mountain 3 Right Open Door
		0x17C42, //Mountainside Discard
		0x002A6, //Mountainside Vault
//		0x03542, //Mountainside Vault Box
//		0x09F7F, //Mountaintop Laser Box
//		0x17C34, //Mountaintop Perspective
		0x0042D, //Mountaintop River
	};
	randomizer.Randomize(mountainPanels, SWAP_LINES | SWAP_COLORS);

//		std::vector<int> utmPanels = { this looks like it swaps ok but crashes to much to tell, not sure why it's not happy
//			0x0A16E, //UTM Challenge Entrance
//	//		0x09DD5, //UTM Challenge Pillar
//			0x00FF8, //UTM Entrance Door
//			0x0A16B, //UTM Green Dots 1
//			0x0A2CE, //UTM Green Dots 2
//			0x0A2D7, //UTM Green Dots 3
//			0x0A2DD, //UTM Green Dots 4
//			0x0A2EA, //UTM Green Dots 5
//			0x17FB9, //UTM Green Dots 6
//			0x335AB, //UTM In Elevator Control
//			0x0008F, //UTM Invisible Dots 1
//			0x0006B, //UTM Invisible Dots 2
//			0x0008B, //UTM Invisible Dots 3
//			0x0008C, //UTM Invisible Dots 4
//			0x0008A, //UTM Invisible Dots 5
//			0x00089, //UTM Invisible Dots 6
//			0x0006A, //UTM Invisible Dots 7
//			0x0006C, //UTM Invisible Dots 8
//			0x00027, //UTM Invisible Dots Symmetry 1
//			0x00028, //UTM Invisible Dots Symmetry 2
//			0x00029, //UTM Invisible Dots Symmetry 3
//			0x3369D, //UTM Lower Elevator Control
//			0x021D7, //UTM Mountainside Shortcut
//	//		0x288EA, //UTM Perspective 1
//	//		0x288FC, //UTM Perspective 2
//	//		0x289E7, //UTM Perspective 3
//	//		0x288AA, //UTM Perspective 4
//			0x00B71, //UTM Quarry
//			0x01A31, //UTM Rainbow
//	//		0x334E1, //UTM Secret Door Control
//			0x32962, //UTM Swamp
//			0x32966, //UTM Treehouse
//			0x335AC, //UTM Upper Elevator Control
//			0x17CF2, //UTM Waterfall Shortcut
//			0x00A72, //UTM Blue Cave In
//			0x009A4, //UTM Blue Discontinuous
//			0x018A0, //UTM Blue Easy Symmetry
//			0x01A0D, //UTM Blue Hard Symmetry
//			0x008B8, //UTM Blue Left 1
//			0x00973, //UTM Blue Left 2
//			0x0097B, //UTM Blue Left 3
//			0x0097D, //UTM Blue Left 4
//			0x0097E, //UTM Blue Left 5
//			0x00994, //UTM Blue Right Far 1
//			0x334D5, //UTM Blue Right Far 2
//			0x00995, //UTM Blue Right Far 3
//			0x00996, //UTM Blue Right Far 4
//			0x00998, //UTM Blue Right Far 5
//			0x00190, //UTM Blue Right Near 1
//			0x00558, //UTM Blue Right Near 2
//			0x00567, //UTM Blue Right Near 3
//			0x006FE, //UTM Blue Right Near 4
//	//		0x2773D, //Tunnels Desert Shortcut
//			0x039B4, //Tunnels Theater Catwalk
//	//		0x27732, //Tunnels Theater Shortcut
//	//		0x2FAF6, //Tunnels Vault Box
//			0x09E85, //Tunnels Town Shortcut
//		};
//		randomizer.Randomize(utmPanels, SWAP_LINES | SWAP_COLORS);


	   	 	/*/


	int BOATH_3_1 = 0x21B5;
	int MILL_L_1 = 0xE0C;
	int MILL_U_1 = 0x557;
	int QUARRY_E_1 = 0x9E57;
	int QUARRY_E_2 = 0x17C09;
	int MILL_E_1 = 0x1E5A;

	randomizer.SwapPanels(BOATH_3_1, QUARRY_E_1, SWAP_LINES | SWAP_COLORS);
	//*/
}

WitnessRandomizer::WitnessRandomizer() : _memory(Memory("witness64_d3d11.exe"))
{
	// Turn off desert flood final
	_memory.WriteData<float>({0x5B28C0, 0x18, 0x18076*8, 0x2A8}, {0.0f, 0.0f});
	// Change desert floating target to desert flood final
	_memory.WriteData<int>({0x5B28C0, 0x18, 0x17ECA*8, 0x2BC}, {0x18077});
}

void WitnessRandomizer::Randomize(std::vector<int> panels, int flags) {
	for (size_t i=panels.size() - 1; i > 1; i--) {
		int target = rand() % i;
		if (i != target) {
			// std::cout << "Swapping panels " << std::hex << panels[i] << " and " << std::hex << panels[target] << std::endl;
			SwapPanels(panels[i], panels[target], flags);
			std::swap(panels[i], panels[target]); // Panel indices in the array
		}
	}
}

void WitnessRandomizer::SwapPanels(int panel1, int panel2, int flags) {
	std::map<int, int> offsets;

	if (flags & SWAP_TARGETS) {
		offsets[0x2BC] = sizeof(int);
	}
	if (flags & SWAP_LINES) {
		offsets[0x3B8] = sizeof(int); // num_dots
		offsets[0x3BC] = sizeof(int); // num_connections
		offsets[0x3C8] = sizeof(void*); // *dot_positions
		offsets[0x3D0] = sizeof(void*); // *dot_flags
		offsets[0x3D8] = sizeof(void*); // *dot_connection_a
		offsets[0x3E0] = sizeof(void*); // *dot_connection_b
		offsets[0x440] = sizeof(void*); // *reflection_data
		offsets[0x448] = sizeof(int); // grid_size_x
		offsets[0x44C] = sizeof(int); // grid_size_y
		offsets[0x450] = sizeof(int); // style_flags // This is required to not ignore dots
		offsets[0x4B0] = sizeof(void*); // *panel_target
		offsets[0x4D8] = sizeof(void*); // *specular_texture

		offsets[0x420] = sizeof(void*); // *decorations
		offsets[0x428] = sizeof(void*); // *decoration_flags
		offsets[0x438] = sizeof(int); // num_decorations

		offsets[0x45C] = sizeof(int); // sequence_len
		offsets[0x460] = sizeof(void*); // *sequence
		offsets[0x468] = sizeof(int); // dot_sequence_len
		offsets[0x470] = sizeof(void*); // *dot_sequence
		offsets[0x478] = sizeof(int); // dot_sequence_len_reflection
		offsets[0x480] = sizeof(void*); // *dot_sequence_reflection

		offsets[0x3A4] = sizeof(float); // path_width_scale
		offsets[0x3A8] = sizeof(float); // startpoint_scale

		offsets[0x230] = 16; // traced_edges

		// TODO: Try using is_cylinder to swap into tutorial pillar. If it fails, discard.
		// Probably not: Extra back distance
		// SwapPanelData(panels[i], panels[target], 0x2FC, 125); // is_cylinder through max_connections
	}
	/*
	if (flags & SWAP_STYLE) {
		// 340 - pattern_scale
		// 288 - flash_mode
	}
	*/
	if (flags & SWAP_COLORS) {
		offsets[0xC8] = 16; // path_color
		offsets[0xD8] = 16; // reflection_path_color
//		offsets[0xE8] = 16; // deprecated_finished_path_color
		offsets[0xF8] = 16; // dot_color
		offsets[0x108] = 16; // active_color
		offsets[0x118] = 16; // background_region_color
		offsets[0x128] = 16; // success_color_a
		offsets[0x138] = 16; // success_color_b
		offsets[0x148] = 16; // strobe_color_a
		offsets[0x158] = 16; // strobe_color_b
		offsets[0x168] = 16; // error_color
//		offsets[0x178] = 16; // video_status_color
		offsets[0x188] = 16; // pattern_point_color
		offsets[0x198] = 16; // pattern_point_color_a
		offsets[0x1A8] = 16; // pattern_point_color_b
		offsets[0x1B8] = 16; // symbol_a
		offsets[0x1C8] = 16; // symbol_b
		offsets[0x1D8] = 16; // symbol_c
		offsets[0x1E8] = 16; // symbol_d
		offsets[0x1F8] = 16; // symbol_e
		offsets[0x208] = sizeof(int); // push_symbol_colors
		offsets[0x20C] = 16; // outer_background
		offsets[0x21C] = sizeof(int); // outer_background_mode
		offsets[0x430] = sizeof(void*); // *decoration_colors
		offsets[0x4A0] = sizeof(int); // num_colored_regions
		offsets[0x4A8] = sizeof(void*); // *colored_regions
//		offsets[0x4B8] = sizeof(void*); // *backing_texture
	}

	for (auto const& [offset, size] : offsets) {
		SwapPanelData(panel1, panel2, offset, size);
	}
}

void WitnessRandomizer::SwapPanelData(int panel1, int panel2, int finalOffset, int dataSize) {
	// Currently wired for old version
	std::vector<int> panel1Offset = {0x5B28C0, 0x18, panel1*8, finalOffset};
	std::vector<int> panel2Offset = {0x5B28C0, 0x18, panel2*8, finalOffset};

	std::vector<byte> panel1Data = _memory.ReadData<byte>(panel1Offset, dataSize);
	std::vector<byte> panel2Data = _memory.ReadData<byte>(panel2Offset, dataSize);

	bool failed = _memory.WriteData<byte>(panel2Offset, panel1Data);
	if (failed) {
		_memory.WriteData<byte>(panel2Offset, panel1Data);
	}
	failed = _memory.WriteData<byte>(panel1Offset, panel2Data);
	if (failed) {
		_memory.WriteData<byte>(panel1Offset, panel2Data);
	}
}