mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-23 23:23:21 -07:00
Comments and editing
This commit is contained in:
@@ -11,6 +11,7 @@ class YachtDiceItem(Item):
|
||||
#the starting index is chosen semi-randomly to be 16871244000
|
||||
|
||||
item_table = {
|
||||
#victory item, always placed manually at goal location
|
||||
"Victory": ItemData(16871244000-1, ItemClassification.progression),
|
||||
|
||||
"Dice": ItemData(16871244000, ItemClassification.progression),
|
||||
@@ -18,7 +19,7 @@ item_table = {
|
||||
"Roll": ItemData(16871244002, ItemClassification.progression),
|
||||
"Roll Fragment": ItemData(16871244003, ItemClassification.progression),
|
||||
|
||||
"Score Multiplier": ItemData(16871244004, ItemClassification.progression),
|
||||
#"Score Multiplier": ItemData(16871244004, ItemClassification.progression), #not used anymore
|
||||
"Fixed Score Multiplier": ItemData(16871244005, ItemClassification.progression),
|
||||
"Step Score Multiplier": ItemData(16871244006, ItemClassification.progression),
|
||||
|
||||
@@ -28,10 +29,8 @@ item_table = {
|
||||
"Category Fours": ItemData(16871244106, ItemClassification.progression),
|
||||
"Category Fives": ItemData(16871244107, ItemClassification.progression),
|
||||
"Category Sixes": ItemData(16871244108, ItemClassification.progression),
|
||||
|
||||
"Category Choice": ItemData(16871244109, ItemClassification.progression),
|
||||
"Category Inverse Choice": ItemData(16871244110, ItemClassification.progression),
|
||||
|
||||
"Category Pair": ItemData(16871244111, ItemClassification.progression),
|
||||
"Category Three of a Kind": ItemData(16871244112, ItemClassification.progression),
|
||||
"Category Four of a Kind": ItemData(16871244113, ItemClassification.progression),
|
||||
@@ -47,10 +46,8 @@ item_table = {
|
||||
"Category Twos and Threes": ItemData(16871244126, ItemClassification.progression),
|
||||
"Category Sum of Odds": ItemData(16871244127, ItemClassification.progression),
|
||||
"Category Sum of Evens": ItemData(16871244128, ItemClassification.progression),
|
||||
|
||||
"Category Double Threes and Fours": ItemData(16871244129, ItemClassification.progression),
|
||||
"Category Quadruple Ones and Twos": ItemData(16871244130, ItemClassification.progression),
|
||||
|
||||
"Category Micro Straight": ItemData(16871244131, ItemClassification.progression),
|
||||
"Category Three Odds": ItemData(16871244132, ItemClassification.progression),
|
||||
"Category 1-2-1 Consecutive": ItemData(16871244133, ItemClassification.progression),
|
||||
@@ -60,7 +57,7 @@ item_table = {
|
||||
"Category Five Distinct Dice": ItemData(16871244137, ItemClassification.progression),
|
||||
"Category 4&5 Full House": ItemData(16871244138, ItemClassification.progression),
|
||||
|
||||
|
||||
#filler items
|
||||
"Encouragement": ItemData(16871244200, ItemClassification.filler),
|
||||
"Fun Fact": ItemData(16871244201, ItemClassification.filler),
|
||||
"Story Chapter": ItemData(16871244202, ItemClassification.filler),
|
||||
@@ -68,14 +65,15 @@ item_table = {
|
||||
"Bad RNG": ItemData(16871244204, ItemClassification.trap),
|
||||
"Bonus Point": ItemData(16871244205, ItemClassification.useful), #not included in logic
|
||||
|
||||
#These points are included in the logic and might be necessary to progress.
|
||||
"1 Point": ItemData(16871244301, ItemClassification.progression_skip_balancing),
|
||||
"10 Points": ItemData(16871244302, ItemClassification.progression),
|
||||
"100 Points": ItemData(16871244303, ItemClassification.progression)
|
||||
}
|
||||
|
||||
#item groups for better hinting
|
||||
item_groups = {
|
||||
"Score Multiplier": {
|
||||
"Score Multiplier",
|
||||
"Step Score Multiplier",
|
||||
"Fixed Score Multiplier"
|
||||
},
|
||||
@@ -86,10 +84,8 @@ item_groups = {
|
||||
"Category Fours",
|
||||
"Category Fives",
|
||||
"Category Sixes",
|
||||
|
||||
"Category Choice",
|
||||
"Category Inverse Choice",
|
||||
|
||||
"Category Pair",
|
||||
"Category Three of a Kind",
|
||||
"Category Four of a Kind",
|
||||
@@ -98,17 +94,14 @@ item_groups = {
|
||||
"Category Large Straight",
|
||||
"Category Full House",
|
||||
"Category Yacht",
|
||||
|
||||
"Category Distincts",
|
||||
"Category Two times Ones",
|
||||
"Category Half of Sixes",
|
||||
"Category Twos and Threes",
|
||||
"Category Sum of Odds",
|
||||
"Category Sum of Evens",
|
||||
|
||||
"Category Double Threes and Fours",
|
||||
"Category Quadruple Ones and Twos",
|
||||
|
||||
"Category Micro Straight",
|
||||
"Category Three Odds",
|
||||
"Category 1-2-1 Consecutive",
|
||||
|
||||
@@ -32,7 +32,7 @@ def ini_locations(goal_score, max_score, num_locs, dif):
|
||||
if dif == 1:
|
||||
scaling = 3
|
||||
elif dif == 2:
|
||||
scaling = 2.2
|
||||
scaling = 2.3
|
||||
|
||||
scores = []
|
||||
#the scores follow the function int( 1 + (perc ** scaling) * (max_score-1) )
|
||||
@@ -64,5 +64,4 @@ def ini_locations(goal_score, max_score, num_locs, dif):
|
||||
lookup_id_to_name: typing.Dict[int, str] = {data.id: item_name for item_name, data in all_locations.items() if data.id}
|
||||
|
||||
# we need to run this function to initialize all scores from 1 to 1000, even though not all are used
|
||||
# this in order to make sure no other worlds use any ids that are similar to Yacht Dice
|
||||
all_locations = all_locations_fun(1000)
|
||||
|
||||
@@ -4,6 +4,7 @@ from .YachtWeights import yacht_weights
|
||||
import math
|
||||
from collections import defaultdict
|
||||
|
||||
#List of categories, and the name of the logic class associated with it
|
||||
category_mappings = {
|
||||
"Category Ones": "Ones",
|
||||
"Category Twos": "Twos",
|
||||
@@ -49,7 +50,6 @@ category_mappings = {
|
||||
#The score is logic is *much* lower than the actual maximum reachable score.
|
||||
|
||||
|
||||
|
||||
class Category:
|
||||
def __init__(self, name, quantity = 1):
|
||||
self.name = name
|
||||
@@ -65,12 +65,11 @@ class Category:
|
||||
return mean_score * self.quantity
|
||||
|
||||
|
||||
|
||||
def extract_progression(state, player, options):
|
||||
#method to obtain a list of what items the player has.
|
||||
#this includes categories, dice, rolls and score multiplier.
|
||||
#this includes categories, dice, rolls and score multiplier etc.
|
||||
|
||||
if player == "state_is_a_list":
|
||||
if player == "state_is_a_list": #the state variable is just a list with the names of the items
|
||||
number_of_dice = (
|
||||
state.count("Dice")
|
||||
+ state.count("Dice Fragment") // options.number_of_dice_fragments_per_dice.value
|
||||
@@ -90,7 +89,7 @@ def extract_progression(state, player, options):
|
||||
extra_points_in_logic = state.count("1 Point")
|
||||
extra_points_in_logic += state.count("10 Points") * 10
|
||||
extra_points_in_logic += state.count("100 Points") * 100
|
||||
else:
|
||||
else: #state is an Archipelago object, so we need state.count(..., player)
|
||||
number_of_dice = (
|
||||
state.count("Dice", player)
|
||||
+ state.count("Dice Fragment", player) // options.number_of_dice_fragments_per_dice.value
|
||||
@@ -126,10 +125,11 @@ def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mu
|
||||
if tup in yachtdice_cache.keys():
|
||||
return yachtdice_cache[tup]
|
||||
|
||||
#sort categories because for the step multiplier, you will want low-scorig categories first
|
||||
#sort categories because for the step multiplier, you will want low-scoring categories first
|
||||
categories.sort(key=lambda category: category.mean_score(num_dice, num_rolls))
|
||||
|
||||
#function to add two discrete distribution.
|
||||
#defaultdict is a dict where you don't need to check if a id is present, you can just use += (lot faster)
|
||||
def add_distributions(dist1, dist2):
|
||||
combined_dist = defaultdict(float)
|
||||
for val1, prob1 in dist1.items():
|
||||
@@ -138,7 +138,7 @@ def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mu
|
||||
return dict(combined_dist)
|
||||
|
||||
#function to take the maximum of "times" i.i.d. dist1.
|
||||
#I have tried using defaultdict but this made it slower.
|
||||
#(I have tried using defaultdict here too but this made it slower.)
|
||||
def max_dist(dist1, mults):
|
||||
new_dist = {0: 1}
|
||||
for mult in mults:
|
||||
@@ -172,7 +172,9 @@ def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mu
|
||||
# Return the first value if percentile is lower than all probabilities
|
||||
return prev_val if prev_val is not None else sorted_values[0]
|
||||
|
||||
|
||||
#parameters for logic.
|
||||
#perc_return is, per difficulty, the percentages of total score it returns (it averages out the values)
|
||||
#diff_divide determines how many shots the logic gets per category. Lower = more shots.
|
||||
perc_return = [[0], [0.1, 0.5], [0.3, 0.7], [0.55, 0.85], [0.85, 0.95]][diff]
|
||||
diff_divide = [0, 9, 7, 3, 2][diff]
|
||||
|
||||
@@ -188,10 +190,10 @@ def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mu
|
||||
dist[key] /= 100000
|
||||
|
||||
cat_mult = 2 ** (categories[j].quantity-1)
|
||||
max_tries = j // diff_divide
|
||||
mults = [(1 + fixed_mult + step_mult * ii) * cat_mult for ii in range(max(0,j - max_tries), j+1)]
|
||||
|
||||
|
||||
#for higher difficulties, the simulation gets multiple tries for categories.
|
||||
max_tries = j // diff_divide
|
||||
mults = [(1 + fixed_mult + step_mult * ii) * cat_mult for ii in range(max(0,j - max_tries), j+1)]
|
||||
dist = max_dist(dist, mults)
|
||||
|
||||
total_dist = add_distributions(total_dist, dist)
|
||||
|
||||
@@ -40,7 +40,7 @@ class YachtDiceWorld(World):
|
||||
|
||||
item_name_groups = item_groups
|
||||
|
||||
ap_world_version = "2.0.3"
|
||||
ap_world_version = "2.0.4"
|
||||
|
||||
def _get_yachtdice_data(self):
|
||||
return {
|
||||
@@ -51,7 +51,8 @@ class YachtDiceWorld(World):
|
||||
"race": self.multiworld.is_race,
|
||||
}
|
||||
|
||||
def generate_early(self):
|
||||
#In generate early, we fill the item-pool, then determine the number of locations, and add filler items.
|
||||
def generate_early(self):
|
||||
self.itempool = []
|
||||
self.precollected = []
|
||||
|
||||
@@ -72,8 +73,6 @@ class YachtDiceWorld(World):
|
||||
if plando_setting.get("from_pool", False) is False:
|
||||
self.extra_plando_items += sum(value for value in plando_setting["items"].values())
|
||||
|
||||
|
||||
|
||||
# Create a list with the specified number of 1s
|
||||
num_ones = self.options.alternative_categories.value
|
||||
categorylist = [1] * num_ones + [0] * (16 - num_ones)
|
||||
@@ -81,8 +80,9 @@ class YachtDiceWorld(World):
|
||||
# Shuffle the list to randomize the order
|
||||
self.multiworld.random.shuffle(categorylist)
|
||||
|
||||
|
||||
#A list of all possible categories.
|
||||
#Every entry in the list has two categories, one 'default' category and one 'alt'.
|
||||
#You get either of the two for every entry, so a total of 16 unique categories.
|
||||
all_categories = [
|
||||
["Category Choice", "Category Double Threes and Fours"],
|
||||
["Category Inverse Choice", "Category Quadruple Ones and Twos"],
|
||||
@@ -135,16 +135,20 @@ class YachtDiceWorld(World):
|
||||
already_items = len(self.itempool) + self.extra_plando_items
|
||||
|
||||
#Yacht Dice needs extra filler items so it doesn't get stuck in generation.
|
||||
#For now, we calculate the number of extra items we'll need later.
|
||||
if self.options.minimize_extra_items.value:
|
||||
extraPercentage = max(0.1, 0.8 - self.multiworld.players / 10)
|
||||
else:
|
||||
extraPercentage = 0.7
|
||||
|
||||
extra_locations_needed = max(10, math.ceil(already_items * extraPercentage))
|
||||
|
||||
#max score is the value of the last check. Goal score is the score needed to 'finish' the game
|
||||
self.max_score = self.options.score_for_last_check.value
|
||||
self.goal_score = min(self.max_score, self.options.score_for_goal.value)
|
||||
|
||||
#Yacht Dice adds items into the pool until a score of at least 1000 is reached.
|
||||
#the yaml contains weights, which determine how likely it is that specific items get added.
|
||||
#If all weights are 0, some of them will be made to be non-zero later.
|
||||
weights = [
|
||||
self.options.weight_of_dice.value,
|
||||
self.options.weight_of_roll.value,
|
||||
@@ -167,19 +171,22 @@ class YachtDiceWorld(World):
|
||||
extra_points_added = 0
|
||||
multipliers_added = 0
|
||||
|
||||
#Keep adding items until a score of 1000 is in logic
|
||||
while dice_simulation(self.itempool + self.precollected, "state_is_a_list", self.options) < 1000:
|
||||
all_items = self.itempool + self.precollected
|
||||
dice_fragments_in_pool = all_items.count("Dice") * frags_per_dice + all_items.count("Dice Fragment")
|
||||
if dice_fragments_in_pool + 1 >= 9 * frags_per_dice:
|
||||
weights[0] = 0 #cannot have 9 dice
|
||||
weights[0] = 0 #don't allow >=9 dice
|
||||
roll_fragments_in_pool = all_items.count("Roll") * frags_per_roll + all_items.count("Roll Fragment")
|
||||
if roll_fragments_in_pool + 1 >= 6 * frags_per_roll:
|
||||
weights[1] = 0 # cannot have 6 rolls
|
||||
weights[1] = 0 # don't allow >= 6 rolls
|
||||
|
||||
#Don't allow too many multipliers
|
||||
if multipliers_added > 50:
|
||||
weights[2] = 0
|
||||
weights[3] = 0
|
||||
|
||||
#Don't allow too many extra points
|
||||
if extra_points_added > 300:
|
||||
weights[5] = 0
|
||||
|
||||
@@ -191,8 +198,8 @@ class YachtDiceWorld(World):
|
||||
if extra_points_added <= 300:
|
||||
weights[5] = 1
|
||||
|
||||
#Next, add the appropriate item. We'll slightly alter weights to avoid too many of the same item
|
||||
which_item_to_add = self.multiworld.random.choices([0,1,2,3,4,5], weights = weights)[0]
|
||||
|
||||
if which_item_to_add == 0:
|
||||
if frags_per_dice == 1:
|
||||
self.itempool += ["Dice"]
|
||||
@@ -214,7 +221,6 @@ class YachtDiceWorld(World):
|
||||
weights[3] /= 1.1
|
||||
multipliers_added += 1
|
||||
elif which_item_to_add == 4:
|
||||
#increase chances of "free-score categories"
|
||||
cat_weights = [2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
self.itempool += self.multiworld.random.choices(possible_categories, weights = cat_weights)
|
||||
weights[4] /= 1.1
|
||||
@@ -247,15 +253,14 @@ class YachtDiceWorld(World):
|
||||
else:
|
||||
raise Exception("Invalid index when adding new items in Yacht Dice")
|
||||
|
||||
#count the number of locations in the game. extra_plando_items is set in generate_early
|
||||
#and counts number of plando items *not* from pool.
|
||||
|
||||
#count the number of locations in the game.
|
||||
already_items = len(self.itempool) + self.extra_plando_items + 1 #+1 because of Victory item
|
||||
|
||||
extra_locations_needed += (already_items - 70) // 20
|
||||
#We need to add more filler/useful items if there are many items in the pool to guarantee succesful generation
|
||||
extra_locations_needed += (already_items - 45) // 15
|
||||
self.number_of_locations = already_items + extra_locations_needed
|
||||
|
||||
# From here, we will count the number of items in the self.itempool, and add items to the pool,
|
||||
# From here, we will count the number of items in the self.itempool, and add usuful/filler items to the pool,
|
||||
# making sure not to exceed the number of locations.
|
||||
|
||||
#first, we flood the entire pool with extra points (useful), if that setting is chosen.
|
||||
@@ -281,7 +286,7 @@ class YachtDiceWorld(World):
|
||||
if(self.number_of_locations - already_items >= 10):
|
||||
self.itempool += ["Story Chapter"] * 10
|
||||
|
||||
#add some extra points if there is still room
|
||||
#add some more extra points if there is still room
|
||||
if self.options.add_bonus_points.value == 2:
|
||||
already_items = len(self.itempool) + self.extra_plando_items + 1
|
||||
self.itempool += ["Bonus Point"] * min(self.number_of_locations - already_items, 10)
|
||||
@@ -299,7 +304,6 @@ class YachtDiceWorld(World):
|
||||
|
||||
#probability of Good and Bad rng, based on difficulty for fun :)
|
||||
p = 1.1 - 0.25 * self.options.game_difficulty.value
|
||||
|
||||
already_items = len(self.itempool) + self.extra_plando_items + 1
|
||||
self.itempool += self.multiworld.random.choices(
|
||||
["Good RNG", "Bad RNG"],
|
||||
@@ -313,15 +317,16 @@ class YachtDiceWorld(World):
|
||||
raise Exception(f"[Yacht Dice] Number in self.itempool is not number of locations "
|
||||
f"{already_items} {self.number_of_locations}.")
|
||||
|
||||
#add precollected items using push_precollected. Items in self.itempool get created in create_items
|
||||
for item in self.precollected:
|
||||
self.multiworld.push_precollected(self.create_item(item))
|
||||
|
||||
def create_items(self):
|
||||
#convert strings to actual items
|
||||
itempoolO = [item for item in map(lambda name: self.create_item(name), self.itempool)]
|
||||
itempool_created = [item for item in map(lambda name: self.create_item(name), self.itempool)]
|
||||
|
||||
#and add them to the itempool
|
||||
for item in itempoolO:
|
||||
for item in itempool_created:
|
||||
self.multiworld.itempool += [item]
|
||||
|
||||
def create_regions(self):
|
||||
@@ -358,11 +363,6 @@ class YachtDiceWorld(World):
|
||||
set_yacht_rules(self.multiworld, self.player, self.options)
|
||||
set_yacht_completion_rules(self.multiworld, self.player)
|
||||
|
||||
maxScoreWithItems = dice_simulation(self.multiworld.get_all_state(False), self.player, self.options)
|
||||
|
||||
if self.goal_score > maxScoreWithItems:
|
||||
raise Exception("In Yacht Dice, with all items in the pool, it is impossible to get to the goal.")
|
||||
|
||||
def pre_fill(self):
|
||||
#in the pre_fill, make sure one dice and one roll is early, so that you will have 2 dice and 2 rolls soon
|
||||
self.multiworld.early_items[self.player]["Dice"] = 1
|
||||
@@ -370,9 +370,7 @@ class YachtDiceWorld(World):
|
||||
|
||||
def fill_slot_data(self):
|
||||
#make slot data, which consists of yachtdice_data, options, and some other variables.
|
||||
|
||||
yacht_dice_data = self._get_yachtdice_data()
|
||||
|
||||
yacht_dice_options = self.options.as_dict(
|
||||
"game_difficulty",
|
||||
"score_for_last_check",
|
||||
@@ -394,9 +392,7 @@ class YachtDiceWorld(World):
|
||||
"which_story",
|
||||
"allow_manual_input"
|
||||
)
|
||||
|
||||
slot_data = {**yacht_dice_data, **yacht_dice_options} #combine the two
|
||||
|
||||
slot_data = {**yacht_dice_data, **yacht_dice_options} #combine the two
|
||||
slot_data["goal_score"] = self.goal_score
|
||||
slot_data["last_check_score"] = self.max_score
|
||||
slot_data["ap_world_version"] = self.ap_world_version
|
||||
|
||||
Reference in New Issue
Block a user