Skip to content

Commit

Permalink
implement difficulty options
Browse files Browse the repository at this point in the history
also a bunch of cleanup and modularize helper.lua
  • Loading branch information
black-sliver committed Dec 24, 2023
1 parent a240aff commit bef6bde
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 46 deletions.
8 changes: 4 additions & 4 deletions items/items.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,22 +165,22 @@
{
"img": "images/logic_settings/normal.png",
"codes": "logic,normal",
"inherit_codes": true
"inherit_codes": false
},
{
"img": "images/logic_settings/hard.png",
"codes": "logic,hard",
"inherit_codes": true
"inherit_codes": false
},
{
"img": "images/logic_settings/expert.png",
"codes": "logic,expert",
"inherit_codes": true
"inherit_codes": false
},
{
"img": "images/logic_settings/lunatic.png",
"codes": "logic,lunatic",
"inherit_codes": true
"inherit_codes": false
}
]
},
Expand Down
9 changes: 9 additions & 0 deletions scripts/logic/constants.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
constants = {
difficulties = {
["NORMAL"] = 1,
["HARD"] = 2,
["EXPERT"] = 3,
["LUNATIC"] = 4,
}
}
return constants
85 changes: 80 additions & 5 deletions scripts/logic/helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ AppendableList.__index = AppendableList
-- Base Classes


State = {}
local State = {}
local Location = {}
local Region = {}
local Entrance = {}
local Definition = {}


State.__index = State

function State:new(definition)
Expand Down Expand Up @@ -95,7 +101,6 @@ function State:update_reachable_regions()
end


Location = {}
Location.__index = Location

function Location:new(name, code, parent_region)
Expand All @@ -117,7 +122,6 @@ function Location:can_reach(state)
end


Region = {}
Region.__index = Region

function Region:new(name, definition)
Expand Down Expand Up @@ -177,7 +181,6 @@ function Region:can_reach(state)
end


Entrance = {}
Entrance.__index = Entrance

function Entrance:new(name, parent_region)
Expand Down Expand Up @@ -205,7 +208,6 @@ function Entrance:can_reach(state)
end


Definition = {}
Definition.__index = Definition

function Definition:new()
Expand Down Expand Up @@ -247,3 +249,76 @@ function Definition:get_location(name)
end
end
end

function Definition:set_options(options, values)
-- missing value will try to resulve through code and fall back to default
if values == nil then
values = {}
end
for name, class in pairs(options) do
self.options[name] = class:new(values[name])
end
end


-- Options


local Choice = {
value_to_code = {}, -- mapping to Tracker codes
default = 0,
}
Choice.__index = Choice

function Choice.new(cls, initial_value)
local self = {}
cls.__index = cls
cls.__eq = Choice.__eq
setmetatable(self, cls)
self.code_to_value = {}
for value, code in pairs(self.value_to_code) do
if value == nil or code == nil then
error("Invalid option in code_to_value")
end
self.code_to_value[code] = value
if initial_value == nil then
-- if value is not provided, try to load from Tracker
if Tracker:ProviderCountForCode(code) > 0 then
initial_value = value
end
end
end
if initial_value == nil then
self.value = self.default
else
self.value = initial_value
end
return self
end

function Choice:__eq(other)
-- NOTE: this is NOT being called for type(other) == string or number. Use .value for that.
if type(other) == type(self) then
return self.value == other.value -- compare value of two instances
else
return self.value == other -- compare value of instance to const
end
end


-- Module


-- create module table
helper = {
AppendableList = AppendableList,
State = State,
Location = Location,
Region = Region,
Entrance = Entrance,
Definition = Definition,
Choice = Choice,
}

-- return the module table for require
return helper
98 changes: 61 additions & 37 deletions scripts/logic/logic.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- ap-style logic
-- TODO: use require
-- TODO: use require; this will need a PopTracker update to make "nested" require() work better
ScriptHost:LoadScript("scripts/logic/helper.lua") -- load helper for AP-style logic
ScriptHost:LoadScript("scripts/logic/locations.lua") -- load location_table
ScriptHost:LoadScript("scripts/logic/regions.lua") -- load region_table
Expand All @@ -8,12 +8,22 @@ ScriptHost:LoadScript("scripts/logic/rules/normal.lua") -- load PseudoregaliaNor
ScriptHost:LoadScript("scripts/logic/rules/hard.lua") -- load PseudoregaliaHardRules
ScriptHost:LoadScript("scripts/logic/rules/expert.lua") -- load PseudoregaliaExpertRules
ScriptHost:LoadScript("scripts/logic/rules/lunatic.lua") -- load PseudoregaliaLunaticRules
-- TODO: normal, hard, expert, lunatic rules
-- TODO: init to set up locations, regions and rules
ScriptHost:LoadScript("scripts/logic/constants.lua")
ScriptHost:LoadScript("scripts/logic/options.lua")

-- shorthand names from imports
local Definition = helper.Definition
local State = helper.State
local Region = helper.Region
local Location = helper.Location
local difficulties = constants.difficulties
local pseudoregalia_options = options.pseudoregalia_options

local def = Definition:new()
local state = State:new(def) -- TODO: add caching and update in watch for code
-- state and world definition variables
local def = Definition:new() -- "world" definition for logic
local state = State:new(def) -- TODO: add caching and update in watch for code
local glitchDef = Definition:new() -- "world" definition for out-of-logic
local glitchState = State:new(glitchDef) -- TODO: add caching and update in watch for code

-- version helper
local v = {}
Expand Down Expand Up @@ -42,7 +52,7 @@ local codes = {

-- patch up State.has to match the codes
local _has = getmetatable(state).has
getmetatable(state).has = function(state, name)
State.has = function(state, name)
local code = codes[name]
if code then
return _has(state, code)
Expand All @@ -51,9 +61,10 @@ getmetatable(state).has = function(state, name)
return _has(state, name)
end
end

-- patch up State.count to match the codes
local _count = getmetatable(state).count
getmetatable(state).count = function(state, name)
State.count = function(state, name)
local code = codes[name]
if code then
return _count(state, code)
Expand All @@ -62,66 +73,76 @@ getmetatable(state).count = function(state, name)
end
end

function can_reach(location_name, out_of_logic)

-- logic resolvers (called from json locations)


function can_reach(location_name)
if not hasAnyWatch then
state.stale = true
end
return def:get_location(location_name):can_reach(state)
end

function can_glitch(location_name)
return can_reach(location_name, true)
if not hasAnyWatch then
glitchState.stale = true
end
return glitchDef:get_location(location_name):can_reach(glitchState)
end

function dump(o, level)
level = level or 0
if level > 10 then
return "F"
end
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v, level + 1) .. ','
end
return s .. '} '
else
return tostring(o)
end

-- logic init (called to init/update def and state for logic and out-of-logic)


function set_options()
def:set_options(pseudoregalia_options)
end

--print(dump(def))
--print(dump(def.regions))
--print(dump(getmetatable(def.regions)))

function create_regions()
function _create_regions(def)
for region_name, _ in pairs(region_table) do
def.regions:append(Region:new(region_name, def))
end

for loc_name, loc_data in pairs(location_table) do
-- if not loc_data.can_create() ...
region = def:get_region(loc_data.region)
local region = def:get_region(loc_data.region)
new_loc = Location:new(loc_name, loc_data.code, region)
region.locations:append(new_loc)
end

for region_name, exit_list in pairs(region_table) do
region = def:get_region(region_name)
local region = def:get_region(region_name)
region:add_exits(exit_list)
end

-- locked items
-- TODO: events if it uses events
end

function create_regions()
_create_regions(def)
_create_regions(glitchDef)
end

function set_rules()
-- TODO: difficulty
-- TODO: setup difficulty toggles/addwatch for codes normal, hard, expert, lunatic
PseudoregaliaNormalRules:new(def):set_pseudoregalia_rules()
PseudoregaliaHardRules:new(def):set_pseudoregalia_rules()
PseudoregaliaExpertRules:new(def):set_pseudoregalia_rules()
PseudoregaliaLunaticRules:new(def):set_pseudoregalia_rules()
local difficulty = def.options.logic_level.value -- .value because lua can't override __eq for number
if difficulty == difficulties.NORMAL then
print("Setting difficulty to normal")
PseudoregaliaNormalRules:new(def):set_pseudoregalia_rules()
elseif difficulty == difficulties.HARD then
print("Setting difficulty to hard")
PseudoregaliaHardRules:new(def):set_pseudoregalia_rules()
elseif difficulty == difficulties.EXPERT then
print("Setting difficulty to expert")
PseudoregaliaExpertRules:new(def):set_pseudoregalia_rules()
elseif difficulty == difficulties.LUNATIC then
print("Setting difficulty to lunatic")
PseudoregaliaLunaticRules:new(def):set_pseudoregalia_rules()
else
error("Unknown difficulty " .. tostring(difficulty.value))
end
PseudoregaliaLunaticRules:new(glitchDef):set_pseudoregalia_rules()
end

function stateChanged(code) -- run by watch for code "*" (any)
Expand All @@ -133,6 +154,7 @@ end

function difficultyChanged() -- run by watch for code "logic"
print("difficulty changed")
set_options() -- update world option emulation
set_rules() -- recreate rules with new code(s) in Tracker
end

Expand All @@ -148,6 +170,8 @@ end


-- LAYOUT SWITCHING


function apLayoutChange1()
local progBreaker = Tracker:FindObjectForCode("progbreakerLayout")
if (string.find(Tracker.ActiveVariantUID, "standard")) then
Expand Down
27 changes: 27 additions & 0 deletions scripts/logic/options.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- this is roughly eqiovalent to AP player options
-- TODO: use require for constants and helper


local difficulties = constants.difficulties
local Choice = helper.Choice


LogicLevel = {
value_to_code = {
[difficulties.NORMAL] = "normal",
[difficulties.HARD] = "hard",
[difficulties.EXPERT] = "expert",
[difficulties.LUNATIC] = "lunatic",
},
default = difficulties.NORMAL,
}
setmetatable(LogicLevel, Choice)


options = {
pseudoregalia_options = {
logic_level = LogicLevel
}
}

return options

0 comments on commit bef6bde

Please sign in to comment.