Какой-то базовый расчёт, просто вероятности без ничего
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
|
||||
class DeckForm extends Model
|
||||
{
|
||||
const COMPUTE_TRIES = 10000;
|
||||
const COMPUTE_ROUNDS = 10;
|
||||
|
||||
const CARD_ANY = 0;
|
||||
const CARD_WEAPON_ITEM = 1;
|
||||
const CARD_WEAPON_SPELL = 2;
|
||||
const CARD_PREPARED = 3;
|
||||
const CARD_BACKPACK_0 = 4;
|
||||
const CARD_BACKPACK_2 = 5;
|
||||
const CARD_INITIATE = 6;
|
||||
|
||||
public $size = 30;
|
||||
public $weapons_items = 0;
|
||||
public $weapons_spells = 0;
|
||||
public $card_prepared_to_worst = 0;
|
||||
public $card_backpack_0 = 0;
|
||||
public $card_backpack_2 = 0;
|
||||
public $card_initiate = 0;
|
||||
|
||||
/**
|
||||
* @return array the validation rules.
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['size', 'weapons_items', 'weapons_spells', 'card_prepared_to_worst', 'card_backpack_0', 'card_backpack_2', 'card_initiate'], 'required'],
|
||||
[['size', 'weapons_items', 'weapons_spells', 'card_prepared_to_worst', 'card_backpack_0', 'card_backpack_2', 'card_initiate'], 'integer'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array customized attribute labels
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'size' => 'Размер колоды',
|
||||
'weapons_items' => 'Оружие (вещь)',
|
||||
'weapons_spells' => 'Оружие (заклинание)',
|
||||
'card_prepared_to_worst' => 'Готовность к худшему',
|
||||
'card_backpack_0' => 'Рюкзак (0)',
|
||||
'card_backpack_2' => 'Рюкзак (2)',
|
||||
'card_initiate' => 'Посвящённая',
|
||||
];
|
||||
}
|
||||
|
||||
private $result;
|
||||
|
||||
public function compute() : ComputationResult
|
||||
{
|
||||
$this->result = new ComputationResult();
|
||||
$this->result->probabilities = [];
|
||||
for ($i = 0; $i < self::COMPUTE_ROUNDS; $i++) $this->result->probabilities[] = 0;
|
||||
for ($i = 0; $i < self::COMPUTE_TRIES; $i++)
|
||||
{
|
||||
$this->generateTry();
|
||||
}
|
||||
for ($i = 0; $i < self::COMPUTE_ROUNDS; $i++) $this->result->probabilities[$i] /= (self::COMPUTE_TRIES + 0.0);
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
private $deck;
|
||||
private $hand;
|
||||
|
||||
private function fillDeck()
|
||||
{
|
||||
$this->deck = [];
|
||||
for ($i = 0; $i < $this->size; $i++) $this->deck[] = self::CARD_ANY;
|
||||
$pos = 0;
|
||||
for ($i = 0; $i < $this->weapons_items && $pos < count($this->deck); $i++)
|
||||
{
|
||||
$this->deck[$pos++] = self::CARD_WEAPON_ITEM;
|
||||
}
|
||||
for ($i = 0; $i < $this->weapons_spells && $pos < count($this->deck); $i++)
|
||||
{
|
||||
$this->deck[$pos++] = self::CARD_WEAPON_SPELL;
|
||||
}
|
||||
for ($i = 0; $i < $this->card_backpack_0 && $pos < count($this->deck); $i++)
|
||||
{
|
||||
$this->deck[$pos++] = self::CARD_BACKPACK_0;
|
||||
}
|
||||
for ($i = 0; $i < $this->card_backpack_2 && $pos < count($this->deck); $i++)
|
||||
{
|
||||
$this->deck[$pos++] = self::CARD_BACKPACK_2;
|
||||
}
|
||||
for ($i = 0; $i < $this->card_prepared_to_worst && $pos < count($this->deck); $i++)
|
||||
{
|
||||
$this->deck[$pos++] = self::CARD_PREPARED;
|
||||
}
|
||||
for ($i = 0; $i < $this->card_initiate && $pos < count($this->deck); $i++)
|
||||
{
|
||||
$this->deck[$pos++] = self::CARD_INITIATE;
|
||||
}
|
||||
}
|
||||
|
||||
private function shuffleDeck()
|
||||
{
|
||||
for ($i = 0; $i < count($this->deck); $i++)
|
||||
{
|
||||
$j = rand(0, $i);
|
||||
$t = $this->deck[$j];
|
||||
$this->deck[$j] = $this->deck[$i];
|
||||
$this->deck[$i] = $t;
|
||||
}
|
||||
}
|
||||
|
||||
private function addProb($round)
|
||||
{
|
||||
for ($i = $round; $i < self::COMPUTE_ROUNDS; $i++) $this->result->probabilities[$i]++;
|
||||
}
|
||||
|
||||
private function haveWeapon()
|
||||
{
|
||||
foreach ($this->hand as $card)
|
||||
{
|
||||
if ($card == self::CARD_WEAPON_ITEM) return true;
|
||||
if ($card == self::CARD_WEAPON_SPELL) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function generateTry()
|
||||
{
|
||||
$this->fillDeck();
|
||||
$this->shuffleDeck();
|
||||
// mulligan
|
||||
$this->hand = [];
|
||||
$replace = [];
|
||||
for ($i = 0; $i < 5; $i++)
|
||||
{
|
||||
$current = array_pop($this->deck);
|
||||
if ($current != self::CARD_ANY) $this->hand[] = $current;
|
||||
else $replace[] = $current;
|
||||
}
|
||||
while (count($this->hand) < 5) $this->hand[] = array_pop($this->deck);
|
||||
foreach ($replace as $r) $this->deck[] = $r;
|
||||
$this->shuffleDeck();
|
||||
for ($round = 0; $round < self::COMPUTE_ROUNDS; $round++)
|
||||
{
|
||||
if ($this->haveWeapon())
|
||||
{
|
||||
$this->addProb($round);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user