Skip to content

Commit f67cff2

Browse files
committed
Improve CountPossibleMinorItems for multiple item palaces
1 parent 5da2b6e commit f67cff2

4 files changed

Lines changed: 62 additions & 41 deletions

File tree

RandomizerCore/EnumTypes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ public enum PalaceLengthOption
837837
SHORT = 0,
838838
[Description("Medium; [60% to 80%]"), RandomRangeDouble(Low = 0.60, High = 0.80)]
839839
MEDIUM = 1,
840-
[Description("Full; [85% to 115%]"), RandomRangeDouble(Low = 0.85, High = 1.15)]
840+
[Description("Full"), RandomRangeDouble(Low = 0.85, High = 1.15)]
841841
FULL = 2, // remains 100% for Vanilla palaces
842842
[Description("Random; [50% to 115%]"), RandomRangeDouble(Low = 0.50, High = 1.15)]
843843
RANDOM = 3

RandomizerCore/Hyrule.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,9 +2327,9 @@ private void RandomizeStartingValues(RandomizerProperties props, Assembler a, Ra
23272327
if (props.EncounterRates == EncounterRate.HALF)
23282328
{
23292329
//terrain timers
2330-
rom.Put(0x250, 0x40);
2331-
rom.Put(0x251, 0x30);
2332-
rom.Put(0x252, 0x30);
2330+
rom.Put(0x250, 0x40); // grass
2331+
rom.Put(0x251, 0x30); // desert
2332+
rom.Put(0x252, 0x30); // forest
23332333
rom.Put(0x253, 0x40);
23342334
rom.Put(0x254, 0x12);
23352335
rom.Put(0x255, 0x06);

RandomizerCore/RandomizerConfiguration.cs

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ public RandomizerProperties Export(Random r)
958958
}
959959

960960

961-
properties.PalaceLengths = Palaces.RollPalaceLengths(r, properties, this);
961+
properties.PalaceLengths = Palaces.RollPalaceLengths(this, properties, r);
962962

963963
properties.DarkLinkMinDistance = GetDarkLinkMinDistance();
964964

@@ -1631,34 +1631,8 @@ public void AssignPalaceItemCounts(RandomizerProperties properties, Random r)
16311631
//I'm not sure whether I like the bias introduced in generating random values and then capping them
16321632
//vs just determining min/max ranges and fair rolling between them. Keeping it for now.
16331633
int[] palaceItemRoomsMin = palaceItemRoomCount == PalaceItemRoomCount.RANDOM_INCLUDE_ZERO ? [0, 0, 0, 0, 0, 0] : [1, 1, 1, 1, 1, 1];
1634-
// To keep weighting consistent between 0-item and 1-item rooms across
1635-
// Standard, Max Rando, etc., we roll the room count the same way
1636-
// regardless of palace type. This also reduces how much (imperfect)
1637-
// information the item count reveals about the palace style.
1638-
int[] palaceItemRoomsMax = palaceItemRoomCount switch
1639-
{
1640-
PalaceItemRoomCount.ZERO => [0, 0, 0, 0, 0, 0],
1641-
PalaceItemRoomCount.ONE => [1, 1, 1, 1, 1, 1],
1642-
PalaceItemRoomCount.TWO => [2, 2, 2, 2, 2, 2],
1643-
PalaceItemRoomCount.RANDOM_NOT_ZERO or
1644-
PalaceItemRoomCount.RANDOM_INCLUDE_ZERO =>
1645-
properties.PalaceLengths.Select(len => len switch
1646-
{
1647-
< 14 => 1,
1648-
< 24 => 2,
1649-
_ => 3,
1650-
}).ToArray(),
1651-
_ => throw new NotImplementedException(),
1652-
};
1653-
// We have to cap the number of item rooms for some styles.
1654-
// Vanilla, because it doesn't make sense to change any rooms,
1655-
// and Vanilla Shuffled, because it crashes with more than two.
1656-
int[] palaceItemRoomsLimit = properties.PalaceStyles.Select(style => style switch
1657-
{
1658-
PalaceStyle.VANILLA => 1,
1659-
PalaceStyle.SHUFFLED => 2,
1660-
_ => int.MaxValue,
1661-
}).ToArray();
1634+
int[] palaceItemRoomsMax = GetPalaceItemRoomMaxCounts(palaceItemRoomCount, properties.PalaceLengths);
1635+
int[] palaceItemRoomsLimit = GetPalaceItemRoomLimits(properties.PalaceStyles);
16621636

16631637
switch (palaceItemRoomCount)
16641638
{
@@ -1702,6 +1676,43 @@ PalaceItemRoomCount.RANDOM_NOT_ZERO or
17021676
}
17031677
}
17041678

1679+
/// Note: this value can be limited by other things, like the style being Vanilla
1680+
public static int[] GetPalaceItemRoomMaxCounts(PalaceItemRoomCount palaceItemRoomCount, int[] palaceLengths)
1681+
{
1682+
// To keep weighting consistent between 0-item and 1-item rooms across
1683+
// Standard, Max Rando, etc., we roll the room count the same way
1684+
// regardless of palace type. This also reduces how much (imperfect)
1685+
// information the item count reveals about the palace style.
1686+
return palaceItemRoomCount switch
1687+
{
1688+
PalaceItemRoomCount.ZERO => [0, 0, 0, 0, 0, 0],
1689+
PalaceItemRoomCount.ONE => [1, 1, 1, 1, 1, 1],
1690+
PalaceItemRoomCount.TWO => [2, 2, 2, 2, 2, 2],
1691+
PalaceItemRoomCount.RANDOM_NOT_ZERO or
1692+
PalaceItemRoomCount.RANDOM_INCLUDE_ZERO =>
1693+
palaceLengths.Select(len => len switch
1694+
{
1695+
< 16 => 1,
1696+
< 26 => 2,
1697+
_ => 3,
1698+
}).ToArray(),
1699+
_ => throw new NotImplementedException(),
1700+
};
1701+
}
1702+
1703+
public static int[] GetPalaceItemRoomLimits(PalaceStyle[] palaceStyles)
1704+
{
1705+
// We have to cap the number of item rooms for some styles.
1706+
// Vanilla, because it doesn't make sense to change any rooms,
1707+
// and Vanilla Shuffled, because it crashes with more than two.
1708+
return palaceStyles.Select(style => style switch
1709+
{
1710+
PalaceStyle.VANILLA => 1,
1711+
PalaceStyle.SHUFFLED => 2,
1712+
_ => int.MaxValue,
1713+
}).ToArray();
1714+
}
1715+
17051716
/// Let the user know when their combination of flags will not be
17061717
/// possible to achieve.
17071718
///
@@ -1714,10 +1725,6 @@ public void CheckForFlagConflicts()
17141725
{
17151726
requiredMinorItemReplacements = 4 - (startingHeartContainersMax ?? 4);
17161727
}
1717-
if (palaceItemRoomCount == PalaceItemRoomCount.ZERO)
1718-
{
1719-
requiredMinorItemReplacements += 6;
1720-
}
17211728
if (CountPossibleMinorItems() < requiredMinorItemReplacements)
17221729
{
17231730
throw new UserFacingException("Impossible Item Flags", "Not enough possible item locations for removed palace items.\n\nAdd more starting items or more palace items.");
@@ -1906,6 +1913,13 @@ private int CountPossibleMinorItems()
19061913

19071914
count += 4 - (8 - (startingMagicContainersMax ?? 8));
19081915

1916+
var palaceLengthsMax = Palaces.VANILLA_LENGTHS[..6].Select(n => Palaces.MaxLengthRoll(n, normalPalaceLength)).ToArray();
1917+
var itemCountMaxRoll = GetPalaceItemRoomMaxCounts(palaceItemRoomCount, palaceLengthsMax);
1918+
var itemCountLimit = GetPalaceItemRoomLimits(Enumerable.Repeat(normalPalaceStyle, 6).ToArray());
1919+
var palaceItemsMaxDiff = itemCountMaxRoll.Zip(itemCountLimit, Math.Min).Sum(n => n - 1);
1920+
1921+
count += palaceItemsMaxDiff;
1922+
19091923
return count;
19101924
}
19111925

RandomizerCore/Sidescroll/Palaces.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Collections.ObjectModel;
3+
using System.Collections.Immutable;
44
using System.IO;
55
using System.Linq;
66
using System.Threading;
@@ -45,8 +45,8 @@ public class Palaces
4545
VANILLA_P7_ALLOWED_BLOCKERS
4646
];
4747

48-
public static readonly ReadOnlyCollection<int> VANILLA_LENGTHS = [14, 21, 15, 21, 28, 27, 55];
49-
public static readonly ReadOnlyCollection<int> VANILLA_MIN_PALACE_LENGTHS = [11, 16, 10, 19, 23, 20, 31];
48+
public static readonly ImmutableArray<int> VANILLA_LENGTHS = [14, 21, 15, 21, 28, 27, 55];
49+
public static readonly ImmutableArray<int> VANILLA_MIN_PALACE_LENGTHS = [11, 16, 10, 19, 23, 20, 31];
5050

5151
public static Dictionary<RoomExitType, int> itemRoomCounts = [];
5252

@@ -158,7 +158,7 @@ public async Task<List<Palace>> CreatePalaces(Random r, RandomizerProperties pro
158158
return palaces;
159159
}
160160

161-
public static int[] RollPalaceLengths(Random r, RandomizerProperties props, RandomizerConfiguration conf)
161+
public static int[] RollPalaceLengths(RandomizerConfiguration conf, RandomizerProperties props, Random r)
162162
{
163163
int[] sizes = [.. VANILLA_LENGTHS];
164164

@@ -264,6 +264,13 @@ public static int RollPalaceLength(Random random, int vanillaLength, PalaceLengt
264264
return Math.Min(Math.Max(random.Next(intMin, intMax), hardMin), hardMax);
265265
}
266266

267+
public static int MaxLengthRoll(int vanillaLength, PalaceLengthOption length)
268+
{
269+
var rr = length.GetRandomRangeDouble()!;
270+
int intMax = (int)(Math.Round(rr.High * vanillaLength) + 1);
271+
return intMax;
272+
}
273+
267274
private static bool ValidatePalaces(RandomizerProperties props, bool raftIsRequired, List<Palace> palaces)
268275
{
269276
//Enforce aggregate max length of enemy data

0 commit comments

Comments
 (0)