Intricacies of byond

How, what and why to code in BYOND.

Moderators: MisterPerson, Code Maintainers

carnie
 
Joined: Thu Apr 17, 2014 4:35 pm

Intricacies of byond

Postby carnie » Thu Jun 12, 2014 4:58 pm #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
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Byond Username: CrimsonVision

Re: Intricacies of byond

Postby Remie Richards » Thu Jun 12, 2014 9:21 pm #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.
私は完璧

User avatar
Malkevin
Confined to the shed
 
Joined: Thu May 01, 2014 4:33 pm
Byond Username: Malkevin

Re: Intricacies of byond

Postby Malkevin » Thu Jun 12, 2014 9:59 pm #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.
This space intentionally left blank.

User avatar
Remie Richards
 
Joined: Thu Apr 17, 2014 7:11 pm
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Byond Username: CrimsonVision

Re: Intricacies of byond

Postby Remie Richards » Thu Jun 12, 2014 10:14 pm #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
Location: in down bad
Byond Username: Paprka

Re: Intricacies of byond

Postby paprika » Thu Jun 12, 2014 10:17 pm #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

Postby carnie » Thu Jun 12, 2014 11:16 pm #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()

User avatar
Miauw
 
Joined: Sat Apr 19, 2014 11:23 am
Byond Username: Miauw62

Re: Intricacies of byond

Postby Miauw » Sat Jun 21, 2014 2:45 pm #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

Postby MisterPerson » Sat Jun 21, 2014 5:58 pm #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

PostThis post was deleted by carnie on Wed Jun 25, 2014 11:52 pm.
Reason: didn't see previous post

User avatar
oranges
Code Maintainer
 
Joined: Tue Apr 15, 2014 9:16 pm
Location: #CHATSHITGETBANGED
Byond Username: Optimumtact
Github Username: optimumtact

Re: Intricacies of byond

Postby oranges » Sun Jul 27, 2014 11:37 pm #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
Location: #CHATSHITGETBANGED
Byond Username: Optimumtact
Github Username: optimumtact

Re: Intricacies of byond

Postby oranges » Thu Aug 14, 2014 1:57 am #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

User avatar
Miauw
 
Joined: Sat Apr 19, 2014 11:23 am
Byond Username: Miauw62

Re: Intricacies of byond

Postby Miauw » Thu Aug 14, 2014 2:36 pm #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

Postby MisterPerson » Thu Aug 14, 2014 10:05 pm #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
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Byond Username: CrimsonVision

Re: Intricacies of byond

Postby Remie Richards » Wed Jan 13, 2016 8:57 pm #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
Location: The Netherlands
Byond Username: Ricotez

Re: Intricacies of byond

Postby Ricotez » Thu Jan 14, 2016 1:16 pm #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
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Byond Username: CrimsonVision

Re: Intricacies of byond

Postby Remie Richards » Thu Jan 14, 2016 1:43 pm #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
Location: The Netherlands
Byond Username: Ricotez

Re: Intricacies of byond

Postby Ricotez » Thu Jan 14, 2016 2:13 pm #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

Postby LiamLime » Thu Jan 14, 2016 3:34 pm #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

Postby MisterPerson » Thu Jan 14, 2016 3:42 pm #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
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Byond Username: CrimsonVision

Re: Intricacies of byond

Postby Remie Richards » Thu Jan 14, 2016 5:55 pm #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
Location: The Netherlands
Byond Username: Ricotez

Re: Intricacies of byond

Postby Ricotez » Thu Jan 14, 2016 8:36 pm #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

Postby LiamLime » Thu Jan 14, 2016 8:54 pm #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
Location: England, UK, Earth, Sol, Milky Way, Local Group, Virgo Supercluster, Known Universe
Byond Username: CrimsonVision

Re: Intricacies of byond

Postby Remie Richards » Thu Jan 14, 2016 9:10 pm #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

Postby Scott » Fri Jan 15, 2016 1:01 am #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

Postby LiamLime » Fri Jan 15, 2016 7:35 am #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.


Return to Coding

Who is online

Users browsing this forum: No registered users