• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Choose random hero for AI

Status
Not open for further replies.
Level 5
Joined
Oct 16, 2015
Messages
132
Ok, I made a map with an AI that can pick its own hero. Rather than picking from tavern, I just made a trigger where it would just create the hero with random type. But the problem is sometimes there can be two heroes at the same time and I only want to limit it to 1 type only.
 
Level 12
Joined
Jun 15, 2016
Messages
472
Could you be a bit more specific? Please post the trigger you created and explain the behavior you're trying to avoid:
are multiple players picking the same hero type? does the trigger pick two heroes for the same player (so you end up with two heroes instead of one)?
 
Level 39
Joined
Feb 27, 2007
Messages
5,057
There are 14 heroes but the way you have set it up the AI can only randomize one of the first 7. Did you intend that?

The problem is that while you do reduce the max number by 1 every time a hero gets chosen, you don't specifically eliminate that hero from the pool. You need to use this sort of logic (not gonna type a trigger because your variable names are arcane):

  • Pick random number between 1 and N, call it X.
  • Make a HeroType[X] for the computer.
  • Set HeroType[X] = HeroType[N] (this makes it so even if the next ai gets the same random number it will be a different hero)
  • Set N = N-1 (reduces the total number of heroes to random from)
 
Level 15
Joined
Aug 14, 2007
Messages
936
I have a better idea, it is good to store hero types in "unit type" arrays but you can use "unit group".
By creating hero at a hidden part of the map and hiding them, (Hide, pause and make invulnerable), then add them into a unit group for A.I hero pick.
Next, use "select random 1 unit from unit group" and then use "remove unit from unit group" and "remove unit from the game".
This will then allow the A.I to pick a random unit (hero) from the unit group. Remember to remove every unit in the unit group to clear the memory so the the game runs better.
This is very simple GUI coding but if you still have question just reply to this and I will see what else I can do to help!

@Pyrogasm, adding on to your suggestion, directly after you set the used random hero id to "N", you need to also loop through the remaining hero types in the array until the last hero before you do N-1. This will then remove the picked random hero from the array entirely.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,057
adding on to your suggestion, directly after you set the used random hero id to "N", you need to also loop through the remaining hero types in the array until the last hero before you do N-1. This will then remove the picked random hero from the array entirely.
Incorrect. By shifting the Nth hero into the Xth slot (the one that was picked) and reducing N by 1, you properly eliminiate heroes from the list of possible ones. By leapfrogging the last into the chosen instead of shifting everything down by 1 number, you save a considerable number if steps/computation. This is exactly how it's done for Dynamic Indexing.

Unit group is a good solution. In JASS there are also unitpools.
 
Last edited:
Level 15
Joined
Aug 14, 2007
Messages
936
@Pyrogasm
Okay, sorry for my simple explanation, I believe I have not made myself very clear but judging from your comment, I believe we are talking about the same thing.
The step I missed explaining was when after you loop through the array, you also need to do X-1 so that the previous Hero type is now taken over by the advancing hero type, until the last array number, which will then effectively remove that single hero that was randomized. Correct me if I am wrong, I just admit that I did not do specific analyzing probably because I was drunk...
What I meant was that you do not just do N -1 because that will remove the last hero type on the array list, what you need to do is what I just said above, to make the removal work in the first place.
Alternatively, you guys can just use unit group, which is much less complicated as mathematics isn't my best subject too... I prefer science more ;p
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,057
Man, I appreciate that you're an old user who's come back to the site like me, but I really feel like you're not actually reading anything in the threads you're responding to.

We are not talking about the same thing. In my previous post (a reply to you) I explained why moving ALL of the other hero types 'down' one slot is more work and is significantly less efficient than just moving the last one into the 'empty' slot. I will state it again in more detail with an example.

There are 7 random heroes (N=7) and we randomize number 3 (X=3). By your method:
  1. Create hero of type 3
  2. Set HeroType[3] = HeroType[4]
  3. Set HeroType[4] = HeroType[5]
  4. Set HeroType[5] = HeroType[6]
  5. Set HeroType[6] = HeroType[7]
  6. Set N = N-1 = 6
By the proper leapfrog method:
  1. Create hero of type 3
  2. Set HeroType[X] = HeroType[N], in other words: Set HeroType[3] = HeroType[7]
  3. Set N = N-1 = 6
The order is now different, but that doesn't matter because you're picking one randomly any way. Now imagine if N was 30 or 200. Which has more steps?
 
Level 15
Joined
Aug 14, 2007
Messages
936
@Pyrogasm
I respect that you are an energy saver and I do not want to debate with your style as it is more effective but I want to close the case as to your method being very chaotic and messy.
The reason why I want to keep things in order although using more computer data is due to the way the OP had placed his heroes. By re-arranging the hero back to their natural order, the OP will still be able to track their positions in the future if he wants to update the system futher... but if the chaos did not matter to you then it should still be alright, as long as you don't make the codes more messy in the future and end up with a ton of bugs that OP can't fix himself... Well anyways I made my point, feel free to abandon them as you see fit.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,057
We not here to start a war, I am just making things easy for the new guys that's all.
But it's not easier or simpler. Which looks easier to understand and use?
  • Unit - Create 1 Hero[x]
  • Set Hero[x] = Hero[N]
  • Set N = N-1
  • Unit - Create 1 Hero[x]
  • For each (Integer A) from x to (N - 1) do (Actions)
    • Loop - Actions
      • Set Hero[(Integer A)] = Hero[(Integer A) + 1]
  • Set N = N-1
 
Level 12
Joined
Nov 3, 2013
Messages
989
EDIT: I just checked the 2nd screenshot, and noticed that you seem to want to make each picked hero unavailable to every player in the game, so you can completely ignore my post...


There are 14 heroes but the way you have set it up the AI can only randomize one of the first 7. Did you intend that?

The problem is that while you do reduce the max number by 1 every time a hero gets chosen, you don't specifically eliminate that hero from the pool. You need to use this sort of logic (not gonna type a trigger because your variable names are arcane):

  • Pick random number between 1 and N, call it X.
  • Make a HeroType[X] for the computer.
  • Set HeroType[X] = HeroType[N] (this makes it so even if the next ai gets the same random number it will be a different hero)
  • Set N = N-1 (reduces the total number of heroes to random from)
I have a better idea, it is good to store hero types in "unit type" arrays but you can use "unit group".
By creating hero at a hidden part of the map and hiding them, (Hide, pause and make invulnerable), then add them into a unit group for A.I hero pick.
Next, use "select random 1 unit from unit group" and then use "remove unit from unit group" and "remove unit from the game".
This will then allow the A.I to pick a random unit (hero) from the unit group.

Either one of these would work, but you'd need to make some changes or it won't work for more than one AI player (unless you don't want any of the AI players to pick the same heroes)

I think the easiest or at least most reasonable way (besides using hashtable) would be to create a second variable array for unit type (or integer if you're using jass), and instead of deindexing or removing the units from the unit group you would simply save the unit type(s) to the new variable.


If we're assuming that it's like in melee and you can have 3 heroes max, you'd need 3 indexes/slots dedicated to each player, e.g. 0-1-2 for player 1, 3-4-5 for player 2, 6-7-8 etc.

That way you can make a sort of 2d array, so you don't have to create another variable for every player.


Anyway, so the easiest/laziest way would be to just choose a random one from the pool, loop through the 3 indexes dedicated to the triggering player, and if the random unit type is the same as one of the 3 unit types the player already has, re-roll the dice again.

Otherwise, just temporarily remove the relevant unit types from the pool so it would be impossible for it to roll a unit type that the AI already has. It would be a bit more work, but it's better since if the dice kept rolling unit types that the AI already picked it could technically go on forever...


Oh and by the way, I don't see anyone mentioning this, but is the hero pool to choose from exactly the same for every player?

In other words, it's not some kind of melee map or something where you have your own race with some exclusive heroes? Cause then you'd probably need to make some further modifications. (It doesn't seem like this is the case, but I'm just making sure to bring this up just in case.)
 
Level 39
Joined
Feb 27, 2007
Messages
5,057
Guys am I going crazy or does it seem like nobody actually reads these threads before replying?
(unless you don't want any of the AI players to pick the same heroes)
That is exactly the situation the OP is trying to achieve:
It is supposed to be limited to 1 type of hero per map but sometimes the AI picks hero which is the same type as mine.

Edit: Ironically I missed Death Adder's edit by not scrolling up.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,057
I'm fully aware this forum has a large contingent of people who do not speak English natively. My frustration has nothing to do with English comprehension and has everything to do with how people approach problem solving. Would you try to write the answer to a math question without reading the entire problem statement first? How about buzzing in to Jeopardy before the host finishes saying the clue? I see those as analogous.

People do make mistakes and miss things (I am not exempt from this, as per my previous post here), so perhaps I seem like I'm being harsh... but I also think it can be very confusing for an inexperienced user to see three competing suggestions to an ostensibly simple problem. Which one does the OP pick when each other poster claims their method is superior and the reasoning/explanation is more advanced than the OP understands? It is definitely important to consider edge cases and special behavior, but I feel that sort of talk really only benefits whomever wants to stroke their ego showing off how much they know (and not the inexperienced thread-starter). The irony that I essentially did that with you earlier in this thread is not lost on me, but defending a simpler (but perfectly adequate) method seemed an appropriate place to write a long-winded explanation.

_____________

@SSJ7107, we all forgot to consider that you need to remove player-chosen heroes from the available hero pool to randomize too:
  • Events
    • Unit - A unit sells a unit
  • Conditions
    • (Unit-type of (Selling unit)) equal to YOUR_TAVERN //Could use triggering unit here, but I wrote it with Selling Unit just to be clear
  • Actions
    • For each (Integer A) from 1 to TOTAL_NUM_HEROES do (Actions)
      • Loop - Actions
        • If (All conditions are true) then do (Then actions) else do (Else actions)
          • If - Conditions
            • (Unit-type of (Sold unit)) equal to HERO_TYPES[(Integer A)]
          • Then - Actions
            • Player Group - Pick every player in (All players) and do (Actions)
              • Loop - Actions
                • Player - Make HERO_TYPES[(Integer A)] unavailable for construction/training by (Picked player)
            • Set HERO_TYPES[(Integer A)] = HERO_TYPES[TOTAL_NUM_HEROES]
            • TOTAL_NUM_HEROES = TOTAL_NUM_HEROES - 1
            • Custom script: exitwhen true
          • Else - Actions
 
Last edited:
Level 15
Joined
Aug 14, 2007
Messages
936
@Pyrogasm Objection! I do not strive to improve my ego as it is already there as to everyone who is alive, what I am interested in is the perfection of codes, it does seem that your codes are very easily understood to a new coder and that is very valid but the fact that they are flawed still is a cause for concerns. I particularly would like to correct it for the greater good, although myself would also argue that my own work is a waste of energy as looping too much can cause problems, problems that only exist if you do not handle the codes perfectly, problems that only happens when the codes have even the slightest bit of flaw, I do see that your codes are not flawed but just messy though. If any messy codes get out of hand then it will definitely cause problems later on, be it a bug or code jam that in the future the programmer will see to it's light but at that future moment it is all too late. All I am asking is a simple precaution, a little more effort into the engine and it solves all problems in all other universes and dimensions that one can imagine, but you do have a point, it takes away a lot of energy, very inefficient just to achieve a bit of order. Would you then suggest another way that is both efficient and orderly at the same time and I would like to see and learn from your knowledge of programming. I, for one is bad at both english and programming and one would only laugh when they see my codes because they are that of what a child would wish to play about. But what I want is an orderly and organised code system that can never go wrong, not even in a power shortage, now that's something to think about. Although personally I do feel that multiple unit systems are cool, those programmers face unknown or unheard of bugs and it takes a team of professional programmers just to debug a few, one of those few incidents can be seen in DotA 2 or other great games where errors can be seen flying around like butterflies in the released games. Look at icefrog, nothing of that scale ever happens in DotA (Warcraft). The only reason I could think of is that he works alone that time, therefore he only listens to his own knowledge and did not have to deal with untrustworthy people which otherwise would have some human error. I am fully aware that codes are almost impossible to do perfectly when it comes to multiple instances as they are so complicated that even the smartest monkey on earth can never dream of achieving but when a human commit his years of experience to fix what the society dreams of achieving, may be we could pass centuries without making those mistakes that had happened since the Jurassic period, I rest my case.
 
Level 5
Joined
Oct 16, 2015
Messages
132
I'm fully aware this forum has a large contingent of people who do not speak English natively. My frustration has nothing to do with English comprehension and has everything to do with how people approach problem solving. Would you try to write the answer to a math question without reading the entire problem statement first? How about buzzing in to Jeopardy before the host finishes saying the clue? I see those as analogous.

People do make mistakes and miss things (I am not exempt from this, as per my previous post here), so perhaps I seem like I'm being harsh... but I also think it can be very confusing for an inexperienced user to see three competing suggestions to an ostensibly simple problem. Which one does the OP pick when each other poster claims their method is superior and the reasoning/explanation is more advanced than the OP understands? It is definitely important to consider edge cases and special behavior, but I feel that sort of talk really only benefits whomever wants to stroke their ego showing off how much they know (and not the inexperienced thread-starter). The irony that I essentially did that with you earlier in this thread is not lost on me, but defending a simpler (but perfectly adequate) method seemed an appropriate place to write a long-winded explanation.

_____________

@SSJ7107, we all forgot to consider that you need to remove player-chosen heroes from the available hero pool to randomize too:
  • Events
    • Unit - A unit sells a unit
  • Conditions
    • (Unit-type of (Selling unit)) equal to YOUR_TAVERN //Could use triggering unit here, but I wrote it with Selling Unit just to be clear
  • Actions
    • For each (Integer A) from 1 to TOTAL_NUM_HEROES do (Actions)
      • Loop - Actions
        • If (All conditions are true) then do (Then actions) else do (Else actions)
          • If - Conditions
            • (Unit-type of (Sold unit)) equal to HERO_TYPES[(Integer A)]
          • Then - Actions
            • Player Group - Pick every player in (All players) and do (Actions)
              • Loop - Actions
                • Player - Make HERO_TYPES[(Integer A)] unavailable for construction/training by (Picked player)
            • Set HERO_TYPES[(Integer A)] = HERO_TYPES[TOTAL_NUM_HEROES]
            • TOTAL_NUM_HEROES = TOTAL_NUM_HEROES - 1
            • Custom script: exitwhen true
          • Else - Actions
Yes I did that already.
I have a better idea, it is good to store hero types in "unit type" arrays but you can use "unit group".
By creating hero at a hidden part of the map and hiding them, (Hide, pause and make invulnerable), then add them into a unit group for A.I hero pick.
Next, use "select random 1 unit from unit group" and then use "remove unit from unit group" and "remove unit from the game".
This will then allow the A.I to pick a random unit (hero) from the unit group. Remember to remove every unit in the unit group to clear the memory so the the game runs better.
This is very simple GUI coding but if you still have question just reply to this and I will see what else I can do to help!

@Pyrogasm, adding on to your suggestion, directly after you set the used random hero id to "N", you need to also loop through the remaining hero types in the array until the last hero before you do N-1. This will then remove the picked random hero from the array entirely.

Looks a nice idea might try later.
 
Status
Not open for further replies.
Top