Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion worlds/crosscode/codegen/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from ..types.condition import Condition
from ..types.locations import AccessInfo, LocationData
from ..types.regions import RegionConnection
from ..types.regions import Goal, RegionConnection
from ..types.items import ItemData, ItemPoolEntry, ProgressiveChainEntry, SingleItemData
from ..types.shops import ShopData

Expand Down Expand Up @@ -294,6 +294,30 @@ def create_expression_region_connection(conn: RegionConnection):

return ast_region

def create_expression_goal(goal: Goal):
"""
Create an expression representing a goal.
"""

ast_goal = ast.Call(
func=ast.Name("Goal"),
args=[],
keywords=[
ast.keyword(
arg="region",
value=ast.Constant(goal.region)
),
ast.keyword(
arg="condition",
value=create_expression_condition_list(goal.condition)
),
]
)

ast.fix_missing_locations(ast_goal)

return ast_goal

def create_expression_shop(data: ShopData) -> ast.Call:
"""
Create an expression that represents a shop region.
Expand Down
32 changes: 23 additions & 9 deletions worlds/crosscode/codegen/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from ..types.items import ItemData, ProgressiveChainEntry, ProgressiveItemChain, ProgressiveItemChainSingle, ProgressiveItemChainMulti, ProgressiveItemSubchain, SingleItemData
from ..types.locations import AccessInfo, Condition
from ..types.regions import RegionConnection, RegionsData
from ..types.regions import Goal, RegionConnection, RegionsData
from ..types.condition import *

class JsonParserError(Exception):
Expand Down Expand Up @@ -305,7 +305,18 @@ def parse_progressive_chain(self, name: str, raw: dict[str, typing.Any]) -> Prog
items=self.__parse_progressive_itemlist(raw_items),
)

def parse_goal(self, raw: dict[str, typing.Any]) -> Goal:
if "region" not in raw:
raise JsonParserError(raw, None, "goal", "goals must have a source region")

region = raw["region"]

if "condition" not in raw or len(raw["condition"]) == 0:
condition = None
else:
condition = self.parse_condition(raw["condition"])

return Goal(region, condition)

def parse_region_connection(self, raw: dict[str, typing.Any]) -> RegionConnection:
"""
Expand Down Expand Up @@ -342,13 +353,6 @@ def parse_regions_data(self, raw: dict[str, typing.Any]) -> RegionsData:
if not isinstance(start, str):
raise JsonParserError(raw, start, "regions data", "starting region must be a string")

if "goal" not in raw:
raise JsonParserError(raw, None, "regions data", "must have goal region")
goal = raw["goal"]

if not isinstance(goal, str):
raise JsonParserError(raw, goal, "regions data", "goal region must be a string")

exclude = []
if "exclude" in raw:
exclude = raw["exclude"]
Expand All @@ -373,11 +377,21 @@ def parse_regions_data(self, raw: dict[str, typing.Any]) -> RegionsData:

connections.append(conn)

if "goals" not in raw:
raise JsonParserError(raw, None, "regions data", "must have goal region")

if not isinstance(raw["goals"], dict):
raise JsonParserError(raw, None, "regions data", "goals must be a dict")

goals = {}
for goal_name, goal in raw["goals"].items():
goals[goal_name] = self.parse_goal(goal)

region_list = list(regions_seen)

region_list.sort(key=lambda x: float(x.strip(string.ascii_letters)))

return RegionsData(start, goal, exclude, region_list, connections)
return RegionsData(start, exclude, region_list, connections, goals)

def parse_regions_data_list(self, raw: dict[str, dict[str, typing.Any]]) -> dict[str, RegionsData]:
"""
Expand Down
13 changes: 13 additions & 0 deletions worlds/crosscode/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@

# default = 1

class Goal(Choice):
"""
Determines what must be done to complete the game.
[Creator] Ascend Vermillion Tower and fight the Creator.
[Monkey] Ascend the Grand Krys'kajo and defeat the Son of the East.
"""
display_name = "Goal"

option_creator = 0
option_monkey = 1
default = 0

class VTShadeLock(Choice):
"""
If set to a non-None value, creates an in-game barrier at the entrance of Vermillion Tower to prevent extremely
Expand Down Expand Up @@ -481,6 +493,7 @@ class CrossCodeOptions(PerGameCommonOptions):
Options dataclass for CrossCode
"""
# logic_mode: LogicMode
goal: Goal
vt_shade_lock: VTShadeLock
vw_meteor_passage: VWMeteorPassage
closed_gaia: ClosedGaia
Expand Down
23 changes: 13 additions & 10 deletions worlds/crosscode/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import typing

from .types.regions import RegionConnection, RegionsData
from .types.regions import Goal, RegionConnection, RegionsData
from .types.condition import *

modes = [
Expand All @@ -18,7 +18,6 @@
region_packs: typing.Dict[str, RegionsData] = {
"linear": RegionsData(
starting_region = "2",
goal_region = "32",
excluded_regions = ['1'],
region_list = [
'2',
Expand Down Expand Up @@ -92,11 +91,13 @@
RegionConnection(region_from='31', region_to='32', cond=[ItemCondition(item_name='Old Dojo Key', amount=1)]),
RegionConnection(region_from='32', region_to='33', cond=[ItemCondition(item_name='Meteor Shade', amount=1)]),
RegionConnection(region_from='31', region_to='22', cond=None),
]
],
goals = {
'creator': Goal(region='32', condition=None),
}
),
"open": RegionsData(
starting_region = "open2",
goal_region = "open19",
excluded_regions = ['open1'],
region_list = [
'open2',
Expand All @@ -122,12 +123,12 @@
'open7.8',
'open8',
'open9',
'open10.Infested',
'open10',
'open10.Grove',
'open10.Left',
'open10.Grove',
'open10.Infested',
'open10.Right',
'open10.Mid',
'open10',
'open11',
'open13.1',
'open13.2',
Expand All @@ -143,7 +144,6 @@
'open16.1',
'open17',
'open18',
'open19',
'open20',
],
region_connections = [
Expand Down Expand Up @@ -194,8 +194,11 @@
RegionConnection(region_from='open16', region_to='open17', cond=[ItemCondition(item_name='Old Dojo Key', amount=1)]),
RegionConnection(region_from='open16', region_to='open16.1', cond=[ItemCondition(item_name='Meteor Shade', amount=1), ItemCondition(item_name='Shock', amount=1)]),
RegionConnection(region_from='open16', region_to='open18', cond=[VariableCondition(name='vwPassage')]),
RegionConnection(region_from='open16.1', region_to='open19', cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Shock', amount=1), ItemCondition(item_name='Wave', amount=1), VariableCondition(name='vtShadeLock')]),
]
],
goals = {
'creator': Goal(region='open16.1', condition=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Shock', amount=1), ItemCondition(item_name='Wave', amount=1), VariableCondition(name='vtShadeLock')]),
'monkey': Goal(region='open15.3', condition=None),
}
),

}
6 changes: 3 additions & 3 deletions worlds/crosscode/templates/regions.template.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import typing

from .types.regions import RegionConnection, RegionsData
from .types.regions import Goal, RegionConnection, RegionsData
from .types.condition import *

modes = {{ modes | emit_list("constant") }}
Expand All @@ -13,10 +13,10 @@
{% for mode, r in region_packs.items() -%}
"{{mode}}": RegionsData(
starting_region = "{{r.starting_region}}",
goal_region = "{{r.goal_region}}",
excluded_regions = {{r.excluded_regions}},
region_list = {{r.region_list | emit_list("constant") | indent(8)}},
region_connections = {{r.region_connections | emit_list("region_connection") | indent(8)}}
region_connections = {{r.region_connections | emit_list("region_connection") | indent(8)}},
goals = {{r.goals.items() | emit_dict("constant", "goal") | indent(8) }}
),
{% endfor %}
}
7 changes: 6 additions & 1 deletion worlds/crosscode/types/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ class RegionConnection:
region_to: str
cond: typing.Optional[list[Condition]]

@dataclass
class Goal:
region: str
condition: typing.Optional[typing.List[Condition]]

@dataclass
class RegionsData:
starting_region: str
goal_region: str
excluded_regions: typing.List[str]
region_list: typing.List[str]
region_connections: typing.List[RegionConnection]
goals: typing.Dict[str, Goal]
19 changes: 15 additions & 4 deletions worlds/crosscode/world.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,22 @@ def create_regions(self):
if self.options.shop_rando:
self.create_shops()

goal_region = self.region_dict[self.region_pack.goal_region]
goal = Location(self.player, "The Creator", parent=goal_region)
goal.place_locked_item(Item("Victory", ItemClassification.progression, None, self.player))
goal_name = self.options.goal.current_key
goal = self.region_pack.goals[goal_name]
goal_region = self.region_dict[goal.region]
goal_location = Location(self.player, "Victory", parent=goal_region)
goal_location.place_locked_item(Item("Victory", ItemClassification.progression, None, self.player))
add_rule(
goal_location,
condition_satisfied(
self.player,
goal.condition if goal.condition is not None else [],
None,
self.logic_dict
)
)
self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
goal_region.locations.append(goal)
goal_region.locations.append(goal_location)

def create_items(self):
exclude = self.multiworld.precollected_items[self.player][:]
Expand Down
Loading