mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-23 14:43:21 -07:00
Formatting style
This commit is contained in:
@@ -73,7 +73,7 @@ item_table = {
|
||||
"100 Points": ItemData(16871244303, ItemClassification.progression)
|
||||
}
|
||||
|
||||
ITEM_GROUPS = {
|
||||
item_groups = {
|
||||
"Score Multiplier": {
|
||||
"Score Multiplier",
|
||||
"Step Score Multiplier",
|
||||
|
||||
@@ -15,7 +15,7 @@ class YachtDiceLocation(Location):
|
||||
self.event = not address
|
||||
|
||||
all_locations = {}
|
||||
starting_index = 16871244500 #500 more than the startin index for items
|
||||
starting_index = 16871244500 #500 more than the starting index for items
|
||||
|
||||
#Function that is called when this file is loaded, which loads in ALL possible locations, score 1 to 1000
|
||||
def all_locations_fun(max_score):
|
||||
|
||||
@@ -5,8 +5,8 @@ class gameDifficulty(Choice):
|
||||
"""
|
||||
Difficulty. This setting determines how difficult the scores are to achieve.
|
||||
Easy: for beginners. No luck required, just roll the dice and have fun. Lower final goal.
|
||||
Medium: intended difficulty. If you play smart, you'll finish the game without any trouble.
|
||||
Hard: you'll need to play smart and be lucky.
|
||||
Medium: intended difficulty. If you play smart, you will finish the game without any trouble.
|
||||
Hard: you will need to play smart and be lucky.
|
||||
Extreme: really hard mode, which requires many brain wrinkles and insane luck. NOT RECOMMENDED FOR MULTIWORLDS.
|
||||
"""
|
||||
display_name = "Game difficulty"
|
||||
@@ -58,7 +58,7 @@ class numberDiceFragmentsPerDice(Range):
|
||||
Dice can be split into fragments, gathering enough will give you an extra dice.
|
||||
You start with one dice, and there will always be one full dice in the pool.
|
||||
The other dice are split into fragments, according to this setting.
|
||||
Setting this to 1 fragment per dice just puts 'Dice' objects in the pool.
|
||||
Setting this to 1 fragment per dice just puts "Dice" objects in the pool.
|
||||
"""
|
||||
display_name = "Number of dice fragments per dice"
|
||||
range_start = 1
|
||||
@@ -70,7 +70,7 @@ class numberRollFragmentsPerRoll(Range):
|
||||
Rolls can be split into fragments, gathering enough will give you an extra roll.
|
||||
You start with one roll, and there will always be one full roll in the pool.
|
||||
The other three rolls are split into fragments, according to this setting.
|
||||
Setting this to 1 fragment per roll just puts 'Roll' objects in the pool.
|
||||
Setting this to 1 fragment per roll just puts "Roll" objects in the pool.
|
||||
"""
|
||||
display_name = "Number of roll fragments per roll"
|
||||
range_start = 1
|
||||
@@ -110,7 +110,7 @@ class chanceOfDice(Range):
|
||||
|
||||
class chanceOfRoll(Range):
|
||||
"""
|
||||
With more rolls, you'll be able to reach higher scores.
|
||||
With more rolls, you will be able to reach higher scores.
|
||||
"""
|
||||
display_name = "Weight of adding Roll"
|
||||
range_start = 0
|
||||
@@ -187,7 +187,7 @@ class addExtraPoints(Choice):
|
||||
|
||||
all_of_it: fill all locations with extra points
|
||||
sure: put some bonus points in
|
||||
never: don't put any bonus points
|
||||
never: do not put any bonus points
|
||||
"""
|
||||
display_name = "Extra bonus in the pool"
|
||||
option_all_of_it = 1
|
||||
@@ -199,11 +199,11 @@ class addStoryChapters(Choice):
|
||||
"""
|
||||
Yacht Dice typically has space for more items.
|
||||
If there is space, would you like story chapters shuffled in the item pool?
|
||||
Note: if you have extra points on "all_of_it", there won't be story chapters.
|
||||
Note: if you have extra points on "all_of_it", there will not be story chapters.
|
||||
|
||||
all_of_it: fill all locations with story chapters
|
||||
sure: if there is space left, put in 10 story chapters.
|
||||
never: don't put any story chapters, I don't like reading (but I'm glad you're reading THIS!)
|
||||
never: do not put any story chapters, I do not like reading (but I am glad you are reading THIS!)
|
||||
"""
|
||||
display_name = "Extra story chapters in the pool"
|
||||
option_all_of_it = 1
|
||||
|
||||
@@ -56,17 +56,17 @@ class Category:
|
||||
self.quantity = quantity #how many times you have the category
|
||||
|
||||
#return mean score of a category
|
||||
def meanScore(self, nbDice, nbRolls):
|
||||
if nbDice == 0 or nbRolls == 0:
|
||||
def mean_score(self, num_dice, num_rolls):
|
||||
if num_dice == 0 or num_rolls == 0:
|
||||
return 0
|
||||
meanScore = 0
|
||||
for key in yacht_weights[self.name, min(8,nbDice), min(8,nbRolls)]:
|
||||
meanScore += key*yacht_weights[self.name, min(8,nbDice), min(8,nbRolls)][key]/100000
|
||||
return meanScore * self.quantity
|
||||
mean_score = 0
|
||||
for key in yacht_weights[self.name, min(8,num_dice), min(8,num_rolls)]:
|
||||
mean_score += key*yacht_weights[self.name, min(8,num_dice), min(8,num_rolls)][key]/100000
|
||||
return mean_score * self.quantity
|
||||
|
||||
|
||||
|
||||
def extractProgression(state, player, options):
|
||||
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.
|
||||
|
||||
@@ -118,16 +118,16 @@ def extractProgression(state, player, options):
|
||||
yachtdice_cache = {}
|
||||
|
||||
#Function that returns the feasible score in logic based on items obtained.
|
||||
def diceSimulationStrings(categories, nbDice, nbRolls, fixed_mult, step_mult, diff):
|
||||
def dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult, diff):
|
||||
tup = tuple([tuple(sorted([c.name+str(c.quantity) for c in categories])),
|
||||
nbDice, nbRolls, fixed_mult, step_mult, diff]) #identifier
|
||||
num_dice, num_rolls, fixed_mult, step_mult, diff]) #identifier
|
||||
|
||||
#if already computed, return the result
|
||||
if tup in yachtdice_cache.keys():
|
||||
return yachtdice_cache[tup]
|
||||
|
||||
#sort categories because for the step multiplier, you will want low-scorig categories first
|
||||
categories.sort(key=lambda category: category.meanScore(nbDice, nbRolls))
|
||||
categories.sort(key=lambda category: category.mean_score(num_dice, num_rolls))
|
||||
|
||||
#function to add two discrete distribution.
|
||||
def add_distributions(dist1, dist2):
|
||||
@@ -137,8 +137,8 @@ def diceSimulationStrings(categories, nbDice, nbRolls, fixed_mult, step_mult, di
|
||||
combined_dist[val1 + val2] += prob1 * prob2
|
||||
return dict(combined_dist)
|
||||
|
||||
#function to take the maximum of 'times' i.i.d. dist1.
|
||||
#I've tried using defaultdict but this made it slower.
|
||||
#function to take the maximum of "times" i.i.d. dist1.
|
||||
#I have tried using defaultdict but this made it slower.
|
||||
def max_dist(dist1, mults):
|
||||
new_dist = {0: 1}
|
||||
for mult in mults:
|
||||
@@ -173,23 +173,22 @@ def diceSimulationStrings(categories, nbDice, nbRolls, fixed_mult, step_mult, di
|
||||
return prev_val if prev_val is not None else sorted_values[0]
|
||||
|
||||
|
||||
percReturn = [[0], [0.1, 0.5], [0.3, 0.7], [0.55, 0.85], [0.85, 0.95]][diff]
|
||||
diffDivide = [0, 9, 7, 3, 2][diff]
|
||||
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]
|
||||
|
||||
|
||||
#calculate total distribution
|
||||
total_dist = {0: 1}
|
||||
for j in range(len(categories)):
|
||||
if nbDice == 0 or nbRolls == 0:
|
||||
if num_dice == 0 or num_rolls == 0:
|
||||
dist = {0: 100000}
|
||||
else:
|
||||
dist = yacht_weights[categories[j].name, min(8,nbDice), min(8,nbRolls)].copy()
|
||||
dist = yacht_weights[categories[j].name, min(8,num_dice), min(8,num_rolls)].copy()
|
||||
|
||||
for key in dist.keys():
|
||||
dist[key] /= 100000
|
||||
|
||||
cat_mult = 2 ** (categories[j].quantity-1)
|
||||
max_tries = j // diffDivide
|
||||
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.
|
||||
@@ -198,13 +197,13 @@ def diceSimulationStrings(categories, nbDice, nbRolls, fixed_mult, step_mult, di
|
||||
total_dist = add_distributions(total_dist, dist)
|
||||
|
||||
#save result into the cache, then return it
|
||||
yachtdice_cache[tup] = math.floor(sum([percentile_distribution(total_dist, perc) for perc in percReturn]) / len(percReturn))
|
||||
yachtdice_cache[tup] = math.floor(sum([percentile_distribution(total_dist, perc) for perc in perc_return]) / len(perc_return))
|
||||
return yachtdice_cache[tup]
|
||||
|
||||
# Returns the feasible score that one can reach with the current state, options and difficulty.
|
||||
def diceSimulation(state, player, options):
|
||||
categories, nbDice, nbRolls, fixed_mult, step_mult, expoints = extractProgression(state, player, options)
|
||||
return diceSimulationStrings(categories, nbDice, nbRolls, fixed_mult, step_mult,
|
||||
def dice_simulation(state, player, options):
|
||||
categories, num_dice, num_rolls, fixed_mult, step_mult, expoints = extract_progression(state, player, options)
|
||||
return dice_simulation_strings(categories, num_dice, num_rolls, fixed_mult, step_mult,
|
||||
options.game_difficulty.value) + expoints
|
||||
|
||||
# Sets rules on entrances and advancements that are always applied
|
||||
@@ -214,7 +213,7 @@ def set_yacht_rules(world: MultiWorld, player: int, options):
|
||||
lambda state,
|
||||
curscore=l.yacht_dice_score,
|
||||
player=player:
|
||||
diceSimulation(state, player, options) >= curscore)
|
||||
dice_simulation(state, player, options) >= curscore)
|
||||
|
||||
# Sets rules on completion condition
|
||||
def set_yacht_completion_rules(world: MultiWorld, player: int):
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,12 +1,14 @@
|
||||
from BaseClasses import Region, Entrance, Item, Tutorial
|
||||
from .Items import YachtDiceItem, item_table, ITEM_GROUPS
|
||||
from .Locations import YachtDiceLocation, all_locations, ini_locations
|
||||
from .Options import YachtDiceOptions
|
||||
from .Rules import set_yacht_rules, set_yacht_completion_rules, diceSimulation
|
||||
from ..AutoWorld import World, WebWorld
|
||||
import math
|
||||
import logging
|
||||
|
||||
from BaseClasses import Region, Entrance, Item, Tutorial
|
||||
from .Items import YachtDiceItem, item_table, item_groups
|
||||
from .Locations import YachtDiceLocation, all_locations, ini_locations
|
||||
from .Options import YachtDiceOptions
|
||||
from .Rules import set_yacht_rules, set_yacht_completion_rules, dice_simulation
|
||||
from ..AutoWorld import World, WebWorld
|
||||
|
||||
|
||||
class YachtDiceWeb(WebWorld):
|
||||
tutorials = [Tutorial(
|
||||
"Multiworld Setup Guide",
|
||||
@@ -24,7 +26,7 @@ class YachtDiceWorld(World):
|
||||
where you cast your dice to chart a course for high scores,
|
||||
unlocking valuable treasures along the way.
|
||||
Discover more dice, extra rolls, multipliers,
|
||||
and unlockable categories to navigate the game's depths.
|
||||
and unlockable categories to navigate the depths of the game.
|
||||
Roll your way to victory by reaching the target score!
|
||||
"""
|
||||
game: str = "Yacht Dice"
|
||||
@@ -36,7 +38,7 @@ class YachtDiceWorld(World):
|
||||
|
||||
location_name_to_id = {name: data.id for name, data in all_locations.items()}
|
||||
|
||||
item_name_groups = ITEM_GROUPS
|
||||
item_name_groups = item_groups
|
||||
|
||||
ap_world_version = "2.0.2"
|
||||
|
||||
@@ -56,12 +58,12 @@ class YachtDiceWorld(World):
|
||||
#number of dice and rolls in the pull
|
||||
ind_dice_rolls = self.options.minimal_number_of_dice_and_rolls.value
|
||||
|
||||
numDice = [0, 2, 5, 5, 6, 7, 8][ind_dice_rolls]
|
||||
numRolls = [0, 2, 3, 5, 4, 3, 2][ind_dice_rolls]
|
||||
num_of_dice = [0, 2, 5, 5, 6, 7, 8][ind_dice_rolls]
|
||||
num_of_rolls = [0, 2, 3, 5, 4, 3, 2][ind_dice_rolls]
|
||||
|
||||
#amount of dice and roll fragments needed to get a dice or roll
|
||||
amDiceF = self.options.number_of_dice_fragments_per_dice.value
|
||||
amRollsF = self.options.number_of_roll_fragments_per_roll.value
|
||||
frags_per_dice = self.options.number_of_dice_fragments_per_dice.value
|
||||
frags_per_roll = self.options.number_of_roll_fragments_per_roll.value
|
||||
|
||||
#count number of plando items not from pool, we need extra locations for them
|
||||
self.extra_plando_items = 0
|
||||
@@ -117,18 +119,18 @@ class YachtDiceWorld(World):
|
||||
self.precollected += ["Dice"]
|
||||
|
||||
#if one fragment per dice, just add "Dice" objects
|
||||
if amDiceF == 1:
|
||||
self.itempool += ["Dice"] * (numDice-1) #minus one because one is in start inventory
|
||||
if frags_per_dice == 1:
|
||||
self.itempool += ["Dice"] * (num_of_dice-1) #minus one because one is in start inventory
|
||||
else:
|
||||
self.itempool += ["Dice"] #always add a full dice to make generation easier (will be 'early')
|
||||
self.itempool += ["Dice Fragment"] * (amDiceF * (numDice-2))
|
||||
self.itempool += ["Dice"] #always add a full dice to make generation easier (will be early)
|
||||
self.itempool += ["Dice Fragment"] * (frags_per_dice * (num_of_dice-2))
|
||||
|
||||
#if one fragment per roll, just add "Roll" objects
|
||||
if amRollsF == 1:
|
||||
self.itempool += ["Roll"] * (numRolls-1) #minus one because one is in start inventory
|
||||
if frags_per_roll == 1:
|
||||
self.itempool += ["Roll"] * (num_of_rolls-1) #minus one because one is in start inventory
|
||||
else:
|
||||
self.itempool += ["Roll"] #always add a full roll to make generation easier (will be 'early')
|
||||
self.itempool += ["Roll Fragment"] * (amRollsF * (numRolls-2))
|
||||
self.itempool += ["Roll"] #always add a full roll to make generation easier (will be early)
|
||||
self.itempool += ["Roll Fragment"] * (frags_per_roll * (num_of_rolls-2))
|
||||
|
||||
already_items = len(self.itempool) + self.extra_plando_items
|
||||
|
||||
@@ -138,7 +140,7 @@ class YachtDiceWorld(World):
|
||||
else:
|
||||
extraPercentage = 0.7
|
||||
|
||||
extraLocationsNeeded = max(10, math.ceil(already_items * extraPercentage))
|
||||
extra_locations_needed = max(10, math.ceil(already_items * extraPercentage))
|
||||
|
||||
self.max_score = self.options.score_for_last_check.value
|
||||
self.goal_score = min(self.max_score, self.options.score_for_goal.value)
|
||||
@@ -153,25 +155,25 @@ class YachtDiceWorld(World):
|
||||
]
|
||||
|
||||
#if the player wants extra rolls or dice, fill the pool with fragments until close to an extra roll/dice
|
||||
if weights[0] > 0 and amDiceF > 1:
|
||||
self.itempool += ["Dice Fragment"] * (amDiceF - 1)
|
||||
if weights[1] > 0 and amRollsF > 1:
|
||||
self.itempool += ["Roll Fragment"] * (amRollsF - 1)
|
||||
if weights[0] > 0 and frags_per_dice > 1:
|
||||
self.itempool += ["Dice Fragment"] * (frags_per_dice - 1)
|
||||
if weights[1] > 0 and frags_per_roll > 1:
|
||||
self.itempool += ["Roll Fragment"] * (frags_per_roll - 1)
|
||||
|
||||
#calibrate the weights, since the impact of each of the items is different
|
||||
weights[0] = weights[0] / 5 * amDiceF
|
||||
weights[1] = weights[1] / 5 * amRollsF
|
||||
weights[0] = weights[0] / 5 * frags_per_dice
|
||||
weights[1] = weights[1] / 5 * frags_per_roll
|
||||
|
||||
extraPointsAdded = 0
|
||||
|
||||
while diceSimulation(self.itempool + self.precollected, "state_is_a_list", self.options) < 1000:
|
||||
allitems = self.itempool + self.precollected
|
||||
dice_fragments_in_pool = allitems.count("Dice") * amDiceF + allitems.count("Dice Fragment")
|
||||
if dice_fragments_in_pool + 1 >= 9 * amDiceF:
|
||||
weights[0] = 0 #can't have 9 dice
|
||||
roll_fragments_in_pool = allitems.count("Roll") * amRollsF + allitems.count("Roll Fragment")
|
||||
if roll_fragments_in_pool + 1 >= 6 * amRollsF:
|
||||
weights[1] = 0 # can't have 6 rolls
|
||||
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
|
||||
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
|
||||
|
||||
if extraPointsAdded > 300:
|
||||
weights[5] = 0
|
||||
@@ -185,17 +187,17 @@ class YachtDiceWorld(World):
|
||||
which_item_to_add = self.multiworld.random.choices([0,1,2,3,4,5], weights = weights)[0]
|
||||
|
||||
if which_item_to_add == 0:
|
||||
if amDiceF == 1:
|
||||
if frags_per_dice == 1:
|
||||
self.itempool += ["Dice"]
|
||||
else:
|
||||
self.itempool += ["Dice Fragment"]
|
||||
weights[0] /= (1 + amDiceF)
|
||||
weights[0] /= (1 + frags_per_dice)
|
||||
elif which_item_to_add == 1:
|
||||
if amRollsF == 1:
|
||||
if frags_per_roll == 1:
|
||||
self.itempool += ["Roll"]
|
||||
else:
|
||||
self.itempool += ["Roll Fragment"]
|
||||
weights[1] /= (1 + amRollsF)
|
||||
weights[1] /= (1 + frags_per_roll)
|
||||
elif which_item_to_add == 2:
|
||||
self.itempool += ["Fixed Score Multiplier"]
|
||||
weights[2] /= 1.05
|
||||
@@ -240,9 +242,9 @@ class YachtDiceWorld(World):
|
||||
#and counts number of plando items *not* from pool.
|
||||
|
||||
already_items = len(self.itempool) + self.extra_plando_items + 1 #+1 because of Victory item
|
||||
self.number_of_locations = already_items + extraLocationsNeeded
|
||||
self.number_of_locations = already_items + extra_locations_needed
|
||||
|
||||
# From here, we'll 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 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.
|
||||
@@ -282,7 +284,7 @@ class YachtDiceWorld(World):
|
||||
self.itempool += ["Fun Fact"] * min(self.number_of_locations - already_items, 5)
|
||||
|
||||
#finally, add some "Good RNG" and "Bad RNG" items to complete the item pool
|
||||
#these items are filler and don't do anything.
|
||||
#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.options.game_difficulty.value
|
||||
@@ -294,7 +296,7 @@ class YachtDiceWorld(World):
|
||||
k=self.number_of_locations - already_items
|
||||
)
|
||||
|
||||
#we're done adding items. Now because of the last step, number of items should be number of locations
|
||||
#we are done adding items. Now because of the last step, number of items should be number of locations
|
||||
already_items = len(self.itempool) + self.extra_plando_items + 1
|
||||
if already_items != self.number_of_locations:
|
||||
raise Exception(f"[Yacht Dice] Number in self.itempool is not number of locations "
|
||||
@@ -345,13 +347,13 @@ class YachtDiceWorld(World):
|
||||
set_yacht_rules(self.multiworld, self.player, self.options)
|
||||
set_yacht_completion_rules(self.multiworld, self.player)
|
||||
|
||||
maxScoreWithItems = diceSimulation(self.multiworld.get_all_state(False), self.player, self.options)
|
||||
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'll have 2 dice and 2 rolls soon
|
||||
#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
|
||||
self.multiworld.early_items[self.player]["Roll"] = 1
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Open the Yacht Dice website. There are two options:
|
||||
- Download the latest release from [Yacht Dice Releases](https://github.com/spinerak/ArchipelagoYachtDice/releases) and unzip the Website.zip. Then open player.html in your browser.
|
||||
- Cruise over to the [Yacht Dice website](https://yacht-dice-ap.netlify.app/). This also works on mobile. If the website is not available, use the first option.
|
||||
|
||||
The website has an offline play option to try out the game without having to generate a game first.
|
||||
Both options have an "offline" play option to try out the game without having to generate a game first.
|
||||
|
||||
## Play with Archipelago
|
||||
|
||||
|
||||
Reference in New Issue
Block a user