[PHP] slagingskans berekening

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • chaozz
  • Registratie: Juni 2000
  • Laatst online: 29-08 01:01

chaozz

Retrofiel

Topicstarter
Voor m'n crime game werk ik met slagingskansen. Dus aan de hand van jouw XP level, jouw skill, jouw systeem etc wordt een fancy berekening gedaan en daar komt dan een slagingskans uit.

Stel, speler A valt speler B aan. De slagingskans op basis van hun onderlinge verschil in hiervoor genoemde punten 30%.

Wat ik dan in PHP doe is hetvolgende:
PHP:
1
2
3
4
5
6
7
8
$chance = 30; // is dus ergens berekend, maar nu even hier als getal
$random = rand(1,100);
if ($random <= $chance) {
 // de aanval is gelukt
}
else {
 // epic fail etc..
}


Mijn vraag is echter, is dit een juiste manier van werken? Of heeft iemand een slimmere methode?

chaozz.nl | RetroGameCouch


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 10:43

Matis

Rubber Rocket

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

Verwijderd

Op basis van je omschrijving zie ik niet in waarom dit anders zou moeten.

Mocht je werken met veel verschillende files dan kan je er een functie van maken:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Func Succes($chance){
 if (rand(1,100)<=$chance){
 return true;
 }
 else }
 return false;
 }
}


if Succes(30){
 // de aanval is gelukt
}
else {
 // epic fail etc..
}

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

chaozz schreef op vrijdag 13 augustus 2010 @ 16:57:
Mijn vraag is echter, is dit een juiste manier van werken? Of heeft iemand een slimmere methode?
Boeit dat echt voor een stukje code van (in essentie) 5 regels? Ik neem aan dat de code doet wat je wil, dus waarom zou het niet voldoen? :) Afgezien van de post van Matis hier boven mij natuurlijk. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • ChickMagneet
  • Registratie: Juli 2010
  • Laatst online: 03-03-2024
Als die eerste berekening goed is dan is dit inderdaad de beste manier.

Acties:
  • 0 Henk 'm!

  • b19a
  • Registratie: September 2002
  • Niet online
Wat je vermoedelijk wilt is een Discrete uniforme verdeling waarbij de kans op elke mogelijke uitkomst even groot is. rand() en mt_rand() geven precies wat je wilt. Verder inderdaad wat Matis schrijft; computers genereren semi-willekeurige getallen.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Als je écht professioneel wilt doen, doe je het met drie stappen:

* Schrijf op wat je verwacht. Ik neem aan: 30% kans, dan zullen er bij 100 pogingen 30 (plus of min 5, marge ivm random) slagen.
* Schrijf hier een test voor - zie ook: unit tests
* Programmeer de implementatie, totdat de test slaagt.

Da's tenminste de theorie.

Acties:
  • 0 Henk 'm!

  • chaozz
  • Registratie: Juni 2000
  • Laatst online: 29-08 01:01

chaozz

Retrofiel

Topicstarter
De vraag komt eigenlijk meer voort uit de vragen van spelers. In het onderdeel small hacks bijvoorbeeld is de slagingskans van sommige hacks bijvoorbeeld 60%. Toch faalt het voor het gevoel vaker dan 4 op de 10 keer. Vandaar ook mijn vraagtekens bij de rand() functie.
Waarom geldt mt_rand() alleen voor een windows server? Ik draai het thuis op een Ubuntu server bak en heb inmiddels alle rand() functies vervangen door mt_rand(). Het zou volgens php.net sneller en beter moeten werken. We zullen zien.

[ Voor 122% gewijzigd door chaozz op 13-08-2010 21:49 ]

chaozz.nl | RetroGameCouch


Acties:
  • 0 Henk 'm!

  • croontje
  • Registratie: April 2004
  • Laatst online: 26-07 00:34
Kan je dan niet gewoon even in een loopje heel veel small hacks achter elkaar doen en dan het percentage vergelijken met je verwachtingen?

Acties:
  • 0 Henk 'm!

  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 01-07-2023
croontje schreef op vrijdag 13 augustus 2010 @ 21:38:
Kan je dan niet gewoon even in een loopje heel veel small hacks achter elkaar doen en dan het percentage vergelijken met je verwachtingen?
Precies, schrijf er een test voor dan weet je het zeker.

Acties:
  • 0 Henk 'm!

  • Ram0n
  • Registratie: Maart 2002
  • Laatst online: 03-07 13:05

Ram0n

Bierbrouwende nerd

chaozz schreef op vrijdag 13 augustus 2010 @ 21:26:
De vraag komt eigenlijk meer voort uit de vragen van spelers. In het onderdeel small hacks bijvoorbeeld is de slagingskans van sommige hacks bijvoorbeeld 60%. Toch faalt het voor het gevoel vaker dan 4 op de 10 keer. Vandaar ook mijn vraagtekens bij de rand() functie.
Zoals eerder gezegd is dit inderdaad enórm eenvoudig te testen. Laat even een flink aantal keer je idee draaien in een loopje en hou bij hoe vaak je script zegt dat iets wel of niet slaagt. Dan kan je in één keer zien of het klopt of niet.

Eigenaar/brouwer Milky Road Brewery


Acties:
  • 0 Henk 'm!

  • b19a
  • Registratie: September 2002
  • Niet online
YopY schreef op vrijdag 13 augustus 2010 @ 21:10:
Als je écht professioneel wilt doen, doe je het met drie stappen:

* Schrijf op wat je verwacht. Ik neem aan: 30% kans, dan zullen er bij 100 pogingen 30 (plus of min 5, marge ivm random) slagen.
* Schrijf hier een test voor - zie ook: unit tests
* Programmeer de implementatie, totdat de test slaagt.

Da's tenminste de theorie.
YopY, in theorie zouden Unit tests inderdaad je code 100% moeten kunnen testen. Probleem hier is echter dat er sprake is van willekeurigheid. Behalve met een complete statistische analyse kun je zoiets niet bevangen in een Unit Test. Bij 30% kans bestaat een grote mogelijkheid dat <25 of >35 van de 100 trekkingen zullen slagen.

Mocht je je niet willen branden aan statistische analyses, pas dan de wet van de grote aantallen toe en voer je functie 100.000 (of vaker voor zover tijd beschikbaar is) keer uit. Naar mater je populatie groter is, zal de slagingskans (mits juiste functie) rond de 30% uitkomen.

Voor eventuele *goede* unit tests zul je toch met statistische analyses bezig moeten. Voor een ruwe benadering, neem een grote trekking en hou rekening met standaarddeviaties en betrouwbaarheidsintervallen als je de uitkomsten interpreteert.

edit:
Hoewel grote aantallen al beter zijn dan kleine trekkingen, zul je vroeg of laat statische analyses moeten doen om de resultaten te interpreteren. Unit-testing zal alleen goed functioneren als je niet met _random_ afwijkingen rekening houdt, maar als beredeneerde (afwijkingen op) standaarddeviaties en betrouwbaarheidsintervallen gebruikt voor de interpretatie

[ Voor 22% gewijzigd door b19a op 15-08-2010 21:45 ]


Acties:
  • 0 Henk 'm!

  • Sendy
  • Registratie: September 2001
  • Niet online
De wet van de grote nummers?!? Aantallen zal je bedoelen.

De truc is om de willekeur heen komen door een vaste seed te gebruiken in unit-tests.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

In de parktijk zal je er weinig van merken met zo'n spel, maar er zit wel een kleine afwijking in je code. Kijk maar naar bijvoorbeeld 50%, dat zou 1 op 2 moeten zijn. Maar de lengte van je interval [1,100] is 99, en de lengte van [1,50] is 49, daar (50,100] lengte 50 heeft. De kans met percentage 50% is dus eigenlijk 0,4949 en geen 0,5.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
BoukeHaarsma schreef op zondag 15 augustus 2010 @ 16:34:
Mocht je je niet willen branden aan statistische analyses, pas dan de wet van de grote nummers toe en voer je functie 100.000 (of vaker voor zover tijd beschikbaar is) keer uit. Naar mater je populatie groter is, zal de slagingskans (mits juiste functie) rond de 30% uitkomen.
Programmers Need To Learn Statistics Or I Will Kill Them All

Als je het goed wil doen (en überhaupt het "slagingspercentage" wil unit-testen) houdt je unit-test er gewoon rekening mee dat er een (kleine) afwijking is. Simple as that.

[ Voor 4% gewijzigd door RobIII op 15-08-2010 16:58 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • chaozz
  • Registratie: Juni 2000
  • Laatst online: 29-08 01:01

chaozz

Retrofiel

Topicstarter
Zoijar schreef op zondag 15 augustus 2010 @ 16:54:
In de parktijk zal je er weinig van merken met zo'n spel, maar er zit wel een kleine afwijking in je code. Kijk maar naar bijvoorbeeld 50%, dat zou 1 op 2 moeten zijn. Maar de lengte van je interval [1,100] is 99, en de lengte van [1,50] is 49, daar (50,100] lengte 50 heeft. De kans met percentage 50% is dus eigenlijk 0,4949 en geen 0,5.
ah, kijk.. inderdaad. dat scheelt op een hack job met 20 procent slagingskans al een mooi eind. moet dus inderdaad [0,100] zijn.

chaozz.nl | RetroGameCouch


Acties:
  • 0 Henk 'm!

  • Sendy
  • Registratie: September 2001
  • Niet online
Nee, rand(1,100) geeft willekeurig een geheel getal terug uit de verzameling (1, 2, ..., 100). Deze verzameling is precies 100 elementen groot. En de <= test is ook prima. Er is geen structurele afwijking in je eerste code.
edit:
als rand() een uniforme verdeling heeft natuurlijk.

[ Voor 25% gewijzigd door Sendy op 15-08-2010 21:14 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

oh ik ging ervan uit dat rand een float terug geeft tussen 1.0 en 100.0. Handig dat php ;) Met een uniforme integer verdeling is het wel goed ja.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
quote: Bouke
YopY, in theorie zouden Unit tests inderdaad je code 100% moeten kunnen testen. Probleem hier is echter dat er sprake is van willekeurigheid. Behalve met een complete statistische analyse kun je zoiets niet bevangen in een Unit Test. Bij 30% kans bestaat een grote mogelijkheid dat <25 of >35 van de 100 trekkingen zullen slagen.
In je unit test kun je daarom ook wel rekening houden met die willekeurigheid, zoals ik aangaf. Er is een mogelijkheid dat er inderdaad <25 of >35 uitkomt, echter als dat het geval is kun je nagaan of je random functie wel echt random is. Even testen:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 
for ($reps = 0; $reps <= 10; $reps++) {
    $percentage = 0;
    for ($i = 0; $i <= 10; $i++) {
        if (rand(1, 100) < 30) {
            $percentage++;
        }
    }
    echo $percentage . "\r\n";
    if ($percentage < 25 || $percentage > 35) {
        echo "percentage < 25 of > 35!11\r\n";
    }
}


Bij 10 reps komt dit wel regelmatig voor, dus je hebt wel gelijk. Echter, ook dit kun je in je functionele eisen stellen - het percentage moet ongeveer 30% zijn (met random), echter het percentage mag niet < 25% of > 35% uitkomen. Dan wordt het niet helemaal random, maar pseudorandom. Er zijn waarschijnlijk statistici en programmeurs die dit beter uit kunnen leggen.

In dit geval: Je kunt er wel een test voor schrijven, echter als je <25 of >35 in je test meeneemt behoort dat ook in de functionele eisen te staan. Je test er immers ook voor.

(Tot zover YopY die in zichzelf post over de relatie functionele eisen <-> unit tests)

Acties:
  • 0 Henk 'm!

  • Sendy
  • Registratie: September 2001
  • Niet online
Tja, YopY, dan krijg je gewoon een andere kansverdeling. Dat verandert niets aan het probleem van lastig testen met iets willekeurigs.

Acties:
  • 0 Henk 'm!

Verwijderd

Hoe goed je testen ook zijn, gevoel is niet te coden. Als het gevoel bij de spelers niet klopt en je weet dat je scripts juist zijn dan moet je wellicht je formule iets bijstellen.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

chaozz schreef op vrijdag 13 augustus 2010 @ 21:26:
Toch faalt het voor het gevoel vaker dan 4 op de 10 keer. Vandaar ook mijn vraagtekens bij de rand() functie.
Gevoel is bij statistiek een enorm slechte raadgever (al was het alleen maar vanwege confirmation bias).

Kun je niet op 1 of andere manier uit je logging alle hackpogingen achterhalen? Dan kun je namelijk heel simpel uitrekenen of het gevoel van de mensen klopte of niet. Als je dat niet uit je logging kunt achterhalen dan wordt het misschien tijd om eens hierover na te gaan denken. Het lijkt mij voor een dergelijke webgame erg handig wanneer op 1 of andere manier het spelverloop ergens terug te halen is.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • chaozz
  • Registratie: Juni 2000
  • Laatst online: 29-08 01:01

chaozz

Retrofiel

Topicstarter
Ja, alles wordt gelogd. Daar moet inderdaad wel een mooie SQL query van te maken zijn. Ik ga eens knutselen.

chaozz.nl | RetroGameCouch


Acties:
  • 0 Henk 'm!

  • Tjeemp
  • Registratie: Januari 2005
  • Laatst online: 03-01-2015

Tjeemp

BEER N TEA

Ik heb een keer een uitbreiding op de rand() functie gezien, omdat blijkbaar de randomness van die functie nog niet optimaal is en dus inderdaad vaker op hetzelfde antwoord uitkomt. Dus als je echt een betrouwbaar random getal moet hebben zou ik daar eens naar zoeken.

www.timovanderzanden.nl | Beer 'n' Tea

Pagina: 1