Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zork Grand Inquisitor: Implement New Game #2539

Merged
merged 46 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
afe0e0a
add world: zork grand inquisitor
nbrochu Nov 19, 2023
acf9cab
add item duplication prevention, fix skip old scratch option, only us…
nbrochu Nov 19, 2023
e870fec
pivot on goal option + fixes
nbrochu Nov 20, 2023
9bdfd82
sword and map as items + new problems :)
nbrochu Nov 20, 2023
e2e38e0
first apworld?
nbrochu Nov 21, 2023
e54394c
Merge remote-tracking branch 'upstream/main' into zgi
nbrochu Nov 28, 2023
9c1f79a
bump required client version; fix unit tests by defining create_item
nbrochu Nov 28, 2023
3967d9d
compare using isinstance and not type; turn off topology_present
nbrochu Nov 29, 2023
6ad6818
add documentation
nbrochu Nov 29, 2023
4b6bdba
remove traps placeholder in item data
nbrochu Nov 29, 2023
19be1c1
add a note for surface teleport
nbrochu Nov 29, 2023
eb1d0cf
remove script name from launcher component
nbrochu Nov 29, 2023
9698b08
extra stuff
nbrochu Nov 29, 2023
c35fcb0
no need to vendor pymem if we are targeting official repo inclusion
nbrochu Nov 29, 2023
2b610b6
add game-specific unit tests
nbrochu Nov 30, 2023
2cb4741
typing pass
nbrochu Nov 30, 2023
0946528
rule optimization
nbrochu Dec 1, 2023
14198b0
docs tweak
nbrochu Dec 1, 2023
c76e06d
Merge branch 'main' into zgi
nbrochu Dec 1, 2023
6a2dfa8
Merge branch 'main' into zgi
nbrochu Dec 21, 2023
b359e66
Merge branch 'main' into zgi
nbrochu Jan 7, 2024
d1727d0
Merge branch 'main' into zgi
nbrochu Jan 14, 2024
53e8a4a
Content Update
nbrochu Feb 6, 2024
b9e4346
change early rope and lantern option to quick port foozle now that we…
nbrochu Feb 8, 2024
1319d06
Update worlds/zork_grand_inquisitor/docs/en_Zork Grand Inquisitor.md
nbrochu Feb 11, 2024
9b74270
Update worlds/zork_grand_inquisitor/docs/setup_en.md
nbrochu Feb 11, 2024
bb9f34d
remove unused import in client
nbrochu Feb 15, 2024
b83ab05
reorder deathsanity locations alphabetically to align with enum + rea…
nbrochu Feb 17, 2024
ec80b42
remove unused tag
nbrochu Feb 17, 2024
9f66b61
replace invalid game location code
nbrochu Feb 18, 2024
81e0f07
make VOXAM useful
nbrochu Feb 18, 2024
3ad6ddb
add IGRAM and hotspot: purple words to requirements for crisis averte…
nbrochu Feb 19, 2024
83e5c2f
new option: grant missable location checks
nbrochu Mar 1, 2024
a5ea87b
new option: start with hotspot items
nbrochu Mar 1, 2024
df75413
how many times will I have to find out again that this cannot be cach…
nbrochu Mar 1, 2024
a0fca39
add item requirements to meet before granting a missable location che…
nbrochu Mar 1, 2024
2530db8
forgot old scratch death as potentially missable
nbrochu Mar 2, 2024
ed8b496
Merge branch 'main' into zgi
nbrochu Mar 5, 2024
a0b28a3
Merge branch 'main' into zgi
nbrochu Mar 6, 2024
3aa9f8f
cleanup
nbrochu Mar 6, 2024
cd181c3
game controller completed locations should be derived from game state…
nbrochu Mar 6, 2024
0dc90b3
use self.random
nbrochu Mar 6, 2024
5661d25
address review feedback
nbrochu Mar 7, 2024
d658100
address more review feedback
nbrochu Mar 11, 2024
c2c5f28
move game controller option setting to on_package and remove unnecess…
nbrochu Mar 13, 2024
4e9791c
formatting
nbrochu Mar 13, 2024
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Currently, the following games are supported:
* TUNIC
* Kirby's Dream Land 3
* Celeste 64
* Zork Grand Inquisitor

For setup and instructions check out our [tutorials page](https://archipelago.gg/tutorial/).
Downloads can be found at [Releases](https://github.com/ArchipelagoMW/Archipelago/releases), including compiled
Expand Down
3 changes: 3 additions & 0 deletions docs/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
# Zillion
/worlds/zillion/ @beauxq

# Zork Grand Inquisitor
/worlds/zork_grand_inquisitor/ @nbrochu

##################################
## Disabled Unmaintained Worlds ##
##################################
Expand Down
21 changes: 21 additions & 0 deletions worlds/zork_grand_inquisitor/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Serpent.AI

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
17 changes: 17 additions & 0 deletions worlds/zork_grand_inquisitor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import worlds.LauncherComponents as LauncherComponents

from .world import ZorkGrandInquisitorWorld


def launch_client() -> None:
from .client import main
LauncherComponents.launch_subprocess(main, name="ZorkGrandInquisitorClient")


LauncherComponents.components.append(
LauncherComponents.Component(
"Zork Grand Inquisitor Client",
func=launch_client,
component_type=LauncherComponents.Type.CLIENT
)
)
186 changes: 186 additions & 0 deletions worlds/zork_grand_inquisitor/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import asyncio

import CommonClient
import NetUtils
import Utils

from typing import Any, Dict, List, Optional, Set, Tuple

from .data_funcs import item_names_to_id, location_names_to_id, id_to_items, id_to_locations, id_to_goals
from .enums import ZorkGrandInquisitorItems, ZorkGrandInquisitorLocations
from .game_controller import GameController


class ZorkGrandInquisitorCommandProcessor(CommonClient.ClientCommandProcessor):
def _cmd_zork(self) -> None:
"""Attach to an open Zork Grand Inquisitor process."""
result: bool = self.ctx.game_controller.open_process_handle()

if result:
self.ctx.process_attached_at_least_once = True
self.output("Successfully attached to Zork Grand Inquisitor process.")
else:
self.output("Failed to attach to Zork Grand Inquisitor process.")

def _cmd_brog(self) -> None:
"""List received Brog items."""
self.ctx.game_controller.list_received_brog_items()

def _cmd_griff(self) -> None:
"""List received Griff items."""
self.ctx.game_controller.list_received_griff_items()

def _cmd_lucy(self) -> None:
"""List received Lucy items."""
self.ctx.game_controller.list_received_lucy_items()

def _cmd_hotspots(self) -> None:
"""List received Hotspots."""
self.ctx.game_controller.list_received_hotspots()


class ZorkGrandInquisitorContext(CommonClient.CommonContext):
tags: Set[str] = {"AP"}
game: str = "Zork Grand Inquisitor"
command_processor: CommonClient.ClientCommandProcessor = ZorkGrandInquisitorCommandProcessor
items_handling: int = 0b111
want_slot_data: bool = True

item_name_to_id: Dict[str, int] = item_names_to_id()
location_name_to_id: Dict[str, int] = location_names_to_id()

id_to_items: Dict[int, ZorkGrandInquisitorItems] = id_to_items()
id_to_locations: Dict[int, ZorkGrandInquisitorLocations] = id_to_locations()

def __init__(self, server_address: Optional[str], password: Optional[str]) -> None:
super().__init__(server_address, password)

self.game_controller: GameController = GameController(logger=CommonClient.logger)

self.controller_task: Optional[asyncio.Task] = None

self.process_attached_at_least_once: bool = False
self.can_display_process_message: bool = True

def run_gui(self) -> None:
from kvui import GameManager

class TextManager(GameManager):
logging_pairs: List[Tuple[str, str]] = [("Client", "Archipelago")]
base_title: str = "Archipelago Zork Grand Inquisitor Client"

self.ui = TextManager(self)
self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI")

async def server_auth(self, password_requested: bool = False):
if password_requested and not self.password:
await super().server_auth(password_requested)

await self.get_username()
await self.send_connect()

def on_package(self, cmd: str, _args: Any) -> None:
if cmd == "Connected":
self.game = self.slot_info[self.slot].game

CommonClient.async_start(process_package(self, cmd, _args))
nbrochu marked this conversation as resolved.
Show resolved Hide resolved

async def controller(self):
while not self.exit_event.is_set():
await asyncio.sleep(0.1)

# Enqueue Received Item Delta
network_item: NetUtils.NetworkItem
for network_item in self.items_received:
item: ZorkGrandInquisitorItems = self.id_to_items[network_item.item]

if item not in self.game_controller.received_items:
if item not in self.game_controller.received_items_queue:
self.game_controller.received_items_queue.append(item)

# Game Controller Update
if self.game_controller.is_process_running():
self.game_controller.update()
self.can_display_process_message = True
else:
process_message: str

if self.process_attached_at_least_once:
process_message = (
"Lost connection to Zork Grand Inquisitor process. Please restart the game and use the /zork "
"command to reattach."
)
else:
process_message = (
"Please use the /zork command to attach to a running Zork Grand Inquisitor process."
)

if self.can_display_process_message:
CommonClient.logger.info(process_message)
self.can_display_process_message = False

# Send Checked Locations
checked_location_ids: List[int] = list()

while len(self.game_controller.completed_locations_queue) > 0:
location: ZorkGrandInquisitorLocations = self.game_controller.completed_locations_queue.popleft()
location_id: int = self.location_name_to_id[location.value]

checked_location_ids.append(location_id)

await self.send_msgs([
{
"cmd": "LocationChecks",
"locations": checked_location_ids
}
])

# Check for Goal Completion
if self.game_controller.goal_completed:
await self.send_msgs([
{
"cmd": "StatusUpdate",
"status": CommonClient.ClientStatus.CLIENT_GOAL
}
])


async def process_package(ctx: ZorkGrandInquisitorContext, cmd: str, _args: Any):
if cmd == "Connected":
# Slot Data - Options
ctx.game_controller.option_goal = id_to_goals()[_args["slot_data"]["goal"]]
ctx.game_controller.option_deathsanity = _args["slot_data"]["deathsanity"] == 1

ctx.game_controller.option_grant_missable_location_checks = (
_args["slot_data"]["grant_missable_location_checks"] == 1
)


def main() -> None:
Utils.init_logging("ZorkGrandInquisitorClient", exception_logger="Client")

async def _main():
ctx: ZorkGrandInquisitorContext = ZorkGrandInquisitorContext(None, None)

ctx.server_task = asyncio.create_task(CommonClient.server_loop(ctx), name="server loop")
ctx.controller_task = asyncio.create_task(ctx.controller(), name="ZorkGrandInquisitorController")

if CommonClient.gui_enabled:
ctx.run_gui()

ctx.run_cli()

await ctx.exit_event.wait()
await ctx.shutdown()

import colorama

colorama.init()

asyncio.run(_main())

colorama.deinit()


if __name__ == "__main__":
main()
Empty file.
Loading
Loading