2

Specifically, this is for Garry's Mod, however I don't think that matters too much in this problem. What I want to do is get one player, and set their value to another random player (so every player has a random 'target'). I want to do this with no repeats, and so that a player is not assigned to their self. To better illustrate:

Player assigning illustation.

The only difference to that picture is that I want each player to be assigned to another random player, so more like player1 => player 5, player 3 => player 2, etc.

Here is my code at the moment, however this always leaves one person unpicked:

validTargets = {}
TargetList = {}

local Swap = function(array, index1, index2)
    array[index1], array[index2] = array[index2], array[index1]
end

GetShuffle = function(numelems)
    local shuffle = {}
    for i = 1, numelems do
        shuffle[#shuffle + 1] = i
    end
    for ii = 1, numelems do
        Swap(shuffle, ii, math.random(ii, numelems))        
    end
    return shuffle
end

function assignTargets()
    local shuffle = GetShuffle(#playing)
    for k,v in ipairs(shuffle) do
        TargetList[k] = v
    end

    SyncTargets()
end

function SyncTargets()
    for k,v in pairs(TargetList) do
        net.Start("sendTarget")
            net.WriteEntity(v)
        net.Send(k)
    end
end
pppery
  • 3,731
  • 22
  • 33
  • 46
Jake Stanger
  • 449
  • 1
  • 8
  • 24

1 Answers1

3

I have a lua function that generates a Random shuffle of numbers from 1 to n, given n. The method is based on a popular algorithm to generate a random permutation of an array of elements .

You can try using that like so:

local Swap = function(array, index1, index2)
    array[index1], array[index2] = array[index2], array[index1]
end


GetShuffle = function(numelems)
    local shuffle = {}
    for i = 1, numelems do
        shuffle[#shuffle + 1] = i
    end
    for ii = 1, numelems do
        Swap(shuffle, ii, math.random(ii, numelems))        
    end
    return shuffle
end

function assignTargets()
    local shuffle = GetShuffle(#playing) --assuming `playing` is a known global
    for k,v in ipairs(shuffle) do
        TargetList[k] = v
    end
end
Arun R
  • 873
  • 6
  • 10
  • Ok I'm a bit of a noob. Can you help me in using this in my own example? – Jake Stanger Jun 10 '14 at 16:54
  • Assuming you want to update `TargetList` each time, the function `assignTargets` does the equivalent thing as your `assignTargets`: after you call `assignTargets`, the `TargetList` will be filled with the new random shuffle of player assignments. – Arun R Jun 10 '14 at 17:12
  • So I just stick this in instead of my code? Do I need to change anything? Sorry - super noob right here. – Jake Stanger Jun 10 '14 at 17:19
  • I've just tried the code, and got "Attempt to call global 'Swap'." Is that not a default function? – Jake Stanger Jun 10 '14 at 18:17
  • Yes, sorry, didn't realize I had another function. But just edited my answer. – Arun R Jun 10 '14 at 18:50
  • Thanks! Only problem is "attempt to index local 'object' (a number value" in my SyncTargets function. I'll change my code to include it, but does the TargetList still store data the same way? – Jake Stanger Jun 10 '14 at 18:54
  • whops forgot to include your name. Please see my last comment. – Jake Stanger Jun 10 '14 at 19:13
  • @Roboguy99 TargetList is an map of number -> number. If you were trying to index either `k` or `v` in `WriteEntity`or in `Send`, it'll fail. – Arun R Jun 10 '14 at 20:27
  • OK. What I need though is PlayerData to PlayerData (which is what the table playing contains). How easy is it to change it? – Jake Stanger Jun 11 '14 at 07:06