Circuit network design
Moderator: ickputzdirwech
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Circuit network design
I want to suggest something about the current circuit network design is unintuitive / inconsistent. My rationale is a little technical, but i think that my main point applies to any audience using logic networks. I'm basing my thoughts off 10ish hours of just playing with networks in Factorio + experience outside of Factorio
I see the current circuit network design as each network instance has its own dictionary of 0+ key -> value pairs. The player can implement custom logic on any network using the three Factorio combinators. These combinators can reference their network in terms of its key -> value pairs. Here are a few restrictions on these key -> value pairs that are relevant to my discussion
All keys must have a non-null value, or they won't be included in the dictionary
0 is treated as a null value
All values must be integers
These properties have some implications
1. This algorithm compresses the 0's out of the network's representation, meaning less overhead for each individual network and less computation for each evaluation of "any", "all", "each" operations. In my thinking, 0's probably form the majority of a Factorio network's unreferenced bloat, caused by reading chest contents
2. 0 as a value in a key -> value pair is always as a null value / missing key rather than as the integer value less than 1 and greater than -1. As an example, for a network with no coal signal, checking network[coal] == 0 implicitly returns false as the 0 on the right represents an integer and the one on the left represents null. The rationale for why this is happening will not be clear for some players
3. A player who wants to reference the integer value 0 in a key->value pair is going to need to jump through hoops
Here's a common example: say I want to check when a chest runs out of entity X, ie its value equals zero. The easiest way to do this with the current implementation is to: read the chest's contents, increase the value of the key(s) that I want to check by 1, and then check that the sum equals 1. While possible, mapping between integer 0 and null 0 poses a repetitive problem for any larger scale abstraction that needs to use both representations of 0
Overall, I think the current implementation conflates too many goals. Aspects of what, to me, is mainly a performance optimization in a way have become the player's problem. Not only do players lack the tools to effectively approach this problem, but, more importantly, they likely have no interest in this specific problem at all (they just wanted to check if the chest was empty!!)
I think the player would be better off having access to 0 as an integer and null as a seperate special value and/or key. While initially I thought I liked the simplicity of dealing with non-nullable ints, now i see that they're still nullable, its just that null is confusingly disguised as 0. I think spelling null out as a special value/key is exclusively more clear for the uninformed user than repurposing 0. Also, you'd probably just label null in the UI as "No signal" or something, and I think that's a pretty intuitive starting point for any audience
This alternative design would need additional development to achieve similar levels of performance as the current. Without knowing more about Factorio's needs for logic network performance and reliability, i'm a little too far out into the unknown to contribute... I don't even know if Factorio's circuit network update implementation is scan based or event based...
I see the current circuit network design as each network instance has its own dictionary of 0+ key -> value pairs. The player can implement custom logic on any network using the three Factorio combinators. These combinators can reference their network in terms of its key -> value pairs. Here are a few restrictions on these key -> value pairs that are relevant to my discussion
All keys must have a non-null value, or they won't be included in the dictionary
0 is treated as a null value
All values must be integers
These properties have some implications
1. This algorithm compresses the 0's out of the network's representation, meaning less overhead for each individual network and less computation for each evaluation of "any", "all", "each" operations. In my thinking, 0's probably form the majority of a Factorio network's unreferenced bloat, caused by reading chest contents
2. 0 as a value in a key -> value pair is always as a null value / missing key rather than as the integer value less than 1 and greater than -1. As an example, for a network with no coal signal, checking network[coal] == 0 implicitly returns false as the 0 on the right represents an integer and the one on the left represents null. The rationale for why this is happening will not be clear for some players
3. A player who wants to reference the integer value 0 in a key->value pair is going to need to jump through hoops
Here's a common example: say I want to check when a chest runs out of entity X, ie its value equals zero. The easiest way to do this with the current implementation is to: read the chest's contents, increase the value of the key(s) that I want to check by 1, and then check that the sum equals 1. While possible, mapping between integer 0 and null 0 poses a repetitive problem for any larger scale abstraction that needs to use both representations of 0
Overall, I think the current implementation conflates too many goals. Aspects of what, to me, is mainly a performance optimization in a way have become the player's problem. Not only do players lack the tools to effectively approach this problem, but, more importantly, they likely have no interest in this specific problem at all (they just wanted to check if the chest was empty!!)
I think the player would be better off having access to 0 as an integer and null as a seperate special value and/or key. While initially I thought I liked the simplicity of dealing with non-nullable ints, now i see that they're still nullable, its just that null is confusingly disguised as 0. I think spelling null out as a special value/key is exclusively more clear for the uninformed user than repurposing 0. Also, you'd probably just label null in the UI as "No signal" or something, and I think that's a pretty intuitive starting point for any audience
This alternative design would need additional development to achieve similar levels of performance as the current. Without knowing more about Factorio's needs for logic network performance and reliability, i'm a little too far out into the unknown to contribute... I don't even know if Factorio's circuit network update implementation is scan based or event based...
Re: Circuit network design
Specific signal == 0 is a valid check and will return true as expected if there is no value on that specific channel. It will likewise behave as expected in the Everything or Each wildcards, returning true if (and only if) all channels have no value. The one exception is Any; Any == 0 will always return false, because only channels with values are considered on the Any side of things.
Re: Circuit network design
Small correction: all three wildcards only consider non-zero signals. E.g. [Each + 2 -> Each] in an arithmetic combinator will not magically return all signals with value 2 (even though I sometimes wish it did). [All = 0] returns true when no values are supplied because the All wildcard always returns true when no signals are supplied, e.g. [All != 0] similarly returns true when no input signals are supplied.
The mental model that I use is as follows:
Each = "for each non-zero value"
Everything = "if all non-zero values (true if none supplied)"
Anything = "if any non-zero values (false if none supplied)"
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
Goes to show, don't test things at 2am and talk about it. I could have sworn it output false for a zero value, but you're totally right that you can check if an individual value equals 0 and get an intuitive result. But i'd only change my argument a little bit, and maybe provide a different example focused on set operators and individual operators conflicting
while the logic for setting a key = 0 and later checking if its specific value equals 0 is now consistent and intuitive in at least its result, the logic between checking zero is now inconsistent between the single key operator and the set operators. For example, if i check if a specific key = 0, and that returns true, then my expectation that checking if anything, including that key, equals 0 should also return true based exclusively on that key and the prior check (but it doesn't necessarily have to, which is a logical inconsistency). A variation of this inconsistency is present for the "all" operator for comparisons against 0 when compared to running the same comparison against 0 on each member of the set individually and combining them all with "and" operators
Obviously i wouldn't call this a showstopper of a design flaw, you don't even see it as an issue, but i still think its a design flaw that causes odd circuit designs when it comes to dealing with 0 on sets and its not the players fault or, i think, the goal of what should be a problem for the player
while the logic for setting a key = 0 and later checking if its specific value equals 0 is now consistent and intuitive in at least its result, the logic between checking zero is now inconsistent between the single key operator and the set operators. For example, if i check if a specific key = 0, and that returns true, then my expectation that checking if anything, including that key, equals 0 should also return true based exclusively on that key and the prior check (but it doesn't necessarily have to, which is a logical inconsistency). A variation of this inconsistency is present for the "all" operator for comparisons against 0 when compared to running the same comparison against 0 on each member of the set individually and combining them all with "and" operators
I'm not sure what you mean when you say "behave as expected". I'd expect saying Any(condition) should return the same thing as testing that condition on each signal present in the network and getting a true for any of them or a false for all of them. However, this expectation doesn't hold when the condition is about 0, due to the design of 0 necessarily representing an absent signal and also potentially representing a integer value (for instance, when the condition is a comparison to 0)It will likewise behave as expected in the Everything or Each wildcards, returning true if (and only if) all channels have no value. The one exception is Any; Any == 0 will always return false, because only channels with values are considered on the Any side of things.
I think we're on a similar page but we're recognizing the same symptoms as different things. You've bolded the non-zero piece of the enum function, which is the inconsistency with individual checks ive described aboveSmall correction: all three wildcards only consider non-zero signals. E.g. [Each + 2 -> Each] in an arithmetic combinator will not magically return all signals with value 2 (even though I sometimes wish it did). [All = 0] returns true when no values are supplied because the All wildcard always returns true when no signals are supplied, e.g. [All != 0] similarly returns true when no input signals are supplied.
The mental model that I use is as follows:
Each = "for each non-zero value"
Everything = "if all non-zero values (true if none supplied)"
Anything = "if any non-zero values (false if none supplied)"
Obviously i wouldn't call this a showstopper of a design flaw, you don't even see it as an issue, but i still think its a design flaw that causes odd circuit designs when it comes to dealing with 0 on sets and its not the players fault or, i think, the goal of what should be a problem for the player
Re: Circuit network design
That's true; *however*, in the specific case I was talking about, Everything == 0 and Each == 0, the combinators will still evaluate to the same results as they would if they *were* actively considering all the channels.Allaizn wrote: βMon Sep 30, 2019 10:20 pmSmall correction: all three wildcards only consider non-zero signals. E.g. [Each + 2 -> Each] in an arithmetic combinator will not magically return all signals with value 2 (even though I sometimes wish it did). [All = 0] returns true when no values are supplied because the All wildcard always returns true when no signals are supplied, e.g. [All != 0] similarly returns true when no input signals are supplied.
The mental model that I use is as follows:
Each = "for each non-zero value"
Everything = "if all non-zero values (true if none supplied)"
Anything = "if any non-zero values (false if none supplied)"
I'm saying Any is the one where it doesn't work as you would expect: Any == 0 is not equivalent to (A == 0 || B == 0 || C == 0 || etc). For Each and for Every, they do evaluate equivalently to (A == 0 && B == 0 && C == 0 && etc).Serenity09 wrote: βMon Sep 30, 2019 11:47 pmI'm not sure what you mean when you say "behave as expected". I'd expect saying Any(condition) should return the same thing as testing that condition on each signal present in the network and getting a true for any of them or a false for all of them. However, this expectation doesn't hold when the condition is about 0, due to the design of 0 necessarily representing an absent signal and also potentially representing a integer value (for instance, when the condition is a comparison to 0)It will likewise behave as expected in the Everything or Each wildcards, returning true if (and only if) all channels have no value. The one exception is Any; Any == 0 will always return false, because only channels with values are considered on the Any side of things.
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
Oh okay, thank you for the addition/correction! i didn't know that about the "everything" wildcard. but i think you can still work a problematic example by swapping the comparison type
if i have a network reading from an almost empty chest and i test individually that entity X,Y equal 0 but Z does not equal 0, and i also test everything in [X,Y,Z] does not equal 0 then ill get true when i should get false
if i have a network reading from an almost empty chest and i test individually that entity X,Y equal 0 but Z does not equal 0, and i also test everything in [X,Y,Z] does not equal 0 then ill get true when i should get false
Also, i forgot about the edge cases for "everything" and "anything" operators on empty networks. First off, if everything can return true while anything returns false then that's probably not great. In this case however, it's more complicated, these contradicting results are your only ability to determine if a network has any signals whatsoever. Even if players find this check useful that just indicates, to me, that being able to properly check for signals completely missing from a network (ie, missing, not equal to 0) may be importantEverything = "if all non-zero values (true if none supplied)"
Re: Circuit network design
You're correct in that Everything != 0 will generate a true result as long as any signal exists. It's a little annoying; to successfully check that all channels in which you are interested have a non-zero value you need to play some additional (though not especially complicated) combinator games. Still, it's significantly easier for players to build that in the circumstances where needed (which isn't particularly common) than it would be to rework the combinator system, I think.Serenity09 wrote: βTue Oct 01, 2019 12:34 amOh okay, thank you for the addition/correction! i didn't know that about the "everything" wildcard. but i think you can still work a problematic example by swapping the comparison type
if i have a network reading from an almost empty chest and i test individually that entity X,Y equal 0 but Z does not equal 0, and i also test everything in [X,Y,Z] does not equal 0 then ill get true when i should get false
Also, i forgot about the edge cases for "everything" and "anything" operators on empty networks. First off, if everything can return true while anything returns false then that's probably not great. In this case however, it's more complicated, these contradicting results are your only ability to determine if a network has any signals whatsoever. Even if players find this check useful that just indicates, to me, that being able to properly check for signals completely missing from a network (ie, missing, not equal to 0) may be importantEverything = "if all non-zero values (true if none supplied)"
Re: Circuit network design
Not quite - [Everything != 0] will always be true, because it will be true in the empty case as well. [Anything != 0] is the one that is true iff there are any signals, and false if there are none.
It's exactly how it should be https://en.wikipedia.org/wiki/Empty_domain:Serenity09 wrote: βTue Oct 01, 2019 12:34 amFirst off, if everything can return true while anything returns false then that's probably not great
The example you gave isn't really convincing imo. You're saying it doesn't work as you expected, but that's not a good reason to change the mechanics - if anything, the description should be adjusted to reflect that zero-valued signals act as if they do not exist.The convention is to assign any formula beginning with a universal quantifier the value truth while any formula beginning with an existential quantifier is assigned the value falsehood. This follows from the idea that existentially quantified statements have existential import (i.e. they imply the existence of something) while universally quantified statements do not.
This sounds like a bad idea to me. Removing signals from a signal set can currently be done rather simply by setting their value to zero, but you're suggesting to not do that *without giving an alternative*. You're currently suffering the rather easily solvable problem of signals disappearing to often, while your suggestion would put you into the hell of them not disappearing often enough - you even said yourself, that there's an easy workaround that consists of simply supplying a value 1 signal for each of the signals of interest to prevent them from getting lost.Serenity09 wrote: βMon Sep 30, 2019 8:10 pmI think the player would be better off having access to 0 as an integer and null as a seperate special value and/or key.
-
- Fast Inserter
- Posts: 167
- Joined: Tue Sep 16, 2014 5:48 pm
- Contact:
Re: Circuit network design
I even don't understand how this should have any effect for players. Maybe you could check whether a train has slots reserved for ore. But the circuit system is THAT primitive and inconvenient, that you can't use this sensibly. For example a smart train station, changing the filter of filter inserters (to avoid unloading the wrong items), would need a horrible cable tangle.
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
foamy wrote:You're correct in that Everything != 0 will generate a true result as long as any signal exists. It's a little annoying; to successfully check that all channels in which you are interested have a non-zero value you need to play some additional (though not especially complicated) combinator games. Still, it's significantly easier for players to build that in the circumstances where needed (which isn't particularly common) than it would be to rework the combinator system, I think.
There must be a distinction somewhere between what types of problems are meant to be involved in Factorio's combinator system and issues that shouldn't need to be solved by the playerFactoruser wrote:I even don't understand how this should have any effect for players. Maybe you could check whether a train has slots reserved for ore. But the circuit system is THAT primitive and inconvenient, that you can't use this sensibly. For example a smart train station, changing the filter of filter inserters (to avoid unloading the wrong items), would need a horrible cable tangle.
I think players should also be able to reference and interact with 0 values consistently and easily across combinator operators, but I also get that the existing 0/null mapping makes it much more complicated than that
I also think that you can't really compare development difficulty to (unintentional) player difficulty. There are times where unintentional difficulty adds to the experience, but i don't think this is one of them. In general, i think systems of symbolic representation inherently allow access to plenty of problems to solve, easy - hard take your pick, and should limit their self-inflicted difficulties when they can. Everybody is okay that you need to speak or write English to communicate with it, but in general people hate the weird rules and nuances associated with the language. Language exceptions don't add to the joy and meaning of the language, they undercut it. This is a similar deal to me, combinators are acceptable communication, weird rules to their logic are their flaw
Cool, thanks for sharing that, i obviously came to the wrong conclusion. That said, i probably shouldn't have even said that bit at the start. This is the piece i think is worth discussing:Allaizn wrote:It's exactly how it should be https://en.wikipedia.org/wiki/Empty_domain:
Serenity wrote:In this case however, it's more complicated, these contradicting results are your only ability to determine if a network has any signals whatsoever. Even if players find this check useful that just indicates, to me, that being able to properly check for signals completely missing from a network (ie, missing, not equal to 0) may be important
I do a better job appreciating what i think is your perspective in my 2nd take (below)Allaizn wrote:The example you gave isn't really convincing imo. You're saying it doesn't work as you expected, but that's not a good reason to change the mechanics - if anything, the description should be adjusted to reflect that zero-valued signals act as if they do not exist.
Something does not need to be impossible for it to be flawed. The issue is not adding or removing 0/null signals/keys from a set, its relating to those values as either 0 or as null, and then continuing to abstract from those relationshipsAllaizn wrote:This sounds like a bad idea to me. Removing signals from a signal set can currently be done rather simply by setting their value to zero, but you're suggesting to not do that *without giving an alternative*. You're currently suffering the rather easily solvable problem of signals disappearing to often, while your suggestion would put you into the hell of them not disappearing often enough - you even said yourself, that there's an easy workaround that consists of simply supplying a value 1 signal for each of the signals of interest to prevent them from getting lost.
Also, how do you check if a key has never appeared on a network vs its currently set to 0? Not necessary if your network controls all its inputs, you simply fix in stone that the key has never and will never exist on that specific network, after all, its for your-use-only and you get to decide such things. But blueprints shared with other players and do not necessarily even want control over some or all of their inputs. Circuit networks are probably one of the best blueprint candidates in Factorio: extremely high LoE to plan and wire, but very low materials cost to actually build. The inability to differentiate between a null key and a 0 value has no workaround and limits designs here
Ive described alternatives a few times, but i wouldnt say i have a single "best" recommendation. The 3 restrictions on keys in my first post form an ambitious design decision that they've made with a lot of good arguments for and against it. I think that the first decision is to revisit Factorio's circuit network requirements - define its target flexibility, ease-of-use, and presentation - and re-assess if the current design meets these goal. If the decision is its fine, then ill say "okay, both it and the English language are perfect, definitely no room for improvement". But if its not fine, maybe in the ways that ive described here, then ill say "okay, maybe we need to allow the user to differentiate between null and 0 some of the time after all, at least in the set operators... i wonder if we can still present them as being the same for most simple networks -- what would that mean for consistency & the other networks & player defined logic & how the hell would we distinguish between network types", then the conversation continues. Trying to have the full conversation without the developer is pointless thoughAllaizn wrote:*without giving an alternative*
Something i didn't consider enough until reading both of your comments is what would i think of the implementation if all operations returned intuitively consistent results, even if they continued to reference, or at least present, 0 and missing signals as being the same thing
To start, I think the simplest definition for consistent would mean that the "everything" and "anything" set operators could take any network, and any condition, and would always return the same result as by checking each key individually against that same condition and then combining the results with the appropriate operator [and, or]
For arguments sake, you can also make an alternative definition of "everything" and "anything" in the way Allaizn/current Factorio does, having not just the standard "everything" / "anything" logic, but also implicitly only include non-zero/null values in their operational set. Now there's no contradiction between these extended set operators and individual operators, but there's also a much blurrier relationship between the two when it comes to interacting with 0
My main problem with this extended definition implicitly excluding 0s/nulls is that it requires more nuanced understanding than i think this feature should require. Occasionally, not having this understanding may lead to set operators that seem buggy, when instead they're just personally unintuitive. This lack of intuition translates to difficulty in abstraction -- Ex,
Code: Select all
(AnythingButA xor A) and A(c)
Going back to the other definition of just including 0s, yeah on the surface its maybe simpler and more intuitive, but now the set operators are much less useful. By including all keys, defaulting nulls to 0, it'll be impossible to distinguish between keys that were never there and keys that could have 0 values. Every network would be as if there was an empty chest reading its contents to it. So including 0s/nulls in set operations would only work when a network is compatible with having 1+ chest output its contents. This alternative probably would fill a much less common need than simply excluding 0s/nulls does, and there are still situations where you'd want to include 0's but not nulls, or vice-versa, so there's still some unfilled usability gap
Beyond the logical consistency / expectation of the player, there's the usability issue of only having the "everything" and "anything" operators to execute conditions on sets, but at the same time being limited to either implicitly including 0s/nulls or excluding them (as is currently happening). By choosing to treat 0 as representing a null key, you effectively forced yourself into making one of these two choices. Either choice of implicit behavior will not fit every network, and those misfits will create extra player implementation and usability hurdles that don't seem to fit my perception of the goals of the rest of the system
Even if you exposed the implicit treatment of 0s/nulls as a UI toggle for set operators and made that inclusive/exclusive behavior the user's responsibility, you'll still be unable to distinguish null from 0. This is largely okay in Factorio, i think it only starts to be limiting if you don't assume responsibility of a network (ie an untrustworthy network from another player, or defining a network to be used by and take input from other players)
It's important to keep in sight that a large % of Factorio networks are and will continue to be perfectly happy implicitly treating 0s/nulls the same and excluding them from their set operators. These generalizations translate to decreased complexity for the player when they're appropriate, and increased complexity otherwise. I'm going to keep thinking, and read any more replies, before suggesting any more hard options
Re: Circuit network design
I still fundamentally think that your opinion/ viewpoint is biased due to not knowing things. You noticed that something didn't behave as you expected it too, and then immediately decided that this was bad. Factorio's circuit networks have a behaviour that is quite different from typical programming, the "0 == null" thing is just a small part of it.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmLanguage exceptions don't add to the joy and meaning of the language, they undercut it.
The only concrete example of the behaviour being undesirable I have seen here is that "Everything != 0" doesn't return true when there's something non-zero, which is logically flawed from the get go - no matter whether you use standard quantifiers, or Factorio's non-zero restricted ones. It's also easily solved by using the correct operation, namely "Any != 0", as I mentioned above.
From my point of view (after having spend hundreds of hours on just the CN, if not more than a thousand already), you're comming to the game and expect to learn the whole thing within a couple hours - and then be surprised when it's a lot harder than that. And after that your immediate reaction is to say "let's replace the whole thing with something that works like I want it to", which is as I said above a very bad place to start any kind of discussion about change - at least go and make the effort of properly explaining why there is any need for change at all.
I don't see how that is supposed to answer what I wrote. Putting it into your words, I wrote that your suggestion introduces an impossibility (removal of signals) and is thus flawed.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmSomething does not need to be impossible for it to be flawed.
It doesn't matter what your mental model of things is, there needs to be an actual way to do things. You suggested to split up the currently merged meaning of 0 and null, but you haven't mentioned in a single sentence how those states should be reached.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmThe issue is not adding or removing 0/null signals/keys from a set, its relating to those values as either 0 or as null, and then continuing to abstract from those relationships
I'm not trying to belittle you, but this is why I'm saying you're biased due to not knowing things. This can be done with a single [Each != 0 -> Each = 1] combinator that loops back on itself. Once any non-zero signal comes to the input, it'll always stay with value 1 on the output, ready to be used for whatever you need that knowledge.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmAlso, how do you check if a key has never appeared on a network vs its currently set to 0?
Yes, designing circuits for general use is hard, doesn't mean it should be changed.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmNot necessary if your network controls all its inputs, you simply fix in stone that the key has never and will never exist on that specific network, after all, its for your-use-only and you get to decide such things. But blueprints shared with other players and do not necessarily even want control over some or all of their inputs. Circuit networks are probably one of the best blueprint candidates in Factorio: extremely high LoE to plan and wire, but very low materials cost to actually build. The inability to differentiate between a null key and a 0 value has no workaround and limits designs here
And I politely disagree, circuits are one of the worst things to blueprint for Factorio, and it's not even relevant how they interact with blueprinting.
You're asserting that the 0 vs null merging is limiting in some way, but as long as you don't give an example of this, I will just as easily dismiss this as unfounded.
Please enlighten me then, because I have seen nothing that comes even close to being an actual alternative. Just saying "don't treat 0 and null identically" is nowhere close to enough.
I don't get where you even come from. It's rather obvious that exactly this already happened, and that the status quo is satisfactory. You making this post just to say "I don't like this, so change until I will, but I won't tell you how to, do the work yourself" is imo pretty arogant.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmThe 3 restrictions on keys in my first post form an ambitious design decision that they've made with a lot of good arguments for and against it. I think that the first decision is to revisit Factorio's circuit network requirements - define its target flexibility, ease-of-use, and presentation - and re-assess if the current design meets these goal. If the decision is its fine, then ill say "okay, both it and the English language are perfect, definitely no room for improvement".
That is not how the conversation continues, but how it starts. And so far you didn't do much if anything towards that.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmBut if its not fine, maybe in the ways that ive described here, then ill say "okay, maybe we need to allow the user to differentiate between null and 0 some of the time after all, at least in the set operators... i wonder if we can still present them as being the same for most simple networks -- what would that mean for consistency & the other networks & player defined logic & how the hell would we distinguish between network types", then the conversation continues.
What are you expecting to happen here? For the devs to jump in and waste hours of their time chatting with everyone who posts here, when other users can point out flaws of suggestions just as well if not better?Serenity09 wrote: βTue Oct 01, 2019 1:48 pmTrying to have the full conversation without the developer is pointless though
That is exactly what they currently do. Hovering over a combinator shows you it's input and output values, and you'll clearly see that it does it's operation for every input signal if configured to do so. They behave exactly like a bag of things would behave - if I ask you whether you have more than 2 of each thing in your bag, you would never say "of course not, I don't have an apple in there, so there's !(0 > 2), the answer will be obviously no! And even if I had an apple, I could do the same argument with pears, pencils, books, glasses, etc etc, so it'll always be no". You would instead go an look inside your bag and only look whether the things that are actually in there have a quantity of more than 2.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmSomething i didn't consider enough until reading both of your comments is what would i think of the implementation if all operations returned intuitively consistent results, even if they continued to reference, or at least present, 0 and missing signals as being the same thing
To start, I think the simplest definition for consistent would mean that the "everything" and "anything" set operators could take any network, and any condition, and would always return the same result as by checking each key individually against that same condition and then combining the results with the appropriate operator [and, or]
Everything before this is mostly nonsense to me, I don't even get what you are saying, because you either don't explain what you mean, or use far to abstract explanations.Serenity09 wrote: βTue Oct 01, 2019 1:48 pmy choosing to treat 0 as representing a null key, you effectively forced yourself into making one of these two choices. Either choice of implicit behavior will not fit every network, and those misfits will create extra player implementation and usability hurdles that don't seem to fit my perception of the goals of the rest of the system
As for the above sentence, that's like saying "when walking, you're either restricted to starting with the left foot or with the right one, and there will always be a situation where one of them is a misfit" and thus argue that you absolutely need to learn to walk on your hands. My answer to that is simply that there is no practical need whatsoever for that. Your "player expectation" may be that it should be possible, but I (and most people I know) would say that this is highly misplaced.
And all of the above still doesn't even get started, since you still didn't really state what and how you want things to change, and why that would be better for most players (that actually use circuits).
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
Okay Allaizn, i think i get what's going on a bit. You're frustrated that im voicing such strong opinions after having played with Factorio's implementation of logic for only a handful of hours. My sentence disclaiming playtime was not for you, a player, it was for the developers to better contextualize my perspectives. I also noted that I have experience with symbolic systems beyond Factorio. That experience happens to be relevant to this topic, and i think that my thoughts are sufficient to discuss this design. My knowledge on Factorio is, by own admission, naive in some ways. Here is the singular detail about my Factorio knowledge that really matters to this conversation:
All signal's must have a non zero value or they won't be included in a network
All values must be integers
The first list are requirements related to the feature's (likely) code implementation, the second list are the requirements as Factorio relates them to the player. You can see that the first two bullets in the top list have collapsed into a single bullet in the bottom list, because that detail has been hidden under Factorio's implementation, and the player has no reason to be aware of it (or, at least, they shouldn't have any awareness of it)
So im not sure why you're talking down to me so much, about not just Factorio knowledge but the implications of it
I'll expand that example of a problematic use cases:
If i want to output wood only when input contains wood and none of the other fuel types, then ill want to check
However this performs unexpectedly if its possible for wood to have a 0/null value. To get around this we boost the signal of wood by 1 and check 1 instead, great. Then in my next component i need to refer to the same 0-safe version of the signal, and even later i want to refer to the original integer. This is such a simple example of the issue and yet its already starting to be a headache. What about trying to make a subsystem reusable, given that it maps 0s and wants to output the mapped value? Do you start have converters between your reusable subsystems to be compatible with both mapped and unmapped integers?
You keep asking for specific problem use-cases, but I think that the rationale for why the current design leads to these problem use cases is actually more important to understand what's not ideal about the design and considering design alternatives. Also, this is a suggested design flaw, not an implementation bug, or a feature request. We already are talking about the topic as concretely as we likely will in this thread
Restated in Factorio's terminology:Serenity wrote:All keys must have a non-null value, or they won't be included in the dictionary
0 is treated as a null value
All values must be integers
All signal's must have a non zero value or they won't be included in a network
All values must be integers
The first list are requirements related to the feature's (likely) code implementation, the second list are the requirements as Factorio relates them to the player. You can see that the first two bullets in the top list have collapsed into a single bullet in the bottom list, because that detail has been hidden under Factorio's implementation, and the player has no reason to be aware of it (or, at least, they shouldn't have any awareness of it)
So im not sure why you're talking down to me so much, about not just Factorio knowledge but the implications of it
I'll expand that example of a problematic use cases:
Code: Select all
(AnythingButA xor A) and A(c)
Code: Select all
(anything(fuel types excluding wood) xor wood) and (wood > 0)
You keep asking for specific problem use-cases, but I think that the rationale for why the current design leads to these problem use cases is actually more important to understand what's not ideal about the design and considering design alternatives. Also, this is a suggested design flaw, not an implementation bug, or a feature request. We already are talking about the topic as concretely as we likely will in this thread
Re: Circuit network design
No, I'm talking as a guy with source access who would potentially try to implement changes if they make sense.Serenity09 wrote: βTue Oct 01, 2019 4:03 pmYou're frustrated that im voicing such strong opinions after having played with Factorio's implementation of logic for only a handful of hours. My sentence disclaiming playtime was not for you, a player, it was for the developers to better contextualize my perspectives.
[Anything != Wood -> D = 1] tells you whether there is anything that has a non-wood value, which can only happen if there is something that is not wood on the network. [Each == Wood -> C = 1] counts the number of signals that are equal to wood and we obviously want that to be 1, but the catch is that it'll be zero if wood is zero, but that's solved by adding a [wood == 0 -> C = 1] combinator in parallel to that. Your request is thus fulfilled by passing the wood signal through iff D is 0 and C is 1, which only happens if their sum is 1, which is nice, since we can just output everything to C directly (no need for D), and get the sum directly.Serenity09 wrote: βTue Oct 01, 2019 4:03 pmIf i want to output wood only when input contains wood and none of the other fuel types, then ill want to check
The whole setup is thus:
1. take the input, and feed it into the following combinators:
a. [Anything != Wood -> C = 1]
b. [Each == Wood -> C = 1]
c. [Wood == 0 -> C = 1]
d. [Anything != 0 -> Wood = input] (don't lose the wanted wood signal)
2. Take the output of the four combinators a-d and feed them into [C = 1 -> Wood = input]
And this is just the first idea I had, it's probably possible to shrinkt it by a combinator or two with some of the more obscure tricks, but it's been a while since I dove that deeply into them.
I again reiterate that you seem to expect to have the whole thing being easy, but it's not. It's meant to be fun, and it wouldn't be fun if it weren't a challenge. If the vanilla functionality is too puzzly for you, I'd suggest to look at some of the mods that add custom combinators, afaik there are some that basically give you full programming ability - but imo that's almost entirely opposite of what combinators are supposed to be.Serenity09 wrote: βTue Oct 01, 2019 4:03 pmThis is such a simple example of the issue and yet its already starting to be a headache.
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
Again, im suggesting that the current design is flawed, not necessarily the goals of it. You are demanding a solution to that design problem that im saying is too complex to have a single "correct" solution, and providing a competitive alternative would require a lot more info on the feature's development and usability goals than i possessAllaizn wrote:No, I'm talking as a guy with source access who would potentially try to implement changes if they make sense.
I'm confident that I've provided enough information for a conversation on development to begin with one of the game's developers. I can't imagine that they'd want more concrete implementation suggestions about such a design from someone with my knowledge of their implementation and goals. If you have source code access than potentially you can provide more insight on Factorio's current implementation, design goals and requirements. Personally, I think the input on the design's current impact and the potential alternative designs that ive provided is much more useful to the conversation
If i get bored or really stubborn later ill write up a slightly more concrete, still very naive design implementation. Though, all ive got for now is regret
You can implement many boolean statements using multiple approaches. The "issue" is not how you implement this specific statement, its whether or not you needed to map from 0 -> 1 to access a value of 0, which you did need to do in step c. You've also implied that mapping from 0->1 is fine so long as you go back to the original unmapped value at the end, which is a way of answering some of my questions about what your end outputs should look like, but one that leaves additional questions. What about people that don't want to commit to that loose standard, and choose to either output mapped only or both raw and mapped values, they're just lepers now? What about subsystems that need its external input signals to have already been mapped from 0->1?[Anything != Wood -> D = 1] tells you whether there is anything that has a non-wood value, which can only happen if there is something that is not wood on the network. [Each == Wood -> C = 1] counts the number of signals that are equal to wood and we obviously want that to be 1, but the catch is that it'll be zero if wood is zero, but that's solved by adding a [wood == 0 -> C = 1] combinator in parallel to that. Your request is thus fulfilled by passing the wood signal through iff D is 0 and C is 1, which only happens if their sum is 1, which is nice, since we can just output everything to C directly (no need for D), and get the sum directly
Re: Circuit network design
Sorry to say this, but the 0 vs null problem is as old as combinators themselves, and it should be obvious that it has been discussed to death already.Serenity09 wrote: βTue Oct 01, 2019 5:02 pmI'm confident that I've provided enough information for a conversation on development to begin with one of the game's developers.
Which is exactly why I'm demanding it: it's a waste of time to unroll the whole reasoning for why the current thing is the way it is if you don't have a good reason for it. Saying "I want to discuss this" is nice, but it doesn't really help at all.Serenity09 wrote: βTue Oct 01, 2019 5:02 pmYou are demanding a solution to that design problem that im saying is too complex to have a single "correct" solution
I'm sure that you want to help, but please consider that the approach you take here isn't realisitc. It's mostly a "I have little to no idea about it, so please explain all of it to me so that I understand, and then also listen to my complaints, and then, if I'm not bored of it at that point, I'll maybe give you a suggestion that actually helps" - nobody has time for that.
I disagree on that one. If there were some magic implementation that perfectly kept the zero signals you wanted while not cluttering everything with unrelated signals, the solution I gave would look nearly identical - just remove combinator c. And given this similarity, it's imo quite a stretch to say that the current system is very restrictive (yes there is some, but hardly a lot once you get used to it).Serenity09 wrote: βTue Oct 01, 2019 5:02 pmThe "issue" is not how you implement this specific statement, its whether or not you needed to map from 0 -> 1 to access a value of 0, which you did need to do in step c.
You try to argue on a very general level, but I reject that because you're lacking the knowledge to make meaningful general statements about circuit networks due to lack of experience with it. That's why I'm saying that you should look for concrete examples. Come up with some circuits that check these two as much as possible:
- they are very useful to have (which needs you to explain why they would be useful - "just to have them/ they're clever" is not a good answer for that)
- they are currently either impossible, or only very hard to do
If you can't do that, then either
- your change helps a usecase that is irrelevant, or
- you're solving an already solved problem, or
- you're breaking everything else just to satisfy yourself
I guess I'm looking forward to it then, and I'm not quite sure what makes you regret anything here - I certainly wouldn't say that you did anything wrong here. It's great to see that someone not only has interest and fun with circuits, but also thinks about how to make them betterIf i get bored or really stubborn later ill write up a slightly more concrete, still very naive design implementation. Though, all ive got for now is regret
Re: Circuit network design
This looks like a good place to (once more) show how a distinction could act and be implemented:
The issue might have moved into modded-only terrain...
That being said, within the circuit network you can work around the zero / not present (or null) merge by carrying presence information separately, at the cost of doubling the combinator count. The real problem arises once we're interacting with (modded) machinery, e.g. AAI's inability to handle coordinate {0, 0}. Before 0.17 there also was the occasional "reading train content gives nothing but wagon still contains 0.x fluid" thread, but as fluid mixing is no longer possible pumps now act intelligently without the help of the circuit network.Nidan wrote: βThu Feb 21, 2019 1:08 amBut I'd like if a distinction between "signal is zero" and "signal is not present" were added.
Most entities would continue to work as now
- Outputting a signal results in that signal being present
- Reading a signal that isn't present is treated as zero
For arithmetic (mainly the arithmetic combinator, but also the implicit add when merging cables), the result is present if at least one signal operand is present, except that division by zero should result in "not present".
For decisions (decider combinator, any entity enable/disable setting) there would be two new tests: checking for the presence and absence of a signal. Output is present when condition is true.
All/Each/Any act on all present signals; as result "any == 0" is no longer a pointless test
The implementation could be a bitset, which should be both compact and efficient to update, as most operations will either output specific signals (machines, combinators not using "each"), forward the input set (arithmetic, decider with output "everything"), or or'ing multiple sets together (implicit add). Deciders using "each" would have to set each bit individually based on the condition, but compared to evaluating said condition setting the presence bit should be minor work.
The issue might have moved into modded-only terrain...
Re: Circuit network design
You're correct and that's my mistake; sorry for the incorrect info.
I'm not sure what you're picturing, but triggering filter inserters off a train's consist, a control signal, or both, isn't hard. If you had, say, a wagon that was to be filled with mixed goods, say for an outpost setup, you'd have a set of target signals and a set of signals from the train. For loading, you subtract the train's consist from the control signals (by inverting the train signals) and for unloading you subtract the control signals from the train's consist (by inverting the control signals). Then you feed the results to the inserters.Factoruser wrote: βTue Oct 01, 2019 12:31 pmI even don't understand how this should have any effect for players. Maybe you could check whether a train has slots reserved for ore. But the circuit system is THAT primitive and inconvenient, that you can't use this sensibly. For example a smart train station, changing the filter of filter inserters (to avoid unloading the wrong items), would need a horrible cable tangle.
What you do here is you take a constant combinator with all the non-wood fuel types output as 1, and feed both that and the value from whatever you're measuring into a decider combinator that outputs a flag signal when all of those are equal to 1. Then you multiply the flag signal by the wood signal from your measurement.Serenity09 wrote: βTue Oct 01, 2019 4:03 pmI'll expand that example of a problematic use cases:If i want to output wood only when input contains wood and none of the other fuel types, then ill want to checkCode: Select all
(AnythingButA xor A) and A(c)
Code: Select all
(anything(fuel types excluding wood) xor wood) and (wood > 0)
In more complex schemas, for multiplexing or filtering, you generally introduce a large bias value on the values you either wish to filter *for* or filter *out*. This is very very common. The specifics rely on knowledge of what domain those values are likely to exist in, but very few signals in Factorio ever *naturally* get to two billion, so you've got quite a bit of room to work with.
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
Okay i thought maybe we'd try a different approach to the topic. I'm going to provide a survey, all related to implications about this design decision, and anyone that would like is encouraged to answer them. Answer "unsure" if you don't really know how the question would apply to your needs
Please answer every question with a clear "yes" or "no", and an explanation, if you want
1. Do you ever want your set operators ("anything", "everything", "each") to include all channels with 0 values as 0, like how checking a channel individually works, rather than exclude them?
2a. Do you enjoy mapping between 0 and other numbers?
2b. Do you enjoy the hurdles of using both set logic and individual logic on the same network channel?
3a. Do you want to make networks that can be reused?
3b. Do you want to share circuit network blueprints? Either make or receive. Playing with other people counts as a 'yes'
3c. Do you want share ideas about circuit networks?
Please also score the following 1-5, with 1 being very low and 5 being very high. No scores ending in .5, please
Your experience with Factorio's circuit networks or similar (1-5):
Your interest in using circuit networks in your factory (1-5):
Your satisfaction currently using circuit networks in your factory (1-5):
Feel free to stop reading here! Thank you for contributing! Everything in my next post is either educational or technical
Please answer every question with a clear "yes" or "no", and an explanation, if you want
1. Do you ever want your set operators ("anything", "everything", "each") to include all channels with 0 values as 0, like how checking a channel individually works, rather than exclude them?
2a. Do you enjoy mapping between 0 and other numbers?
2b. Do you enjoy the hurdles of using both set logic and individual logic on the same network channel?
3a. Do you want to make networks that can be reused?
3b. Do you want to share circuit network blueprints? Either make or receive. Playing with other people counts as a 'yes'
3c. Do you want share ideas about circuit networks?
Please also score the following 1-5, with 1 being very low and 5 being very high. No scores ending in .5, please
Your experience with Factorio's circuit networks or similar (1-5):
Your interest in using circuit networks in your factory (1-5):
Your satisfaction currently using circuit networks in your factory (1-5):
Feel free to stop reading here! Thank you for contributing! Everything in my next post is either educational or technical
-
- Burner Inserter
- Posts: 15
- Joined: Mon Sep 30, 2019 4:26 pm
- Contact:
Re: Circuit network design
Ive realised that ive created a rather technical topic and encouraged you all to take the time to read it. I think i owe some of you a better explanation, if you want it. Here's a bit more background on the coding and terminology that's (probably) behind the scenes, and the terminology ive been using to describe this problem. I've also included an implementation alternative as a learning example
Null, in programming, roughly means "the abscence of." If you go to use toilet paper and the roll is now empty, that's a value of 0, but if the entire dispenser is just gone, that's a null.
By "null key" I always mean shorthand for a key that is not contained within a dictionary. This is a nice piece of short hand, because it's generally understood by the people using dictionaries without needing to explain
Dictionaries are a coding tool meant to describe a group of stuff. There are many descriptions of groups, but this particular description of a group emphasises each member in the group having some kind of identifier, like Factorio's Coal is a sort of an ID, mapping to any type of value, like Factorio's integer signals output by channels
A hashset is like a dictionary but, in most programming languages, is optimized to make getting a value from a key consistently fast. This property would appeal to Factorio networks, because many networks do exactly that
This description hopefully highlights why either a dictionary or a hashset likely form part of the core underlying code's implementation for networks and channels. I'm going to assume that is how Factorio implemented its system, but there are many other competitive options
For example, the set logic that likely generates an also significant amount of hardware use, would be happier just having a simple collection of values. My guess is that the overhead of accessing all values on a network from a dictionary definition is still better than having iterating the list to access/check for presence of specific elements. Still, both options are competitive, since they have different but relevant strengths
Yet another alternative would be to reimplement any of the above abstractions, or combination thereof, from the ground up, in an attempt to get better control over their performance and maybe better fit their implementation to the circuit network need.
This is part of why i didn't want to talk about this topic concretely, there's very little i can say confidently without further information. Let's go back to the semi-likely implementation option of using a Dictionary base and extending that
Assuming all that, it's likely that extending on top of that underlying dictionary logic is Factorio's logic representing their circuit network implementation. This logic would be what's responsible for defining the data types for their keys and their values, and some of these abstractions would be responsible for the systems presentation to the player:
The extended dictionary is presented as a "network"
The keys of the dictionary are referred to as "channels", and are probably of type EntityID, though the player just see's the Factorio inventory UI
The values of the dictionary are (i think?) referred to as "signals" ... whatever they're called, they're of type integer and the player see's them as an input box and slider
Then there's the additional logic not native to the base collection's implementation, which looks something like:
Setting a network's channel to 0 results in no change to the network
Reading a channel that does not exist within the network returns 0
Reading a set of channels has two implementation options resulting in different behaviors, and they each have separate pros and cons. You can either exclude 0s from the set, and be inconsistent with reading a single channel, or you can include them, and flood your set logic with more 0s than most networks want or know what to do with. The former, and current Factorio design, definitely seems to be the more appropriate for Factorio's usage, but there are times when the latter would be better
Before I talk about an alternative implementation, here's a list of crucial information that i'd suggest means we, and maybe even the game's developers, are not ready to discuss alternative implementations at all yet: what do Factorio's players want / enjoy from the circuit network feature; what characteristics for the circuit network's design best fit that user data; the possibility of presenting networks based partially on their definition; should any UI tools would exist for the player to interact with null keys; potentially UI alternatives and code to minimize nulls relevance on the player; potential exposure of the implicit set read behavior to the player as an entirely different alternative; optimization potential/constraints to support new overhead and computational cost of pushing 0s across the network; fuck it, at this point, let's just revisit execution consistency/determinism now too
Still, if you went with one person's personal preference, which would be a selfishly easy way to approach this problem, I'd suggest changing the value's data type to nullable, and allow 0 values to enter a dictionary. The existing logic around 0 values would then need to be redefined/removed. New logic would be introduced defining the behavior for Factorio's operators on nulls, which i believe would be mostly to not output anything ever, no matter the operation. The existing "everything" and "anything" logic for an empty dictionary would continue to fit their definition without change, and everything would output true. There is only one meaningful behavior for the set operator now. Originally i thought that i'd also suggest a special channel/key representing a null key as a way to interact with null separately, but now im thinking that would reintroduce many of the original needs and flaws of mapping unshareable values to shareable ones. I think the strength of this approach is in isolating nulls importance to both the player and their ideal presentation, and making it purely about key presence
With this implementation, input and (both) output operators will behave consistently. Usage of them will sometimes require more comparators to represent logic, and sometimes less. One performance implication of the current system, not including 0 values in the network, is that it offers both hardware compression and, when you don't need to remap 0 values, Factorio comparator compression. I think this is one cool thing about the current implementation's design, though i do wonder how cool it is for how many audiences. Anyways, this proposed alternative implementation means that instead of mapping 0s to another int value, you'll instead be dealing with pieces that do not need any remapping. The key implications of this exchange are hinted at in the questions above and elaborated on in the rationale below
Finally, Im also going to go through the rationale behind why each question is relevant to this design decision
1. Because a key having a value of 0 is the same as a null key, set logic must decide which way to treat channels that are missing. Either it must include as 0 or exclude it as a null key. This forces either a consistency issue by choosing to exclude them, or a too-large usability gap by including them. Differentiating between 0 and null means there's no longer any choice to be made in behavior at the implementation level, it's left up to the player at the circuit network level
2ab. These questions are unique to the current implementation. They can be seen as your quick take on certain aspects of Factorio's circuit network design, even when applied at some of the smallest scales. These questions do not need any complex situation or goal to be relevant, they will be relevant for almost all users of circuit networks. 2b will be particularly relevant but hard to gather unbiased player data on, and is a very large part of why i think developer/UI designer led formal user testing is necessary to better explore this topic
3abc. Remapping 0 to any other integer can be seen as starting a loose convention. A loose convention is something that you arbitrarily decided to be true and keep true. You get the non-zero version by performing the exact same calculation and you get back to the zero version by doing the exact reverse. This might not seem immediately problematic, after all, you say, you have 10 ways of remapping from 0 in your system! However, these individual loose conventions cause issues in isolating subsystems from your network for your personal re-use, and make it virtually impossible to share those isolated subsystems with others, unless they use the exact same conventions that your subsystems required. This is because your subsystem now contains a decision that was, originally, arbitrary. There is no way to anticipate, predict or build off of that arbitrary decision without electing to make the exact same one. If that arbitrary decision is not isolated within the subsystem then it will leak into other subsystems that relate to it. This is a problem for modularity, and as a player you currently have no tools to satisfactorily deal with it. While you can still technically share ideas about circuit networks without knowing eachother's conventions, loose conventions can still be a roadblock to clearly understanding eachother's points of view
The need to remap from 0, and the conventions that are introduced by doing so, is replaced in entirety by the ability to simply use 0
My personal experience is that this sort of survey will only be of interest to players already using the circuit network system. Generally, people that like to use inherently difficult systems are less likely to advertise how hard that same system is to use ("there's no issues as-is" / "it's not the problem, you're the problem"). This same emphasis on expertise will be, by definition, discouraging to players new to circuit networks or opposed to dealing with that level of complexity. To get a less biased view on your players, I'd highly recommend 1-1 and/or guided group user testing on both the existing implementation and prototypes of alternatives, trying to keep your sample diverse. I dont think any survey will give you a good snapshot on your players for this decision, but creating a survey is where i top out
Null, in programming, roughly means "the abscence of." If you go to use toilet paper and the roll is now empty, that's a value of 0, but if the entire dispenser is just gone, that's a null.
By "null key" I always mean shorthand for a key that is not contained within a dictionary. This is a nice piece of short hand, because it's generally understood by the people using dictionaries without needing to explain
Dictionaries are a coding tool meant to describe a group of stuff. There are many descriptions of groups, but this particular description of a group emphasises each member in the group having some kind of identifier, like Factorio's Coal is a sort of an ID, mapping to any type of value, like Factorio's integer signals output by channels
A hashset is like a dictionary but, in most programming languages, is optimized to make getting a value from a key consistently fast. This property would appeal to Factorio networks, because many networks do exactly that
This description hopefully highlights why either a dictionary or a hashset likely form part of the core underlying code's implementation for networks and channels. I'm going to assume that is how Factorio implemented its system, but there are many other competitive options
For example, the set logic that likely generates an also significant amount of hardware use, would be happier just having a simple collection of values. My guess is that the overhead of accessing all values on a network from a dictionary definition is still better than having iterating the list to access/check for presence of specific elements. Still, both options are competitive, since they have different but relevant strengths
Yet another alternative would be to reimplement any of the above abstractions, or combination thereof, from the ground up, in an attempt to get better control over their performance and maybe better fit their implementation to the circuit network need.
This is part of why i didn't want to talk about this topic concretely, there's very little i can say confidently without further information. Let's go back to the semi-likely implementation option of using a Dictionary base and extending that
Assuming all that, it's likely that extending on top of that underlying dictionary logic is Factorio's logic representing their circuit network implementation. This logic would be what's responsible for defining the data types for their keys and their values, and some of these abstractions would be responsible for the systems presentation to the player:
The extended dictionary is presented as a "network"
The keys of the dictionary are referred to as "channels", and are probably of type EntityID, though the player just see's the Factorio inventory UI
The values of the dictionary are (i think?) referred to as "signals" ... whatever they're called, they're of type integer and the player see's them as an input box and slider
Then there's the additional logic not native to the base collection's implementation, which looks something like:
Setting a network's channel to 0 results in no change to the network
Reading a channel that does not exist within the network returns 0
Reading a set of channels has two implementation options resulting in different behaviors, and they each have separate pros and cons. You can either exclude 0s from the set, and be inconsistent with reading a single channel, or you can include them, and flood your set logic with more 0s than most networks want or know what to do with. The former, and current Factorio design, definitely seems to be the more appropriate for Factorio's usage, but there are times when the latter would be better
Before I talk about an alternative implementation, here's a list of crucial information that i'd suggest means we, and maybe even the game's developers, are not ready to discuss alternative implementations at all yet: what do Factorio's players want / enjoy from the circuit network feature; what characteristics for the circuit network's design best fit that user data; the possibility of presenting networks based partially on their definition; should any UI tools would exist for the player to interact with null keys; potentially UI alternatives and code to minimize nulls relevance on the player; potential exposure of the implicit set read behavior to the player as an entirely different alternative; optimization potential/constraints to support new overhead and computational cost of pushing 0s across the network; fuck it, at this point, let's just revisit execution consistency/determinism now too
Still, if you went with one person's personal preference, which would be a selfishly easy way to approach this problem, I'd suggest changing the value's data type to nullable, and allow 0 values to enter a dictionary. The existing logic around 0 values would then need to be redefined/removed. New logic would be introduced defining the behavior for Factorio's operators on nulls, which i believe would be mostly to not output anything ever, no matter the operation. The existing "everything" and "anything" logic for an empty dictionary would continue to fit their definition without change, and everything would output true. There is only one meaningful behavior for the set operator now. Originally i thought that i'd also suggest a special channel/key representing a null key as a way to interact with null separately, but now im thinking that would reintroduce many of the original needs and flaws of mapping unshareable values to shareable ones. I think the strength of this approach is in isolating nulls importance to both the player and their ideal presentation, and making it purely about key presence
With this implementation, input and (both) output operators will behave consistently. Usage of them will sometimes require more comparators to represent logic, and sometimes less. One performance implication of the current system, not including 0 values in the network, is that it offers both hardware compression and, when you don't need to remap 0 values, Factorio comparator compression. I think this is one cool thing about the current implementation's design, though i do wonder how cool it is for how many audiences. Anyways, this proposed alternative implementation means that instead of mapping 0s to another int value, you'll instead be dealing with pieces that do not need any remapping. The key implications of this exchange are hinted at in the questions above and elaborated on in the rationale below
Finally, Im also going to go through the rationale behind why each question is relevant to this design decision
1. Because a key having a value of 0 is the same as a null key, set logic must decide which way to treat channels that are missing. Either it must include as 0 or exclude it as a null key. This forces either a consistency issue by choosing to exclude them, or a too-large usability gap by including them. Differentiating between 0 and null means there's no longer any choice to be made in behavior at the implementation level, it's left up to the player at the circuit network level
2ab. These questions are unique to the current implementation. They can be seen as your quick take on certain aspects of Factorio's circuit network design, even when applied at some of the smallest scales. These questions do not need any complex situation or goal to be relevant, they will be relevant for almost all users of circuit networks. 2b will be particularly relevant but hard to gather unbiased player data on, and is a very large part of why i think developer/UI designer led formal user testing is necessary to better explore this topic
3abc. Remapping 0 to any other integer can be seen as starting a loose convention. A loose convention is something that you arbitrarily decided to be true and keep true. You get the non-zero version by performing the exact same calculation and you get back to the zero version by doing the exact reverse. This might not seem immediately problematic, after all, you say, you have 10 ways of remapping from 0 in your system! However, these individual loose conventions cause issues in isolating subsystems from your network for your personal re-use, and make it virtually impossible to share those isolated subsystems with others, unless they use the exact same conventions that your subsystems required. This is because your subsystem now contains a decision that was, originally, arbitrary. There is no way to anticipate, predict or build off of that arbitrary decision without electing to make the exact same one. If that arbitrary decision is not isolated within the subsystem then it will leak into other subsystems that relate to it. This is a problem for modularity, and as a player you currently have no tools to satisfactorily deal with it. While you can still technically share ideas about circuit networks without knowing eachother's conventions, loose conventions can still be a roadblock to clearly understanding eachother's points of view
The need to remap from 0, and the conventions that are introduced by doing so, is replaced in entirety by the ability to simply use 0
My personal experience is that this sort of survey will only be of interest to players already using the circuit network system. Generally, people that like to use inherently difficult systems are less likely to advertise how hard that same system is to use ("there's no issues as-is" / "it's not the problem, you're the problem"). This same emphasis on expertise will be, by definition, discouraging to players new to circuit networks or opposed to dealing with that level of complexity. To get a less biased view on your players, I'd highly recommend 1-1 and/or guided group user testing on both the existing implementation and prototypes of alternatives, trying to keep your sample diverse. I dont think any survey will give you a good snapshot on your players for this decision, but creating a survey is where i top out
Last edited by Serenity09 on Thu Oct 03, 2019 1:32 pm, edited 1 time in total.
Re: Circuit network design
So, I'm going to vent for a bit, since this whole topic is starting to make me angry, which is why I'm probably not going to bother reading any further posts depending on how I feel after writing this. And to start off:
PSA and TLDR for OPs last post (below some more concrete things):
1. He goes over the absolute basics over what null, 0 and dictionary/hashset means, and then wrongly assumes that CNs are implemented like that (even quite simple performance tests would show you that it's at the very least very unlikely that that would be the case, and some knowledge about performance characteristics make it not too hard to guess what the actual implementation is), as well as weird guesses over some types, which are also highly unlikely after a look into the lua api.
2. Then he lists a few basic points to consider about the design of CNs, only to fully ignore them after that, while saying lots of "this shouldn't work like this" without saying how it should work instead.
3. Finally he gives some loose rational behind his survey questions that I summarize below.
First question is literally a "do you want to have a cake and eat it too?", whose answer is easily predicted to have a majorty "yes" vote, which tells you nothing. Britain wanted to leave EU and keep all benefits - and we saw how that went. The question also literally does not make any sense, because there are no channels with value 0, they literally do not exist, and if you ever manage to make a network have one and by chance did not immediately crash, then go and make a bug report about it.
2a. is making up an imaginary problem and then asking things about it: "do you like to be hit by a meteor on tuesday?" - what meteor, and why the hell only on tuesday?! Given that you wrote a huge wall of text below these questions, I'm simply assuming that you still didn't get the memo that you barely never have to map to or away from zero in nontrivial ways. It's not a problem, it never was, and as I have said it repeatedly: starting from some abstract principles and then arriving at "null != 0 is a problem" is not even close to showing that it is.
2b. What hurdle? There are no inconsistencies in the CN logic, and no hurdles to be taken apart from understanding things in the first place.
3a-c are another set of cake questions that are similarly pointless, and have nothing to do with the question at hand. Whether null and 0 are different or not has no implications about the shareability of circuits.
Thus, congratulations, you managed to make a survey that didn't just not make any step towards being "related to implications about this design decision", but instead went ahead and go straight for the opposite.
Now to the bits of that wall of text not already addressed above:
And with that I'm confirming what I said at the very start of this - this whole thread is pointless at best, and trolling at worst. There is no value in continuing this at all, so I'm out and I won't be back again.
PSA and TLDR for OPs last post (below some more concrete things):
1. He goes over the absolute basics over what null, 0 and dictionary/hashset means, and then wrongly assumes that CNs are implemented like that (even quite simple performance tests would show you that it's at the very least very unlikely that that would be the case, and some knowledge about performance characteristics make it not too hard to guess what the actual implementation is), as well as weird guesses over some types, which are also highly unlikely after a look into the lua api.
2. Then he lists a few basic points to consider about the design of CNs, only to fully ignore them after that, while saying lots of "this shouldn't work like this" without saying how it should work instead.
3. Finally he gives some loose rational behind his survey questions that I summarize below.
make up your mind! What's the point of "unsure", if you then immediately say "only yes or no please".Serenity09 wrote: βThu Oct 03, 2019 12:54 amI'm going to provide a survey, all related to implications about this design decision, and anyone that would like is encouraged to answer them. Answer "unsure" if you don't really know how the question would apply to your needs
Please answer every question with a clear "yes" or "no", and an explanation, if you want
That question set is imo severely lacking in practically every aspect.Serenity09 wrote: βThu Oct 03, 2019 12:54 am1. Do you ever want your set operators ("anything", "everything", "each") to include all channels with 0 values as 0, like how checking a channel individually works, rather than exclude them?
2a. Do you enjoy mapping between 0 and other numbers?
2b. Do you enjoy the hurdles of using both set logic and individual logic on the same network channel?
3a. Do you want to make networks that can be reused?
3b. Do you want to share circuit network blueprints? Either make or receive. Playing with other people counts as a 'yes'
3c. Do you want share ideas about circuit networks?
First question is literally a "do you want to have a cake and eat it too?", whose answer is easily predicted to have a majorty "yes" vote, which tells you nothing. Britain wanted to leave EU and keep all benefits - and we saw how that went. The question also literally does not make any sense, because there are no channels with value 0, they literally do not exist, and if you ever manage to make a network have one and by chance did not immediately crash, then go and make a bug report about it.
2a. is making up an imaginary problem and then asking things about it: "do you like to be hit by a meteor on tuesday?" - what meteor, and why the hell only on tuesday?! Given that you wrote a huge wall of text below these questions, I'm simply assuming that you still didn't get the memo that you barely never have to map to or away from zero in nontrivial ways. It's not a problem, it never was, and as I have said it repeatedly: starting from some abstract principles and then arriving at "null != 0 is a problem" is not even close to showing that it is.
2b. What hurdle? There are no inconsistencies in the CN logic, and no hurdles to be taken apart from understanding things in the first place.
3a-c are another set of cake questions that are similarly pointless, and have nothing to do with the question at hand. Whether null and 0 are different or not has no implications about the shareability of circuits.
This is at least something that isn't nonsensical in the first place, but it's pointless information regarding the topic. Whether I tell you that my answer is a straight 3 5s (which it is for the record), or whether it's 3 1s or anything in between has literally no bearing. All of your "survey" is asking how people *feel* about CNs, which is literally the last thing you want ever to know during a discussion. A game mechanic is characterized by it's interaction with the rest of the game, how well it fits into them, what it enables the player to do and how well it does that - neither of which has anything to do with feelings on the matter.Serenity09 wrote: βThu Oct 03, 2019 12:54 amPlease also score the following 1-5, with 1 being very low and 5 being very high. No scores ending in .5, please
Your experience with Factorio's circuit networks or similar (1-5):
Your interest in using circuit networks in your factory (1-5):
Your satisfaction currently using circuit networks in your factory (1-5):
Thus, congratulations, you managed to make a survey that didn't just not make any step towards being "related to implications about this design decision", but instead went ahead and go straight for the opposite.
Given that everything you wrote so far is still pretty much characterized by "I doesn't feel right to me", I'd say whatever you tried, it certainly wasn't a different approach.Serenity09 wrote: βThu Oct 03, 2019 12:54 amOkay i thought maybe we'd try a different approach to the topic.
Now to the bits of that wall of text not already addressed above:
You still failed to point out any inconstistency. I'd say given that 0 == null, then [coal == 0] being equivalent to [coal == null] is entirely consistent with the behaviour. [Everything == null] being false if there's even a single signal on the network also works out perfectly. Things like [Each < 5] ignoring null values is also perfectly reasonable, given that "null < 5" is at best invalid.
You still failed to even give a single example of where it would be better.Serenity09 wrote: βThu Oct 03, 2019 12:54 amThe former, and current Factorio design, definitely seems to be the more appropriate for Factorio's usage, but there are times when the latter would be better
You neither gave anything close to an implementation, nor did you show that it's consistent. Your text is a whole lot "I wish xxx, you go figure out the details", which is not how any of this works. You also failed to even acknowledge a major counter point for including 0 valued signals and how you'd attempt to solve it:Serenity09 wrote: βThu Oct 03, 2019 12:54 amThere is only one meaningful behavior for the set operator now. [...] With this implementation, input and (both) output operators will behave consistently.
I hoped it didn't need me to spell it out, but I was obviously wrong, so here you go: not providing a way to get rid of unwanted signals is a surefire way to pessimize the performance of any possible implementation of circuit networks, since any implementation will be slower in dealing with 300 signals per network than with 3.
Your rationale is heavily flawed in that the same reasoning can be applied to literally everything software related. There will always be things that have options (and there better be a lot of those for a game, or it failed being the thing it's supposed to be), and people will take different options which then make it harder to share things. Your argument is basically "I can't use your bot build in my belt design, so let's get rid of bots!" - yeah, no.
There's also the Dunning-Kruger effect and people think they have insight into something while having no idea what they even talk about.Serenity09 wrote: βThu Oct 03, 2019 12:54 amGenerally, people that like to use inherently difficult systems are less likely to advertise how hard that same system is to use ("there's no issues as-is" / "it's not the problem, you're the problem").
And with that I'm confirming what I said at the very start of this - this whole thread is pointless at best, and trolling at worst. There is no value in continuing this at all, so I'm out and I won't be back again.