Added logic, can still be locked
This commit is contained in:
@@ -52,7 +52,22 @@
|
||||
TMP_HOME=$(mktemp -d)
|
||||
HOME=$TMP_HOME ${pkgs.archipelago}/bin/archipelago --update_settings
|
||||
ln -s ${nodecames-apworld} "$TMP_HOME/.local/share/Archipelago/worlds/nodecames.apworld"
|
||||
HOME=$TMP_HOME ${pkgs.archipelago}/bin/archipelago
|
||||
chmod +w "$TMP_HOME/.local/share/Archipelago/Players/"
|
||||
ln -s ${./src/main/resources/apworld/test.yml} "$TMP_HOME/.local/share/Archipelago/Players/Tester.yaml"
|
||||
HOME=$TMP_HOME ${pkgs.archipelago}/bin/archipelago "$@"
|
||||
'';
|
||||
};
|
||||
archipelago-host = pkgs.writeShellApplication {
|
||||
name = "archipelago-host";
|
||||
text = ''
|
||||
TMP_HOME=$(mktemp -d)
|
||||
HOME=$TMP_HOME ${pkgs.archipelago}/bin/archipelago --update_settings
|
||||
ln -s ${nodecames-apworld} "$TMP_HOME/.local/share/Archipelago/worlds/nodecames.apworld"
|
||||
chmod +w "$TMP_HOME/.local/share/Archipelago/Players/"
|
||||
ln -s ${./src/main/resources/apworld/test.yml} "$TMP_HOME/.local/share/Archipelago/Players/Tester.yaml"
|
||||
HOME=$TMP_HOME ${pkgs.archipelago}/bin/archipelago Generate
|
||||
GENFILE=$(find "$TMP_HOME/.local/share/Archipelago/output/" -name "*.zip")
|
||||
HOME=$TMP_HOME ${pkgs.archipelago}/bin/archipelago Host "$GENFILE"
|
||||
'';
|
||||
};
|
||||
in {
|
||||
@@ -66,6 +81,7 @@
|
||||
nodecames = { type = "app"; program = "${nodecames-launcher}/bin/nodecames"; };
|
||||
postgres-server = { type = "app"; program = "${postgres-server}/bin/postgres-server"; };
|
||||
archipelago = { type = "app"; program = "${test-archipelago}/bin/archipelago"; };
|
||||
archipelago-host = { type = "app"; program = "${archipelago-host}/bin/archipelago-host"; };
|
||||
};
|
||||
|
||||
devShells.${system} = {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import re
|
||||
|
||||
MAX_WORLD_COUNT=100
|
||||
MAX_WORD_PER_WORLD=99
|
||||
|
||||
def parseWordDistribution(s):
|
||||
components = s.split(';')
|
||||
out = {}
|
||||
for comp in components:
|
||||
p = re.match("^([GWB])([GWB])([0-9]+)$", comp)
|
||||
if not p:
|
||||
raise ValueError("Invalid component of word distribution")
|
||||
colora = p.group(1)
|
||||
colorb = p.group(2)
|
||||
count = int(p.group(3))
|
||||
if (colora + colorb in out):
|
||||
raise ValueError(f"Component {colora}{colorb} defined twice")
|
||||
out[colora + colorb] = count
|
||||
return out
|
||||
|
||||
filler_item = "filler"
|
||||
|
||||
ITEM_NAME_TO_ID = {
|
||||
"progressive_hint_count" : 1,
|
||||
"zero_hint" : 2,
|
||||
"infinity_hint" : 3,
|
||||
"one_more_guess" : 4,
|
||||
"hint_max_length" : 5,
|
||||
"end_guessing" : 6,
|
||||
"only_one_green_green" : 7,
|
||||
"sudden_death" : 8,
|
||||
"structured_grid" : 9,
|
||||
"hints_in_a_row" : 10,
|
||||
"anyone_starts" : 11,
|
||||
"progressive_hint_word_count": 12,
|
||||
"progressive_hint_word_length": 13,
|
||||
"filler": 14
|
||||
}
|
||||
for w in range(MAX_WORLD_COUNT):
|
||||
ITEM_NAME_TO_ID[f"unlock_world_{w+1}"] = 100+w
|
||||
|
||||
def location_id_of_world_and_word(world, word):
|
||||
return 10000 + (world-1)*(MAX_WORD_PER_WORLD+1) + word
|
||||
def world_and_word_of_location(id):
|
||||
world = (id - 10000)//(MAX_WORD_PER_WORLD+1) + 1
|
||||
word = (id - 10000) % (MAX_WORD_PER_WORLD+1)
|
||||
return (world, word)
|
||||
def location_name_of_world_and_word(world, word):
|
||||
return f"World {world} word {word}"
|
||||
|
||||
LOCATION_NAME_TO_ID = {location_name_of_world_and_word(world,word) : location_id_of_world_and_word(world,word) for world in range(1,MAX_WORLD_COUNT+1) for word in range(0,MAX_WORD_PER_WORLD+1)}
|
||||
+12
-24
@@ -1,46 +1,27 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .world import NodecamesWorld
|
||||
|
||||
ITEM_NAME_TO_ID = {
|
||||
"progressive_hint_count" : 1,
|
||||
"zero_hint" : 2,
|
||||
"infinity_hint" : 3,
|
||||
"one_more_guess" : 4,
|
||||
"hint_max_length" : 5,
|
||||
"end_guessing" : 6,
|
||||
"only_one_green_green" : 7,
|
||||
"sudden_death" : 8,
|
||||
"structured_grid" : 9,
|
||||
"hints_in_a_row" : 10,
|
||||
"anyone_starts" : 11,
|
||||
"progressive_hint_word_count": 12,
|
||||
"progressive_hint_word_length": 13,
|
||||
"filler": 14
|
||||
}
|
||||
for w in range(1,12+1):
|
||||
ITEM_NAME_TO_ID[f"unlock_world_{w}"] = 100+w
|
||||
from BaseClasses import Item, ItemClassification
|
||||
|
||||
from . import const as c
|
||||
|
||||
class NodecamesItem(Item):
|
||||
game = "Nodecames"
|
||||
|
||||
def get_random_filler_item_name(world: NodecamesWorld) -> str:
|
||||
return "filler"
|
||||
return c.filler_item
|
||||
|
||||
|
||||
def create_item_with_correct_classification(
|
||||
world: NodecamesWorld, name: str
|
||||
) -> NodecamesItem:
|
||||
classification = ItemClassification.progression
|
||||
if name == "filler":
|
||||
if name == c.filler_item:
|
||||
classification = ItemClassification.filler
|
||||
return NodecamesItem(name, classification, ITEM_NAME_TO_ID[name], world.player)
|
||||
return NodecamesItem(name, classification, c.ITEM_NAME_TO_ID[name], world.player)
|
||||
|
||||
|
||||
def create_all_items(world: NodecamesWorld) -> None:
|
||||
@@ -64,9 +45,16 @@ def create_all_items(world: NodecamesWorld) -> None:
|
||||
world.create_item("hints_in_a_row"),
|
||||
world.create_item("anyone_starts"),
|
||||
]
|
||||
for wi,wn in enumerate(world.options.worlds.keys()):
|
||||
w = world.options.worlds[wn]
|
||||
if w['locked']:
|
||||
itempool.append(world.create_item(f"unlock_world_{wi}"))
|
||||
|
||||
|
||||
to_complete = len(world.multiworld.get_unfilled_locations(world.player)) - len(itempool)
|
||||
|
||||
print(to_complete,"items to fill")
|
||||
|
||||
itempool += [world.create_filler() for _ in range(to_complete)]
|
||||
|
||||
world.multiworld.itempool += itempool
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from BaseClasses import ItemClassification, Location
|
||||
|
||||
from . import items
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .world import NodecamesWorld
|
||||
|
||||
|
||||
GREEN_COUNT_PER_WORLD = [6, 9, 9, 12, 16, 16, 20, 25, 25, 30, 36, 36]
|
||||
|
||||
def worldName(index):
|
||||
return f"{(index//3)+1}-{(index%3)+1}"
|
||||
|
||||
LOCATION_NAME_TO_ID = {}
|
||||
LOCATION_NAME_FROM_WORLD = {}
|
||||
id = 0
|
||||
for w in range(len(GREEN_COUNT_PER_WORLD)):
|
||||
LOCATION_NAME_FROM_WORLD[w] = []
|
||||
for i in range(1, GREEN_COUNT_PER_WORLD[w]):
|
||||
name = f"World {worldName(w)} word {i}"
|
||||
id += 1
|
||||
LOCATION_NAME_FROM_WORLD[w].append(name)
|
||||
LOCATION_NAME_TO_ID[name] = id
|
||||
name = f"Complete {worldName(w)}"
|
||||
id += 1
|
||||
LOCATION_NAME_FROM_WORLD[w].append(name)
|
||||
LOCATION_NAME_TO_ID[name] = id
|
||||
|
||||
|
||||
class NodecamesLocation(Location):
|
||||
game = "Nodecames"
|
||||
|
||||
|
||||
def create_all_locations(world: NodecamesWorld) -> None:
|
||||
create_world_locations(world)
|
||||
create_events(world)
|
||||
|
||||
|
||||
def create_world_locations(world: NodecamesWorld) -> None:
|
||||
overworld = world.get_region("Overworld")
|
||||
|
||||
for w in LOCATION_NAME_FROM_WORLD:
|
||||
for l in range(len(LOCATION_NAME_FROM_WORLD[w])-1):
|
||||
name = LOCATION_NAME_FROM_WORLD[w][l]
|
||||
loc = NodecamesLocation(
|
||||
world.player,
|
||||
name,
|
||||
LOCATION_NAME_TO_ID[name],
|
||||
overworld,
|
||||
)
|
||||
overworld.locations.append(loc)
|
||||
|
||||
def all_completion_items(world: NodecamesWorld) -> list[str]:
|
||||
return [LOCATION_NAME_FROM_WORLD[w][-1]+" item" for w in LOCATION_NAME_FROM_WORLD]
|
||||
|
||||
def create_events(world: NodecamesWorld) -> None:
|
||||
overworld = world.get_region("Overworld")
|
||||
for w in LOCATION_NAME_FROM_WORLD:
|
||||
overworld.add_event(
|
||||
LOCATION_NAME_FROM_WORLD[w][-1],
|
||||
LOCATION_NAME_FROM_WORLD[w][-1]+" item",
|
||||
location_type = NodecamesLocation,
|
||||
item_type = items.NodecamesItem)
|
||||
@@ -1,7 +1,8 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from Options import Choice, OptionGroup, PerGameCommonOptions, Range, DefaultOnToggle
|
||||
|
||||
from Options import Choice, OptionGroup, PerGameCommonOptions, Range, DefaultOnToggle, OptionDict
|
||||
from schema import Schema, And
|
||||
from . import const as c
|
||||
|
||||
class WorldsLocked(DefaultOnToggle):
|
||||
"""
|
||||
@@ -10,6 +11,16 @@ class WorldsLocked(DefaultOnToggle):
|
||||
|
||||
display_name = "Worlds locked"
|
||||
|
||||
class HintWordLogicRatio(Range):
|
||||
"""
|
||||
How many hints per word count in the grid is needed as a minimum.
|
||||
Used to compute the logic
|
||||
Divide by 10
|
||||
"""
|
||||
range_start = 10
|
||||
range_end = 80
|
||||
display_name = "Hint Word Logic Ration"
|
||||
|
||||
|
||||
class StartHintCount(Range):
|
||||
"""
|
||||
@@ -183,12 +194,29 @@ class VictoryCondition(Choice):
|
||||
option_LastWorld = 2
|
||||
default = 2
|
||||
|
||||
class WorldsOption(OptionDict):
|
||||
"""
|
||||
Which nodecames worlds will be in the game and their options
|
||||
|
||||
It takes the following parameters:
|
||||
|
||||
locked: wether the world is unlocked by default, or needs an item to be unlocked
|
||||
word_distribution: a string describing the distributions of colors on the grid
|
||||
"""
|
||||
display_name = "Worlds"
|
||||
schema = Schema({
|
||||
str: {
|
||||
"locked": bool,
|
||||
"word_distribution": And(str, c.parseWordDistribution),
|
||||
"required": bool
|
||||
}})
|
||||
|
||||
# We must now define a dataclass inheriting from PerGameCommonOptions that we put all our options in.
|
||||
# This is in the format "option_name_in_snake_case: OptionClassName".
|
||||
@dataclass
|
||||
class NodecamesOptions(PerGameCommonOptions):
|
||||
worlds_locked: WorldsLocked
|
||||
hint_word_logic_ratio: HintWordLogicRatio
|
||||
victory_condition: VictoryCondition
|
||||
start_hint_count: StartHintCount
|
||||
max_hint_count: MaxHintCount
|
||||
@@ -205,14 +233,14 @@ class NodecamesOptions(PerGameCommonOptions):
|
||||
structured_grid: StructuredGrid
|
||||
hints_in_a_row: HintsInARow
|
||||
anyone_starts: AnyoneStarts
|
||||
world_count: WorldCount
|
||||
worlds: WorldsOption
|
||||
|
||||
|
||||
# If we want to group our options by similar type, we can do so as well. This looks nice on the website.
|
||||
option_groups = [
|
||||
OptionGroup(
|
||||
"General Options",
|
||||
[WorldsLocked, VictoryCondition],
|
||||
[WorldsLocked, VictoryCondition, HintWordLogicRatio],
|
||||
),
|
||||
OptionGroup(
|
||||
"Grid Options",
|
||||
@@ -232,12 +260,13 @@ option_groups = [
|
||||
AnyoneStarts,
|
||||
],
|
||||
),
|
||||
OptionGroup("Worlds Options", [WorldCount]),
|
||||
OptionGroup("Worlds Options", [WorldsOption]),
|
||||
]
|
||||
|
||||
# Finally, we can define some option presets if we want the player to be able to quickly choose a specific "mode".
|
||||
option_presets = {
|
||||
"default": {
|
||||
"hint_word_logic_ratio": 25,
|
||||
"worlds_locked": True,
|
||||
"start_hint_count": 1,
|
||||
"max_hint_count": 10,
|
||||
@@ -254,7 +283,56 @@ option_presets = {
|
||||
"structured_grid": 1,
|
||||
"hints_in_a_row": 1,
|
||||
"anyone_starts": 1,
|
||||
"world_count": 12,
|
||||
"worlds": {
|
||||
"1-1": {
|
||||
"locked": False,
|
||||
"word_distribution": "GG1;GW2;GB0;WG2;WW1;WB0;BG0;BW0;BB0"
|
||||
},
|
||||
"1-2": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG2;GW1;GB1;WG1;WW2;WB0;BG1;BW0;BB1"
|
||||
},
|
||||
"1-3": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG2;GW1;GB1;WG1;WW2;WB0;BG1;BW0;BB1"
|
||||
},
|
||||
"2-1": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG2;GW1;GB1;WG1;WW3;WB1;BG1;BW1;BB1"
|
||||
},
|
||||
"2-2": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG2;GW2;GB1;WG2;WW5;WB1;BG1;BW1;BB1"
|
||||
},
|
||||
"2-3": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG2;GW2;GB1;WG2;WW5;WB1;BG1;BW1;BB1"
|
||||
},
|
||||
"3-1": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG2;GW4;GB1;WG4;WW5;WB1;BG1;BW1;BB1"
|
||||
},
|
||||
"3-2": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG3;GW5;GB1;WG5;WW7;WB1;BG1;BW1;BB1"
|
||||
},
|
||||
"3-3": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG3;GW5;GB1;WG5;WW7;WB1;BG1;BW1;BB1"
|
||||
},
|
||||
"4-1": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG3;GW5;GB2;WG5;WW7;WB2;BG2;BW2;BB1"
|
||||
},
|
||||
"4-2": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG5;GW6;GB2;WG6;WW9;WB2;BG2;BW2;BB2"
|
||||
},
|
||||
"4-3": {
|
||||
"locked": True,
|
||||
"word_distribution": "GG5;GW6;GB2;WG6;WW9;WB2;BG2;BW2;BB2"
|
||||
}
|
||||
},
|
||||
"victory_condition": 2,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from BaseClasses import Entrance, Region
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .world import NodecamesWorld
|
||||
|
||||
|
||||
def create_and_connect_regions(world: NodecamesWorld) -> None:
|
||||
create_all_regions(world)
|
||||
connect_regions(world)
|
||||
|
||||
|
||||
def create_all_regions(world: NodecamesWorld) -> None:
|
||||
overworld = Region("Overworld", world.player, world.multiworld)
|
||||
world.multiworld.regions += [overworld]
|
||||
|
||||
|
||||
def connect_regions(world: NodecamesWorld) -> None:
|
||||
overworld = world.get_region("Overworld")
|
||||
+64
-17
@@ -1,31 +1,78 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from rule_builder.options import OptionFilter
|
||||
from rule_builder.rules import Has, HasAll, Rule
|
||||
|
||||
from . import locations
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .world import NodecamesWorld
|
||||
|
||||
|
||||
def set_all_rules(world: NodecamesWorld) -> None:
|
||||
set_all_entrance_rules(world)
|
||||
set_all_location_rules(world)
|
||||
set_completion_condition(world)
|
||||
from rule_builder.options import OptionFilter
|
||||
from rule_builder.rules import Has, HasAll, Rule, True_
|
||||
from BaseClasses import Region, Location
|
||||
from . import const as c
|
||||
import math
|
||||
from . import items
|
||||
|
||||
def print_graph(world : NodecamesWorld):
|
||||
for region in world.multiworld.regions:
|
||||
print(region)
|
||||
for exit in region.exits:
|
||||
print("->",exit,"--",exit.access_rule)
|
||||
|
||||
def set_all_entrance_rules(world: NodecamesWorld) -> None:
|
||||
pass
|
||||
class NodecamesLocation(Location):
|
||||
game = "Nodecames"
|
||||
|
||||
def total_word_count(distribution):
|
||||
return distribution['GB']+distribution['BG']+distribution['GW']+distribution['WG']+distribution['GG']
|
||||
|
||||
def set_all_location_rules(world: NodecamesWorld) -> None:
|
||||
pass
|
||||
def can_access_word(options, word):
|
||||
ratio = options.hint_word_logic_ratio/10
|
||||
min_hint_count = math.ceil(word/ratio)
|
||||
min_hint_word_count = math.ceil(word/min_hint_count) # min_hint_count * min_hint_word_count >= word
|
||||
|
||||
return Has("progressive_hint_word_count", count=max(min_hint_word_count-options.start_hint_word_count,0)) & Has("progressive_hint_count", count=max(min_hint_count-options.start_hint_count,0))
|
||||
|
||||
def set_completion_condition(world: NodecamesWorld) -> None:
|
||||
def can_access_world(options, wn, wi):
|
||||
if options.worlds[wn]['locked']:
|
||||
return Has(f"unlock_world_{wi}")
|
||||
else:
|
||||
return True_()
|
||||
|
||||
worldLocations = locations.all_completion_items(world)
|
||||
world.set_completion_rule(HasAll(*worldLocations))
|
||||
def create_all_regions(world: NodecamesWorld) -> None:
|
||||
#TODO make a helper to add new regions
|
||||
owmap = Region("Map", world.player, world.multiworld)
|
||||
|
||||
wregions = dict()
|
||||
toComplete = list()
|
||||
|
||||
for wi,wn in enumerate(world.options.worlds.keys()):
|
||||
w = world.options.worlds[wn]
|
||||
distrib = c.parseWordDistribution(w['word_distribution'])
|
||||
wregions[wn] = list()
|
||||
for i in range(total_word_count(distrib)+1):
|
||||
name = c.location_name_of_world_and_word(wi+1,i)
|
||||
wregions[wn].append(Region(name, world.player, world.multiworld))
|
||||
if i>0:
|
||||
wregions[wn][i-1].connect(wregions[wn][i], rule = can_access_word(world.options, i))
|
||||
else:
|
||||
owmap.connect(wregions[wn][i], rule = can_access_world(world.options, wn, wi))
|
||||
loc = NodecamesLocation(
|
||||
world.player,
|
||||
name,
|
||||
c.LOCATION_NAME_TO_ID[name],
|
||||
wregions[wn][i]
|
||||
)
|
||||
wregions[wn][i].locations.append(loc)
|
||||
wregions[wn][-1].add_event(
|
||||
f"World {wn} complete",
|
||||
f"World {wn} completion item",
|
||||
location_type = NodecamesLocation,
|
||||
item_type = items.NodecamesItem)
|
||||
if w['required']:
|
||||
toComplete.append(f"World {wn} completion item")
|
||||
|
||||
world.set_completion_rule(HasAll(*toComplete))
|
||||
|
||||
allregions = [owmap] + [wrxv for wrv in wregions.values() for wrxv in wrv]
|
||||
print(f"Generated {len(allregions)} regions")
|
||||
print(f"Generated {sum([len(reg.locations) for reg in allregions])} locations")
|
||||
world.multiworld.regions += allregions
|
||||
@@ -3,9 +3,9 @@ from typing import Any
|
||||
|
||||
from worlds.AutoWorld import World
|
||||
|
||||
from . import items, locations, regions, rules
|
||||
from . import items, rules
|
||||
from . import options as nodecames_options
|
||||
|
||||
from . import const as c
|
||||
|
||||
class NodecamesWorld(World):
|
||||
"""
|
||||
@@ -17,17 +17,14 @@ class NodecamesWorld(World):
|
||||
options_dataclass = nodecames_options.NodecamesOptions
|
||||
options: nodecames_options.NodecamesOptions
|
||||
|
||||
location_name_to_id = locations.LOCATION_NAME_TO_ID
|
||||
item_name_to_id = items.ITEM_NAME_TO_ID
|
||||
location_name_to_id = c.LOCATION_NAME_TO_ID
|
||||
item_name_to_id = c.ITEM_NAME_TO_ID
|
||||
|
||||
origin_region_name = "Overworld"
|
||||
origin_region_name = "Map"
|
||||
|
||||
# Create regions, locations and rules
|
||||
def create_regions(self) -> None:
|
||||
regions.create_and_connect_regions(self)
|
||||
locations.create_all_locations(self)
|
||||
|
||||
def set_rules(self) -> None:
|
||||
rules.set_all_rules(self)
|
||||
rules.create_all_regions(self)
|
||||
|
||||
def create_items(self) -> None:
|
||||
items.create_all_items(self)
|
||||
@@ -40,27 +37,10 @@ class NodecamesWorld(World):
|
||||
def get_filler_item_name(self) -> str:
|
||||
return items.get_random_filler_item_name(self)
|
||||
|
||||
def generate_output(self, outdir : str) -> None:
|
||||
# Generates the output file
|
||||
def generate_output(self, outdir : str) -> None:
|
||||
pass
|
||||
|
||||
# Data sent to the client
|
||||
def fill_slot_data(self) -> Mapping[str, Any]:
|
||||
return self.options.as_dict(
|
||||
"worlds_locked",
|
||||
"start_hint_count",
|
||||
"max_hint_count",
|
||||
"start_hint_length",
|
||||
"max_hint_length",
|
||||
"zero_hint",
|
||||
"infinity_hint",
|
||||
"one_more_guess",
|
||||
"end_guessing",
|
||||
"only_one_green_green",
|
||||
"sudden_death",
|
||||
"structured_grid",
|
||||
"hints_in_a_row",
|
||||
"anyone_starts",
|
||||
"world_count",
|
||||
"victory_condition",
|
||||
)
|
||||
return []
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
name: Tester
|
||||
game: nodecames
|
||||
nodecames:
|
||||
progression_balancing: normal
|
||||
accessibility: full
|
||||
hint_word_logic_ratio: 25
|
||||
|
||||
start_hint_count: 1
|
||||
max_hint_count: 10
|
||||
start_hint_length: 3
|
||||
max_hint_length: 12
|
||||
start_hint_word_count: 1
|
||||
max_hint_word_count: 16
|
||||
|
||||
worlds:
|
||||
1-1:
|
||||
locked: false
|
||||
word_distribution: "GG1;GW2;GB0;WG2;WW1;WB0;BG0;BW0;BB0"
|
||||
required: false
|
||||
1-2:
|
||||
locked: true
|
||||
word_distribution: "GG2;GW1;GB1;WG1;WW2;WB0;BG1;BW0;BB1"
|
||||
required: false
|
||||
1-3:
|
||||
locked: true
|
||||
word_distribution: "GG2;GW1;GB1;WG1;WW2;WB0;BG1;BW0;BB1"
|
||||
required: true
|
||||
2-1:
|
||||
locked: true
|
||||
word_distribution: "GG2;GW1;GB1;WG1;WW3;WB1;BG1;BW1;BB1"
|
||||
required: false
|
||||
2-2:
|
||||
locked: true
|
||||
word_distribution: "GG2;GW2;GB1;WG2;WW5;WB1;BG1;BW1;BB1"
|
||||
required: false
|
||||
2-3:
|
||||
locked: true
|
||||
word_distribution: "GG2;GW2;GB1;WG2;WW5;WB1;BG1;BW1;BB1"
|
||||
required: true
|
||||
3-1:
|
||||
locked: true
|
||||
word_distribution: "GG2;GW4;GB1;WG4;WW5;WB1;BG1;BW1;BB1"
|
||||
required: false
|
||||
3-2:
|
||||
locked: true
|
||||
word_distribution: "GG3;GW5;GB1;WG5;WW7;WB1;BG1;BW1;BB1"
|
||||
required: false
|
||||
3-3:
|
||||
locked: true
|
||||
word_distribution: "GG3;GW5;GB1;WG5;WW7;WB1;BG1;BW1;BB1"
|
||||
required: true
|
||||
4-1:
|
||||
locked: true
|
||||
word_distribution: "GG3;GW5;GB2;WG5;WW7;WB2;BG2;BW2;BB1"
|
||||
required: false
|
||||
4-2:
|
||||
locked: true
|
||||
word_distribution: "GG5;GW6;GB2;WG6;WW9;WB2;BG2;BW2;BB2"
|
||||
required: false
|
||||
4-3:
|
||||
locked: true
|
||||
word_distribution: "GG5;GW6;GB2;WG6;WW9;WB2;BG2;BW2;BB2"
|
||||
required: true
|
||||
Reference in New Issue
Block a user