| 12-08-2008, 12:37 PM | #1 |
Hey! I started with JASS some time ago and wrote my first code now. The function: It's a simple calculator. But, of course, it does not work properly. The problem is, that it shows the result two times if one of the 2 numbers is negative and the arithmetic operator is not - . The syntax and other things are explained at the beginning of the code. This is the complete trigger: JASS://///////////////////////////////////////////////////////////////////////////////////// /// /// THIS TRIGGER WAS CREATED BY IDONTNEEDANAME (Europe/Northrend). DO NOT USE WITHOUT CREDITS! /// /////////////////////////////////////////////////////////////////////////////////////// /// /// The syntax is .=<number1><arithmetic_operator><number2> /// It accepts both , and . as commas and knows the a.operators + - * / ^ /// For example, .=-2,4--1.2 gives " -2.4 - -1.2 = -1.2 " /// You cannot fool Warcraft with that: .=-9^0.5 (which would be impossible normally), by any reason it returns " -9 ^ 0.5 = 3 " /// /// It accepts only one a.operator and does not know ) and ( /// /// /// Bug reports and/or ideas may be sent to [email][email protected][/email] /// /// /// Idontneedaname, 7.12.2008 /////////////////////////////////////////////////////////////////////////////////////// function Trig_Nahkampf_Initialisierung_Kopieren_Actions takes nothing returns nothing local integer a = 0 //Position of the comma in the first number local integer b = 0 //Position of the comma in the second number local integer c = 0 //Position of the a.operator local real d = 0.0 //The first number local real e = 0.0 //The second number if ( SubStringBJ(GetEventPlayerChatString(), 1, 2) == ".=") then /////////////////////////////////////////////////////////////////////////////////////// /// /// Get the position of the a.operator and the positions of the commas. /// /////////////////////////////////////////////////////////////////////////////////////// set bj_forLoopAIndex = 4 set bj_forLoopAIndexEnd = ( StringLength(GetEventPlayerChatString()) - 1 ) loop exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd if ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "+" ) then if ( c == 0 ) then set c = GetForLoopIndexA() else endif elseif ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "-" ) then if ( c == 0 ) then set c = GetForLoopIndexA() else endif elseif ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "*" ) then set c = GetForLoopIndexA() elseif ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "/" ) then set c = GetForLoopIndexA() elseif ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "^" ) then set c = GetForLoopIndexA() else if ( ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "," ) or ( SubStringBJ(GetEventPlayerChatString(), GetForLoopIndexA(), GetForLoopIndexA()) == "." ) ) then if ( c == 0 ) then // which means that we are still before the a.operator. set a = GetForLoopIndexA() else set b = GetForLoopIndexA() endif else endif endif set bj_forLoopAIndex = bj_forLoopAIndex + 1 endloop /////////////////////////////////////////////////////////////////////////////////////// /// /// Create the numbers /// /////////////////////////////////////////////////////////////////////////////////////// if ( a == 0 ) then set d = S2R(SubStringBJ(GetEventPlayerChatString(), 3, ( c - 1 ))) else set d = (S2R(( SubStringBJ(GetEventPlayerChatString(), 3, ( a - 1 )) + SubStringBJ(GetEventPlayerChatString(), ( a + 1 ), ( c - 1 )) ))) * ( Pow(0.1,((c-a)-1)) ) endif if ( b == 0 ) then set e = S2R(SubStringBJ(GetEventPlayerChatString(), ( c + 1 ), StringLength(GetEventPlayerChatString()))) else set e = (S2R(( SubStringBJ(GetEventPlayerChatString(), ( c + 1 ), ( b - 1 )) + SubStringBJ(GetEventPlayerChatString(), ( b + 1 ), StringLength(GetEventPlayerChatString())) ))) * ( Pow(0.1, (StringLength(GetEventPlayerChatString())-b))) endif /////////////////////////////////////////////////////////////////////////////////////// /// /// Do the calculation and display the result to all players. /// /////////////////////////////////////////////////////////////////////////////////////// if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "^" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" ^ "+R2S(e)+" = "+R2S( Pow(d, e)) ) else if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "+" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" + "+R2S(e)+" = "+R2S(( d + e )) ) else if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "-" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" - "+R2S(e)+" = "+R2S(( d - e )) ) else if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "*" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" * "+R2S(e)+" = "+R2S(( d * e )) ) else call DisplayTextToForce( GetPlayersAll(), R2S(d)+" / "+R2S(e)+" = "+R2S(( d / e )) ) endif endif endif endif else endif endfunction function InitTrig_Trigger takes nothing returns nothing set gg_trg_Trigger = CreateTrigger( ) call TriggerRegisterPlayerChatEvent( gg_trg_Trigger, Player(0), "+", false ) call TriggerRegisterPlayerChatEvent( gg_trg_Trigger, Player(0), "-", false ) call TriggerRegisterPlayerChatEvent( gg_trg_Trigger, Player(0), "*", false ) call TriggerRegisterPlayerChatEvent( gg_trg_Trigger, Player(0), "/", false ) call TriggerRegisterPlayerChatEvent( gg_trg_Trigger, Player(0), "^", false ) call TriggerAddAction( gg_trg_Trigger, function Trig_Nahkampf_Initialisierung_Kopieren_Actions ) endfunction I don't know what causes that, so I can't have an idea how to fix it. (Okay, perhaps my warcraft has some errors in it, you may copy it and use it in a test map, as it does not use global variables.) Thanks in advance, Idontneedaname |
| 12-09-2008, 05:34 AM | #2 |
Your code is sort-of convoluted and hard to read because it looks like half-converted GUI code. You should look at others' code and see how long if-then-else blocks can be re-written, excess parenthesis can be removed, and that sort of thing. For example: JASS:if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "^" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" ^ "+R2S(e)+" = "+R2S( Pow(d, e)) ) else if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "+" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" + "+R2S(e)+" = "+R2S(( d + e )) ) else if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "-" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" - "+R2S(e)+" = "+R2S(( d - e )) ) else if ( SubStringBJ(GetEventPlayerChatString(), c, c) == "*" ) then call DisplayTextToForce( GetPlayersAll(), R2S(d)+" * "+R2S(e)+" = "+R2S(( d * e )) ) else call DisplayTextToForce( GetPlayersAll(), R2S(d)+" / "+R2S(e)+" = "+R2S(( d / e )) ) endif endif endif endif //Becomes: //local string Display = "" //local string Check = "" set Check = SubStringBJ(GetEventPlayerChatString(), c, c) if Check == "^" then set Display = R2S(d)+" ^ "+R2S(e)+" = "+R2S(Pow(d, e)) elseif Check == "+" then set Display = R2S(d)+" + "+R2S(e)+" = "+R2S(d + e) elseif Check == "-" then set Display = R2S(d)+" - "+R2S(e)+" = "+R2S(d - e) elseif Check == "*" then set Display = R2S(d)+" * "+R2S(e)+" = "+R2S(d * e) elseif Check == "/" then set Display = R2S(d)+" / "+R2S(e)+" = "+R2S(d/e) endif call DisplayTextToForce(GetPlayersAll(), Display) |
| 12-09-2008, 01:14 PM | #3 |
Tried it - that was exactly the problem. Yeah, it was made out of GUI (c'mon, it's my first JASS trigger!) and I made parts of it shorter, but I forgot the elseifs in the 3rd part. +Rep |
| 04-13-2010, 01:46 PM | #4 |
Ok before I start a new thread, I can also use this old one - it's the same topic anyway. The triggers work, but I need some comments and/or critics on the coding (simpler solutions somewhere or need of more locals etc.; you get my point). JASS:function calc takes real a, real b, string x returns real local real r if x == "+" then set r = a + b elseif x == "-" then set r = a - b elseif x == "*" then set r = a * b elseif x == "/" then set r = a / b elseif x == "^" then set r = Pow(a,b) endif return r endfunction function constants takes string s returns real local real r if s == "g" then set r = I2R(GetPlayerState(Player(0), PLAYER_STATE_RESOURCE_GOLD)) elseif s == "l" then set r = I2R(GetPlayerState(Player(0), PLAYER_STATE_RESOURCE_LUMBER)) elseif s == "f" then set r = I2R(GetPlayerState(Player(0), PLAYER_STATE_RESOURCE_FOOD_USED)) endif return r endfunction function cutter takes string s returns real local string STBC = s local string a local integer g = StringLength(STBC) local integer i = 1 local integer l = 0 local integer u local real re loop set a = SubString(STBC, i - 1, i) if a == "+" or a == "-" or a == "*" or a == "/" or a == "^" then if ((a == "-" or a == "+") and i == l + 1) then else if l == 0 then set l = i else set u = g set STBC = R2S(calc(S2R(SubString(STBC, 0, l - 1)),S2R(SubString(STBC, l, i - 1)),SubString(STBC, l - 1, l)))+SubString(STBC, i - 1, u) set g = StringLength(STBC) set l = i - (u - g) set i = i - (u - g) endif endif else if a == "$" then set u = g set STBC = SubString(STBC, 0, i - 1)+R2S(constants(SubString(STBC, i, i + 1)))+SubString(STBC, i + 1, u) set g = StringLength(STBC) set i = 1 + i + (u - g) endif if i == g and l == 0 then set re = S2R(STBC) elseif i >= g and l != 0 then set re = calc(S2R(SubString(STBC, 0, l - 1)),S2R(SubString(STBC, l, i)),SubString(STBC, l - 1, l)) endif endif exitwhen i >= g set i = i + 1 endloop return re endfunction function colors takes string s returns nothing local string a = s local string b local string c local string d local integer e = 1 loop set b = SubString(a, e - 1, e) set c = SubString(a, 0, e-1) set d = SubString(a, e, StringLength(a)) if (b == "+") or (b == "-") or (b == "*") or (b == "/") or (b == "^") then set a = c + " |c00FF5151" + b + "|r " + d set e = e + 14 elseif (b == "(") or (b == ")") then set a = c + "|c000080FF" + b + "|r" + d set e = e + 12 elseif (b == ".") then set a = c + "|c004FFF4F.|r" + d set e = e + 12 elseif b == "$" then set a = c + "|c00990099" + SubString(a, e - 1, e + 1) + "|r"+ SubString(a, e + 1, StringLength(a)) set e = e + 13 endif exitwhen e == StringLength(a) set e = e + 1 endloop set a = a + " |c00FFFF80=|r" call DisplayTimedTextToForce(GetPlayersAll(), 6.00, a) set a = "" endfunction function Trig_Parser_Actions takes nothing returns nothing //the locals are in order of appearance :D local string S = SubString(GetEventPlayerChatString(), 2, StringLength(GetEventPlayerChatString())) //writen in mayor letter because it's teh string!! local integer a = 1 local string b local integer c = 1 local string d local real e call colors(S) if StringLength(GetEventPlayerChatString()) > 2 and SubString(GetEventPlayerChatString(), 0, 2) == ".=" then loop exitwhen a > StringLength(S) set b = SubString(S, a-1, a) if b == "(" then set c = a + 1 loop exitwhen c > StringLength(S) set d = SubString(S, c - 1, c) if d == ")" then set e = cutter(SubString(S, a, c - 1)) if SubString(S, a - 5, a - 1) == "sqrt" then set S = SubString(S, 0, a - 5) + R2S(SquareRoot(e)) + SubString(S, c, StringLength(S)) elseif SubString(S, a - 4, a - 1) == "abs" then set S = SubString(S, 0, a - 4) + R2S(RAbsBJ(e)) + SubString(S, c, StringLength(S)) else set S = SubString(S, 0, a - 1 ) + R2S(e) + SubString(S, c, StringLength(S)) endif set a = 0 exitwhen true else if d == "(" then set a = c else endif endif set c = c + 1 endloop else endif set a = a + 1 endloop // One last run in case there have been no brickets. set S = R2S(cutter(S)) if S2R(S) == I2R(R2I(S2R(S))) then set S = I2S(R2I(S2R(S))) else endif call DisplayTimedTextToForce(bj_FORCE_PLAYER[0], 6.00, S) else endif endfunction function InitTrig_Parser takes nothing returns nothing set gg_trg_Parser = CreateTrigger( ) call TriggerRegisterPlayerChatEvent( gg_trg_Parser, Player(0), ".=", false ) call TriggerAddAction( gg_trg_Parser, function Trig_Parser_Actions ) endfunction If the answer doesn't continue any advice to get vJASS (i know it kthx) and is helpfull, i'll give +Rep of course. |
| 04-13-2010, 03:03 PM | #5 |
It is hard to read your code, because you don't use indentation correctly. Look at any script in the resource section to find out how it should be. Secondly, please don't use a,b,c etc. as variable names. The names should describe what the variable is there for. It is very hard to figure out what your code does because of this, and therefore it is hard to give you any advice. |
| 04-14-2010, 12:58 AM | #6 |
This: JASS://is this needed? =P function calc takes real a, real b, string x returns real //local real r if x == "+" then /*set r =*/ return a + b elseif x == "-" then /*set r =*/ return a - b elseif x == "*" then /*set r =*/ return a * b elseif x == "/" then /*set r =*/ return a / b elseif x == "^" then /*set r = Pow(a,b)*/ return a^b //should be faster endif return 0 endfunction For function "constants", just use direct returns (as done above) as well. JASS:call DisplayTimedTextToForce(GetPlayersAll(), 6.00, a) set a = "" Use bj_FORCE_ALL_PLAYERS directly instead of GetPlayersAll(), and you don't need to set a to "". Also, I don't understand this code that much: JASS:if S2R(S) == I2R(R2I(S2R(S))) then set S = I2S(R2I(S2R(S))) endif Well, unless you are trying to compare it to the truncated value. That's all I could really find at the moment. |
| 04-14-2010, 01:00 PM | #7 |
Thanks for doing more than just flipping over the code. return a^b is not possible, but the others work fine. Thanks. The part you don't understand is just to check if the real has numbers after the comma 12.200 -> 12 -> 12.000 != 12.200 , display real but 13.000 -> 13 -> 13.000 == 13.000, display integer |
| 04-15-2010, 11:57 PM | #8 |
not ModuloReal(a, 1.)==0.
Thats how |
