Added my game made specifically for AP, ChecksFinder (Minesweeper) (#302)

This commit is contained in:
jonloveslegos
2022-03-22 18:30:10 -04:00
committed by GitHub
parent 7f1371ec00
commit 4bf8b98681
13 changed files with 993 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
from BaseClasses import Item
import typing
class ItemData(typing.NamedTuple):
code: typing.Optional[int]
progression: bool
class ChecksFinderItem(Item):
game: str = "ChecksFinder"
item_table = {
"Map Width": ItemData(80000, True),
"Map Height": ItemData(80001, True),
"Map Bombs": ItemData(80002, True),
}
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}

View File

@@ -0,0 +1,52 @@
from BaseClasses import Location
import typing
class AdvData(typing.NamedTuple):
id: typing.Optional[int]
region: str
class ChecksFinderAdvancement(Location):
game: str = "ChecksFinder"
def __init__(self, player: int, name: str, address: typing.Optional[int], parent):
super().__init__(player, name, address, parent)
self.event = not address
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}

View File

@@ -0,0 +1,6 @@
import typing
from Options import Option
checksfinder_options: typing.Dict[str, type(Option)] = {
}

View File

@@ -0,0 +1,16 @@
def link_checksfinder_structures(world, player):
for (exit, region) in mandatory_connections:
world.get_entrance(exit, player).connect(world.get_region(region, player))
# (Region name, list of exits)
checksfinder_regions = [
('Menu', ['New Board']),
('Board',[]),
]
# (Entrance, region pointed to)
mandatory_connections = [
('New Board', 'Board'),
]

View File

@@ -0,0 +1,47 @@
from ..generic.Rules import set_rule, add_rule
from BaseClasses import MultiWorld
from ..AutoWorld import LogicMixin
class ChecksFinderLogic(LogicMixin):
def _has_total(self, player: int, total: int):
return (self.item_count('Map Width', player)+self.item_count('Map Height', player)+
self.item_count('Map Bombs', player)) >= total
# 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: state._has_total(player, 1))
set_rule(world.get_location(("Tile 7"), player), lambda state: state._has_total(player, 2))
set_rule(world.get_location(("Tile 8"), player), lambda state: state._has_total(player, 3))
set_rule(world.get_location(("Tile 9"), player), lambda state: state._has_total(player, 4))
set_rule(world.get_location(("Tile 10"), player), lambda state: state._has_total(player, 5))
set_rule(world.get_location(("Tile 11"), player), lambda state: state._has_total(player, 6))
set_rule(world.get_location(("Tile 12"), player), lambda state: state._has_total(player, 7))
set_rule(world.get_location(("Tile 13"), player), lambda state: state._has_total(player, 8))
set_rule(world.get_location(("Tile 14"), player), lambda state: state._has_total(player, 9))
set_rule(world.get_location(("Tile 15"), player), lambda state: state._has_total(player, 10))
set_rule(world.get_location(("Tile 16"), player), lambda state: state._has_total(player, 11))
set_rule(world.get_location(("Tile 17"), player), lambda state: state._has_total(player, 12))
set_rule(world.get_location(("Tile 18"), player), lambda state: state._has_total(player, 13))
set_rule(world.get_location(("Tile 19"), player), lambda state: state._has_total(player, 14))
set_rule(world.get_location(("Tile 20"), player), lambda state: state._has_total(player, 15))
set_rule(world.get_location(("Tile 21"), player), lambda state: state._has_total(player, 16))
set_rule(world.get_location(("Tile 22"), player), lambda state: state._has_total(player, 17))
set_rule(world.get_location(("Tile 23"), player), lambda state: state._has_total(player, 18))
set_rule(world.get_location(("Tile 24"), player), lambda state: state._has_total(player, 19))
set_rule(world.get_location(("Tile 25"), player), lambda state: state._has_total(player, 20))
# 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)

View File

@@ -0,0 +1,90 @@
import os
import json
from base64 import b64encode, b64decode
from math import ceil
from .Items import ChecksFinderItem, item_table, required_items
from .Locations import ChecksFinderAdvancement, advancement_table, exclusion_table
from .Regions import checksfinder_regions, link_checksfinder_structures
from .Rules import set_rules, set_completion_rules
from worlds.generic.Rules import exclusion_rules
from BaseClasses import Region, Entrance, Item
from .Options import checksfinder_options
from ..AutoWorld import World
client_version = 7
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"
options = checksfinder_options
topology_present = True
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()}
data_version = 4
def _get_checksfinder_data(self):
return {
'world_seed': self.world.slot_seeds[self.player].getrandbits(32),
'seed_name': self.world.seed_name,
'player_name': self.world.get_player_name(self.player),
'player_id': self.player,
'client_version': client_version,
'race': self.world.is_race,
}
def generate_basic(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)
# Add the map bombs
itempool += ["Map Bombs"] * (20-5)
# Convert itempool into real items
itempool = [item for item in map(lambda name: self.create_item(name), itempool)]
# Choose locations to automatically exclude based on settings
exclusion_pool = set()
self.world.itempool += itempool
def set_rules(self):
set_rules(self.world, self.player)
set_completion_rules(self.world, self.player)
def create_regions(self):
def ChecksFinderRegion(region_name: str, exits=[]):
ret = Region(region_name, None, region_name, self.player, self.world)
ret.locations = [ChecksFinderAdvancement(self.player, loc_name, loc_data.id, ret)
for loc_name, loc_data in advancement_table.items()
if loc_data.region == region_name]
for exit in exits:
ret.exits.append(Entrance(self.player, exit, ret))
return ret
self.world.regions += [ChecksFinderRegion(*r) for r in checksfinder_regions]
link_checksfinder_structures(self.world, self.player)
def fill_slot_data(self):
slot_data = self._get_checksfinder_data()
for option_name in checksfinder_options:
option = getattr(self.world, 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
def create_item(self, name: str) -> Item:
item_data = item_table[name]
item = ChecksFinderItem(name, item_data.progression, item_data.code, self.player)
return item