Permalink
Browse files

jacksonmj: EMP lag is hereby banished. eeef50c

EMP destruction loop now happens once per frame instead of once per EMP
particle.
  • Loading branch information...
jacob1 committed Dec 19, 2015
1 parent 74b8ba8 commit bb9b35f01d3b9d5341cc31baa323a9440af38343
@@ -0,0 +1,55 @@
#include <numeric>
#include <cstdlib>
#include "Probability.h"
namespace Probability
{
float binomial_gte1(int n, float p)
{
return 1.0f - std::pow(1.0f-p, n);
}
float randFloat()
{
return static_cast<float>(rand())/RAND_MAX;
}
SmallKBinomialGenerator::SmallKBinomialGenerator(unsigned int n, float p, unsigned int maxK_)
{
maxK = maxK_;
cdf = new float[maxK];
float *pdf = new float[maxK];
// initial values, k=0:
float pTerm = std::pow(1.0f-p, n); // the p^k * (1-p)^(n-k) term
unsigned int coeffN = 1, coeffD = 1; // (N / D) evaluates to the same result as the n!/(k!(n-k)!) term
for (unsigned int k=0; k<maxK; k++)
{
pdf[k] = pTerm * (float(coeffN) / coeffD);
pTerm *= p/(1.0f-p);
coeffN *= n-k; // Part of the n! will no longer cancelled out by (n-k)!
coeffD *= k+1; // k! (k+1 because this is for next k)
}
std::partial_sum(pdf, pdf+maxK, cdf);
delete[] pdf;
}
SmallKBinomialGenerator::~SmallKBinomialGenerator()
{
delete[] cdf;
}
unsigned int SmallKBinomialGenerator::calc(float randFloat)
{
for (unsigned int k=0; k<maxK; k++)
{
if (randFloat<cdf[k])
return k;
}
return maxK;
}
}
@@ -0,0 +1,45 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef tptmath_h
#define tptmath_h
// This file is used for EMP, to simulate many EMP going off at once at the end of the frame
#include <cmath>
namespace Probability
{
// X ~ binomial(n,p), returns P(X>=1)
// e.g. If a reaction has n chances of occurring, each time with probability p, this returns the probability that it occurs at least once.
float binomial_gte1(int n, float p);
float randFloat();
class SmallKBinomialGenerator
{
protected:
float *cdf;
unsigned int maxK;
public:
// Class to generate numbers from a binomial distribution, up to a maximum value (maxK).
// Results which would have been above maxK return maxK.
// Note: maxK must be small, otherwise the method used in this class is inefficient. (n and p can be any valid value)
SmallKBinomialGenerator(unsigned int n, float p, unsigned int maxK_);
~SmallKBinomialGenerator();
unsigned int calc(float randFloat);
};
}
#endif
@@ -879,9 +879,12 @@ void GameController::Update()
gameView->SetSample(gameModel->GetSimulation()->GetSample(pos.X, pos.Y));
Simulation * sim = gameModel->GetSimulation();
sim->UpdateSim();
sim->BeforeSim();
if (!sim->sys_pause || sim->framerender)
{
sim->UpdateParticles(0, NPART);
sim->AfterSim();
}
//if either STKM or STK2 isn't out, reset it's selected element. Defaults to PT_DUST unless right selected is something else
//This won't run if the stickmen dies in a frame, since it respawns instantly
@@ -1459,8 +1462,9 @@ void GameController::ParticleDebug(int mode, int x, int y)
sim->debug_currentParticle = i+1;
else
{
sim->Aftersim();
sim->framerender = 1;
sim->UpdateSim();
sim->BeforeSim();
sim->framerender = 0;
sim->debug_currentParticle = 0;
}
@@ -1912,6 +1912,7 @@ void Simulation::create_arc(int sx, int sy, int dx, int dy, int midpoints, int v
void Simulation::clear_sim(void)
{
emp_decor = 0;
emp_trigger_count = 0;
signs.clear();
memset(bmap, 0, sizeof(bmap));
memset(emap, 0, sizeof(emap));
@@ -4783,7 +4784,7 @@ void Simulation::CheckStacking()
}
//updates pmap, gol, and some other simulation stuff (but not particles)
void Simulation::UpdateSim()
void Simulation::BeforeSim()
{
int i, x, y, t;
int lastPartUsed = 0;
@@ -5056,6 +5057,15 @@ void Simulation::UpdateSim()
}
}
void Simulation::AfterSim()
{
if (emp_trigger_count)
{
Element_EMP::Trigger(this, emp_trigger_count);
emp_trigger_count = 0;
}
}
Simulation::~Simulation()
{
delete[] platent;
@@ -5072,6 +5082,7 @@ Simulation::Simulation():
ISWIRE(0),
force_stacking_check(0),
emp_decor(0),
emp_trigger_count(0),
lightningRecreate(0),
gravWallChanged(false),
CGOL(0),
@@ -62,6 +62,7 @@ class Simulation
int ISWIRE;
int force_stacking_check;
int emp_decor;
int emp_trigger_count;
int lightningRecreate;
//Stickman
playerst player;
@@ -159,7 +160,8 @@ class Simulation
void UpdateParticles(int start, int end);
void SimulateGoL();
void CheckStacking();
void UpdateSim();
void BeforeSim();
void AfterSim();
void rotate_area(int area_x, int area_y, int area_w, int area_h, int invert);
void clear_area(int area_x, int area_y, int area_w, int area_h);
Oops, something went wrong.

0 comments on commit bb9b35f

Please sign in to comment.