This commit is contained in:
spinerak
2024-06-14 22:12:53 +02:00
parent 6342335cb6
commit 0c020d9609
5 changed files with 4601 additions and 53 deletions

View File

@@ -110,9 +110,9 @@ item_groups = {
"Category 4&5 Full House",
},
"Points": {
"100 Points",
"10 Points",
"1 Point",
"100 Points",
"10 Points",
"1 Point",
"Bonus Point"
}
}

View File

@@ -315,7 +315,7 @@ yd_option_groups = [
ChanceOfDoubleCategory,
ChanceOfPoints,
PointsSize,
],
]
),
OptionGroup(
"Other items",

View File

@@ -69,8 +69,6 @@ class Category:
return mean_score * self.quantity
class ListState:
def __init__(self, state: List[str]):
self.state = state
@@ -89,29 +87,29 @@ def extract_progression(state, player, frags_per_dice, frags_per_roll):
if isinstance(state, list):
state = ListState(state=state)
number_of_dice = (
state.count("Dice", player)
+ state.count("Dice Fragment", player) // frags_per_dice
)
number_of_rerolls = (
state.count("Roll", player)
+ state.count("Roll Fragment", player) // frags_per_roll
)
number_of_dice = state.count("Dice", player) + state.count("Dice Fragment", player) // frags_per_dice
number_of_rerolls = state.count("Roll", player) + state.count("Roll Fragment", player) // frags_per_roll
number_of_fixed_mults = state.count("Fixed Score Multiplier", player)
number_of_step_mults = state.count("Step Score Multiplier", player)
categories = [
Category(category_value, state.count(category_name, player))
for category_name, category_value in category_mappings.items()
if state.count(category_name, player) # want all categories that have count >= 1
]
]
extra_points_in_logic = state.count("1 Point", player)
extra_points_in_logic += state.count("10 Points", player) * 10
extra_points_in_logic += state.count("100 Points", player) * 100
return categories, number_of_dice, number_of_rerolls, number_of_fixed_mults * 0.1, number_of_step_mults * 0.01, extra_points_in_logic,
return (
categories,
number_of_dice,
number_of_rerolls,
number_of_fixed_mults * 0.1,
number_of_step_mults * 0.01,
extra_points_in_logic,
)
# We will store the results of this function as it is called often for the same parameters.
@@ -211,7 +209,7 @@ def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mu
# save result into the cache, then return it
outcome = sum([percentile_distribution(total_dist, perc) for perc in perc_return]) / len(perc_return)
yachtdice_cache[tup] = max(5, math.floor(outcome)) # at least 5.
return yachtdice_cache[tup]
@@ -220,13 +218,11 @@ def dice_simulation_fill_pool(state, frags_per_dice, frags_per_roll, difficulty)
Returns the feasible score that one can reach with the current state, options and difficulty.
This function is called with state being a list, during filling of item pool.
"""
categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression(state, "state_is_a_list", frags_per_dice, frags_per_roll)
return (
dice_simulation_strings(
categories, num_dice, num_rolls, fixed_mult, step_mult, difficulty
)
+ expoints
categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression(
state, "state_is_a_list", frags_per_dice, frags_per_roll
)
return dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult, difficulty) + expoints
def dice_simulation_state_change(state, player, frags_per_dice, frags_per_roll, difficulty):
"""
@@ -236,18 +232,16 @@ def dice_simulation_state_change(state, player, frags_per_dice, frags_per_roll,
if state.prog_items[player]["state_is_fresh"] == 0:
state.prog_items[player]["state_is_fresh"] = 1
categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression(state, player, frags_per_dice, frags_per_roll)
categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression(
state, player, frags_per_dice, frags_per_roll
)
state.prog_items[player]["maximum_achievable_score"] = (
dice_simulation_strings(
categories, num_dice, num_rolls, fixed_mult, step_mult, difficulty
)
+ expoints
dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult, difficulty) + expoints
)
return state.prog_items[player]["maximum_achievable_score"]
def set_yacht_rules(world: MultiWorld, player: int, frags_per_dice, frags_per_roll, difficulty):
"""
Sets rules on entrances and advancements that are always applied
@@ -256,7 +250,9 @@ def set_yacht_rules(world: MultiWorld, player: int, frags_per_dice, frags_per_ro
for location in world.get_locations(player):
set_rule(
location,
lambda state, curscore=location.yacht_dice_score, player=player: dice_simulation_state_change(state, player, frags_per_dice, frags_per_roll, difficulty)
lambda state, curscore=location.yacht_dice_score, player=player: dice_simulation_state_change(
state, player, frags_per_dice, frags_per_roll, difficulty
)
>= curscore,
)
@@ -266,4 +262,3 @@ def set_yacht_completion_rules(world: MultiWorld, player: int):
Sets rules on completion condition
"""
world.completion_condition[player] = lambda state: state.has("Victory", player)

File diff suppressed because one or more lines are too long

View File

@@ -6,7 +6,18 @@ from worlds.AutoWorld import WebWorld, World
from .Items import YachtDiceItem, item_groups, item_table
from .Locations import YachtDiceLocation, all_locations, ini_locations
from .Options import YachtDiceOptions, yd_option_groups, GameDifficulty,MinimalNumberOfDiceAndRolls,PointsSize,MinimizeExtraItems,AddExtraPoints,AddStoryChapters,WhichStory,AllowManual
from .Options import (
YachtDiceOptions,
yd_option_groups,
GameDifficulty,
MinimalNumberOfDiceAndRolls,
PointsSize,
MinimizeExtraItems,
AddExtraPoints,
AddStoryChapters,
WhichStory,
AllowManual,
)
from .Rules import dice_simulation_fill_pool, set_yacht_completion_rules, set_yacht_rules
@@ -66,7 +77,7 @@ class YachtDiceWorld(World):
# number of dice and rolls in the pull
opt_dice_and_rolls = self.options.minimal_number_of_dice_and_rolls
if opt_dice_and_rolls == MinimalNumberOfDiceAndRolls.option_5_dice_and_3_rolls:
num_of_dice = 5
num_of_rolls = 3
@@ -84,12 +95,11 @@ class YachtDiceWorld(World):
num_of_rolls = 2
else:
raise Exception(f"[Yacht Dice] Unknown MinimalNumberOfDiceAndRolls options {opt_dice_and_rolls}")
# amount of dice and roll fragments needed to get a dice or roll
self.frags_per_dice = self.options.number_of_dice_fragments_per_dice.value
self.frags_per_roll = self.options.number_of_roll_fragments_per_roll.value
# set difficulty
diff_value = self.options.game_difficulty
if diff_value == GameDifficulty.option_easy:
@@ -187,7 +197,7 @@ class YachtDiceWorld(World):
"Fixed Score Multiplier": self.options.weight_of_fixed_score_multiplier.value,
"Step Score Multiplier": self.options.weight_of_step_score_multiplier.value,
"Double category": self.options.weight_of_double_category.value,
"Points": self.options.weight_of_points.value,
"Points": self.options.weight_of_points.value,
}
# if the player wants extra rolls or dice, fill the pool with fragments until close to an extra roll/dice
@@ -235,7 +245,6 @@ class YachtDiceWorld(World):
# Next, add the appropriate item. We'll slightly alter weights to avoid too many of the same item
which_item_to_add = self.random.choices(list(weights.keys()), weights=list(weights.values()))[0]
if which_item_to_add == "Dice":
weights["Dice"] /= 1 + self.frags_per_dice
return "Dice" if self.frags_per_dice == 1 else "Dice Fragment"
@@ -259,15 +268,15 @@ class YachtDiceWorld(World):
return self.random.choices(possible_categories, weights=cat_weights)[0]
elif which_item_to_add == "Points":
score_dist = self.options.points_size
probs = { "1 Point": 1, "10 Points": 0, "100 Points": 0}
probs = {"1 Point": 1, "10 Points": 0, "100 Points": 0}
if score_dist == PointsSize.option_small:
probs = { "1 Point": 0.9, "10 Points": 0.1, "100 Points": 0}
probs = {"1 Point": 0.9, "10 Points": 0.1, "100 Points": 0}
elif score_dist == PointsSize.option_medium:
probs = { "1 Point": 0, "10 Points": 1, "100 Points": 0}
probs = {"1 Point": 0, "10 Points": 1, "100 Points": 0}
elif score_dist == PointsSize.option_large:
probs = { "1 Point": 0, "10 Points": 0.3, "100 Points": 0.7}
probs = {"1 Point": 0, "10 Points": 0.3, "100 Points": 0.7}
elif score_dist == PointsSize.option_mix:
probs = { "1 Point": 0.3, "10 Points": 0.4, "100 Points": 0.3}
probs = {"1 Point": 0.3, "10 Points": 0.4, "100 Points": 0.3}
else:
raise Exception(f"[Yacht Dice] Unknown PointsSize options {score_dist}")
choice = self.random.choices(list(probs.keys()), weights=list(probs.values()))[0]
@@ -292,14 +301,18 @@ class YachtDiceWorld(World):
for _ in range(17):
self.itempool.append(get_item_to_add(weights, extra_points_added, multipliers_added, items_added))
score_in_logic = dice_simulation_fill_pool(self.itempool + self.precollected, self.frags_per_dice, self.frags_per_roll, self.difficulty)
score_in_logic = dice_simulation_fill_pool(
self.itempool + self.precollected, self.frags_per_dice, self.frags_per_roll, self.difficulty
)
# if we overshoot, remove items until you get below 1000, then return the last removed item
if score_in_logic > 1000:
removed_item = ""
while score_in_logic > 1000:
removed_item = self.itempool.pop()
score_in_logic = dice_simulation_fill_pool(self.itempool + self.precollected, self.frags_per_dice, self.frags_per_roll, self.difficulty)
score_in_logic = dice_simulation_fill_pool(
self.itempool + self.precollected, self.frags_per_dice, self.frags_per_roll, self.difficulty
)
self.itempool.append(removed_item)
else:
# Keep adding items until a score of 1000 is in logic
@@ -313,7 +326,9 @@ class YachtDiceWorld(World):
elif item_to_add == "100 Points":
score_in_logic += 100
else:
score_in_logic = dice_simulation_fill_pool(self.itempool + self.precollected, self.frags_per_dice, self.frags_per_roll, self.difficulty)
score_in_logic = dice_simulation_fill_pool(
self.itempool + self.precollected, self.frags_per_dice, self.frags_per_roll, self.difficulty
)
# count the number of locations in the game.
already_items = len(self.itempool) + 1 # +1 because of Victory item
@@ -365,7 +380,7 @@ class YachtDiceWorld(World):
# these items are filler and do not do anything.
# probability of Good and Bad rng, based on difficulty for fun :)
p = 1.1 - 0.25 * self.difficulty
already_items = len(self.itempool) + 1
self.itempool += self.random.choices(
@@ -393,9 +408,7 @@ class YachtDiceWorld(World):
def create_regions(self):
# call the ini_locations function, that generates locations based on the inputs.
location_table = ini_locations(
self.goal_score, self.max_score, self.number_of_locations, self.difficulty
)
location_table = ini_locations(self.goal_score, self.max_score, self.number_of_locations, self.difficulty)
# simple menu-board construction
menu = Region("Menu", self.player, self.multiworld)