Simply Pointless

But hey, why not?

By

Pool Of Randomness

For my current Unity project I had to convert Kipp Ashford’s Weighted Array script into something I could use in my C# environment. I had a similar solution already working in ISIS but Ashford’s script was much more elegant since it includes a number of useful functions my bare-boned version was lacking.

A clever (or so I hope) use of a hashtable allowed me to trim some of the variables the orginial script had used to keep it as slim as possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// WeightedRandomPool.cs
// 2013-10-09 by Thomas Touzimsky
// http://www.simplypointless.com/
//
// Adds, deletes and returns a random item from a pool of objects based on each item's associated weight
//
// A conversion of the original JS script by Kipp Ashford
// http://blog.teamthinklabs.com/index.php/2011/08/23/grabbing-items-from-an-array-based-on-probability/
 
using UnityEngine;
using System.Collections;
 
public class WeightedRandomPool
{
 
    // Our pool is stored in a hashtable where
    // key   = (Object)item
    // value = (int)weight
    public Hashtable htItems = new Hashtable();
 
 
    /// <summary>
    /// Adds a new item to the hashtable or changes its weight if has been added before
    /// </summary>
    /// <param name="item">The object you want to add to the pool</param>
    /// <param name="weight">The object's weight within the pool</param>
    public void Add(Object item, int weight)
    {
        if (!htItems.ContainsKey(item))
        {
            htItems.Add(item, weight);
        }
        else
        {
            Debug.Log("WeightedRandomPool::Add() --- WARNING: Object is already added. Changing weight of object instead.");
 
            htItems[item] = weight;
        }
    }
 
 
    /// <summary>
    /// Changes the weight of an object within the pool
    /// </summary>
    /// <param name="item">The object whose weight you want to change</param>
    /// <param name="nWeight">The object's new weight within the pool</param>
    public void ChangeWeight(Object item, int nWeight)
    {
        if (htItems.ContainsKey(item))
        {
            htItems[item] = nWeight;
        }
        else
        {
            Debug.Log("WeightedRandomPool::ChangeWeight() --- WARNING: Object '" + item + "' is not a member of this pool.");
        }
    }
 
 
    /// <summary>
    /// Removes an object from the pool
    /// </summary>
    /// <param name="item">The object you want to remove</param>
    public void Remove(Object item)
    {
        if (htItems.ContainsKey(item))
        {
            htItems.Remove(item);
        }
        else
        {
            Debug.Log("WeightedRandomPool::ChangeWeight() --- WARNING: Object '" + item + "' is not a member of this pool.");
        }
    }
 
 
    /// <summary>
    /// Returns a randomly chosen object from the pool depending on all members' weight
    /// </summary>
    /// <returns></returns>
    public Object Get()
    {
        int nSumOfWeights = 0;
 
        foreach (DictionaryEntry item in htItems)
        {
            nSumOfWeights += (int)item.Value;
        }
 
        int k = Random.Range(0, nSumOfWeights + 1);
        // +1 to make sure we can actually find the last item if it has a weight of 1
        // since Random.Range never hits the maximum value
 
        foreach (DictionaryEntry item in htItems)
        {
            // walk the pool one item at a time and see whether its weight is lower than k
            // if yes, return the current item ; if no, subtract the item's weight from k
 
            // if, for example, the pool includes three items with a weight of 40/40/60 and
            // k = 70, the first loop's result will be negative and k gets reduced by 40;
            // the next loop's result is positive since k (now 30) is lower than the second
            // item's weight
 
            if (k > (int)item.Value)
            {
                k -= (int)item.Value;
            }
            else
            {
                return (Object)item.Key;
            }
        }
 
        return null;
    }
 
 
    /// <summary>
    /// Clears the pool
    /// </summary>
    public void Clear()
    {
        htItems.Clear();
    }
 
}

The class itself is used just like Ashford’s original.

WeightedRandomPool myPool = new WeightedRandomPool();
 
myPool.Add(myFirstItem, 15);
myPool.Add(mySecondItem, 5);
myPool.Add(myThirdItem, 2);
 
UnityEngine.Object myRandomItem = myPool.Get();

Feel free to suggest any ideas on how to improve the script – after all, I am still a novice coder. 🙂

By

ISIS Canned For Now

Looks like there won’t be a finished version of ISIS anytime soon – after putting some more work into it, I had some of the more important mechanics working, but realized that it just wasn’t fun.

Back to the electronic drawing board.

By

So… what is ISIS?

ISIS is my attempt at creating – and eventually finishing this time around – a small game in Unity. The basic premise is creating a Space Invaders-inspired game that breaks away from the standard “You down here, they up there” scheme the original and its various clones rely on. How to do this? By placing the game on a hexagon!

Apart from the obvious difference that there are no borders on the sides of the screen which stop your movement, the biggest advantage is that the game will allow you to go beyond the standard “One screen, one stage” template by creating layouts of various separate hexagons, allowing the introduction of proper level design and objectives (like destroying the power generators in the three outer sections before being able to harm the centre section’s main enemy).

I will post screenshots of the current version later.