ChecksFinder: Refactor/Cleaning (#3725)
* Update ChecksFinder * minor cleanup * Check for compatible name * Enable APWorld * Update setup_en.md * Update en_ChecksFinder.md * The client is getting updated instead * Qwint suggestions, ' -> ", streamline fill_slot_data * Oops, too many refactors --------- Co-authored-by: SunCat <suncat.game@ya.ru>
This commit is contained in:
parent
98bb8517e1
commit
90446ad175
1
setup.py
1
setup.py
|
@ -66,7 +66,6 @@ non_apworlds: set = {
|
|||
"Adventure",
|
||||
"ArchipIDLE",
|
||||
"Archipelago",
|
||||
"ChecksFinder",
|
||||
"Clique",
|
||||
"Final Fantasy",
|
||||
"Lufia II Ancient Cave",
|
||||
|
|
|
@ -3,8 +3,8 @@ import typing
|
|||
|
||||
|
||||
class ItemData(typing.NamedTuple):
|
||||
code: typing.Optional[int]
|
||||
progression: bool
|
||||
code: int
|
||||
progression: bool = True
|
||||
|
||||
|
||||
class ChecksFinderItem(Item):
|
||||
|
@ -12,16 +12,9 @@ class ChecksFinderItem(Item):
|
|||
|
||||
|
||||
item_table = {
|
||||
"Map Width": ItemData(80000, True),
|
||||
"Map Height": ItemData(80001, True),
|
||||
"Map Bombs": ItemData(80002, True),
|
||||
"Map Width": ItemData(80000),
|
||||
"Map Height": ItemData(80001),
|
||||
"Map Bombs": ItemData(80002),
|
||||
}
|
||||
|
||||
required_items = {
|
||||
}
|
||||
|
||||
item_frequencies = {
|
||||
|
||||
}
|
||||
|
||||
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code}
|
||||
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items()}
|
||||
|
|
|
@ -3,46 +3,14 @@ import typing
|
|||
|
||||
|
||||
class AdvData(typing.NamedTuple):
|
||||
id: typing.Optional[int]
|
||||
region: str
|
||||
id: int
|
||||
region: str = "Board"
|
||||
|
||||
|
||||
class ChecksFinderAdvancement(Location):
|
||||
class ChecksFinderLocation(Location):
|
||||
game: str = "ChecksFinder"
|
||||
|
||||
|
||||
advancement_table = {
|
||||
"Tile 1": AdvData(81000, 'Board'),
|
||||
"Tile 2": AdvData(81001, 'Board'),
|
||||
"Tile 3": AdvData(81002, 'Board'),
|
||||
"Tile 4": AdvData(81003, 'Board'),
|
||||
"Tile 5": AdvData(81004, 'Board'),
|
||||
"Tile 6": AdvData(81005, 'Board'),
|
||||
"Tile 7": AdvData(81006, 'Board'),
|
||||
"Tile 8": AdvData(81007, 'Board'),
|
||||
"Tile 9": AdvData(81008, 'Board'),
|
||||
"Tile 10": AdvData(81009, 'Board'),
|
||||
"Tile 11": AdvData(81010, 'Board'),
|
||||
"Tile 12": AdvData(81011, 'Board'),
|
||||
"Tile 13": AdvData(81012, 'Board'),
|
||||
"Tile 14": AdvData(81013, 'Board'),
|
||||
"Tile 15": AdvData(81014, 'Board'),
|
||||
"Tile 16": AdvData(81015, 'Board'),
|
||||
"Tile 17": AdvData(81016, 'Board'),
|
||||
"Tile 18": AdvData(81017, 'Board'),
|
||||
"Tile 19": AdvData(81018, 'Board'),
|
||||
"Tile 20": AdvData(81019, 'Board'),
|
||||
"Tile 21": AdvData(81020, 'Board'),
|
||||
"Tile 22": AdvData(81021, 'Board'),
|
||||
"Tile 23": AdvData(81022, 'Board'),
|
||||
"Tile 24": AdvData(81023, 'Board'),
|
||||
"Tile 25": AdvData(81024, 'Board'),
|
||||
}
|
||||
|
||||
exclusion_table = {
|
||||
}
|
||||
|
||||
events_table = {
|
||||
}
|
||||
|
||||
lookup_id_to_name: typing.Dict[int, str] = {data.id: item_name for item_name, data in advancement_table.items() if data.id}
|
||||
base_id = 81000
|
||||
advancement_table = {f"Tile {i+1}": AdvData(base_id+i) for i in range(25)}
|
||||
lookup_id_to_name: typing.Dict[int, str] = {data.id: item_name for item_name, data in advancement_table.items()}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
import typing
|
||||
from Options import Option
|
||||
|
||||
|
||||
checksfinder_options: typing.Dict[str, type(Option)] = {
|
||||
}
|
|
@ -1,44 +1,24 @@
|
|||
from ..generic.Rules import set_rule
|
||||
from BaseClasses import MultiWorld, CollectionState
|
||||
from worlds.generic.Rules import set_rule
|
||||
from BaseClasses import MultiWorld
|
||||
|
||||
|
||||
def _has_total(state: CollectionState, player: int, total: int):
|
||||
return (state.count('Map Width', player) + state.count('Map Height', player) +
|
||||
state.count('Map Bombs', player)) >= total
|
||||
items = ["Map Width", "Map Height", "Map Bombs"]
|
||||
|
||||
|
||||
# Sets rules on entrances and advancements that are always applied
|
||||
def set_rules(world: MultiWorld, player: int):
|
||||
set_rule(world.get_location("Tile 6", player), lambda state: _has_total(state, player, 1))
|
||||
set_rule(world.get_location("Tile 7", player), lambda state: _has_total(state, player, 2))
|
||||
set_rule(world.get_location("Tile 8", player), lambda state: _has_total(state, player, 3))
|
||||
set_rule(world.get_location("Tile 9", player), lambda state: _has_total(state, player, 4))
|
||||
set_rule(world.get_location("Tile 10", player), lambda state: _has_total(state, player, 5))
|
||||
set_rule(world.get_location("Tile 11", player), lambda state: _has_total(state, player, 6))
|
||||
set_rule(world.get_location("Tile 12", player), lambda state: _has_total(state, player, 7))
|
||||
set_rule(world.get_location("Tile 13", player), lambda state: _has_total(state, player, 8))
|
||||
set_rule(world.get_location("Tile 14", player), lambda state: _has_total(state, player, 9))
|
||||
set_rule(world.get_location("Tile 15", player), lambda state: _has_total(state, player, 10))
|
||||
set_rule(world.get_location("Tile 16", player), lambda state: _has_total(state, player, 11))
|
||||
set_rule(world.get_location("Tile 17", player), lambda state: _has_total(state, player, 12))
|
||||
set_rule(world.get_location("Tile 18", player), lambda state: _has_total(state, player, 13))
|
||||
set_rule(world.get_location("Tile 19", player), lambda state: _has_total(state, player, 14))
|
||||
set_rule(world.get_location("Tile 20", player), lambda state: _has_total(state, player, 15))
|
||||
set_rule(world.get_location("Tile 21", player), lambda state: _has_total(state, player, 16))
|
||||
set_rule(world.get_location("Tile 22", player), lambda state: _has_total(state, player, 17))
|
||||
set_rule(world.get_location("Tile 23", player), lambda state: _has_total(state, player, 18))
|
||||
set_rule(world.get_location("Tile 24", player), lambda state: _has_total(state, player, 19))
|
||||
set_rule(world.get_location("Tile 25", player), lambda state: _has_total(state, player, 20))
|
||||
def set_rules(multiworld: MultiWorld, player: int):
|
||||
for i in range(20):
|
||||
set_rule(multiworld.get_location(f"Tile {i+6}", player), lambda state, i=i: state.has_from_list(items, player, i+1))
|
||||
|
||||
|
||||
# Sets rules on completion condition
|
||||
def set_completion_rules(world: MultiWorld, player: int):
|
||||
|
||||
width_req = 10-5
|
||||
height_req = 10-5
|
||||
bomb_req = 20-5
|
||||
completion_requirements = lambda state: \
|
||||
state.has("Map Width", player, width_req) and \
|
||||
state.has("Map Height", player, height_req) and \
|
||||
state.has("Map Bombs", player, bomb_req)
|
||||
world.completion_condition[player] = lambda state: completion_requirements(state)
|
||||
def set_completion_rules(multiworld: MultiWorld, player: int):
|
||||
width_req = 5 # 10 - 5
|
||||
height_req = 5 # 10 - 5
|
||||
bomb_req = 15 # 20 - 5
|
||||
multiworld.completion_condition[player] = lambda state: state.has_all_counts(
|
||||
{
|
||||
"Map Width": width_req,
|
||||
"Map Height": height_req,
|
||||
"Map Bombs": bomb_req,
|
||||
}, player)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from BaseClasses import Region, Entrance, Item, Tutorial, ItemClassification
|
||||
from .Items import ChecksFinderItem, item_table, required_items
|
||||
from .Locations import ChecksFinderAdvancement, advancement_table, exclusion_table
|
||||
from .Options import checksfinder_options
|
||||
from BaseClasses import Region, Entrance, Tutorial, ItemClassification
|
||||
from .Items import ChecksFinderItem, item_table
|
||||
from .Locations import ChecksFinderLocation, advancement_table
|
||||
from Options import PerGameCommonOptions
|
||||
from .Rules import set_rules, set_completion_rules
|
||||
from ..AutoWorld import World, WebWorld
|
||||
from worlds.AutoWorld import World, WebWorld
|
||||
|
||||
client_version = 7
|
||||
|
||||
|
@ -25,38 +25,34 @@ class ChecksFinderWorld(World):
|
|||
ChecksFinder is a game where you avoid mines and find checks inside the board
|
||||
with the mines! You win when you get all your items and beat the board!
|
||||
"""
|
||||
game: str = "ChecksFinder"
|
||||
option_definitions = checksfinder_options
|
||||
topology_present = True
|
||||
game = "ChecksFinder"
|
||||
options_dataclass = PerGameCommonOptions
|
||||
web = ChecksFinderWeb()
|
||||
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
location_name_to_id = {name: data.id for name, data in advancement_table.items()}
|
||||
|
||||
def _get_checksfinder_data(self):
|
||||
return {
|
||||
'world_seed': self.multiworld.per_slot_randoms[self.player].getrandbits(32),
|
||||
'seed_name': self.multiworld.seed_name,
|
||||
'player_name': self.multiworld.get_player_name(self.player),
|
||||
'player_id': self.player,
|
||||
'client_version': client_version,
|
||||
'race': self.multiworld.is_race,
|
||||
}
|
||||
def create_regions(self):
|
||||
menu = Region("Menu", self.player, self.multiworld)
|
||||
board = Region("Board", self.player, self.multiworld)
|
||||
board.locations += [ChecksFinderLocation(self.player, loc_name, loc_data.id, board)
|
||||
for loc_name, loc_data in advancement_table.items()]
|
||||
|
||||
connection = Entrance(self.player, "New Board", menu)
|
||||
menu.exits.append(connection)
|
||||
connection.connect(board)
|
||||
self.multiworld.regions += [menu, board]
|
||||
|
||||
def create_items(self):
|
||||
|
||||
# Generate item pool
|
||||
itempool = []
|
||||
# Add all required progression items
|
||||
for (name, num) in required_items.items():
|
||||
itempool += [name] * num
|
||||
# Add the map width and height stuff
|
||||
itempool += ["Map Width"] * (10-5)
|
||||
itempool += ["Map Height"] * (10-5)
|
||||
itempool += ["Map Width"] * 5 # 10 - 5
|
||||
itempool += ["Map Height"] * 5 # 10 - 5
|
||||
# Add the map bombs
|
||||
itempool += ["Map Bombs"] * (20-5)
|
||||
itempool += ["Map Bombs"] * 15 # 20 - 5
|
||||
# Convert itempool into real items
|
||||
itempool = [item for item in map(lambda name: self.create_item(name), itempool)]
|
||||
itempool = [self.create_item(item) for item in itempool]
|
||||
|
||||
self.multiworld.itempool += itempool
|
||||
|
||||
|
@ -64,28 +60,16 @@ class ChecksFinderWorld(World):
|
|||
set_rules(self.multiworld, self.player)
|
||||
set_completion_rules(self.multiworld, self.player)
|
||||
|
||||
def create_regions(self):
|
||||
menu = Region("Menu", self.player, self.multiworld)
|
||||
board = Region("Board", self.player, self.multiworld)
|
||||
board.locations += [ChecksFinderAdvancement(self.player, loc_name, loc_data.id, board)
|
||||
for loc_name, loc_data in advancement_table.items() if loc_data.region == board.name]
|
||||
|
||||
connection = Entrance(self.player, "New Board", menu)
|
||||
menu.exits.append(connection)
|
||||
connection.connect(board)
|
||||
self.multiworld.regions += [menu, board]
|
||||
|
||||
def fill_slot_data(self):
|
||||
slot_data = self._get_checksfinder_data()
|
||||
for option_name in checksfinder_options:
|
||||
option = getattr(self.multiworld, option_name)[self.player]
|
||||
if slot_data.get(option_name, None) is None and type(option.value) in {str, int}:
|
||||
slot_data[option_name] = int(option.value)
|
||||
return slot_data
|
||||
return {
|
||||
"world_seed": self.random.getrandbits(32),
|
||||
"seed_name": self.multiworld.seed_name,
|
||||
"player_name": self.player_name,
|
||||
"player_id": self.player,
|
||||
"client_version": client_version,
|
||||
"race": self.multiworld.is_race,
|
||||
}
|
||||
|
||||
def create_item(self, name: str) -> Item:
|
||||
def create_item(self, name: str) -> ChecksFinderItem:
|
||||
item_data = item_table[name]
|
||||
item = ChecksFinderItem(name,
|
||||
ItemClassification.progression if item_data.progression else ItemClassification.filler,
|
||||
item_data.code, self.player)
|
||||
return item
|
||||
return ChecksFinderItem(name, ItemClassification.progression, item_data.code, self.player)
|
||||
|
|
|
@ -24,8 +24,3 @@ next to an icon, the number is how many you have gotten and the icon represents
|
|||
Victory is achieved when the player wins a board they were given after they have received all of their Map Width, Map
|
||||
Height, and Map Bomb items. The game will say at the bottom of the screen how many of each you have received.
|
||||
|
||||
## Unique Local Commands
|
||||
|
||||
The following command is only available when using the ChecksFinderClient to play with Archipelago.
|
||||
|
||||
- `/resync` Manually trigger a resync.
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
- ChecksFinder from
|
||||
the [Github releases Page for the game](https://github.com/jonloveslegos/ChecksFinder/releases) (latest version)
|
||||
- Archipelago from the [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
|
||||
## Configuring your YAML file
|
||||
|
||||
|
@ -17,28 +16,15 @@ guide: [Basic Multiworld Setup Guide](/tutorial/Archipelago/setup/en)
|
|||
|
||||
You can customize your options by visiting the [ChecksFinder Player Options Page](/games/ChecksFinder/player-options)
|
||||
|
||||
### Generating a ChecksFinder game
|
||||
## Joining a MultiWorld Game
|
||||
|
||||
**ChecksFinder is meant to be played _alongside_ another game! You may not be playing it for long periods of time if
|
||||
you play it by itself with another person!**
|
||||
|
||||
When you join a multiworld game, you will be asked to provide your YAML file to whoever is hosting. Once that is done,
|
||||
the host will provide you with either a link to download your data file, or with a zip file containing everyone's data
|
||||
files. You do not have a file inside that zip though!
|
||||
|
||||
You need to start ChecksFinder client yourself, it is located within the Archipelago folder.
|
||||
|
||||
### Connect to the MultiServer
|
||||
|
||||
First start ChecksFinder.
|
||||
|
||||
Once both ChecksFinder and the client are started. In the client at the top type in the spot labeled `Server` type the
|
||||
`Ip Address` and `Port` separated with a `:` symbol.
|
||||
|
||||
The client will then ask for the username you chose, input that in the text box at the bottom of the client.
|
||||
|
||||
### Play the game
|
||||
|
||||
When the console tells you that you have joined the room, you're all set. Congratulations on successfully joining a
|
||||
multiworld game!
|
||||
1. Start ChecksFinder
|
||||
2. Enter the following information:
|
||||
- Enter the server url (starting from `wss://` for https connection like archipelago.gg, and starting from `ws://` for http connection and local multiserver)
|
||||
- Enter server port
|
||||
- Enter the name of the slot you wish to connect to
|
||||
- Enter the room password (optional)
|
||||
- Press `Play Online` to connect
|
||||
3. Start playing!
|
||||
|
||||
Game options and controls are described in the readme on the github repository for the game
|
||||
|
|
Loading…
Reference in New Issue