Jump to content

Hashmaps


postie

Recommended Posts

I've been trying to make a world hopper with a timer that i can use for buying items or mining. I have been using hashmaps to keep the world and system time but my problem is that as of right now i can't seem seem to find a way to instantly return a world once it goes over "X" amount of time, the only method i have checks if the key i give it is in the hashmap and then checks to see if its been longer than "X" amount of time. generating the worlds using a RNG means if it doesn't generate the world then it never revisits it or at least not soon enough to buy when items re-spawn.


 


Does anyone have an ideas to another method of storing keys and values together that would let me check by value and return a key, or a work around for the hashmap.


 


//postie


Link to comment
Share on other sites

I'm not sure why either you're attempting to over complicate things on purpose or without knowing it, but literally creating an array of worlds to hop to and then passing the hopWorld() method a random index will do exactly what you want.

worldHopper.hopWorld(WORLD_ARRAY[Math.random() * WORLD_ARRAY.length]);
Link to comment
Share on other sites

 

I'm not sure why either you're attempting to over complicate things on purpose or without knowing it, but literally creating an array of worlds to hop to and then passing the hopWorld() method a random index will do exactly what you want.

worldHopper.hopWorld(WORLD_ARRAY[Math.random() * WORLD_ARRAY.length]);

Well, in that case you won't be able to save the respawn time of the certain item/object you want. I guess HashMap with a class that stores the respawn time and uses the world as a key would work. You could use a simple for loop to go through every value in the hashmap and then if one of them has reached the respawn time you simply hop to the world with the id of that key

  • Like 1
Link to comment
Share on other sites

Hey I wrote a class to help you with the problem

 

The pool introduces a random element without having to randomly iterate through the list each time (prioritising worlds we haven't visited for longer).

import java.util.LinkedList;
import java.util.Random;

/**
 *
 * @author Ziy
 */
public class WorldManager {

    private int[] worlds = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // Example worlds
    private final int POOLSIZE = 5; // Size of pool (must be <= number of worlds)
    private final int ACCEPTABLE_TIME = 10; // in seconds

    private final LinkedList<Integer> queue = new LinkedList<>();
    private final int[] pool = new int[POOLSIZE];
    private final Random random = new Random();
    private final long startTime;

    public WorldManager() {

        // Start by shuffling the worlds
        shuffleArray(worlds);

        // Add all the worlds to the queue
        for (int world : worlds) {
            queue.add(world);
        }

        // Move the first n (where n is the pool size) into the pool
        for (int i = 0; i < pool.length; i++) {
            pool[i] = queue.remove();
        }

        // Repurpose the world array so we can now use it to house the times
        // We will index it using the world number
        worlds = new int[100];

        // Set the start time
        startTime = System.currentTimeMillis();

    }

    public int getNext() // returns world or -1 if no world satisfies
    {

        int startingRandom = random.nextInt(pool.length);

        // Pick a random world from the pool and iterate through the rest 
        // to look for a valid world
        for (int i = 0; i < pool.length; i++) {
            int startingIndex = (startingRandom + i) % pool.length;
            int nextWorld = pool[startingIndex];

            if (getTime() - worlds[nextWorld] >= ACCEPTABLE_TIME - 1
                    || worlds[nextWorld] == 0) {
                // Update world time
                worlds[nextWorld] = getTime() + 1;

                // Add world back to the queue
                queue.add(nextWorld);

                // Add the head of the queue to the pool
                pool[startingIndex] = queue.remove();

                return 300 + nextWorld; // 300 added for OS
            }
        }

        // No world satisfies the time required
        return -1;
    }

    private int getTime() {
        return (int) ((System.currentTimeMillis() - startTime) / 1000);
    }

    private void shuffleArray(int[] array) {
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            // Simple swap
            int a = array[index];
            array[index] = array[i];
            array[i] = a;
        }
    }

    // Test main - remove if unwanted
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        WorldManager wm = new WorldManager();

        while (System.currentTimeMillis() < startTime + 30000) // crudely run for 30 secs
        {
            int world = wm.getNext();
            long time = (System.currentTimeMillis() - startTime) / 1000;
            if (world != -1) {
                System.out.println("World: " + world + " Time: " + time + "s");
            }
        }

    }

}

Here is what it looks like when we run the main

run:
World: 307 Time: 0s
World: 301 Time: 0s
World: 305 Time: 0s
World: 310 Time: 0s
World: 308 Time: 0s
World: 304 Time: 0s
World: 309 Time: 0s
World: 302 Time: 0s
World: 306 Time: 0s
World: 303 Time: 0s
World: 308 Time: 10s
World: 301 Time: 10s
World: 304 Time: 10s
World: 305 Time: 10s
World: 306 Time: 10s
World: 303 Time: 10s
World: 307 Time: 10s
World: 310 Time: 10s
World: 302 Time: 10s
World: 309 Time: 10s
World: 304 Time: 20s
World: 305 Time: 20s
World: 307 Time: 20s
World: 308 Time: 20s
World: 306 Time: 20s
World: 303 Time: 20s
World: 310 Time: 20s
World: 309 Time: 20s
World: 302 Time: 20s
World: 301 Time: 20s
BUILD SUCCESSFUL (total time: 30 seconds)

Quickly drawn diagram to explain the process

 

zZ4k0OF.png

  • Like 1
Link to comment
Share on other sites

you're all overcomplicating this guys :|

you can keep using a HashMap<Integer, Integer> (or HashMap<Integer, Long>, whatever you prefer)

just iterate over map.entrySet() and find the entry with the lowest value property; then return that entry and grab the key from it (aka your world)

 

Your approach will work, but..

 

Why not have worst case O(1) lookup each time if you can?

 

You are iterating over the entire set of worlds each time which is unnecessary and can prove to be inefficient if you polling for available worlds continually

 

This will repeat the same sequence of worlds every time

 

You haven't mentioned the time constraint

Link to comment
Share on other sites

Your approach will work, but..

 

Why not have worst case O(1) lookup each time if you can?

 

You are iterating over the entire set of worlds each time which is unnecessary and can prove to be inefficient if you polling for available worlds continually

 

This will repeat the same sequence of worlds every time

 

You haven't mentioned the time constraint

Except...

Having constant-time lookups is not necessary in this case.

RS scripting should not care about lookup efficiency in most cases, since all delay comes from the game itself.

Also, I seriously doubt the OP will continually poll for available worlds; once he finds an available one, he will hop there. In the meantime, either OP won't poll or he will be waiting for a world to become available.

HashMaps will keep his code simple and clean, too.

Also, the HashMap won't contain thousands of elements; at most 50-ish.

 

tl;dr rs isn't performance sensitive, writing new class is useless

Link to comment
Share on other sites

 

Except...

Having constant-time lookups is not necessary in this case.

RS scripting should not care about lookup efficiency in most cases, since all delay comes from the game itself.

Also, I seriously doubt the OP will continually poll for available worlds; once he finds an available one, he will hop there. In the meantime, either OP won't poll or he will be waiting for a world to become available.

HashMaps will keep his code simple and clean, too.

Also, the HashMap won't contain thousands of elements; at most 50-ish.

 

tl;dr rs isn't performance sensitive, writing new class is useless

 

I think my understanding of "useless" is different from yours

I really can't be bothered discussing this further. It is all subjective after all. I prefer to spend a little bit of time and thought and produce reusable resources with minimal overheads

Link to comment
Share on other sites

   

I think my understanding of "useless" is different from yours

I really can't be bothered discussing this further. It is all subjective after all. I prefer to spend a little bit of time and thought and produce reusable resources with minimal overheads

Your reasoning is understandable but it's pretty irrelevant in this case. It's never wrong to care about performance though, haha.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...