Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sistema Cerca #20

Closed
daevamelia opened this issue May 12, 2013 · 17 comments
Closed

Sistema Cerca #20

daevamelia opened this issue May 12, 2013 · 17 comments

Comments

@daevamelia
Copy link

Sarebbe utile averlo per gli oggetti ma se verranno tolti,non so. Però molti giochi utilizzano la funzione giornaliera della caccia o della cerca che comporta il trovare un'oggetto qualsiasi o un fallimento.

@breakeryouko
Copy link
Contributor

Il sistema in se è semplicissimo da fare, saranno si e no 20 minuti di lavoro.
Il problema è gestire quali oggetti trovare e con quali probabilità.
Dipendono da land a land ed è difficile generalizzare il tutto. Se hai qualche idea esponila pure

@ste-camp
Copy link
Member

Se ogni oggetto ha probabilità diverse di venire estratto la cosa si fa complessa, perchè pur potendo memorizzare per ogni oggetto la probabilità di essere ritrovato, quest'ultima è legata al totale degli oggetti presenti; all'aumentare degli oggetti esistenti la probabilità di trovare un oggetto in particolare si diluisce. Bisogna anche contare che la probabilità totale deve essere 100 (meno il valore dell probabilità del fallimento, eventualmente), e quindi ogni volta che si aggiunge o toglie un oggetto è necessario risistemare le probabilità memorizzate per tutti gli oggetti. In effetti la cosa è problematica. Non sono una cima in probabilità.....esiste un qualche indice che non dipende dal numero totale di oggetti?

Se invece tutti gli oggetti hanno la stessa probabilità di essere ritrovati allora la cosa è davvero molto semplice. Ma non credo che qualcuno vorrebbe un sistema in cui una spada leggendaria abbia la stessa probabilità di essere ritrovata di un vecchio stivale.

@breakeryouko
Copy link
Contributor

Secondo me bisognerebbe mettere un valore "%di trovarlo" poi si sommano tutti i valori degli oggetti trovabili e si lancia un dado in base al numero che esce so va a ripescare l'oggetto.
Esempio:
Spada 10
Cristallo 1
Ascia 7

10+1+7= 18 quindi 1d18
Se esce 1-10 prendi una spada, se esce 11 prendi cristallo se esce 12-18 prendi l'ascia.
Questo potrebbe essere un sistema generalizzato

@daevamelia
Copy link
Author

Il problema è quello ci sono oggetti infatti che sono più difficili da trovare,quindi,correggetemi se sbaglio va impostato sull'oggetto la rarità che viene poi elaborata come dici tu breaker,no?

@ste-camp
Copy link
Member

si dovrebbe andare.

@breakeryouko
Copy link
Contributor

Se esce 1-10 prendi una spada, se esce 11 prendi cristallo se esce 12-18 prendi l'ascia.

Questo passaggio non ho idea di come scriverlo xD

@ste-camp
Copy link
Member

Quando fai la somma per trovare il totale su cui fare il random devi decidere un ordinamento fisso che terrai per gli oggetti. Mettili in un array in quell'ordine, ogni elemento dell'array deve contenere l'ID dell'oggetto e la sua probabilità. Ora inizia a scandire l'array dall'inizio e a ogni iterazione somma in una variabile la probabilità dell'oggetto attuale. Nel momento in cui la somma passa da minore a maggiore o uguale del numero estratto a caso fermati. L'oggetto corrente è quello da selezionare.
O comunque un algoritmo simile ;)

@blancks
Copy link
Member

blancks commented May 15, 2013

Boh, ti ho scritto in 2 minuti come lo farei io senza sbatterci molto la testa.

Edit: forse come lo avevo scritto faceva confusione, intendevo il mio sistema lavora in percentuale ma i valori di rarità che puoi assegnare ad ogni oggetto non definiscono la sua diretta percentuale, quanto più la sovrabbondanza (o carenza) di esso rispetto a qualcun altro in lista.

Se in lista ho un oggetto che vale 5 e un altro che vale 10, significa che quello che vale 10 si trova in proporzione il doppio delle volte rispetto a quello che vale 5, mentre si trova 10 volte più spesso contro un ipotetico oggetto che vale 1.

Spero sia più chiaro così ;)

<?php
#> Agevoliamoci la vita
function calcolaPercentuale($totale, $valore)
{
    return intval((100/$totale)*$valore);
}


#> Elenco oggetti e percentuali
$valori = array(
    'idoggetto1' => 30,
    'idoggetto2' => 25,
    'idoggetto3' => 15,
    'idoggetto4' => 44,
    'nulla' => 80);

#> L'ordinamento è fondamentale
asort($valori);


#> Totale ci serve per fare i calcoli
$totale = array_sum($valori);


#> Tiriamo il nostro dado immaginario
$casualita = mt_rand(0,100);


foreach ($valori as $riferimento => $valore)
{
    $calcolo = calcolaPercentuale($totale, $valore);

    echo 'Il riferimento "', 
        $riferimento, 
        '" ha una percentuale di uscita del ', 
        $calcolo,
        '... ';

    if ($casualita <= $calcolo)
    {
        echo 'Trovato!';

        #> Trovato, interrompo bruscamente il mio foreach
        break;

    }else{
        echo 'Non trovato.';
    }

    echo '<br>';
}


echo '<br><br>
    Coff, coff, ripeto se non ti fosse chiaro che ho trovato un "', 
    $riferimento, 
    '" !';

?>

@ste-camp
Copy link
Member

Potrei sbagliarmi ma l'algoritmo qui sopra non mi sembra essere corretto.
Se esistono più oggetti con la stessa probabilità di uscire, uscirà sicuramente sempre il primo, a causa dell'ordinamento fisso.

@blancks
Copy link
Member

blancks commented May 15, 2013

Mi sa che hai pienamente ragione, per completarlo a dovere ci vorrebbe una funzione di ordinamento casuale degli indici aventi gli stessi valori.

@blancks
Copy link
Member

blancks commented May 15, 2013

Toh, oggi ho qualche minuto libero xD
Da sostituire all'asort di prima chiaramente.

function riordinaValori($valori)
{
    asort($valori);

    $oggetti = array();

    foreach ($valori as $idOgg => $valOgg)
    {
        if (!isset($oggetti[$valOgg]))
            $oggetti[$valOgg] = array();

        $oggetti[$valOgg][] = $idOgg;
    }


    $valori = array();

    foreach ($oggetti as $valOgg => $idOgg)
    {
        if (count($idOgg) == 1)
        {
            $valori[$idOgg[0]] = $valOgg;

        }elseif (count($idOgg) > 1) {

            shuffle($idOgg);

            foreach ($idOgg as $singoloOgg)
            {
                $valori[$singoloOgg] = $valOgg;
            }
        }
    }


    return $valori;
}

@ste-camp
Copy link
Member

Oppure fai il tiro casuale tra 0 e $totale e selezioni l'oggetto che deve uscire in base all'intervallo in cui si trova il numero casuale, come voleva fare sopra breaker

@blancks
Copy link
Member

blancks commented May 15, 2013

Anche il mio usa la stessa logica, solo che standardizza i range nell'intervallo 0-100%
Ripeto il fatto che si tratta di un mio personale approccio al problema comunque.

@ste-camp
Copy link
Member

Eh non esattamente. Con il tuo approccio hai bisogno dell'operazione che hai appena scritto, che contiene codice con complessità abbastanza alta. Questa operazione non è necessaria con l'approccio che ho descritto nel mio commento di ieri, che quindi risulta avere una complessità più bassa.

@blancks
Copy link
Member

blancks commented May 15, 2013

Ah questo è sicuro, il tuo approccio è più conveniente dal momento in cui mi hai fatto notare quel problema.

@ste-camp
Copy link
Member

Ora che ho un po' di tempo posso mettere in codice il mio algoritmo, affitto il codice di @PHPmyWay modificandolo XD

#> Elenco oggetti e percentuali
$valori = array(
    'idoggetto1' => 30,
    'idoggetto2' => 25,
    'idoggetto3' => 15,
    'idoggetto4' => 44,
    'nulla' => 80);//Ricordati di inserire nell'array anche la percentuale di non trovare nulla

/**
 * L'ordinamento è importante per avere risultati più consistenti tra diverse chiamate alla funzione ricerca.
 * Se riesci a farlo nella query SQL piuttosto che in PHP è molto meglio!
 * Non importa che tipo di ordinamento fai, l'importante è che sia deterministico
 */
asort($valori);

#> Totale ci serve per fare i calcoli
$totale = array_sum($valori);

#> Tiriamo il nostro dado immaginario
$casualita = mt_rand(0,$totale);

$sum=0;
foreach ($valori as $riferimento => $valore)
{
   $sum+=$valore;
   if ($sum>=$casualita)
   {
        echo 'Trovato un ".$riferimento."!';
        break;
    }
}
?>

Dovrebbe andare

@breakeryouko
Copy link
Contributor

chiudo per inattività.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants