/**
  * Generate a new galaxy.
  *
  * @return \Illuminate\Http\RedirectResponse
  */
 public function generate()
 {
     // Start with a clean slate.
     DB::table('stars')->delete();
     DB::table('star_links')->delete();
     // Create new stars.
     $starCount = 200;
     /**
      * @var Star[] $unvisitedStars
      * @var Star[] $visitedStars
      * @var Star[] $allStars
      */
     $unvisitedStars = [];
     $visitedStars = [];
     $allStars = [];
     for ($i = 0; $i < $starCount; $i++) {
         $star = new Star(['name' => $this->generateName()]);
         $star->save();
         $unvisitedStars[$star->getKey()] = true;
         $allStars[$star->getKey()] = $star;
     }
     // Create links between stars.
     $totalLinks = 0;
     $starId = array_rand($allStars);
     $visitedStars[$starId] = $allStars[$starId];
     unset($unvisitedStars[$starId]);
     // Random walk to generate a uniform spanning tree.
     while (!empty($unvisitedStars)) {
         $star = $visitedStars[$starId];
         $otherStarId = array_rand($allStars);
         $otherStar = $allStars[$otherStarId];
         if (!isset($visitedStars[$otherStarId])) {
             $star->exits()->attach($otherStar);
             $otherStar->exits()->attach($star);
             $visitedStars[$otherStarId] = $allStars[$otherStarId];
             unset($unvisitedStars[$otherStarId]);
             $totalLinks++;
         }
         $starId = $otherStarId;
     }
     // Add some extra links to create cycles.
     for ($i = 0; $i < $totalLinks / 10; $i++) {
         $star = $allStars[array_rand($allStars)];
         $otherStar = $allStars[array_rand($allStars)];
         if ($star != $otherStar) {
             $star->exits()->attach($otherStar);
             $otherStar->exits()->attach($star);
             $totalLinks++;
         }
     }
     return redirect()->back()->with('status', 'Generated ' . $starCount . ' stars and ' . $totalLinks . ' star links.');
 }
 /**
  * Generate the starting ship for all players.
  *
  * @param User $player
  *
  * @return Ship
  */
 public static function getStartingShip(User $player)
 {
     $ship = new Ship(['name' => self::randomShipName()]);
     // Start with an 'Explorer' class hip.
     $shipType = ShipType::whereName('Explorer')->first();
     $ship->type()->associate($shipType);
     // Place it at a random star.
     $star = Star::findStartLocation();
     $ship->location()->associate($star);
     // Give it to the player.
     $ship->owner()->associate($player);
     $ship->save();
     // Add a jumpstore and a cargo item.
     $item = JumpStore::whereValue(1)->get()->random();
     $ship->items()->attach($item, ['amount' => 1]);
     switch (mt_rand(0, 2)) {
         case 0:
             $item = BiologyCargo::whereValue(1)->get()->random();
             break;
         case 1:
             $item = TechnologyCargo::whereValue(1)->get()->random();
             break;
         case 2:
             $item = LuxuryCargo::whereValue(1)->get()->random();
             break;
     }
     $ship->items()->attach($item, ['amount' => 1]);
     // Start with a bit of money and full energy.
     $ship->credits = 1000;
     $ship->energy = $ship->energy_capacity;
     $ship->structure = $shipType->structure;
     $ship->save();
     return $ship;
 }