Skip to content

Commit

Permalink
Add neon rank
Browse files Browse the repository at this point in the history
  • Loading branch information
s5bug committed Aug 25, 2024
1 parent f206908 commit 4351921
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 33 deletions.
51 changes: 29 additions & 22 deletions worlds/neon_white/Items.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
from BaseClasses import Item, ItemClassification
from worlds.neon_white import Locations

base_item_namespace = 2874297668000000

chapter_unlock_offset = 1000
level_unlock_offset = 1000
cards_offset = 2000
card_abilities_offset = 3000
insight_offset = 4000
neon_rank_offset = 5000

chapters = [
'M01 Rebirth',
'M02 Killer Inside',
'M03 Only Shallow',
'M04 The Old City',
'M05 The Burn That Cures',
'M06 Covenant',
'M07 Reckoning',
'M08 Benediction',
'M09 Apocrypha',
'M10 The Third Temple',
'M11 Thousand Pound Butterfly',
'M12 Hand of God'
]
levels = []

chapter_num = 1
for chapter in Locations.job_names:
level_num = 1
for level in chapter:
levels.append(f'M{chapter_num:02d}L{level_num:02d} {level}')
level_num += 1

chapter_num += 1

cards = [
'Card: Katana',
Expand Down Expand Up @@ -52,13 +50,17 @@
('Insight: Green', 4)
]

neon_rank = [
('Neon Rank', 100)
]

all_items = {}
item_name_to_id = {}

item_individual_offset = 0
for chapter in chapters:
all_items[chapter] = 1
item_name_to_id[chapter] = base_item_namespace + chapter_unlock_offset + item_individual_offset
for level in levels:
all_items[level] = 1
item_name_to_id[level] = base_item_namespace + level_unlock_offset + item_individual_offset
item_individual_offset += 1

item_individual_offset = 0
Expand All @@ -79,21 +81,26 @@
item_name_to_id[name] = base_item_namespace + insight_offset + item_individual_offset
item_individual_offset += 1

all_items['Neon Rank'] = 100
item_name_to_id['Neon Rank'] = base_item_namespace + neon_rank_offset

item_name_groups = {
'Chapters': set(chapters),
'Levels': set(levels),
'Cards': set(cards),
'CardAbilities': set(card_abilities),
'Insights': set([name for (name, _) in insights])
'Insights': set([name for (name, _) in insights]),
'NeonRank': {'Neon Rank'}
}


progression_items = set(chapters) | set(cards) | set(card_abilities)
progression_items = {'Neon Rank'} | set(cards) | set(card_abilities) | {'M12L02 Absolution'}
useful_items = set(levels) | {'Insight: Yellow', 'Insight: Red', 'Insight: Violet'}


def item_classification(item: str) -> ItemClassification:
if item in progression_items:
return ItemClassification.progression
elif item in cards or item in card_abilities:
elif item in useful_items:
return ItemClassification.useful
else:
return ItemClassification.filler
Expand Down
5 changes: 5 additions & 0 deletions worlds/neon_white/Locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ def map_medals(self,
location_name_to_id = {}
location_name_to_path = {}
location_name_lfunct: NeonWhiteLocations[str] = NeonWhiteLocations.deep_empty()
level_name_lfunct: NeonWhiteLocationsJobs[str] = NeonWhiteLocationsJobs.deep_empty()

medal_name_offsets = [
('Bronze', job_bronze_offset),
Expand All @@ -563,11 +564,13 @@ def map_medals(self,
for chapter_field in dataclasses.fields(location_name_lfunct.jobs):
chapter_path = ["jobs", chapter_field.name]
chapter_lfunct = getattr(location_name_lfunct.jobs, chapter_field.name)
chapter_lname_lfunct = getattr(level_name_lfunct, chapter_field.name)
job_name_list = job_names[chapter_idx]
job_idx = 0
for job_field in dataclasses.fields(chapter_lfunct):
job_path = chapter_path + [job_field.name]
job_lfunct = getattr(chapter_lfunct, job_field.name)
job_lname_lfunct = getattr(chapter_lname_lfunct, job_field.name)
job_full_name = f'M{chapter_idx + 1:02d}L{job_idx + 1:02d} {job_name_list[job_idx]}'

for (medal_name, offset) in medal_name_offsets:
Expand All @@ -577,6 +580,7 @@ def map_medals(self,
location_name_to_id[medal_full_name] = base_location_namespace + offset + total_job_id
location_name_to_path[medal_full_name] = medal_path
setattr(job_lfunct, medal_field_name, medal_full_name)
setattr(job_lname_lfunct, medal_field_name, job_full_name)
all_locations.append(medal_full_name)

if hasattr(job_lfunct, 'gift'):
Expand All @@ -585,6 +589,7 @@ def map_medals(self,
location_name_to_id[gift_full_name] = base_location_namespace + job_gift_offset + total_job_id
location_name_to_path[gift_full_name] = gift_path
setattr(job_lfunct, 'gift', gift_full_name)
setattr(job_lname_lfunct, 'gift', job_full_name)
all_locations.append(gift_full_name)

total_job_id += 1
Expand Down
10 changes: 9 additions & 1 deletion worlds/neon_white/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,4 +572,12 @@ def cascade_medals(jm: NeonWhiteLocationsJobMedals[Variable[bool]]) -> NeonWhite
return plus


reachability_full = reachability.map_medals(cascade_medals)
def level_required(path: list[str], variable: Variable[bool]) -> Variable[bool]:
if path[0] == "jobs":
from worlds.neon_white.Locations import level_name_lfunct
return variable & HasItemVariable(level_name_lfunct.lget(path[1:]))
else:
return variable


reachability_full = reachability.map_medals(cascade_medals).lmap([], level_required)
43 changes: 33 additions & 10 deletions worlds/neon_white/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from .Items import (item_name_to_id as i_item_name_to_id, all_items as i_all_items,
item_name_groups as i_item_name_groups, item_classification as i_item_classification, NeonWhiteItem,
chapters as i_chapters)
levels as i_levels)

from .Locations import location_name_to_id as l_location_name_to_id, all_locations as l_all_locations, \
job_names as l_job_names, NeonWhiteLocation, giftless_jobs as l_giftless_jobs, \
Expand Down Expand Up @@ -48,6 +48,22 @@ def generate_early(self) -> None:
self.reward_gifts = self.options.reward_gifts.value
self.reward_sidequests = self.options.reward_sidequests.value

self.location_count = 0
for chapter in range(0, 12):
chapter_l = l_job_names[chapter]
job_idx = 1
for job in chapter_l:
self.location_count += len(self.reward_medals)

if job not in l_giftless_jobs and self.reward_gifts:
self.location_count += 1

job_idx += 1

if self.reward_sidequests:
for (companion, companion_l) in l_companion_sidequests:
self.location_count += len(companion_l)

def create_item(self, name: str) -> NeonWhiteItem:
return NeonWhiteItem(name, i_item_classification(name), self.item_name_to_id[name], self.player)

Expand All @@ -57,13 +73,12 @@ def create_event(self, name: str) -> NeonWhiteItem:
def create_items(self) -> None:
# TODO: exclusions
total_item_count = 0
location_count = len(l_all_locations)
for item_name in i_all_items:
count = i_all_items[item_name]
total_item_count += count
self.multiworld.itempool += [self.create_item(item_name) for _ in range(count)]

junk = location_count - total_item_count
junk = self.location_count - total_item_count
# TODO: actual junk items
self.multiworld.itempool += [self.create_item('Insight: Green') for _ in range(junk)]

Expand Down Expand Up @@ -92,12 +107,10 @@ def create_regions(self) -> None:
chapter_region.add_locations(chapter_dict, NeonWhiteLocation)

if chapter == 11:
absolution_loc = NeonWhiteLocation(self.player, 'M12L02 Absolution: Clear', None, chapter_region)
absolution_loc = NeonWhiteLocation(self.player, 'M12L02 Absolution: Clear', None, menu_region)
chapter_region.locations.append(absolution_loc)

def has_item_capture(item: str):
return lambda state: state.has(item, self.player)
menu_region.connect(chapter_region, rule=has_item_capture(i_chapters[chapter]))
menu_region.connect(chapter_region)

if self.reward_sidequests:
for (companion, companion_l) in l_companion_sidequests:
Expand Down Expand Up @@ -136,7 +149,17 @@ def lset_rule(path: list[str], rule) -> None:

reachability_full.lmap([], lset_rule)

def clear_rule(state) -> bool:
has_level = state.has('M12L02 Absolution', self.player)
has_cards = state.has(
'Card: Book of Life', self.player
) and state.has(
'Ability: Book of Life', self.player
) and state.has(
'Card: Dominion', self.player
)
has_rank = state.has('Neon Rank', self.player, 70)
return has_level and has_cards and has_rank

set_rule(self.multiworld.get_location('M12L02 Absolution: Clear', self.player),
lambda state: state.has('Card: Book of Life', self.player) and
state.has('Ability: Book of Life', self.player) and
state.has('Card: Dominion', self.player))
clear_rule)

0 comments on commit 4351921

Please sign in to comment.