forked from mirror/Archipelago
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
182 lines
8.5 KiB
Python
182 lines
8.5 KiB
Python
from typing import NamedTuple, TYPE_CHECKING
|
|
|
|
from BaseClasses import Location
|
|
from . import game_data, items, version
|
|
|
|
if TYPE_CHECKING:
|
|
from . import MkddWorld
|
|
|
|
|
|
TAG_CUP_PERFECT = "Perfect Cup"
|
|
TAG_CUP_GOLD = "Gold Cup"
|
|
TAG_CUP_SILVER = "Silver Cup"
|
|
TAG_CUP_BRONZE = "Bronze Cup"
|
|
TAG_CUP_FINISH = "Finish Cup"
|
|
TAG_CUP_TROPHY = "Cup Trophy"
|
|
TAG_COURSE_FIRST = "Finish First"
|
|
TAG_COURSE_LEAD = "Take The Lead"
|
|
TAG_COURSE_FINISH = "Finish Course"
|
|
TAG_WIN_COMBO = "Win With Certain Characters"
|
|
TAG_TT = "Time Trial"
|
|
TAG_TT_GOOD = "Time Trial Good Time"
|
|
TAG_TT_GHOST = "Time Trial Staff Ghost"
|
|
TAG_ITEM_BOX = "Item Box"
|
|
|
|
|
|
class MkddLocation(Location):
|
|
game = version.get_game_name()
|
|
|
|
|
|
class MkddLocationData(NamedTuple):
|
|
name: str
|
|
difficulty: int = 0
|
|
region: str = "Menu"
|
|
required_items: dict[str, int] = {}
|
|
tags: set[str] = {}
|
|
|
|
BOX_NAMES = {
|
|
"Mushroom Bridge": ["Pipe", "Sidewalk", "Bridge"],
|
|
"Peach Beach": ["Hidden Pipe", "Beach Jump", "Fountain"],
|
|
"Luigi Circuit": ["Chomp Shortcut", "Last Curve Shortcut"],
|
|
"Wario Colosseum": ["Great Jump"],
|
|
"Daisy Cruiser": ["Cargo Area"],
|
|
"Dino Dino Jungle": ["Bridge Side"]
|
|
}
|
|
|
|
def get_loc_name_cup(cup: str, ranking: int, vehicle_class: int) -> str:
|
|
try:
|
|
rank_name = ["Gold", "Silver", "Bronze"][ranking]
|
|
class_name = ["50cc", "100cc", "150cc", "Mirror"][vehicle_class]
|
|
return f"{cup} {rank_name} {class_name}"
|
|
except:
|
|
return ""
|
|
|
|
def get_loc_name_trophy(cup: str, vehicle_class: int) -> str:
|
|
try:
|
|
class_name = ["50cc", "100cc", "150cc", "Mirror"][vehicle_class]
|
|
return f"{cup} Gold {class_name} (Trophy)"
|
|
except:
|
|
return ""
|
|
|
|
def get_loc_name_perfect(cup: str) -> str:
|
|
return f"{cup} Perfect"
|
|
|
|
def get_loc_name_finish(course_or_cup: str) -> str:
|
|
return f"{course_or_cup} Finish"
|
|
|
|
def get_loc_name_lead(course: str) -> str:
|
|
return f"{course} Take The Lead"
|
|
|
|
def get_loc_name_first(course: str) -> str:
|
|
return f"{course} 1st"
|
|
|
|
def get_loc_name_good_time(course: game_data.Course) -> str:
|
|
seconds = course.good_time
|
|
minutes = int(seconds / 60)
|
|
seconds -= minutes * 60
|
|
return f"{course.name} Time Trial in {minutes}:{seconds:02d}"
|
|
|
|
def get_loc_name_ghost(course: str) -> str:
|
|
return f"{course} Defeat Staff Ghost"
|
|
|
|
def get_loc_name_win_char_kart(character: str, kart: str) -> str:
|
|
return f"Win With {character} Driving {kart}"
|
|
|
|
def get_loc_name_win_characters(character1: str, character2: str) -> str:
|
|
return f"Win With {character1} and {character2}"
|
|
|
|
def get_loc_name_win_course_char(course: game_data.Course) -> str:
|
|
characters = [game_data.CHARACTERS[character].name for character in course.owners]
|
|
if len(characters) == 1:
|
|
return f"Win in {course.name} With {characters[0]}"
|
|
else:
|
|
return f"Win in {course.name} With {characters[0]} and {characters[1]}"
|
|
|
|
def get_loc_name_item_box(course: str, box_id: int) -> str:
|
|
names = BOX_NAMES.get(course, [])
|
|
return f"{course} - {names[box_id]} Box"
|
|
|
|
data_table: list[MkddLocationData] = [MkddLocationData("", 0)] # Id 0 is reserved.
|
|
|
|
# Cup related locations.
|
|
for cup in game_data.NORMAL_CUPS:
|
|
data_table.append(MkddLocationData(get_loc_name_finish(cup), 0, cup, tags = {cup, TAG_CUP_FINISH}))
|
|
data_table.append(MkddLocationData(get_loc_name_perfect(cup), 70, cup, tags = {cup, TAG_CUP_PERFECT}))
|
|
# 50cc
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 2, 0), 10, cup, tags = {cup, TAG_CUP_BRONZE}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 1, 0), 20, cup, tags = {cup, TAG_CUP_SILVER}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 0, 0), 40, cup, tags = {cup, TAG_CUP_GOLD}))
|
|
data_table.append(MkddLocationData(get_loc_name_trophy(cup, 0), 40, cup, tags = {TAG_CUP_TROPHY}))
|
|
# 100cc
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 2, 1), 40, cup, {items.PROGRESSIVE_CLASS:1}, {cup, TAG_CUP_BRONZE}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 1, 1), 60, cup, {items.PROGRESSIVE_CLASS:1}, {cup, TAG_CUP_SILVER}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 0, 1), 70, cup, {items.PROGRESSIVE_CLASS:1}, {cup, TAG_CUP_GOLD}))
|
|
data_table.append(MkddLocationData(get_loc_name_trophy(cup, 1), 70, cup, {items.PROGRESSIVE_CLASS:1}, {TAG_CUP_TROPHY}))
|
|
# 150cc
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 2, 2), 60, cup, {items.PROGRESSIVE_CLASS:2}, {cup, TAG_CUP_BRONZE}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 1, 2), 80, cup, {items.PROGRESSIVE_CLASS:2}, {cup, TAG_CUP_SILVER}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 0, 2), 90, cup, {items.PROGRESSIVE_CLASS:2}, {cup, TAG_CUP_GOLD}))
|
|
data_table.append(MkddLocationData(get_loc_name_trophy(cup, 2), 90, cup, {items.PROGRESSIVE_CLASS:2}, {TAG_CUP_TROPHY}))
|
|
# Mirror
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 2, 3), 70, cup, {items.PROGRESSIVE_CLASS:3}, {cup, TAG_CUP_BRONZE}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 1, 3), 90, cup, {items.PROGRESSIVE_CLASS:3}, {cup, TAG_CUP_SILVER}))
|
|
data_table.append(MkddLocationData(get_loc_name_cup(cup, 0, 3), 100, cup, {items.PROGRESSIVE_CLASS:3}, {cup, TAG_CUP_GOLD}))
|
|
data_table.append(MkddLocationData(get_loc_name_trophy(cup, 3), 100, cup, {items.PROGRESSIVE_CLASS:3}, {TAG_CUP_TROPHY}))
|
|
|
|
# Course related locations.
|
|
for course in game_data.RACE_COURSES:
|
|
data_table.append(MkddLocationData(get_loc_name_finish(course.name), 0, course.name, tags = {course.name, TAG_COURSE_FINISH}))
|
|
data_table.append(MkddLocationData(get_loc_name_lead(course.name), 30, course.name + " GP", tags = {course.name, TAG_COURSE_LEAD}))
|
|
data_table.append(MkddLocationData(get_loc_name_first(course.name), 40, course.name + " GP", tags = {course.name, TAG_COURSE_FIRST}))
|
|
data_table.append(MkddLocationData(get_loc_name_good_time(course), 70, course.name + " TT", tags = {course.name, TAG_TT, TAG_TT_GOOD}))
|
|
data_table.append(MkddLocationData(get_loc_name_ghost(course.name), 100, course.name + " TT", tags = {course.name, TAG_TT, TAG_TT_GHOST}))
|
|
|
|
# Win with default character pairs.
|
|
for character_id in range(0, len(game_data.CHARACTERS), 2):
|
|
character1 = game_data.CHARACTERS[character_id]
|
|
character2 = game_data.CHARACTERS[character_id + 1]
|
|
data_table.append(MkddLocationData(get_loc_name_win_characters(character1.name, character2.name), 40, "Menu", {character1.name:1, character2.name:1}, {TAG_WIN_COMBO}))
|
|
|
|
# Win with a default kart + character combination.
|
|
for character in game_data.CHARACTERS:
|
|
kart = game_data.KARTS[character.default_kart]
|
|
data_table.append(MkddLocationData(get_loc_name_win_char_kart(character.name, kart.name), 40, "Menu", {character.name:1, kart.name:1}, {TAG_WIN_COMBO}))
|
|
|
|
# Win courses with certain characters.
|
|
for course in [course for course in game_data.RACE_COURSES if len(course.owners) > 0]:
|
|
data_table.append(MkddLocationData(get_loc_name_win_course_char(course), 40, course.name + " GP", {game_data.CHARACTERS[o].name:1 for o in course.owners}, {course.name, TAG_WIN_COMBO}))
|
|
|
|
# Misc locations.
|
|
GOLD_LIGHT = "Win Gold With a Light Kart"
|
|
GOLD_MEDIUM = "Win Gold With a Medium Kart"
|
|
GOLD_HEAVY = "Win Gold With a Heavy Kart"
|
|
GOLD_PARADE = "Win Gold With Parade Kart"
|
|
TROPHY_GOAL = "Trophy Goal Completed"
|
|
WIN_ALL_CUP_TOUR = "All Cup Tour Gold"
|
|
|
|
# Don't define difficulty here, it will be handled by rules.
|
|
data_table.append(MkddLocationData(GOLD_LIGHT, 0))
|
|
data_table.append(MkddLocationData(GOLD_MEDIUM, 0))
|
|
data_table.append(MkddLocationData(GOLD_HEAVY, 0))
|
|
data_table.append(MkddLocationData(GOLD_PARADE, 40, required_items = {"Parade Kart":1}))
|
|
data_table.append(MkddLocationData(TROPHY_GOAL, 0))
|
|
data_table.append(MkddLocationData(WIN_ALL_CUP_TOUR, 0, game_data.CUPS[game_data.CUP_ALL_CUP_TOUR]))
|
|
|
|
# Box in course related locations.
|
|
for course in game_data.RACE_COURSES:
|
|
boxes = BOX_NAMES.get(course.name, [])
|
|
for i, box_nickname in enumerate(boxes):
|
|
if course.name == "Luigi Circuit":
|
|
data_table.append(MkddLocationData(get_loc_name_item_box(course.name, i), 0, f"{course.name} GP", {items.PROGRESSIVE_CLASS:1}, tags={course.name, TAG_ITEM_BOX}))
|
|
else:
|
|
data_table.append(MkddLocationData(get_loc_name_item_box(course.name, i), 0, f"{course.name} GP", tags={course.name, TAG_ITEM_BOX}))
|
|
|
|
name_to_id: dict[str, int] = {data.name:id for (id, data) in enumerate(data_table) if id > 0}
|
|
|
|
group_names: set[str] = set()
|
|
for data in data_table:
|
|
group_names.update(data.tags)
|
|
groups: dict[str: set[str]] = {
|
|
group:{data.name for data in data_table if group in data.tags}
|
|
for group in group_names
|
|
} |