• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

Wanderer - Submission

Status
Not open for further replies.
JASS:
library Wanderer initializer Init
    globals
        hashtable h = InitHashtable()
    endglobals
    private function Periodic takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local unit u = LoadUnitHandle(h, i, 0)
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real a = GetRandomReal(0, 360) * bj_DEGTORAD
        local real d = GetRandomReal(500, 1500)
        local real xx = x + d * Cos(a)
        local real yy = y + d * Sin(a)
        call IssuePointOrder(u, "move", xx, yy)
        call SetTerrainType(LoadReal(h, i, 1), LoadReal(h, i, 2), LoadInteger(h, i, 3), LoadInteger(h, i, 4), 1, 0)
        call SaveReal(h, i, 1, x)
        call SaveReal(h, i, 2, y)
        call SaveInteger(h, i, 3, GetTerrainType(x, y))
        call SaveInteger(h, i, 4, GetTerrainVariance(x, y))
        call SetTerrainType(x, y, 'Nsnw', 0, 1, 0)
        call TimerStart(t, d / GetUnitMoveSpeed(u), false, function Periodic)
        set t = null
        set u = null
    endfunction
    function Wander takes unit u returns nothing
        local timer t = CreateTimer()
        local integer i = GetHandleId(t)
        call SaveUnitHandle(h, i, 0, u)
        call TimerStart(t, 0, false, function Periodic)
        set t = null
    endfunction
    private function Init takes nothing returns nothing
        local unit u = CreateUnit(Player(0), 'hgry', 0, 0, 0)
        call Wander(u)
        set u = null
    endfunction
endlibrary


//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
 

Attachments

  • Wanderer.w3m
    8.3 KB · Views: 43
Last edited:
Level 15
Joined
Mar 25, 2016
Messages
1,327
I don't think the way you use timers in this code is good. You need to have a periodic trigger, that checks, whether the unit has reached the target location. If you assume, that the duration is distance/movespeed your system will be very limited.
It will only work, if the unit moves at linear distance. This will be the case for air units in most cases, but not always. Your system will also not work with various movement modifying abilities such as speed bonus, slow, stun.
However your system is more efficient than a periodic check, so it is better in a "perfect world", where you can ensure, that the unit will move at linear distance in constant speed.

You should indent your code to make it easier to read.

The first time Periodic runs, the hashtable won't have data, so
JASS:
call SetTerrainType(LoadReal(h,i,1),LoadReal(h,i,2),LoadInteger(h,i,3),LoadInteger(h,i,4),1,0)
might not work correctly. I don't if anything bad could happen though.
 
This is an efficient design, whereas, if the unit does not arrive in the elapsed time, it will wander in a different direction. This is good for cases in which the path is blocked. Additionally, checking once every 1-5 seconds is far superior than checking every .03125 seconds or so.

There is no issue with the first enumeration having null values.

It works correctly, as it needs to, according to the mission description.
 
Example: once the unit gets stuck it completely breaks the wander effect, whilst the timer is still checking every .03 seconds until the end of time. If you still think this way is the way to go, you need to check and see if your unit got stuck and reroute it. Essentially what I am doing, but on the principles of logic alone, without having to use resources to check periodically.
@Jampion

Try your test map now that your unit is stuck.
 

Attachments

  • JASS Class Mission 2.w3x
    24.8 KB · Views: 51
Level 15
Joined
Mar 25, 2016
Messages
1,327
I can see what you mean. It really depends on what you need the wander system for. Both your and my system work correctly for the given mission, but both will fail under certain circumstances.
I still think periodic checks are better, because otherwise the system won't work correctly, if the unit's movement speed is changed.
This is good for cases in which the path is blocked.
It is only good, if the path is fully blocked. If it is only partially blocked, the unit won't arrive in time and the desired location won't be reached.
Example: once the unit gets stuck it completely breaks the wander effect, whilst the timer is still checking every .03 seconds until the end of time.
One would have to detect this situation and find another location to move to.

This is an efficient design
That's true. Your system is more efficient. But at the end of the day it comes down to whether it is important for the unit to actually reach the target point or just to move around.
 
Okay, in that case, we need to consider if the unit was given an alternate order. Do we cancel the wander script upon receiving an outside order or force the wandering unit to ignore outside orders? Additionally we need to check if the wander point is reachable, if they are stuck or interrupted...

I don't understand the resource intensive approach over the simple approach. It's quite easy to make the changes you have requested. I just don't understand why teaching people this way would help. If this system were used in any kind of scale, you'd run into problems. You would not want this system to iterate 30 times a second per unit. Not to mention you would have to add about 5+ checks to ensure the system wouldn't break down.

To each their own I suppose. I'll make the changes.

That's true. Your system is more efficient. But at the end of the day it comes down to whether it is important for the unit to actually reach the target point or just to move around.
Agreed. I feel your description needs clarification, IceManBo.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
^this is not very acceptable, needs to be precise condition when unit arrives there. In real cases we must consider units being slowed or anything, and making assumptions is not best.
Except it is wandering around so does not ever need to arrive anywhere? Maybe the mission description should be reworded if you want it to definitively arrive at the chosen point before finding a new point.

I would be more concerned about the lack of map boundary checks, something missing from the initial mission description. WC3 has been know to crash when orders and movement off the map bounds occurs.
 
Okay, in that case, we need to consider if the unit was given an alternate order.
No, it's not required to build in extra safety logics.

If this system were used in any kind of scale, you'd run into problems. You would not want this system to iterate 30 times a second per unit. Not to mention you would have to add about 5+ checks to ensure the system wouldn't break down.
Problems are in your theory only; there are no problems. And I believe 30 iterations are not even required. Something like 10-20 checks per second would do, too.
The system would break down? I don't see why /when ; but what I see is that your code does not technicaly checked for wanted condition, that :
"When reaching the target location point, then the tileset should become the original tileset again"

^What makes it unclear?

Maybe the mission description should be reworded if you want it to definitively arrive at the chosen point before finding a new point.
isn't it worded like it?

I would be more concerned about the lack of map boundary checks, something missing from the initial mission description. WC3 has been know to crash when orders and movement off the map bounds occurs.
True, I'm currently aware of it, but didn't want to put extra content to this start mission (later it's asked for boundary checks); maybe it could be changed though, yes.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
isn't it worded like it?
Part 1

Create a gryphon rider at center of the map.
The gryphon must receive a move order to a random location. The random location is defined to have a random distance between 500 and 1500 and to have a random angle towards the gryphon. (so basicly the location is a random point in a circular range of 500-1500 from the gryphon)
Part 2

Now when receiving the move order to the random location, then the tileset at target location should turn to snow, 'Nsnw'. When reaching the target location point, then the tileset should become the original tileset again, and the unit should repeat the procedure, receiving a new order, tile becomes snow, etc... again and again.
It is mentioned, but not where the movement is first set up. I would imagine something like this would be more clear.

Part 1
Create a gryphon rider at center of the map.
The gryphon must receive a move order to a random location. The random location is defined to have a random distance between 500 and 1500 range and to have a random angle away from the gryphon (any point on a 1500 range disk with a 500 range hole centred in it around the gryphon).
Upon arrival at the random location a new move order should be received towards a new random location such that the unit is kept in near constant motion.

The random location must be within map boundaries. Assume the terrain has no air collision so that all playable map area is potentially a valid random point. Assume the gryphon has a non-constant speed and will not have any of its orders interrupted.

Part 2
When issuing a move order to the gryphon the tile type at the target random location should be changed to snow of type 'Nsnw'.
Upon arriving at the random location the tile type and variation should be restored to its previous, unmodified, state.

Assume that there is enough free tileset space to dynamically load the required tile type. The tile variation of a generated snow tile does not matter.

This breaks it down such that part 1 fully focuses on movement while part 2 extends part 1 to change the tile type. It also removes ambiguity.
 
Status
Not open for further replies.
Top