Intricacies of byond

How, what and why to code in BYOND.
Post Reply
carnie
Joined: Thu Apr 17, 2014 4:35 pm

Intricacies of byond

Post by carnie » #13182

General thread for informing others about hidden-features, quirks, tricks etc with byond.

Try to provide as much info as possible about stuff, as to avoid misunderstandings.
Preferably avoid submitting anything which is in the DMreference, which you simply only just found out about, this is more for obscure inner workings and such, beyond that which the DMreference tells us.

I'll start with how the map is instanced and initialized at round start:
First to explain what I mean by instance, instanced and initialized, since I am self-taught and probably misusing these terms in some way.

instance = any 'thing' which is created. For example, /atom, /datum, /list, /image, /icon are all instances. i.e. and class which has been brought into existence.
instanced = the creation of an instance. e.g. calling new /some/typepath()
initialized = probably completely misusing this term. I'm using it to mean New() has been called for this instance.

Ok, so when the map is created, as far as I can tell, this roughly outlines the order of things. Some of this is no doubt inaccurate in some insignificant technicalities, but it's accurate enough to draw some helpful conclusions (which I will get to later):
1) all turfs are instanced according to the dmm
2) all areas are instanced and any turfs are added to their contents
3) area/New() called for all areas starting from bottom left travelling left-to-right
(//Note: I have yet to test whether -all- areas are instanced and -then- -all- their New are called, or if each area is instanced and initialized sequentially.)
4) turf/New() called for all turfs starting from the top right, travelling right-to-left
5) for each turf, starting at the bottom left, travelling left-to-right, we instance and initialize objects for that turf, then before moving on to the next turf, instance and initialize mobs.
(//Note: this may actually be instancing all atom/movable for the turf and inserting them into the contents list in this order (as they always appear in that order in the contents list), then simply calling New() for each thing in the turf's contents)

If you can improve this please do.

conclusions:
much code contained in spawn() within New() procs can be reworked to not need spawn() by using the information above.
for instance, take:

Code: Select all

/area/station/ai_monitored/New()
	..()
	spawn(4)
		// locate and store the motioncamera
		for(var/obj/machinery/camera/M in src)
			if(M.isMotion())
				motioncamera = M
				M.area_motion = src
Since areas are created before objects, we could simply move this to:

Code: Select all

/obj/machinery/camera/New()
	..()
	if(isMotion())
		var/area/station/ai_monitored/A = get_area(src)
		if(istype(A))
			A.motioncamera = src
			area_motion = A
eliminating the need for spawn (and a loop through a large contents list)

another example would be mimic crates collecting all objects in loc.contents and moving them to its contents during mimic/crate/New(). This was originally done with a spawn, but since we know that mobs are initialized after objects, we can just omit the spawn, since we do not need to collect objects from neighbouring turfs (which would not even be instanced yet), just our own turf.

Another case would be the smoothwall code. This is performed in turf/New() obj/structure/falsewall/New() and /obj/structure/falserwall/New(). It searches surrounding turfs for these objects/turfs to update their icon_states.
It can work without spawn because we know that all turfs will be instanced for any of those New() calls.
However, neighbouring objects -not- necessarily be instanced yet. So those will not be smoothwalled.
But if we think carefully about it, we know that objects are initialized from bottom left to top-right. So the smooth-wall code will smooth all of these objects with anything to the west, southwest, southeast or south. Therefore, everything will be smoothed properly since we are travelling in the opposite direction. No need to wait until the map is fully instanced.

Another more difficult case, is when a machine looks to 'link' itself with neighbours during New(). Since only objects to the south,west, southeast and southwest will be instanced by this point. However, by having both partners in the link attempting to find partners, rather than just one of the partners searching, we will always find any partners to the bottom left. Meaning that we no longer need a spawn() in their New().

Sorry if this is really hard to read, I'm not the best at explaining stuff. I hope it helps somebody.
User avatar
Remie Richards
Joined: Thu Apr 17, 2014 7:11 pm
Byond Username: CrimsonVision
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Contact:

Re: Intricacies of byond

Post by Remie Richards » #13229

PARENT_TYPE VAR:

Not sure whether it's known but:
You can change the parent_type var of anything.
This has the unique bonus of Object oriented programming in situations it'd be hard to do.

For example, you can have a /datum that is at it's most basic level, just /datum (it's /datum/atom isn't it?) But you can set it's parent_type var to /obj and then you can place that datum on the map, because it's a /datum/obj/datum technically. This is really dark magic tier coding and I have no idea if this is used anywhere in SS13, but it let's something have the flexibility of it's own typepath and any typepath supplied to parent_type.

However, I do believe it makes ..() calls check the parent_type var, and not the "real" typepath, which might not be wanted.

TYPE VAR:

Also if you wanted to check the type of an instance without allowing it's children through the check (like istype() does) you can literally just if(type == /atom/exampletypepath) and that will allow ONLY exact matches through. Sadly you can't change the type var for "safety" reasons, but if you could, you'd probably ruin the world.
Last edited by Remie Richards on Sat Jun 21, 2014 10:51 pm, edited 1 time in total.
私は完璧
Malkevin

Re: Intricacies of byond

Post by Malkevin » #13235

Don't start an atom name with a number, e.g.

Code: Select all

obj/ammo/44magnum
Dream maker will throw a fit and wont compile, and it will give you a completely useless error that gives no indicate that the issue is in the typepath.


Pickweight() also does not like nums, unless they're in strings, e.g.:
Bad:

Code: Select all

pickweight(10 = 1, 5 = 2)
Good:

Code: Select all

text2num(pickweight("10" = 1, "5" = 2))
Trying to do it the bad way WILL compile without errors but will cause a runtime: "array index out of bounds" when called.
User avatar
Remie Richards
Joined: Thu Apr 17, 2014 7:11 pm
Byond Username: CrimsonVision
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Contact:

Re: Intricacies of byond

Post by Remie Richards » #13237

Malkevin wrote:Don't start an atom name with a number, e.g.

Code: Select all

obj/ammo/44magnum
Dream maker will throw a fit and wont compile, and it will give you a completely useless error that gives no indicate that the issue is in the typepath.
The same goes for +- and a few other operators
the typepath is not the place for those!
私は完璧
User avatar
paprika
Rarely plays
Joined: Fri Apr 18, 2014 10:20 pm
Byond Username: Paprka
Location: in down bad

Re: Intricacies of byond

Post by paprika » #13239

this is why the 1911 is the m1911 in the code
Oldman Robustin wrote:It's an established meme that coders don't play this game.
carnie
Joined: Thu Apr 17, 2014 4:35 pm

Re: Intricacies of byond

Post by carnie » #13250

Malkevin wrote:Pickweight() also does not like nums, unless they're in strings, e.g.:
Bad:

Code: Select all

pickweight(10 = 1, 5 = 2)
Good:

Code: Select all

text2num(pickweight("10" = 1, "5" = 2))
Trying to do it the bad way WILL compile without errors but will cause a runtime: "array index out of bounds" when called.
I have a class for weighted lists if anybody wants it. It's basically just two sync'd lists with a total_weight variable. It gets around this problem, and you don't have to loop through the entire list each time to get the total_weight for doing pickweight()
Miauw
Joined: Sat Apr 19, 2014 11:23 am
Byond Username: Miauw62

Re: Intricacies of byond

Post by Miauw » #14995

src is a var that can be set just like any other var. i guess you could use this to delete the parent object but keep a proc running when youre for example doing something like monkify (but it's still rather useless).



PREFIXING THINGS WITH SRC. IS ALMOST ALWAYS UNNEEDED SO DONT DO IT FOR FUCKS SAKE



there's a special thing you can do where you add

Code: Select all

set waitfor = 1
to a proc and it makes sleep act like spawn. It's undocumented though so dont use it.



There's a "to" operator in BYOND that generates a list of numbers containing all numbers between two given numbers
(e.g. 5 to 10 gives [5, 6, 7, 8, 9, 10] (and no im not sure wether 10 is included but im fairly sure about 5 (not entirely though)))
<wb> For one, the spaghetti is killing me. It's everywhere in food code, and makes it harder to clean those up.
<Tobba> I stared into BYOND and it farted
User avatar
MisterPerson
Board Moderator
Joined: Tue Apr 15, 2014 4:26 pm
Byond Username: MisterPerson

Re: Intricacies of byond

Post by MisterPerson » #15012

5 to 10 is inclusive.

You can do a for-loop like this.
for(var/i in 1 to 10)
world << i

You can even do steps of more than 1 at a time like this
for(var/i in 1 to 10 step 2)
world << i
I code for the code project and moderate the code sections of the forums.

Feedback is dumb and it doesn't matter
User avatar
oranges
Code Maintainer
Joined: Tue Apr 15, 2014 9:16 pm
Byond Username: Optimumtact
Github Username: optimumtact
Location: #CHATSHITGETBANGED

Re: Intricacies of byond

Post by oranges » #21737

MisterPerson on github wrote:
input() won't crash if you include a default value or allow null using syntax like input(usr, "Choose one of the following", "Choose!") as null|anything in list("one", "two", "red", "blue"). In fact in general all input() procs should allow null or have a default because otherwise they runtime if the user disconnects with the input open.
Nabbing this to here from github since it could be useful.
https://github.com/tgstation/-tg-station/pull/4198
User avatar
oranges
Code Maintainer
Joined: Tue Apr 15, 2014 9:16 pm
Byond Username: Optimumtact
Github Username: optimumtact
Location: #CHATSHITGETBANGED

Re: Intricacies of byond

Post by oranges » #24063

. in BYOND is a special var that will be returned automatically at the end of the proc if there is no return statement.

You can assign things to this i.e
. = list()

Courtesy of #coderbus
Miauw
Joined: Sat Apr 19, 2014 11:23 am
Byond Username: Miauw62

Re: Intricacies of byond

Post by Miauw » #24146

If you use /* and */ for multi-line comments, BYOND will ignore */ if it's behind a //
aka this won't compile and throw a "comment reached end of file" error:

Code: Select all

/* wtf who made this this is terrible
if(src == "a huge faggot")
    butt = "fart" //shitty workaround -some dude */
<wb> For one, the spaghetti is killing me. It's everywhere in food code, and makes it harder to clean those up.
<Tobba> I stared into BYOND and it farted
User avatar
MisterPerson
Board Moderator
Joined: Tue Apr 15, 2014 4:26 pm
Byond Username: MisterPerson

Re: Intricacies of byond

Post by MisterPerson » #24208

However, BYOND will not ignore multiline comments contained within other multiline comments.

For example, this will also throw an "end of file reached inside of comment" error:

Code: Select all

/* First set   /* Second set    */ End of second set
I code for the code project and moderate the code sections of the forums.

Feedback is dumb and it doesn't matter
User avatar
Remie Richards
Joined: Thu Apr 17, 2014 7:11 pm
Byond Username: CrimsonVision
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Contact:

Re: Intricacies of byond

Post by Remie Richards » #146453

Necroing ancient thread at the request of oranges.

I wrote this https://github.com/tgstation/-tg-statio ... irkstricks recently, which covers some Performance related byond quirks.
私は完璧
User avatar
Ricotez
Joined: Thu Apr 17, 2014 9:21 pm
Byond Username: Ricotez
Location: The Netherlands

Re: Intricacies of byond

Post by Ricotez » #146639

I don't get what you are trying to say about the dot operator at all
MimicFaux wrote:I remember my first time, full of wonderment and excitement playing this game I had heard so many stories about.
on the arrival shuttle, I saw the iconic toolbox on the ground. I clubbed myself in the head with it trying to figure out the controls.
Setting the tool box, now bloodied, back on the table; I went to heal myself with a medkit. I clubbed myself in the head with that too.
I've come a long ways from asking how to switch hands.
Spoiler:
#coderbus wrote:<MrPerson> How many coders does it take to make a lightbulb? Three, one to make it, one to pull the pull request, and one to fix the bugs
Kor wrote:The lifeweb playerbase is primarily old server 2 players so technically its our cancer that invaded them
peoplearestrange wrote:Scared of shadows whispers in their final breath, "/tg/station... goes on the tabl..."
DemonFiren wrote:Please, an Engineer's first response to a problem is "throw it into the singulo".
tedward1337 wrote:Donald Trump is literally what /pol/ would look like as a person
CrunchyCHEEZIT wrote:why does everything on this server have to be a federal fucking issue.
Saegrimr wrote:One guy was running around popping hand tele portals down in the halls before OPs even showed up and got several stranded out on lavaland.
The HoP just toolboxes someone to death out of nowhere, then gets speared by a chemist who saw him murder a guy, then the chemist gets beaten to death because someone else saw him kill the HoP.
Tele-man somehow dies and gets its looted by an atmos tech who managed to use it to send two nuke ops to lavaland, who were then surrounded by several very angry people from earlier and some extra golems on top of it.
Captain dies, gets cloned/revived, lasers the guy holding the disk into crit to take it back.
Some idiot tries to welderbomb the AI hiding out at mining for no discernible reason.
Two permabans and a dayban, i'm expecting a snarky appeal from one of them soon. What the fuck.
ShadowDimentio wrote:I am the problem
User avatar
Remie Richards
Joined: Thu Apr 17, 2014 7:11 pm
Byond Username: CrimsonVision
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Contact:

Re: Intricacies of byond

Post by Remie Richards » #146644

Ricotez wrote:I don't get what you are trying to say about the dot operator at all
It's also a temporary variable present in all procs and automatically returned at the end of a proc, and you can use it to avoid:
  • Defining your own var
  • The return statement (small overhead)
It also obeys operators like ++ and [], since it's just another variable, it just looks weird to see .[] or .++ despite it being perfectly valid.
私は完璧
User avatar
Ricotez
Joined: Thu Apr 17, 2014 9:21 pm
Byond Username: Ricotez
Location: The Netherlands

Re: Intricacies of byond

Post by Ricotez » #146652

oh so if you just use . to store the variable you want the proc to return you'll save computation time?
MimicFaux wrote:I remember my first time, full of wonderment and excitement playing this game I had heard so many stories about.
on the arrival shuttle, I saw the iconic toolbox on the ground. I clubbed myself in the head with it trying to figure out the controls.
Setting the tool box, now bloodied, back on the table; I went to heal myself with a medkit. I clubbed myself in the head with that too.
I've come a long ways from asking how to switch hands.
Spoiler:
#coderbus wrote:<MrPerson> How many coders does it take to make a lightbulb? Three, one to make it, one to pull the pull request, and one to fix the bugs
Kor wrote:The lifeweb playerbase is primarily old server 2 players so technically its our cancer that invaded them
peoplearestrange wrote:Scared of shadows whispers in their final breath, "/tg/station... goes on the tabl..."
DemonFiren wrote:Please, an Engineer's first response to a problem is "throw it into the singulo".
tedward1337 wrote:Donald Trump is literally what /pol/ would look like as a person
CrunchyCHEEZIT wrote:why does everything on this server have to be a federal fucking issue.
Saegrimr wrote:One guy was running around popping hand tele portals down in the halls before OPs even showed up and got several stranded out on lavaland.
The HoP just toolboxes someone to death out of nowhere, then gets speared by a chemist who saw him murder a guy, then the chemist gets beaten to death because someone else saw him kill the HoP.
Tele-man somehow dies and gets its looted by an atmos tech who managed to use it to send two nuke ops to lavaland, who were then surrounded by several very angry people from earlier and some extra golems on top of it.
Captain dies, gets cloned/revived, lasers the guy holding the disk into crit to take it back.
Some idiot tries to welderbomb the AI hiding out at mining for no discernible reason.
Two permabans and a dayban, i'm expecting a snarky appeal from one of them soon. What the fuck.
ShadowDimentio wrote:I am the problem
LiamLime
Joined: Tue Aug 25, 2015 12:59 pm
Byond Username: LiamLime

Re: Intricacies of byond

Post by LiamLime » #146665

Assuming I'm understanding the amount of difference it makes to use the dot variable over the return statement+variable declaration, I'd still opt for variable declaration + return. All things being equal, the way I order code properties is:
correctness > readability > efficiency
The only time when efficiency overtakes readability is in academic work and general-purpose algorithms (machine learning, for example)
The only time when efficiency overtakes even correctness is in specialized general-purpose algorithms, which perform a general purpose task on only a subset of possible problems. (For example, some cases of NP-hard problems can be solved in polynomial time if the problems have certain properties. But the algorithm that solves them can only do so if the cases have these properties).

When it comes to games, apps, websites or servers, efficiency is the lowest of priorities. Don't get me wrong, I won't use bubble sort if quicksort exists, but I won't write a non-general-purpose script (for example an inventory system) in a hardcoded spaghetti magic number way, just because I can save some CPU time in variable assignments.

That's the theory though. When it comes to this specific dot thing, it's nowhere near as big a problem as the example I gave. There is actually even a language that does it in a similar way: Pascal. In pascal functions, the function's name becomes a variable within the function and is returned at the end. It is however quite likely that new coders will be more familiar with return than the pascal way, which is why I think it should probably be the way that's taught to them as the "usual way". Using ". = val" is just confusing, and it's hard enough to explain what ..() does, adding another of these dumb byond syntax things as a requirement would make the language even less appealing for people to learn.

I guess what I'm saying is... It might be a slight improvement, but probably nowhere near big enough to make its use a requirement, especially since it lowers code readability.
The bureaucracy is expanding to meet the needs of the expanding bureaucracy.
User avatar
MisterPerson
Board Moderator
Joined: Tue Apr 15, 2014 4:26 pm
Byond Username: MisterPerson

Re: Intricacies of byond

Post by MisterPerson » #146669

The difference between . = 1 and return 1 are so minor that if it was really the biggest waste of cycles, I would sooner suggest starting from scratch with C# since we'd be done with the game.
I code for the code project and moderate the code sections of the forums.

Feedback is dumb and it doesn't matter
User avatar
Remie Richards
Joined: Thu Apr 17, 2014 7:11 pm
Byond Username: CrimsonVision
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Contact:

Re: Intricacies of byond

Post by Remie Richards » #146687

These aren't in the requirements or rules, but If I spot them I will ask you to correct them, and as for other things like the loops other maintainers have pointed them out too.
Kor has started writing some of these improvements BEFORE making his PRs, if Kor can pick it up anyone can :P
私は完璧
User avatar
Ricotez
Joined: Thu Apr 17, 2014 9:21 pm
Byond Username: Ricotez
Location: The Netherlands

Re: Intricacies of byond

Post by Ricotez » #146710

if we'd start using it universally it would make it instantly obvious what variable is the most important one in every proc
MimicFaux wrote:I remember my first time, full of wonderment and excitement playing this game I had heard so many stories about.
on the arrival shuttle, I saw the iconic toolbox on the ground. I clubbed myself in the head with it trying to figure out the controls.
Setting the tool box, now bloodied, back on the table; I went to heal myself with a medkit. I clubbed myself in the head with that too.
I've come a long ways from asking how to switch hands.
Spoiler:
#coderbus wrote:<MrPerson> How many coders does it take to make a lightbulb? Three, one to make it, one to pull the pull request, and one to fix the bugs
Kor wrote:The lifeweb playerbase is primarily old server 2 players so technically its our cancer that invaded them
peoplearestrange wrote:Scared of shadows whispers in their final breath, "/tg/station... goes on the tabl..."
DemonFiren wrote:Please, an Engineer's first response to a problem is "throw it into the singulo".
tedward1337 wrote:Donald Trump is literally what /pol/ would look like as a person
CrunchyCHEEZIT wrote:why does everything on this server have to be a federal fucking issue.
Saegrimr wrote:One guy was running around popping hand tele portals down in the halls before OPs even showed up and got several stranded out on lavaland.
The HoP just toolboxes someone to death out of nowhere, then gets speared by a chemist who saw him murder a guy, then the chemist gets beaten to death because someone else saw him kill the HoP.
Tele-man somehow dies and gets its looted by an atmos tech who managed to use it to send two nuke ops to lavaland, who were then surrounded by several very angry people from earlier and some extra golems on top of it.
Captain dies, gets cloned/revived, lasers the guy holding the disk into crit to take it back.
Some idiot tries to welderbomb the AI hiding out at mining for no discernible reason.
Two permabans and a dayban, i'm expecting a snarky appeal from one of them soon. What the fuck.
ShadowDimentio wrote:I am the problem
LiamLime
Joined: Tue Aug 25, 2015 12:59 pm
Byond Username: LiamLime

Re: Intricacies of byond

Post by LiamLime » #146716

As ever, my concern is with the novice coder. Those of you who are already familiar with SS13 code would have no problem adapting, but it would mean that making those very first steps into SS13 coding would be just a bit much more confusing for the novice coder. Again, explaining ..() already takes a non-negligible amount of time, explaining . = val in addition to thiw would just make it take longer, and thus potentially result in losing even more coders to the early learning curve. I have no idea how noticeable this effect would be though, I kinda don't think it'd be negligible though.
The bureaucracy is expanding to meet the needs of the expanding bureaucracy.
User avatar
Remie Richards
Joined: Thu Apr 17, 2014 7:11 pm
Byond Username: CrimsonVision
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Contact:

Re: Intricacies of byond

Post by Remie Richards » #146724

LiamLime wrote:As ever, my concern is with the novice coder. Those of you who are already familiar with SS13 code would have no problem adapting, but it would mean that making those very first steps into SS13 coding would be just a bit much more confusing for the novice coder. Again, explaining ..() already takes a non-negligible amount of time, explaining . = val in addition to thiw would just make it take longer, and thus potentially result in losing even more coders to the early learning curve. I have no idea how noticeable this effect would be though, I kinda don't think it'd be negligible though.
Personally I believe it changes nothing, yes ..() is relatively complex, yes . = val is relatively complex, but the . = ..() construct exists FREQUENTLY in code, and they're going to come across that too, this is simply a perfect opportunity to explain . = val by piggy backing off what we already need to teach about ..()
私は完璧
Scott
Github User
Joined: Fri Apr 18, 2014 1:50 pm
Byond Username: Xxnoob
Github Username: xxalpha

Re: Intricacies of byond

Post by Scott » #146776

I believe that when a novice coder has need of the . or to call ..() they will be given that information and they will immediately understand it. There is no point in trying to teach people ahead of time and no point worrying about people not understanding things, when the need to know arises they will easily learn.
LiamLime
Joined: Tue Aug 25, 2015 12:59 pm
Byond Username: LiamLime

Re: Intricacies of byond

Post by LiamLime » #146814

Novice coders start by reading code, not by writing, so needing to understand ..() is a requirement from day one. If ". = val" replaced "return val" everywhere, then understanding ". = val" would become a day one requirement aswell.

If what Remie says is true, then this is however proably already the case. I don't think it was back when I learned TGS code though.
The bureaucracy is expanding to meet the needs of the expanding bureaucracy.
Post Reply

Who is online

Users browsing this forum: No registered users