ID:143178
 
Code:
                if(usr.field=="Physiology")
var/V=rand(1,2)
if(V==1)
var/Psiblast = pick(question_list3)
var/Answer = ParseQuestion3(usr,Psiblast)
if(Answer == TRUE)
goto End
else
if(V==2)
var/Psiblast = pick(question_list1)
var/Answer = ParseQuestion(usr,Psiblast)
if(Answer == TRUE)
goto End
else
else if(usr.field=="Microbiology")
var/Psiblast = pick(question_list2)
var/Answer = ParseQuestion2(usr,Psiblast)
if(Answer == TRUE)
goto End
End
usr.psionicgraphic()


So basically i'm getting an error:dm\Equipment.dm:460:error:goto End: bad link
dm\Equipment.dm:466:error:goto End: bad link

As I understand it goto will jump you to another part of the current proc which is what I'm trying to do, but since it's not happy with my format it's not doing that. Basically I'm just trying to base a couple of fairly complex vars on a character var without having a if/else tree that's 3 times larger than it needs to be. I would just use another proc that would trigger but I run into problems with the proc recognizing the vars from the rest of the earlier proc when I trigger a new proc so I was trying to stay in the same proc to avoid that.

mike-



Get rid of the gotos and figure out a better way to do it. goto has its uses, but at this point in time you won't find them. It also produces spaghetti code, which is bad.
In response to Popisfizzy
If just to understand the proper goto format to have the option of using it in the future I would want to learn it, as I've read anyhow goto is often the most efficient way to program as it cuts down on code length, as long as it's understood to be basically another if/else function I don't see the problem with it. Anyhow if anyone sees why the format is incorrect in my code I'd love to know the solution, (Think of it as the teach a man to fish type of thing, as once I get it I won't need to ask about it again)

Mike-
In response to Kichimichi
goto has absolutely nothing to do with if/else statements, unless if you're writing in something like BASIC or assembly. Fact of the matter is, if() blocks and while() loops and for() loops were introduced for a DAMN good reason: because they're easier to read than goto statements. Use those.
In response to Garthor
I think I figured it out anyway, it won't, once a new chunk of if or whatever begins it won't be able to recognize the label even if they're under the same parent, zuckis.
In response to Kichimichi
anyway your label needs to be untabbed further.

But listen to PIF, the first thing they teach you in high level programming is that Gotos should almost never be used... and then they also say you should comment every line, but thats crap.
In response to Masterdan
You don't have any concept of what "high level" means in relation to programming, do you?
This code does not need goto at all. Your if() statements are almost correct, except for the if(ANSWER == TRUE) ones. If you fix those, you won't need goto at all.

I'm surprised you're not gettning errors for those empty else clauses. You don't need those either. Nothing wrong with else, you're just not using them (no code after the else, see?), so don't include them.

To fix your code, then, simply remove all goto and else statements under if(ANSWER == TRUE), and then change that if to be if(ANSWER != TRUE) return. That checks to see if it's NOT TRUE, and if so, to return, or escape out of the proc.

If it is TRUE, however, the proc will keep on going. But where will it go? Right to the end, automatically. Why is that? Because you used if() and else if() the right way at the beginning. It will only execute the if(usr.field=="Microbiology") statement when if(usr.field=="Physiology") is false. That's what the else if() means. If this, else if this, else this.

                if(usr.field=="Physiology")
var/V=rand(1,2)
if(V==1)
var/Psiblast = pick(question_list3)
var/Answer = ParseQuestion3(usr,Psiblast)
if(Answer != TRUE) return
else if(V==2)
var/Psiblast = pick(question_list1)
var/Answer = ParseQuestion(usr,Psiblast)
if(Answer != TRUE) return
else if(usr.field=="Microbiology")
var/Psiblast = pick(question_list2)
var/Answer = ParseQuestion2(usr,Psiblast)
if(Answer != TRUE) return
usr.psionicgraphic()


By using if() and else the right way, goto becomes useless here. If it has no use, don't use it. ;)

Now, if you want to get into good coding practices, we could look at your random pick() and if(V==1) lines. That's not exactly efficient. Rather, just use if(rand(0,1)) where if(V==1) is, and make the if(V==2) an else statement instead. And your main if() statements can be turned into a switch() statement, negating any need for the else in the second main if():

                switch(usr.field)
if("Physiology")
if(rand(0,1))
var/Psiblast = pick(question_list3)
var/Answer = ParseQuestion3(usr,Psiblast)
if(!Answer) return
else
var/Psiblast = pick(question_list1)
var/Answer = ParseQuestion(usr,Psiblast)
if(!Answer) return
if("Microbiology")
var/Psiblast = pick(question_list2)
var/Answer = ParseQuestion2(usr,Psiblast)
if(!Answer) return
usr.psionicgraphic()


That's how I would write it.

Oh, and is that usr in a proc? No put usr in proc, ungh. It's fine in a verb, or in something that the player will call like a verb (like the Click() proc), but really bad to use usr in a proc, since those won't always have a usr.

~X
In response to Xooxer
I was wondering about elses at the end of if statements that don't do anything, I was getting empty else errors sometimes but then other times I wasn't so I wasn't sure what the proper format was, I'll leave them out from now on.

The reason I was using goto is because I didn't want to have to have the same code after each section (where the goto's I put in were) since they all have the same result with just different questions being asked to the player from a different list to see if they get a true responce or not, the portion after each one of the if sections is like 30 lines or so, and I was just trying to modularize it, I knew on the last goto that there was no real point for it other than I just was messing with it to get goto to work at least in one place and at least there it did run through the proc just fine, so for future reference I will know that on a line like that I can use it, but not apparently between seperate if sections.

Your switch format looks interesting, I haven't seen switch used that way before, but it looks like a solution to my problem.

So
1-"if(rand(0,1)" will run that if half the time otherwise go on to do the other half the time?

2-"if(!Answer) return" = "if(Answer != TRUE) return" basically

3- return by itself should be returning null right, and just ending the proc basically? I guess I just need to put a proc before the returns to get a negative result with additional code. I looked up "return" I just don't get how to handle what it's returning or where the return vars are being sent ect if I wanted to use that var to continue a proc.

4- (no usr in proc ungh!) This is called on just like a verb, only a player can activate it no danger of the process being automated by the comp as the 2 vars there activate procs that require usr input to resolve anyhow so if theyre not involved it doesn't work at all, also theyre specifically activated by a verb these are just children procs of that verb.

5- I'm gonna play with this a bit, see if I can answer most of my own questions, anyhow thanks alot, good stuff.

Mike
Edit()
I've gotten most of this worked out so I can understand the principles here for the most part, just the last bit of making the negative result codes more effecient since they'll all be the same regardless of usr.field, just a it more work i think and i'll have it.
mob/verb/meh()
var/Answer=TRUE
switch(usr.field)
if("Physiology")
if(rand(0,1))
var/Psiblast = pick(question_list3)
Answer = ParseQuestion3(usr,Psiblast)
if(!Answer)
Answer=FALSE

else
var/Psiblast = pick(question_list1)
Answer = ParseQuestion(usr,Psiblast)
if(!Answer)
Answer=FALSE


if("Microbiology")
var/Psiblast = pick(question_list2)
Answer = ParseQuestion2(usr,Psiblast)
if(!Answer)
Answer=FALSE




if(Answer == TRUE)
usr.psionicgraphic()
else
usr<<"wrong"


How's this look then? seems to do what I want.(just turned the snip into a verb to test on it's own.)

Mike-

Edit()
Got it all to work great thanx again cut this section of code into 1/4 it's original size and for future addition it'll be so much more managable.

Mike-
In response to Masterdan
Masterdan wrote:
But listen to PIF, the first thing they teach you in high level programming is that Gotos should almost never be used... and then they also say you should comment every line, but thats crap.

The zealots of high-level programming will say that goto should never be used period, but frankly that's hogwash. However it's a good rule of thumb, to be broken when all other good options are exhausted.

I've never heard any serious programmer say you should comment every line, though. Comment liberally, yes, but not so much that it becomes impossible to read the code. BYOND is littered with demos where the author decided to comment lines like "mob" and "obj" as if it's a beginner's tutorial. Even then there are better ways to comment than that.

Lummox JR
In response to Kichimichi
Kichimichi wrote:
So
1-"if(rand(0,1))" will run that if half the time otherwise go on to do the other half the time?

Yep. It may not always be exactly 50% 50%, but it'll be as close as any random generator is likely to get. It's the same as flipping a coin, sometime heads, sometimes tails.

2-"if(!Answer) return" = "if(Answer != TRUE) return" basically

Right again.


3- return by itself should be returning null right, and just ending the proc basically? I guess I just need to put a proc before the returns to get a negative result with additional code. I looked up "return" I just don't get how to handle what it's returning or where the return vars are being sent ect if I wanted to use that var to continue a proc.

Return ends the proc and passes it's value back to that which called it. If you don't set some soert of value, and just use return all by itself, then yes, it returns null, which is the same as FALSE or 0, for most purposes. Null isn't either of those values completely, but you can test for those and null will match.

mob/verb/Hello()
usr << DoHello("Hello Wolrd!")

mob/proc/DoHello(msg)
return msg


The above returs the value of the msg variabel. This is a poor example, I know, but I just woke up -_-.


4- (no usr in proc ungh!) This is called on just like a verb, only a player can activate it no danger of the process being automated by the comp as the 2 vars there activate procs that require usr input to resolve anyhow so if theyre not involved it doesn't work at all, also theyre specifically activated by a verb these are just children procs of that verb.

That's fine, just so you're aware of it. Hard to tell sometimes where these code snippets come from or how they might be used.

~X
In response to Lummox JR
Lummox JR wrote:
BYOND is littered with demos where the author decided to comment lines like "mob" and "obj" as if it's a beginner's tutorial. Even then there are better ways to comment than that.

I'd say that that is a result of there not being any sort of organization of demos. If somebody took the time to sort demos by programming experience, and it became an easily accessible resource, I imagine that people would start making better demos.

Well, the people who are able to start making better demos would. There's not that much that can be done for the people making demos that shouldn't be.