HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Triggers - Debugging

04-27-2004, 01:16 AM#1
ThyFlame
Debugging - Facts and Myths


I will guarentee you that if you use triggers, be it spell-enhanced or otherwise, you will have an error at some point. Sure, you can stare blankly at the screen for hours until it pops out at you, or you can take action.


  1. Debugging Definition
  2. Common Mistakes
  3. Debugging Methods
  4. Checking Your Values
  5. Hang-Ups After Game Ends
  6. Credits



First off, I'll start with the basics.
Definition of Debugging

Debugging, essentially, is the removal of all problems that lay in your triggers. You only need to debug if your trigger is not working, be it not running at all, not yielding the correct results, or only running in part.


Common Mistakes
  • You will use loops at some point. They are the greatest thing that ever happened to programming, in my opinion. However, be wary -- only use ONE of each For Integer X. If you use two nested {One inside another} For Integer A or B your trigger will very likely get errors.


Debugging Methods

If your trigger is having problems, put in debug lines to make sure each section is occuring. A debug line is quite simply displaying a line of text when the trigger reaches a certain point.

Game - Display Text

Make sure the text you display is detailed. For example, you have a trigger that runs three loops. Don't put Display Text (Loop has run) before each loop -- put Loop 1 is about to run before the loop and Loop 1 has just finished running after the loop. Another smart idea is to display a concatenate string. (Concatenate means nothing more than a combined string. A + A = AA. A + -A = A-A. It's that simple.)

Now, inside the loop, Game - Display to (All players) the text: (Loop 1 is currently on loop + (String((Integer A)))).

Zoom (requires log in)

Okay... but what's the point?
The point is that this will tell you that the loop is being run, how many times it's being run, and if the loop is finishing.

If Loop 1 is about to run never is displayed, your loop isn't occuring.
If Loop 1 has just finished never is displayed, then the trigger, and likely the loop as well, was ended prematurely.
If you get an incorrect amount of debug lines inside the loop, then something went wrong inside your loop.


Knowing where the problem occured is the first step towards fixing it.


Checking Your Values

The other major problem is that a value is not correct. The first thing I would check is to make sure every variable you are using is the variable you meant for it to be.

Secondly, make a situation on your map where you can test the trigger so you know what the values should be at each step.


Lets take an easy trigger and look at how it's done.

Let me explain this trigger. Player 1 types -deposit XXX and if Player 1 has enough gold, XXX will be deposited into the bank and removed from his "on-hand" gold count. If not, it tells him that he didn't have enough gold. Afterwards, it tells him his current bank balance.

Trigger:
Bank Deposit Copy 2
Collapse Events
Player - Player 1 (Red) types a chat message containing -deposit as A substring
Conditions
Collapse Actions
Set DepositAmount = (Integer((Substring((Entered chat string), 8, (Length of (Entered chat string))))))
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
DepositAmount Less than or equal to ((Triggering player) Current gold)
Collapse Then - Actions
Set PlayerBank[(Player number of (Triggering player))] = (PlayerBank[(Player number of (Triggering player))] + DepositAmount)
Player - Add (DepositAmount x -1) to (Triggering player) Current gold
Collapse Else - Actions
Game - Display to (Player group((Triggering player))) the text: (You do not have enough to gold to make a deposit of + (String(DepositAmount)))
Game - Display to (Player group((Triggering player))) the text: (Your current balance is: + (String(PlayerBank[(Player number of (Triggering player))])))

Quick overview first: Substring = Tear apart a word. Format of StringToTear, StartingPoint, StoppingPoint. Die, 1, 2 = Di

Basically, you run this trigger and the balance remains the same, but there is no message saying you didn't have enough money when you deposited. This tells you two things: 1.) That the problem is very likely the value being used for the IF/THEN/ELSE and 2.) That the trigger is running and completing.

Since the problem appears to be before the IF/THEN/ELSE, we start our debugging up there. What's above the IF/THEN/ELSE? Only the substring. So, let's test that.
Trigger:
Game - Display to (Player group((Triggering player))) the text: (Entered chat string)
Game - Display to (Player group((Triggering player))) the text: (Substring((Entered chat string), 8, (Length of (Entered chat string))))

This will repeat what you said and tell you what's being used in the substring. So we run the trigger now and what do we get?

Zoom (requires log in)

As you can see, we're not just getting the number we deposited. We're still getting a t and a space, which means we started the substring too far over left. We count again and see we wanted to start at 10, not 8. Change that, and the trigger works.


Game Hang-Ups After The Game Ends
This is because of Memory leaks. Visit Cubasis' tutorial on removing memory leaks for this.



Comments? Suggestions? Feel free to ask and I will update as needed.


Credits

Author: ThyFlame
Last Update: May 10, 2004. 4:16 PM EST.
Version: 1.03
Sample Code: ThyFlame
Sample Pictures: ThyFlame
Code Inspiration: cfmonkey45
Memory Leak Tutorial [Linked To]: Cubasis
Attached Images
File type: jpgMoar BM Evil Kael.jpg (157.4 KB)
04-28-2004, 08:48 AM#2
Youma
Quote:
Originally Posted by ThyFlame
[size=5]only use ONE of each For Integer X. If you use two For Integer A or B your trigger will very likely get errors.

You'll get problems if you use two A's one inside the other, but two separate A's don't affect each other.
04-28-2004, 05:38 PM#3
ThyFlame
Added the "nested" to it.
04-28-2004, 06:11 PM#4
Youma
"nested" is solely a programming term, isn't it? You think people knows what it means?

Nice tutorial by the way! I was in the process of making my own, but it's not easy to put this in general terms.
04-28-2004, 08:51 PM#5
ThyFlame
It is updated.
04-29-2004, 09:41 PM#6
JTG
Edit: Oops, sorry, didn't mean to invade...
However, the trace system I just removed would have worked for this just as well, it's only more specificly tuned to Custom-Script, It would have been easily implemented by copying the functions to the custom-script area of the map and using the "Custom Script" to call the function. I'm sure it couldn't be THAT difficult to try.
04-30-2004, 12:45 AM#7
ThyFlame
Still, this is GUI, and I may add the causes and fixes of "leaks" to this. Wondering if anyone would find it useful, though.
05-07-2004, 02:35 PM#8
Cubasis
Good article!

*submitted*

~Cubasis
05-09-2004, 09:54 PM#9
johnfn
Good idea for a tut, and you did it well. I already know how to debug but wc3c needed a tutorial like this. But...

Quote:
Originally Posted by ThyFlame

You will use loops at some point. They are the greatest thing that ever happened to programming, in my opinion. However, be wary -- only use ONE of each For Integer X. If you use two nested {One inside another} For Integer A or B your trigger will very likely get errors.

Neh. Ive used nested loops many times with no errors. Its probably the code inside of the loops thats the problem.


Although I think this is a little uneffecient ( making a message before it starts to run?), I only print out numbers/letters/symbols at where I guess the bug is, but its a good beginning guide.
05-11-2004, 12:02 AM#10
ThyFlame
Well from my own experience it has indeed been the difference between a working trigger and a nonworking trigger. Any language is this way I believe; embedded loops have to have different variables.

[Edit for spelling]
05-11-2004, 01:02 AM#11
johnfn
Quote:
Originally Posted by ThyFlame
Well from my own experience it has indeed been the different between a working trigger and a nonworking trigger. Any language is this way I believe; embedded loops have to have different variables.
Oh, I'm sorry. From the way you wrote it i though you meant

For each integer A...
For each integer B...

When in actuallity you mean

For each integer A...
For each integer A...

Which I agree is inherently dangerous. Naturally since two loops are setting and resetting the variable it will in effect wreck any code in the loops. Of course I question the logic in this anyway, but its good to point out nonetheless.


Could the guy who said "Worthless Post" tell me exactly WHY this is a worthless post? I corrected a mistake, and agreed with him. Why on Earth is this "Worthless"?
01-28-2006, 08:54 PM#12
Mr.Mxyzptlk
You're not limited to using "For" Integers A and B; you can substitute your own integer variables and nest as many loops as you need. First define an Integer Variable (example: M), then use the following GUI action:

For each (Integer Variable) from 1 to 10, do (Actions)

WE will ask you to specify Variable. Select M from the Variable pick-list.