Come posso distribuire equamente le risorse tra le fabbriche quando le risorse sono quasi esaurite?


12

La risorsa principale nel mio gioco è la massa , memorizzata come un numero in virgola mobile che cambia nel tempo. I nodi di risorse aumentano la massa e le fabbriche la drenano. Ad esempio, se ho un nodo di risorse che produce 5 masse al secondo, guadagnerò 5 * deltaTmassa ad ogni passo del gioco. La massa viene visualizzata arrotondata al numero intero più vicino e gli indicatori di guadagno / perdita sono visualizzati in decimi.

Come dovrei gestire lo zero di massa? Questo crea una condizione di competizione se più fabbriche stanno cercando di costruire contemporaneamente: le fabbriche prima in coda o che consumano meno risorse hanno la priorità una volta che arrivano più risorse e quindi costruite più velocemente delle altre.

Come posso gestirlo? Devo saltare completamente il passo?


Bah, il mio commento non è stato salvato. Ho avuto una spiegazione migliore. Fondamentalmente ho una risorsa a cui si accede ad ogni passo da ogni oggetto. Ogni oggetto aggiunge o sottrae dalla risorsa. Il mio problema è che se la risorsa arriva a 0 non so cosa fare. Devo fare una coda di qualche tipo? Devo saltare il passaggio di un oggetto. Che cosa?
Mob

3
Round robin. Problema risolto.
Patrick Hughes,

La risposta di Roy in basso combinata con il commento ad esso descrive un sistema di robin rotondo decente, di facile manutenzione e messa a punto. Finché il tuo immediato problema di progettazione viene risolto, va tutto bene =)
Patrick Hughes,

Risposte:


9

Sono d'accordo con Petr: non esiste un modo preciso per farlo. Come vuoi farlo dipende da come vuoi progettare il tuo gioco.

In questa circostanza, tuttavia, penso che sia immediatamente ovvio il tipo di meccanico che stai cercando di ottenere: vuoi solo che le cose producano il più velocemente possibile, entro la quantità di massa che hai a disposizione.

Produrre entro la capacità

Prenderò un foglio dal libro del comandante supremo, dal momento che stai facendo un sistema molto simile al loro: se stai producendo al di sopra della capacità, il modo migliore per affrontarlo è rallentare la produzione su tutta la linea. La riduzione della capacità produttiva è in realtà piuttosto semplice.

Un meccanico di velocità di produzione

Ad ogni fase di aggiornamento, le tue fabbriche non producono solo una quantità prestabilita: operano in base a una velocità di produzione , che determina quanti progressi fanno in ciascuna fase e quanta massa consumano. Quando produci con una capacità del 75%, le tue fabbriche fanno il 75% di progressi in più a ogni passaggio e utilizzano fino al 75% della massa rispetto al 100% della capacità.

Per calcolare la velocità di produzione, prima di creare qualsiasi cosa, è necessario interrogare le fabbriche per determinare le risorse totali che verrebbero utilizzate a pieno regime. Quindi esegui un semplice calcolo:

production speed = (total mass capacity / mass required this step)
if (production speed > 1.0) production speed = 1.0

Supponiamo che tu abbia bisogno di 125 masse in questo passaggio per produrre a piena capacità, ma ne hai solo 100 in questo passaggio. Questa equazione fornisce una velocità di produzione di 0,8 (la rappresentazione decimale dell'80%). Quando dite alle vostre fabbriche di eseguire effettivamente il loro edificio , date loro questo valore per dire loro a quale velocità stanno costruendo: e ora la vostra produzione viene rallentata su tutta la linea.

alternative

Potresti anche iniziare a chiudere temporaneamente le fabbriche fino a quando la capacità produttiva non si libera, e potrebbe essere molto interessante vedere che ciò accade alle fabbriche più lontane dai generatori quando a capacità estremamente bassa.

Più risorse?

Decidi tu come gestirlo; ci sono tante opzioni. Il più semplice è probabilmente calcolare una capacità produttiva per ogni risorsa e quindi scegliere quella più bassa , in modo tale che la risorsa più debole diventi un collo di bottiglia per tutto il resto.


Penso che non sia nemmeno necessario dire alla fabbrica di produrre all'80% di velocità, perché qualunque cosa la tua fabbrica crei utilizza una quantità fissa di massa. Ad esempio: costruisci un serbatoio che impiega 100 masse per essere costruito, normalmente la fabbrica può usare 2 masse per ciclo. Ciò significa che sono necessari 50 cicli per completare il serbatoio e ogni ciclo aggiunto 2 alla massa corrente del serbatoio. Ora, hai solo 1 massa disponibile, questo significa che questo ciclo, i serbatoi attualmente spesi aumentano di 1 invece di 2. Dopo ogni ciclo basta controllare la massa corrente rispetto alla massa totale richiesta per vedere se il serbatoio è completamente costruito o no.
Thomas,

Se hai 0 masse disponibili, non aggiungere alcuna massa al serbatoio. Il tempo necessario per costruire qualcosa in questo modo può variare a seconda del tuo reddito di massa. se hai 2 fabbriche che possono usare 2 massa / ciclo e solo 3 entrate, il serbatoio 1 viene costruito in 50 cicli, il serbatoio 2 in 100. Un altro modo è quello di dividere la quantità totale di massa disponibile tra tutte le fabbriche che lo usano (sono attivamente costruendo qualcosa). La quantità totale di massa che una fabbrica può utilizzare può essere aggiornata aggiungendo livelli alla fabbrica. Ad esempio al livello 1 possono spendere 2 masse, al livello 2: 3 masse ecc. Ecc.
Thomas,

@Thomas L'aggiunta di massa a un prodotto in fase di realizzazione sembra un modo eccessivamente complesso rispetto al semplice completamento di una percentuale del prodotto. Soprattutto perché la tua fabbrica deve sapere tutto sul tuo sistema di risorse invece di una semplice proprietà "rate di produzione". Se il risultato per il giocatore è lo stesso, mantieni l'implementazione il più semplice possibile. Ciò semplifica anche le modifiche in futuro, ad esempio quando si aggiungono / rimuovono risorse.
Hackworth,

@Hackworth Tendo a non essere d'accordo, la fabbrica non ha bisogno di conoscere il sistema di risorse. La fabbrica sa solo cosa sta costruendo e quanto dista. Il sistema di risorse dice semplicemente alla fabbrica di aggiungere una quantità X alla build. In questo modo non è necessario calcolare la percentuale di entrate delle risorse di questa fabbrica e non è necessario tradurre le entrate delle risorse in percentuale di completamento aggiunta.
Thomas,

6

Anche se mi piace la risposta di Jonathan Hobbs, penso che un sistema di code sia ancora più semplice:

Queue<Factory> queue = ...;
int numFactories = ...;

Update()
{
    int resources = GetAllResourcesForThisStep();
    for(int i = 0; i < numFactories; i++)
    {
        if(queue.Peak().RequiredResources <= resources)
        {
            Factory f = queue.Pop();
            resources -= f.RequiredResources;
            queue.Push(f);
        }
        else
        {
            break;
        }
    }
}

Questo probabilmente funzionerà in media allo stesso modo dell'implementazione di Jonathan. Tuttavia, la soluzione di Jonathan potrebbe dare problemi se la velocità di lavoro è impostata su un valore molto basso e la mia implementazione potrebbe avere una fabbrica con una richiesta di risorse molto elevata per questo frame, perché potrebbe bloccare altre fabbriche per diversi frame.


+1 Sto sviluppando un gioco con due risorse, proprio come nella domanda, e quando cerco di risolvere il problema del blocco delle forniture, ho intenzione di utilizzare qualcosa di simile a questo. Non quel codice esatto, ma l'idea alla base. I consumatori che sono in grado di utilizzare le risorse in un tick avranno una priorità inferiore durante il tick successivo. Ho anche intenzione di aggiungere un flag per indicare se questo consumatore ha la massima priorità e dare il controllo di tale flag all'utente.
John McDonald,

Fai attenzione alla fame se dai loro priorità separate. :)
Roy T.

Lo scopo sarebbe la fame con priorità separate. Hai mai giocato a Settlers 4 o Knights & Merchants? Se costruisci eccessivamente edifici, le risorse limitate vanno a edifici casuali e ci vuole un'eternità per finire qualsiasi cosa. Ma consentono anche di selezionare se un edificio è importante o meno, nel qual caso le risorse andranno prima a quegli edifici importanti. La chiave è non costruire mai troppo, o se lo fai, costruire troppo il meno possibile.
John McDonald,

5

Sto sviluppando un sistema di approvvigionamento simile nel mio gioco, quindi ho anche pensato a come risolvere il problema del blocco delle forniture e al favoritismo. Per illustrare il problema, creerò un semplice esempio:

Se hai un elenco: [produttore1, consumatore1, consumatore2, consumatore3] e aggiorni in ordine, a partire da fornitura = 0, otterrai questo:

producer1 produces 5 mass. You now have 5 mass
consumer1 wants 3 mass. Success, you now have 2 mass
consumer2 wants 3 mass. Fail
consumer3 wants 3 mass. Fail
[next tick]
producer1 produces 5 mass. You now have 7 mass
consumer1 wants 3 mass. Success, you now have 4 mass
consumer2 wants 3 mass. Success, you now have 1 mass
consumer3 wants 3 mass. Fail
etc...

consumer1 diventa divertente, mentre i consumatori 2 e 3 muoiono di fame fino a quando il consumatore 1 non è soddisfatto. A seconda del tuo gioco, questo potrebbe non essere desiderabile. Lo so nel mio gioco, non lo è. Quando ci arrivo, creerò una coda in cui i consumatori che sono stati alimentati in un tick si sposteranno sul retro della coda per il tick successivo, che credo sia quello a cui Roy T. sta arrivando. L'esempio sopra sarebbe simile al seguente:

producer1 produces 5 mass. You now have 5 mass
consumer1 wants 3 mass. Success, you now have 2 mass. <-- Move to end of queue
consumer2 wants 3 mass. Fail
consumer3 wants 3 mass. Fail
[next tick]
producer1 produces 5 mass. You now have 7 mass
consumer2 wants 3 mass. Success, you now have 4 mass  <-- Note the order change
consumer3 wants 3 mass. Success, you now have 1 mass
consumer1 wants 3 mass. Fail
etc...

In questo modo, tutti avranno la loro giusta quota delle risorse.

Ho anche intenzione di implementare una coda aggiuntiva da utilizzare come coda prioritaria in modo che l'utente possa selezionare determinate strutture per avere la priorità delle risorse. La coda prioritaria verrà sempre servita prima della coda standard. Assicurati che tutti i produttori vengano prima aggiornati, quindi consuma tutte le risorse in secondo luogo, altrimenti la coda si interromperà quando produci risorse a metà tick e alcuni consumatori sono già affamati.

Quindi, per ricapitolare: aggiorna i produttori, quindi la coda prioritaria, spostando i consumatori alimentati alla fine della coda prioritaria, quindi aggiorna la coda standard, spostando i consumatori nutriti alla fine della coda standard.


Preso al limite, potrebbe significare che nessun consumatore finisce fino a quando ogni consumatore non può finire. In uno scenario realistico della catena di produzione, è abbastanza improbabile e potrebbe essere abbastanza disastroso se qualcuno volesse avere una coda di costruzione per un esercito enorme. Sarà praticamente senza truppe per tutto il tempo in cui l'esercito verrà costruito.
Cardin,

Quella risposta è stata il mio pensiero iniziale quando ho letto la domanda. Inoltre, va notato che la massa consumata per tick non è necessariamente la massa per creare un'unità completa, ma piuttosto il costo unitario nel tempo richiesto, quindi non sono sicuro che le preoccupazioni di @ Cardin siano valide, a meno che la tua unità il costo per tick è molto vicino al tasso di raccolta totale. Avrei semplicemente la coda di priorità esplicitamente gestita dal giocatore, in modo che possa decidere chi muore di fame.
brice il

@Cardin, hai ragione, ma può anche essere usato come meccanico di gioco. Settlers 4, Knights & Merchants, Total Annihilation, Supreme Commander sono giochi che so che hanno fatto questo. Il trucco è non raggiungere questo blocco delle forniture e, in tal caso, assicurarsi di uscire dal blocco delle forniture al più presto. L'aggiunta di una coda di priorità consente alle persone di uscire più facilmente.
John McDonald,

3

Bene, mi espanderò sull'idea di John, dato che ne abbiamo discusso un po ' in chat .

modifica: questa soluzione è in realtà preferibile solo se consumableAmount è rilevante per la frequenza con cui la fabbrica dovrebbe ottenere un lotto di risorse. Se è lo stesso, allora puoi semplicemente usare una coda.

La mia soluzione: tutte le fabbriche elencate in una coda prioritaria. La priorità è aumentata poiché una fabbrica soffre di fame. La fame, la priorità, impostata su zero quando la fabbrica ha consumato risorse. La massima priorità è sempre ottenere il prossimo lotto di risorse.

Per determinare quale factory ottiene quali risorse, in una sorta di pseudo codice:

iterator i = factoryqueue.start()
bool starvation = false
while(i.next())
  if(i.ready)
    if (!starvation) 
      if (i.consumeAmount < resource.count) starvation = true
      else 
        i.consume(resource)
        i.priority = 0
    if (starvation)
      i.priority += 1

In questo modo le vostre fabbriche produrranno 1 prodotto ciascuna a turno, se si desidera adeguarsi prendendo in considerazione il consumo di conto in modo che i prodotti più economici vengano realizzati più frequentemente, è possibile aumentare la priorità di 1 / consumo ad esempio.


Vorrei votare questo, ma non sono sicuro di cosa debba fare: tiene traccia della fame, ma altrimenti (presumibilmente) ruota semplicemente attraverso la coda esattamente come di consueto, e sia la fame che la priorità non finiscono mai per apparire fare qualsiasi cosa.
doppelgreener,

la differenza diventa evidente se si aumenta la priorità di + = 1 / amountThisFactoryConsumes, quindi quelli che richiedono più risorse per creare un prodotto resteranno indietro un po ', consentendo a quelli meno costosi di prendere proporzionalmente più lotti di risorse. Ciò eliminerebbe il rapporto risorse per fabbrica. Tuttavia, questo non è esattamente a prova di errore, dato che il numero di fame è impostato sul numero magico 0 ogni volta che le risorse vengono consumate dalla fabbrica, quindi non verrà messo in quarantena per essere distribuito esattamente in modo uniforme quando il rinnovo delle risorse è interrotto.
Toni,

In realtà ora non sono così sicuro se in realtà non è garantito. Avrei bisogno di disegnare alcuni grafici e testarlo per essere sicuro.
Toni,

oh, e la priorità è una qualità della coda di priorità stessa. Non mi preoccuperò di spiegare come costruirne uno. La coda di priorità stessa viene sempre ordinata in base al valore di priorità dei suoi membri.
Toni,

+1 Capendo che si tratta di una coda prioritaria, il suo funzionamento ora sembra semplice: setacciare la coda e individuare la cosa più presto che potrebbe consumare risorse. Se la capacità è fortemente divisa (hai 1000 risorse in questo segno di spunta, ma cento build da 100 risorse) questo non dovrebbe essere un problema e le cose si alimentano abbastanza bene. Anche se qualcosa è molto al di sopra delle tue risorse in questo segno di spunta, alla fine potrebbe risparmiare abbastanza da fare un po 'di progressi - il che ha l'effetto di rallentarlo o di chiudere completamente grandi cose a favore di cose più piccole, il che è una buona cosa. Mi piace molto questo. :)
doppelgreener,

2

Strana domanda.

Il mio problema è che se la risorsa arriva a 0 non so cosa fare. Devo fare una coda di qualche tipo? Devo saltare il passaggio di un oggetto. Che cosa?

Quello che devi fare dipende dalla logica di gioco che crei. Puoi fare una coda, puoi saltare. Dipende da come pensi che il tuo gioco dovrebbe comportarsi. Correggimi, se sbaglio sulla tua domanda.


1

È possibile mantenere un numero della domanda totale di risorse per tick per tutte le costruzioni. Se l'archiviazione di una risorsa raggiunge un valore inferiore a questo importo richiesto, tutta la costruzione si arresterebbe completamente fino a quando l'archiviazione non si fosse raccolta abbastanza per supportare almeno 1 tick di produzione. Quindi la produzione può riprendere.

Quindi, invece di archiviare il tasso di produzione come float, è binario - o la tua fabbrica produce alla massima velocità oppure no.

Detto questo, questo approccio è essenzialmente lo stesso della risposta di Jonathan, per i casi speciali di tasso di produzione 0,0 e 1,0 - un float arbitrario f con 0,0 <= f <= 1,0 è probabilmente più elegante in quanto non si ottengono movimenti a scatti della quantità di memoria , ma la logica dovrebbe essere un po 'più semplice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.