Skip to content

Commit

Permalink
jacksonmj: Reduce ETRD lag e7c4b98
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jacob1 committed Dec 19, 2015
1 parent af48997 commit 5ba3402
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 27 deletions.
38 changes: 15 additions & 23 deletions src/simulation/Simulation.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]--;
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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++;

Expand Down Expand Up @@ -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),
Expand Down
3 changes: 2 additions & 1 deletion src/simulation/Simulation.h
Expand Up @@ -63,6 +63,8 @@ class Simulation
int force_stacking_check;
int emp_decor;
int emp_trigger_count;
bool etrd_count_valid;
int etrd_life0_count;
int lightningRecreate;
//Stickman
playerst player;
Expand Down Expand Up @@ -156,7 +158,6 @@ class Simulation
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();
Expand Down
125 changes: 125 additions & 0 deletions src/simulation/elements/ETRD.cpp
@@ -1,4 +1,6 @@
#include <algorithm>
#include "simulation/Elements.h"

//#TPT-Directive ElementClass Element_ETRD PT_ETRD 50
Element_ETRD::Element_ETRD()
{
Expand Down Expand Up @@ -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() {}
6 changes: 3 additions & 3 deletions src/simulation/elements/SPRK.cpp
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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;
Expand Down

0 comments on commit 5ba3402

Please sign in to comment.