Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

2 Stron V   1 2 >  
Reply to this topicStart new topic
> Wypadanie przedmiotów w grze
Diwi
post 29.08.2005, 12:12:43
Post #1





Grupa: Zarejestrowani
Postów: 245
Pomógł: 4
Dołączył: 22.01.2005

Ostrzeżenie: (0%)
-----


Witam. Pisząc silnik gry napotkałem problem. Otóż zazwyczaj po zabiciu potwora wypadają z niego jakieś przedmioty, załóżmy że np. jest 1% szansy że wypadnie jakiś drogocenny kamień ale 20% że jakiś średni miecz. Czy istnieje jakiś algorytm który jest w stanie wybrać co wypadło wg procentu szansy ?

Pozdrawiam
Go to the top of the page
+Quote Post
Fipaj
post 29.08.2005, 12:19:15
Post #2





Grupa: Zarejestrowani
Postów: 691
Pomógł: 0
Dołączył: 19.01.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Robisz tablicę, na sto elementów... (można to zrobić jakąś jedną funkcją, nie pamiętam jaką). Potem rand(), jeśli wypadło 1, dostaje kamień; else { robisz tablicę na pięć elementów, wybierasz 1, jeśli wypadło na ten jeden jedyny - dostajesz miec }

Proste, pomyśl trochę...


--------------------
Go to the top of the page
+Quote Post
tiraeth
post 29.08.2005, 12:36:29
Post #3





Grupa: Przyjaciele php.pl
Postów: 1 789
Pomógł: 41
Dołączył: 30.10.2003
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


A ja to rozwiązałem tak:

  1. <?php
  2. $przedmioty[] = array(
  3. 'name' => 'Magiczny miecz wilka',
  4. 'p' => '20');
  5. $przedmioty[] = array(
  6. 'name' => 'Nadkruszony szafir',
  7. 'p' => '1');
  8.  
  9. /***
  10.  * Powiedzmy, że tablica $przedmioty to zwrócona przez MySQL tablica z przedmiot
    ami (posortowanymi wg. procentu malejąco):
  11.  * while($row = mysql_fetch_assoc($result))
  12.  * { $przedmioty[] = $row; }
  13.  */
  14.  
  15. $items = count($przedmioty); # Liczba przedmiotow
  16. $i=0;
  17. do
  18. {
  19.  $name = $przedmioty[$i]['name'];
  20.  $p = $przedmioty[$i]['p'];
  21.  $a = 100/$p;
  22.  $r = rand(1, $a);
  23.  if($r == 1)
  24.  {
  25. $item = true;
  26. $item_name = $name;
  27.  }
  28.  $i++;
  29. }
  30. while($item == false && $i < $items);
  31.  
  32. if($item == true)
  33. {
  34.  echo 'Z pola walki zabrano <b>'.$item_name.'</b>';
  35. }
  36. else
  37. {
  38.  echo 'Nie znaleziono żadnych przedmiotów';
  39. }
  40. ?>


W komentarzu napisałem, że pobierasz z bazy danych przedmioty sortując je wg. procentu malejąco smile.gif

I wcale nie jest tutaj potrzebna tablica 100-elementowa smile.gif
Go to the top of the page
+Quote Post
mike
post 29.08.2005, 13:01:42
Post #4





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


IMO, przekombinowaliści.
  1. <?php
  2.  
  3. // tabela items to dane o przedmiocie i procent szans jak tzreb mieć żeby go zdoby
    ć
  4.  
  5. $objDB->query( 'SELECT * FROM items WHERE percentage >= ' . rand( 1, 100 ) . 'ORDER BY RAND() LIMIT 1' );
  6.  
  7. // i już mamy przedmiot tongue.gif
  8.  
  9. ?>


1. Losujemy procent szans, np.: 40%
a) Możemy dostać każdy przedmiot, który wymaga 40%
b ) ... ale i każdy, który wymaga więcj, np.: 60%, 70%, ...
c) ... no oczywiście nie możemy dostać tego, któremu trzeba 5%.

2. Resztę załatwia baza. Losuje ona jeden element, który wymaga szans większych, bądź równych tym które wylosowaliśmy. Czyli dostać możemy przedmiot, który wymaga przykładowych 40% ale i taki który wymaga 80%.

Ja bym to widział tak.
Go to the top of the page
+Quote Post
ebe
post 29.08.2005, 13:22:11
Post #5





Grupa: Zarejestrowani
Postów: 150
Pomógł: 1
Dołączył: 23.01.2004

Ostrzeżenie: (0%)
-----


Cytat
Robisz tablicę, na sto elementów... (można to zrobić jakąś jedną funkcją, nie pamiętam jaką). Potem rand(), jeśli wypadło 1, dostaje kamień; else { robisz tablicę na pięć elementów, wybierasz 1, jeśli wypadło na ten jeden jedyny - dostajesz miec }

Proste, pomyśl trochę...


Jednocześnie dokupujesz kostki RAM do serwera tongue.gif


--------------------
Słyszałem, że macie tutaj jakieś takie php... fajne to, dobre to jest?
Go to the top of the page
+Quote Post
dr_bonzo
post 29.08.2005, 13:38:12
Post #6





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Cytat
załóżmy że np. jest 1% szansy że wypadnie jakiś drogocenny kamień ale 20% że jakiś średni miecz

I tak dalej? A procenty uzupelniaja sie do 100?


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
SongoQ
post 29.08.2005, 13:39:34
Post #7





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


W programowaniu jak w zyciu, czym prostrzy algorytm tym efektowniejszy.


--------------------
Go to the top of the page
+Quote Post
Diwi
post 29.08.2005, 14:42:54
Post #8





Grupa: Zarejestrowani
Postów: 245
Pomógł: 4
Dołączył: 22.01.2005

Ostrzeżenie: (0%)
-----


Hmm.. Pomysł mike_mecha wydaje mi się najprostszy biggrin.gif. Będe musiał przetestować smile.gif.

Pozdrawiam
Go to the top of the page
+Quote Post
php programmer
post 29.08.2005, 15:26:31
Post #9





Grupa: Zarejestrowani
Postów: 1 045
Pomógł: 5
Dołączył: 8.11.2004
Skąd: trójmiasto

Ostrzeżenie: (0%)
-----


// wersja z możliwośćią wielokrotnego wyboru

szansa['miecz'] = 20;
szansa['kamien'] = 1;
itd

foreach ($szansa as $nazwa => $wartosc)
if ( $wartosc >= rand(1,100) ) WyrzućPrzedmiot[$nazwa];
Go to the top of the page
+Quote Post
mike
post 29.08.2005, 15:40:45
Post #10





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


Cytat(php programmer @ 2005-08-29 15:26:31)
// wersja z możliwośćią wielokrotnego wyboru

A po co zaraz puszczać pętlę questionmark.gif

U mnie taka możliwośc jest na końcu zapytania tongue.gif

  1. ... ORDER BY RAND() LIMIT 1


Zmieniasz wartość w LIMIT, lub go usuwasz i masz wielokrotny wybór.
Go to the top of the page
+Quote Post
splatch
post 30.08.2005, 07:52:25
Post #11





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(mike_mech)
W programowaniu jak w zyciu, czym prostrzy algorytm tym efektowniejszy.


Chyba miałeś na myśli - w programowaniu jak w życiu, im prostszy skrypt tym efektywniejszy...
"Efektowny" to chyba nie jest odpowiednie słowo w tym miejscu.


--------------------
Łukasz Dywicki
Independent Java and open source software consultant.
Blog - Java, OSGi, integracja oprogramowania..
Go to the top of the page
+Quote Post
FiDO
post 30.08.2005, 09:55:30
Post #12





Grupa: Przyjaciele php.pl
Postów: 1 717
Pomógł: 0
Dołączył: 12.06.2002
Skąd: Wolsztyn..... Studia: Zielona Góra

Ostrzeżenie: (0%)
-----


Cytat
IMO, przekombinowaliści.

IMO niedoceniles problemu ;]


Cytat
$objDB->query( 'SELECT * FROM items WHERE percentage >= ' . rand( 1, 100 ) . 'ORDER BY RAND() LIMIT 1' );

// i już mamy przedmiot tongue.gif

Tylko, ze losowany niezgodnie z zasadami podanymi na poczatku.
Po wylosowaniu jakiegos progu procentowego zostaja nam tylko rekordy z wiekszym prawdopodobienstwem wystapienia niz wylosowane.. i do tego momentu jest dobrze (no prawie..), bo sposrod tych elementow losujesz kolejny niestety juz na rownych prawach, czyli jesli wylosuje sie prog dajmy na to 30% to zarownio element majacy 31% jak i element majacy prawdopodobienstwo wystapienia rowne 50% beda mialy rowne szanse przy losowaniu a tak nie mialo byc.

Robilem cos podobnego niedawno w pracy (losowanie wazone), zrobilem do tego procedure, ale mysql takich mozliwosci jeszcze w wersji produkcyjnej nie daje, wiec trzeba sobie radzic inaczej smile.gif. Algorytm polega na tym, ze do jakiejs tymczasowej tablicy (czy to w bazie czy php) wpisujemy kazdy element tyle razy ile wynosi jego waga, czyli np. dla wartosci 20%, 25% i 50% wpisujemy kolejne elementy w ilosciach 20, 25 i 50 (w tym przypadku akurat mozna te wagi skrocic, bo maja NWD > 1), a nastepnie losujemy z tej tablicy/tabeli w sposob tradycyjny. Teraz elementy maja takie szanse jak miec powinny smile.gif


--------------------
Brak czasu :/
Go to the top of the page
+Quote Post
mike
post 30.08.2005, 10:14:01
Post #13





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


Cytat(FiDO @ 2005-08-30 09:55:30)
IMO niedoceniles problemu ;]

Masz racje. Po tym jak wypowiedziałem się tutaj zaczął mnie ten problem nurtować. I doszedłem do takich samych wniosków co Ty.

Gdyby nie to drugie losowanie ( już na takich samych prawach ) nie byłó by tak źle. Ale wprowadzenie losowania ważonego wydaje się koniecznością.
Go to the top of the page
+Quote Post
ActivePlayer
post 30.08.2005, 18:46:44
Post #14





Grupa: Przyjaciele php.pl
Postów: 1 224
Pomógł: 40
Dołączył: 6.07.2004
Skąd: Wuppertal

Ostrzeżenie: (0%)
-----


a co jeśli przedmiotów jest hm.... 10 000... dajmy na to 100 rodzajów chełmów, 1000 rodzajów mieczy, itp itd... (tak duzo po powiedzmy generuje dynamicznie)... procent tez jest skladany dynamicznie... zakladając ze srednie prawdopodobienstwo wynosci 50%... mamy 10 000 * 50 = 500 000.
Tworzymy taka tablice po to zeby wylosowac z niej 1 element ?hm... any other ideas?
Go to the top of the page
+Quote Post
FiDO
post 30.08.2005, 19:50:32
Post #15





Grupa: Przyjaciele php.pl
Postów: 1 717
Pomógł: 0
Dołączył: 12.06.2002
Skąd: Wolsztyn..... Studia: Zielona Góra

Ostrzeżenie: (0%)
-----


Wtedy gorzej.. znalazlem takie cos: http://forums.devarticles.com/t8783/s.html
Niezbyt rozumiem na pierwszy rzut oka dlaczego to dziala, ale dziala.. i jest zdecydowanie bardziej wydajne i mniej pamieciozerne.


--------------------
Brak czasu :/
Go to the top of the page
+Quote Post
ActivePlayer
post 31.08.2005, 09:22:47
Post #16





Grupa: Przyjaciele php.pl
Postów: 1 224
Pomógł: 40
Dołączył: 6.07.2004
Skąd: Wuppertal

Ostrzeżenie: (0%)
-----


z linka:
  1. SELECT [FieldsList]
  2. FROM [TableName] WHERE [WhereStatements]
  3. ORDER BY Rand()*(1/Weight) LIMIT 1;


1/waga * losowy float ... <hmmm> moze to i dziala...
Go to the top of the page
+Quote Post
Diwi
post 2.09.2005, 18:18:11
Post #17





Grupa: Zarejestrowani
Postów: 245
Pomógł: 4
Dołączył: 22.01.2005

Ostrzeżenie: (0%)
-----


Dobrze. To teraz następny problem który pojawił się podczas pisania skryptu który walczy z czymś biggrin.gif. Mamy sobie algorytm który oblicza szanse wygrania z przeciwnikiem. No i załóżmy że wyjdzie 70% szans na wybranie. Jak wg tych szans zdobyć informacje czy ktoś wygrał ?

Pozdrawiam
Go to the top of the page
+Quote Post
dr_bonzo
post 2.09.2005, 18:51:02
Post #18





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Rzuc K100 i jesli wynik bedzie mniejszy niz 70 to wygra walke. No chyba ze walka wyglada: cios za cios.


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
FiDO
post 2.09.2005, 18:52:14
Post #19





Grupa: Przyjaciele php.pl
Postów: 1 717
Pomógł: 0
Dołączył: 12.06.2002
Skąd: Wolsztyn..... Studia: Zielona Góra

Ostrzeżenie: (0%)
-----


Wylosowac liczbe z przedzialu 1-100, szanse na wylosowanie liczby mniejszej lub rownej 70 sa rowne mniej wiecej wlasnie 70%, dalej powalcz sam smile.gif

edit: ech.. nie zdazylem ;p


--------------------
Brak czasu :/
Go to the top of the page
+Quote Post
L_Devil
post 4.09.2005, 08:54:23
Post #20





Grupa: Zarejestrowani
Postów: 195
Pomógł: 0
Dołączył: 13.04.2004
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Gdy przeczytałem problem zaczął mnie nurtować i wpadłem na takie rozwiązanie... nie jest najlepsze, gdyż dwukrotnie musimy wykonać pętle for, ale mam nadzieję że ci się do czegoś przda smile.gif

  1. <?php
  2. /* Definiujemy tablice naszego ekwipunku */
  3. $arrItemChance = array();
  4. $arrItemName = array();
  5.  
  6. /* wpiszmy coś do tych tablic */
  7. $arrItemChance[] = 1;
  8. $arrItemName[] = "Szlachetny kamień";
  9. $arrItemChance[] = 10;
  10. $arrItemName[] = "Cenny miecz";
  11. $arrItemChance[] = 45;
  12. $arrItemName[] = "Normalny miecz";
  13. $arrItemChance[] = 80;
  14. $arrItemName[] = "Zardzewiały miecz";
  15.  
  16. /* Do obliczeń */
  17. $intMaxChance = 0;
  18.  
  19. /* Pierwsza pętla, obliczająca maskymalną szansę */
  20. $l = count($arrItemChance);
  21. for($i=0; $i < $l; $i++)
  22. {
  23. $intMaxChance += $arrItemChance[$i];
  24. }
  25.  
  26. /* Bierzemy się za losowanie :) */
  27. $intChance = rand(0, $intMaxChance);
  28.  
  29. /* No i ostatnia pętla, pobierająca dany przedmiot;-) */
  30. $l = count($arrItemChance);
  31. for($i=0; $i < $l; $i++)
  32. {
  33. if($intChance > $arrItemChance[$i])
  34. {
  35. $intChance -= $arrItemChance[$i];
  36. }
  37. else
  38. {
  39. echo "Na placu broni znalazłeś " . $arrItemName[$i];
  40. break;
  41. }
  42. }
  43. ?>


Ten post edytował L_Devil 4.09.2005, 09:40:36


--------------------
Językiem którym najlepiej operują wszyscy programiści są przekleństwa.
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.08.2025 - 02:19