jacksonmj: Reduce ETRD lag e7c4b989654e

Improvement isn't as good as the EMP one in normal cases, but for intentional lag bomb saves it is much better. Tested it and confirmed it worked just like before this commit. etrd_life0_count is hopefully valid, the accuracy may not be as good as in jacksonmj's fork
This commit is contained in:
jacob1 2015-12-19 01:39:03 -05:00
parent af48997228
commit 5ba34021bc
4 changed files with 145 additions and 27 deletions

View File

@ -1851,29 +1851,6 @@ int Simulation::parts_avg(int ci, int ni,int t)
}
int Simulation::nearest_part(int ci, int t, int max_d)
{
int distance = (max_d!=-1)?max_d:MAX_DISTANCE;
int ndistance = 0;
int id = -1;
int i = 0;
int cx = (int)parts[ci].x;
int cy = (int)parts[ci].y;
for (i=0; i<=parts_lastActiveIndex; i++)
{
if ((parts[i].type==t||(t==-1&&parts[i].type))&&!parts[i].life&&i!=ci)
{
ndistance = abs(cx-parts[i].x)+abs(cy-parts[i].y);// Faster but less accurate Older: sqrt(pow(cx-parts[i].x, 2)+pow(cy-parts[i].y, 2));
if (ndistance<distance)
{
distance = ndistance;
id = i;
}
}
}
return id;
}
// unused function
void Simulation::create_arc(int sx, int sy, int dx, int dy, int midpoints, int variance, int type, int flags)
{
@ -2686,6 +2663,8 @@ void Simulation::kill_part(int i)//kills particle number i
{
Element_SOAP::detach(this, i);
}
else if (parts[i].type == PT_ETRD && parts[i].life == 0)
etrd_life0_count--;
parts[i].type = PT_NONE;
parts[i].life = pfree;
@ -2735,6 +2714,8 @@ void Simulation::part_change_type(int i, int x, int y, int t)//changes the type
}
else if (parts[i].type == PT_SOAP)
Element_SOAP::detach(this, i);
else if (parts[i].type == PT_ETRD && parts[i].life == 0)
etrd_life0_count--;
if (parts[i].type > 0 && parts[i].type < PT_NUM && elementCount[parts[i].type])
elementCount[parts[i].type]--;
@ -2753,6 +2734,8 @@ void Simulation::part_change_type(int i, int x, int y, int t)//changes the type
if (parts[i].tmp >= 0 && parts[i].tmp < MAX_FIGHTERS)
Element_STKM::STKM_init_legs(this, &fighters[parts[i].tmp], i);
}
else if (t == PT_ETRD && parts[i].life == 0)
etrd_life0_count++;
parts[i].type = t;
if (elements[t].Properties & TYPE_ENERGY)
@ -2934,6 +2917,8 @@ int Simulation::create_part(int p, int x, int y, int tv)
{
Element_SOAP::detach(this, p);
}
else if (parts[p].type == PT_ETRD && parts[p].life == 0)
etrd_life0_count--;
i = p;
}
@ -3083,6 +3068,9 @@ int Simulation::create_part(int p, int x, int y, int tv)
case PT_CRMC:
parts[i].tmp2 = (rand() % 5);
break;
case PT_ETRD:
etrd_life0_count++;
break;
case PT_STKM:
{
if (player.spwn == 0)
@ -4820,6 +4808,8 @@ void Simulation::BeforeSim()
emp_decor -= emp_decor/25+2;
if(emp_decor < 0)
emp_decor = 0;
etrd_count_valid = false;
etrd_life0_count = 0;
currentTick++;
@ -5083,6 +5073,8 @@ Simulation::Simulation():
force_stacking_check(0),
emp_decor(0),
emp_trigger_count(0),
etrd_count_valid(false),
etrd_life0_count(0),
lightningRecreate(0),
gravWallChanged(false),
CGOL(0),

View File

@ -63,6 +63,8 @@ public:
int force_stacking_check;
int emp_decor;
int emp_trigger_count;
bool etrd_count_valid;
int etrd_life0_count;
int lightningRecreate;
//Stickman
playerst player;
@ -156,7 +158,6 @@ public:
void set_emap(int x, int y);
int parts_avg(int ci, int ni, int t);
void create_arc(int sx, int sy, int dx, int dy, int midpoints, int variance, int type, int flags);
int nearest_part(int ci, int t, int max_d);
void UpdateParticles(int start, int end);
void SimulateGoL();
void CheckStacking();

View File

@ -1,4 +1,6 @@
#include <algorithm>
#include "simulation/Elements.h"
//#TPT-Directive ElementClass Element_ETRD PT_ETRD 50
Element_ETRD::Element_ETRD()
{
@ -42,6 +44,129 @@ Element_ETRD::Element_ETRD()
HighTemperatureTransition = NT;
Update = NULL;
Element_ETRD::initDeltaPos();
}
class ETRD_deltaWithLength
{
public:
ETRD_deltaWithLength(ui::Point a, int b):
d(a),
length(b)
{
}
ui::Point d;
int length;
};
const int maxLength = 12;
std::vector<ETRD_deltaWithLength> deltaPos;
bool compareFunc(const ETRD_deltaWithLength &a, const ETRD_deltaWithLength &b)
{
return a.length < b.length;
}
//#TPT-Directive ElementHeader Element_ETRD static void initDeltaPos()
void Element_ETRD::initDeltaPos()
{
deltaPos.clear();
for (int ry = -maxLength; ry <= maxLength; ry++)
for (int rx = -maxLength; rx <= maxLength; rx++)
{
ui::Point d(rx, ry);
if (std::abs(d.X) + std::abs(d.Y) <= maxLength)
deltaPos.push_back(ETRD_deltaWithLength(d, std::abs(d.X) + std::abs(d.Y)));
}
std::stable_sort(deltaPos.begin(), deltaPos.end(), compareFunc);
}
//#TPT-Directive ElementHeader Element_ETRD static int nearestSparkablePart(Simulation *sim, int targetId)
int Element_ETRD::nearestSparkablePart(Simulation *sim, int targetId)
{
if (!sim->elementCount[PT_ETRD])
return -1;
if (sim->etrd_count_valid && sim->etrd_life0_count <= 0)
return -1;
Particle *parts = sim->parts;
int foundDistance = XRES + YRES;
int foundI = -1;
ui::Point targetPos = ui::Point(parts[targetId].x, parts[targetId].y);
if (sim->etrd_count_valid)
{
// countLife0 doesn't need recalculating, so just focus on finding the nearest particle
// If the simulation contains lots of particles, check near the target position first since going through all particles will be slow.
// Threshold = number of positions checked, *2 because it's likely to access memory all over the place (less cache friendly) and there's extra logic needed
// TODO: probably not optimal if excessive stacking is used
if (sim->parts_lastActiveIndex > (int)deltaPos.size()*2)
{
for (std::vector<ETRD_deltaWithLength>::iterator iter = deltaPos.begin(), end = deltaPos.end(); iter != end; ++iter)
{
ETRD_deltaWithLength delta = (*iter);
ui::Point checkPos = targetPos + delta.d;
int checkDistance = delta.length;
if (foundDistance < checkDistance)
{
// deltaPos is sorted in order of ascending length, so foundDistance < checkDistance means all later items are further away.
break;
}
if (sim->InBounds(checkPos.X, checkPos.Y) && checkDistance <= foundDistance)
{
int r = sim->pmap[checkPos.Y][checkPos.X];
if (r && (r&0xFF) == PT_ETRD && !parts[r>>8].life && r>>8 != targetId && checkDistance < foundDistance)
{
foundDistance = checkDistance;
foundI = r>>8;
}
}
}
}
// If neighbor search didn't find a suitable particle, search all particles
if (foundI < 0)
{
for (int i = 0; i <= sim->parts_lastActiveIndex; i++)
{
if (parts[i].type == PT_ETRD && !parts[i].life)
{
ui::Point checkPos = ui::Point(parts[i].x-targetPos.X, parts[i].y-targetPos.Y);
int checkDistance = std::abs(checkPos.X) + std::abs(checkPos.Y);
if (checkDistance < foundDistance && i != targetId)
{
foundDistance = checkDistance;
foundI = i;
}
}
}
}
}
else
{
// Recalculate countLife0, and search for the closest suitable particle
int countLife0 = 0;
for (int i = 0; i <= sim->parts_lastActiveIndex; i++)
{
if (parts[i].type == PT_ETRD && !parts[i].life)
{
countLife0++;
ui::Point checkPos = ui::Point(parts[i].x-targetPos.X, parts[i].y-targetPos.Y);
int checkDistance = std::abs(checkPos.X) + std::abs(checkPos.Y);
if (checkDistance < foundDistance && i != targetId)
{
foundDistance = checkDistance;
foundI = i;
}
}
}
sim->etrd_life0_count = countLife0;
sim->etrd_count_valid = true;
}
return foundI;
}
Element_ETRD::~Element_ETRD() {}

View File

@ -57,7 +57,6 @@ int Element_SPRK::update(UPDATE_FUNC_ARGS)
parts[i].temp = R_TEMP + 273.15f;
if (ct<=0 || ct>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
ct = PT_METL;
sim->part_change_type(i,x,y,ct);
parts[i].ctype = PT_NONE;
parts[i].life = 4;
if (ct == PT_WATR)
@ -66,6 +65,7 @@ int Element_SPRK::update(UPDATE_FUNC_ARGS)
parts[i].life = 54;
else if (ct == PT_SWCH)
parts[i].life = 14;
sim->part_change_type(i,x,y,ct);
return 0;
}
//Some functions of SPRK based on ctype (what it is on)
@ -81,13 +81,13 @@ int Element_SPRK::update(UPDATE_FUNC_ARGS)
case PT_ETRD:
if (parts[i].life==1)
{
nearp = sim->nearest_part(i, PT_ETRD, -1);
nearp = Element_ETRD::nearestSparkablePart(sim, i);
if (nearp!=-1 && sim->parts_avg(i, nearp, PT_INSL)!=PT_INSL)
{
sim->CreateLine(x, y, (int)(parts[nearp].x+0.5f), (int)(parts[nearp].y+0.5f), PT_PLSM);
parts[i].life = 20;
sim->part_change_type(i,x,y,ct);
ct = parts[i].ctype = PT_NONE;
parts[i].life = 20;
sim->part_change_type(nearp,(int)(parts[nearp].x+0.5f),(int)(parts[nearp].y+0.5f),PT_SPRK);
parts[nearp].life = 9;
parts[nearp].ctype = PT_ETRD;