 8ddb49f071
			
		
	
	8ddb49f071
	
	
	
		
			
			* MMBN3: Press program now has proper color index when received remotely * Initial commit of OSRS untangled from MMBN3 branch * Fixes some broken region connections * Removes some locations * Rearranges locations to fill in slots left by removed locations * Adds starting area rando * Moves Oak and Willow trees to resource regions * Fixes various PEP8 violations * Refactor of regions * Fixes variable capture issue with region rules * Partial completion of brutal grind logic * Finishes can_reach_skill function * Adds skill requirements to location rules, fixes regions rules * Adds documentation for OSRS * Removes match statement * Updates Data Version to test mode to prevent item name caching * Fixes starting spawn logic for east varrock * Fixes river lum crossing logic to not assume you can phase across water * Prevents equipping items when you haven't unlocked them * Changes canoe logic to not require huge levels * Skeletoning out some data I'll need for variable task system * Adds csvs and parser for logic * Adds Items parsing * Fixes the spawning logic to not default to Chunksanity when you didn't pick it * Begins adding generation rules for data-driven logic * Moves region handling and location creating to different methods * Adds logic limits to Options * Begun the location generation has * Randomly generates tasks for each skill until populated * Mopping up improper names, adding custom logic, and fixes location rolling * Drastically cleans up the location rolling loop * Modifies generation to properly use local variables and pass unit tests * Game is now generating, but rules don't seem to work * Lambda capture, my old nemesis. We meet again * Fixes issue with Corsair Cove item requirement causing logic loop * Okay one more fix, another variable capture * On second thought lets not have skull sceptre tasks. 'Tis a silly place * Removes QP from item pool (they're events not items) * Removes Stronghold floor tasks, no varbit to track them * Loads CSV with pkutil so it can be used in apworld * Fixes logic of skill tasks and adds QP requirements to long grinds * Fixes pathing in pkgutil call * Better handling for empty task categories, no longer throws errors * Fixes order for progressive tasks, removes un-checkable spider task * Fixes logic issues related to stew and the Blurite caves * Fixes issues generating causing tests to sporadically fail * Adds missing task that caused off-by-one error * Updates to new Options API * Updates generation to function properly with the Universal Tracker (Thanks Faris) * Replaces runtime CSV parsing with pre-made python files generated from CSVs * Switches to self.random and uses random.choice instead of doing it manually * Fixes to typing, variable names, iterators, and continue conditions * Replaces Name classes with Enums * Fixes parse error on region special rules * Skill requirements check now returns an accessrule instead of being one that checks options * Updates documentation and setup guide * Adjusts maximum numbers for combat and general tasks * Fixes region names so dictionary lookup works for chunksanity * Update worlds/osrs/docs/en_Old School Runescape.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Update worlds/osrs/docs/en_Old School Runescape.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Updates readme.md and codeowners doc * Removes erroneous East Varrock -> Al Kharid connection * Changes to canoe logic to account for woodcutting level options * Fixes embarassing typo on 'Edgeville' * Moves Logic CSVs to separate repository, addresses suggested changes on PR * Fixes logic error in east/west lumbridge regions. Fixes incorrect List typing in main * Removes task types with weight 0 from the list of rollable tasks * Missed another place that the task type had to be removed if 0 weight * Prevents adding an empty task weight if levels are too restrictive for tasks to be added * Removes giant blank space in error message * Adds player name to error for not having enough available tasks --------- Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com>
		
			
				
	
	
		
			475 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			475 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from dataclasses import dataclass
 | |
| 
 | |
| from Options import Choice, Toggle, Range, PerGameCommonOptions
 | |
| 
 | |
| MAX_COMBAT_TASKS = 16
 | |
| MAX_PRAYER_TASKS = 3
 | |
| MAX_MAGIC_TASKS = 4
 | |
| MAX_RUNECRAFT_TASKS = 3
 | |
| MAX_CRAFTING_TASKS = 5
 | |
| MAX_MINING_TASKS = 5
 | |
| MAX_SMITHING_TASKS = 4
 | |
| MAX_FISHING_TASKS = 5
 | |
| MAX_COOKING_TASKS = 5
 | |
| MAX_FIREMAKING_TASKS = 2
 | |
| MAX_WOODCUTTING_TASKS = 3
 | |
| 
 | |
| NON_QUEST_LOCATION_COUNT = 22
 | |
| 
 | |
| 
 | |
| class StartingArea(Choice):
 | |
|     """
 | |
|     Which chunks are available at the start. The player may need to move through locked chunks to reach the starting
 | |
|     area, but any areas that require quests, skills, or coins are not available as a starting location.
 | |
| 
 | |
|     "Any Bank" rolls a random region that contains a bank.
 | |
|     Chunksanity can start you in any chunk. Hope you like woodcutting!
 | |
|     """
 | |
|     display_name = "Starting Region"
 | |
|     option_lumbridge = 0
 | |
|     option_al_kharid = 1
 | |
|     option_varrock_east = 2
 | |
|     option_varrock_west = 3
 | |
|     option_edgeville = 4
 | |
|     option_falador = 5
 | |
|     option_draynor = 6
 | |
|     option_wilderness = 7
 | |
|     option_any_bank = 8
 | |
|     option_chunksanity = 9
 | |
|     default = 0
 | |
| 
 | |
| 
 | |
| class BrutalGrinds(Toggle):
 | |
|     """
 | |
|     Whether to allow skill tasks without having reasonable access to the usual skill training path.
 | |
|     For example, if enabled, you could be forced to train smithing without an anvil purely by smelting bars,
 | |
|     or training fishing to high levels entirely on shrimp.
 | |
|     """
 | |
|     display_name = "Allow Brutal Grinds"
 | |
| 
 | |
| 
 | |
| class ProgressiveTasks(Toggle):
 | |
|     """
 | |
|     Whether skill tasks should always be generated in order of easiest to hardest.
 | |
|     If enabled, you would not be assigned "Mine Gold" without also being assigned
 | |
|     "Mine Silver", "Mine Coal", and "Mine Iron". Enabling this will result in a generally shorter seed, but with
 | |
|     a lower variety of tasks.
 | |
|     """
 | |
|     display_name = "Progressive Tasks"
 | |
| 
 | |
| 
 | |
| class MaxCombatLevel(Range):
 | |
|     """
 | |
|     The highest combat level of monster to possibly be assigned as a task.
 | |
|     If set to 0, no combat tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 1520
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxCombatTasks(Range):
 | |
|     """
 | |
|     The maximum number of Combat Tasks to possibly be assigned.
 | |
|     If set to 0, no combat tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_COMBAT_TASKS
 | |
|     default = MAX_COMBAT_TASKS
 | |
| 
 | |
| 
 | |
| class CombatTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating combat tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxPrayerLevel(Range):
 | |
|     """
 | |
|     The highest Prayer requirement of any task generated.
 | |
|     If set to 0, no Prayer tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxPrayerTasks(Range):
 | |
|     """
 | |
|     The maximum number of Prayer Tasks to possibly be assigned.
 | |
|     If set to 0, no Prayer tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_PRAYER_TASKS
 | |
|     default = MAX_PRAYER_TASKS
 | |
| 
 | |
| 
 | |
| class PrayerTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Prayer tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxMagicLevel(Range):
 | |
|     """
 | |
|     The highest Magic requirement of any task generated.
 | |
|     If set to 0, no Magic tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxMagicTasks(Range):
 | |
|     """
 | |
|     The maximum number of Magic Tasks to possibly be assigned.
 | |
|     If set to 0, no Magic tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_MAGIC_TASKS
 | |
|     default = MAX_MAGIC_TASKS
 | |
| 
 | |
| 
 | |
| class MagicTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Magic tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxRunecraftLevel(Range):
 | |
|     """
 | |
|     The highest Runecraft requirement of any task generated.
 | |
|     If set to 0, no Runecraft tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxRunecraftTasks(Range):
 | |
|     """
 | |
|     The maximum number of Runecraft Tasks to possibly be assigned.
 | |
|     If set to 0, no Runecraft tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_RUNECRAFT_TASKS
 | |
|     default = MAX_RUNECRAFT_TASKS
 | |
| 
 | |
| 
 | |
| class RunecraftTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Runecraft tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxCraftingLevel(Range):
 | |
|     """
 | |
|     The highest Crafting requirement of any task generated.
 | |
|     If set to 0, no Crafting tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxCraftingTasks(Range):
 | |
|     """
 | |
|     The maximum number of Crafting Tasks to possibly be assigned.
 | |
|     If set to 0, no Crafting tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_CRAFTING_TASKS
 | |
|     default = MAX_CRAFTING_TASKS
 | |
| 
 | |
| 
 | |
| class CraftingTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Crafting tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxMiningLevel(Range):
 | |
|     """
 | |
|     The highest Mining requirement of any task generated.
 | |
|     If set to 0, no Mining tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxMiningTasks(Range):
 | |
|     """
 | |
|     The maximum number of Mining Tasks to possibly be assigned.
 | |
|     If set to 0, no Mining tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_MINING_TASKS
 | |
|     default = MAX_MINING_TASKS
 | |
| 
 | |
| 
 | |
| class MiningTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Mining tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxSmithingLevel(Range):
 | |
|     """
 | |
|     The highest Smithing requirement of any task generated.
 | |
|     If set to 0, no Smithing tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxSmithingTasks(Range):
 | |
|     """
 | |
|     The maximum number of Smithing Tasks to possibly be assigned.
 | |
|     If set to 0, no Smithing tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_SMITHING_TASKS
 | |
|     default = MAX_SMITHING_TASKS
 | |
| 
 | |
| 
 | |
| class SmithingTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Smithing tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxFishingLevel(Range):
 | |
|     """
 | |
|     The highest Fishing requirement of any task generated.
 | |
|     If set to 0, no Fishing tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxFishingTasks(Range):
 | |
|     """
 | |
|     The maximum number of Fishing Tasks to possibly be assigned.
 | |
|     If set to 0, no Fishing tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_FISHING_TASKS
 | |
|     default = MAX_FISHING_TASKS
 | |
| 
 | |
| 
 | |
| class FishingTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Fishing tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxCookingLevel(Range):
 | |
|     """
 | |
|     The highest Cooking requirement of any task generated.
 | |
|     If set to 0, no Cooking tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxCookingTasks(Range):
 | |
|     """
 | |
|     The maximum number of Cooking Tasks to possibly be assigned.
 | |
|     If set to 0, no Cooking tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_COOKING_TASKS
 | |
|     default = MAX_COOKING_TASKS
 | |
| 
 | |
| 
 | |
| class CookingTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Cooking tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxFiremakingLevel(Range):
 | |
|     """
 | |
|     The highest Firemaking requirement of any task generated.
 | |
|     If set to 0, no Firemaking tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxFiremakingTasks(Range):
 | |
|     """
 | |
|     The maximum number of Firemaking Tasks to possibly be assigned.
 | |
|     If set to 0, no Firemaking tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_FIREMAKING_TASKS
 | |
|     default = MAX_FIREMAKING_TASKS
 | |
| 
 | |
| 
 | |
| class FiremakingTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Firemaking tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxWoodcuttingLevel(Range):
 | |
|     """
 | |
|     The highest Woodcutting requirement of any task generated.
 | |
|     If set to 0, no Woodcutting tasks will be generated.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MaxWoodcuttingTasks(Range):
 | |
|     """
 | |
|     The maximum number of Woodcutting Tasks to possibly be assigned.
 | |
|     If set to 0, no Woodcutting tasks will be generated.
 | |
|     This only determines the maximum possible, fewer than the maximum could be assigned.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = MAX_WOODCUTTING_TASKS
 | |
|     default = MAX_WOODCUTTING_TASKS
 | |
| 
 | |
| 
 | |
| class WoodcuttingTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating Woodcutting tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| class MinimumGeneralTasks(Range):
 | |
|     """
 | |
|     How many guaranteed general progression tasks to be assigned (total level, total XP, etc.).
 | |
|     General progression tasks will be used to fill out any holes caused by having fewer possible tasks than needed, so
 | |
|     there is no maximum.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = NON_QUEST_LOCATION_COUNT
 | |
|     default = 10
 | |
| 
 | |
| 
 | |
| class GeneralTaskWeight(Range):
 | |
|     """
 | |
|     How much to favor generating General tasks over other types of task.
 | |
|     Weights of all Task Types will be compared against each other, a task with 50 weight
 | |
|     is twice as likely to appear as one with 25.
 | |
|     """
 | |
|     range_start = 0
 | |
|     range_end = 99
 | |
|     default = 50
 | |
| 
 | |
| 
 | |
| @dataclass
 | |
| class OSRSOptions(PerGameCommonOptions):
 | |
|     starting_area: StartingArea
 | |
|     brutal_grinds: BrutalGrinds
 | |
|     progressive_tasks: ProgressiveTasks
 | |
|     max_combat_level: MaxCombatLevel
 | |
|     max_combat_tasks: MaxCombatTasks
 | |
|     combat_task_weight: CombatTaskWeight
 | |
|     max_prayer_level: MaxPrayerLevel
 | |
|     max_prayer_tasks: MaxPrayerTasks
 | |
|     prayer_task_weight: PrayerTaskWeight
 | |
|     max_magic_level: MaxMagicLevel
 | |
|     max_magic_tasks: MaxMagicTasks
 | |
|     magic_task_weight: MagicTaskWeight
 | |
|     max_runecraft_level: MaxRunecraftLevel
 | |
|     max_runecraft_tasks: MaxRunecraftTasks
 | |
|     runecraft_task_weight: RunecraftTaskWeight
 | |
|     max_crafting_level: MaxCraftingLevel
 | |
|     max_crafting_tasks: MaxCraftingTasks
 | |
|     crafting_task_weight: CraftingTaskWeight
 | |
|     max_mining_level: MaxMiningLevel
 | |
|     max_mining_tasks: MaxMiningTasks
 | |
|     mining_task_weight: MiningTaskWeight
 | |
|     max_smithing_level: MaxSmithingLevel
 | |
|     max_smithing_tasks: MaxSmithingTasks
 | |
|     smithing_task_weight: SmithingTaskWeight
 | |
|     max_fishing_level: MaxFishingLevel
 | |
|     max_fishing_tasks: MaxFishingTasks
 | |
|     fishing_task_weight: FishingTaskWeight
 | |
|     max_cooking_level: MaxCookingLevel
 | |
|     max_cooking_tasks: MaxCookingTasks
 | |
|     cooking_task_weight: CookingTaskWeight
 | |
|     max_firemaking_level: MaxFiremakingLevel
 | |
|     max_firemaking_tasks: MaxFiremakingTasks
 | |
|     firemaking_task_weight: FiremakingTaskWeight
 | |
|     max_woodcutting_level: MaxWoodcuttingLevel
 | |
|     max_woodcutting_tasks: MaxWoodcuttingTasks
 | |
|     woodcutting_task_weight: WoodcuttingTaskWeight
 | |
|     minimum_general_tasks: MinimumGeneralTasks
 | |
|     general_task_weight: GeneralTaskWeight
 |