This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/simulation/Simulation.h
2023-09-20 07:16:28 +02:00

251 lines
8.0 KiB
C++

#pragma once
#include "Particle.h"
#include "Stickman.h"
#include "WallType.h"
#include "Sign.h"
#include "ElementDefs.h"
#include "BuiltinGOL.h"
#include "MenuSection.h"
#include "CoordStack.h"
#include "gravity/GravityPtr.h"
#include "common/tpt-rand.h"
#include "Element.h"
#include "SimulationConfig.h"
#include <cstring>
#include <cstddef>
#include <vector>
#include <array>
#include <memory>
#include <optional>
constexpr int CHANNELS = int(MAX_TEMP - 73) / 100 + 2;
class Snapshot;
class SimTool;
class Brush;
class SimulationSample;
struct matrix2d;
struct vector2d;
class Simulation;
class Renderer;
class Gravity;
class Air;
class GameSave;
class Simulation
{
public:
GravityPtr grav;
Air * air;
RNG rng;
std::vector<sign> signs;
std::array<Element, PT_NUM> elements;
//Element * elements;
std::vector<SimTool> tools;
std::vector<unsigned int> platent;
std::vector<wall_type> wtypes;
std::vector<menu_section> msections;
int currentTick;
int replaceModeSelected;
int replaceModeFlags;
char can_move[PT_NUM][PT_NUM];
int debug_nextToUpdate;
int debug_mostRecentlyUpdated = -1; // -1 when between full update loops
int parts_lastActiveIndex;
int pfree;
int NUM_PARTS;
bool elementRecount;
int elementCount[PT_NUM];
int ISWIRE;
bool force_stacking_check;
int emp_decor;
int emp_trigger_count;
bool etrd_count_valid;
int etrd_life0_count;
int lightningRecreate;
//Stickman
playerst player;
playerst player2;
playerst fighters[MAX_FIGHTERS]; //Defined in Stickman.h
unsigned char fighcount; //Contains the number of fighters
bool gravWallChanged;
//Portals and Wifi
Particle portalp[CHANNELS][8][80];
int portal_rx[8];
int portal_ry[8];
int wireless[CHANNELS][2];
//Gol sim
int CGOL;
int GSPEED;
unsigned int gol[YRES][XRES][5];
//Air sim
float (*vx)[XCELLS];
float (*vy)[XCELLS];
float (*pv)[XCELLS];
float (*hv)[XCELLS];
//Gravity sim
float *gravx;//gravx[YCELLS * XCELLS];
float *gravy;//gravy[YCELLS * XCELLS];
float *gravp;//gravp[YCELLS * XCELLS];
float *gravmap;//gravmap[YCELLS * XCELLS];
//Walls
unsigned char bmap[YCELLS][XCELLS];
unsigned char emap[YCELLS][XCELLS];
float fvx[YCELLS][XCELLS];
float fvy[YCELLS][XCELLS];
//Particles
Particle parts[NPART];
int pmap[YRES][XRES];
int photons[YRES][XRES];
unsigned int pmap_count[YRES][XRES];
//Simulation Settings
int edgeMode;
int gravityMode;
float customGravityX;
float customGravityY;
int legacy_enable;
int aheat_enable;
int water_equal_test;
int sys_pause;
int framerender;
int pretty_powder;
int sandcolour;
int sandcolour_interface;
int sandcolour_frame;
int deco_space;
uint64_t frameCount;
bool ensureDeterminism;
void Load(const GameSave *save, bool includePressure, Vec2<int> blockP); // block coordinates
std::unique_ptr<GameSave> Save(bool includePressure, Rect<int> partR); // particle coordinates
void SaveSimOptions(GameSave &gameSave);
SimulationSample GetSample(int x, int y);
std::unique_ptr<Snapshot> CreateSnapshot();
void Restore(const Snapshot &snap);
int is_blocking(int t, int x, int y);
int is_boundary(int pt, int x, int y);
int find_next_boundary(int pt, int *x, int *y, int dm, int *em, bool reverse);
void photoelectric_effect(int nx, int ny);
int do_move(int i, int x, int y, float nxf, float nyf);
bool move(int i, int x, int y, float nxf, float nyf);
int try_move(int i, int x, int y, int nx, int ny);
int eval_move(int pt, int nx, int ny, unsigned *rr);
void init_can_move();
bool IsWallBlocking(int x, int y, int type);
bool IsElement(int type) const {
return (type > 0 && type < PT_NUM && elements[type].Enabled);
}
bool IsElementOrNone(int type) const {
return (type >= 0 && type < PT_NUM && elements[type].Enabled);
}
void create_cherenkov_photon(int pp);
void create_gain_photon(int pp);
void kill_part(int i);
bool FloodFillPmapCheck(int x, int y, int type);
int flood_prop(int x, int y, StructProperty prop, PropertyValue propvalue);
bool flood_water(int x, int y, int i);
int FloodINST(int x, int y);
void detach(int i);
bool part_change_type(int i, int x, int y, int t);
//int InCurrentBrush(int i, int j, int rx, int ry);
//int get_brush_flags();
int create_part(int p, int x, int y, int t, int v = -1);
void delete_part(int x, int y);
void get_sign_pos(int i, int *x0, int *y0, int *w, int *h);
int is_wire(int x, int y);
int is_wire_off(int x, int y);
void set_emap(int x, int y);
int parts_avg(int ci, int ni, int t);
void UpdateParticles(int start, int end); // Dispatches an update to the range [start, end).
void SimulateGoL();
void RecalcFreeParticles(bool do_life_dec);
void CheckStacking();
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);
void SetEdgeMode(int newEdgeMode);
void SetDecoSpace(int newDecoSpace);
//Drawing Deco
void ApplyDecoration(int x, int y, int colR, int colG, int colB, int colA, int mode);
void ApplyDecorationPoint(int x, int y, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush);
void ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush);
void ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode);
bool ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB);
void ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB);
//Drawing Tools like HEAT, AIR, and GRAV
int Tool(int x, int y, int tool, int brushX, int brushY, float strength = 1.0f);
int ToolBrush(int x, int y, int tool, Brush const &cBrush, float strength = 1.0f);
void ToolLine(int x1, int y1, int x2, int y2, int tool, Brush const &cBrush, float strength = 1.0f);
void ToolBox(int x1, int y1, int x2, int y2, int tool, float strength = 1.0f);
//Drawing Walls
int CreateWalls(int x, int y, int rx, int ry, int wall, Brush const *cBrush = nullptr);
void CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush const *cBrush = nullptr);
void CreateWallBox(int x1, int y1, int x2, int y2, int wall);
int FloodWalls(int x, int y, int wall, int bm);
//Drawing Particles
int CreateParts(int positionX, int positionY, int c, Brush const &cBrush, int flags = -1);
int CreateParts(int x, int y, int rx, int ry, int c, int flags = -1);
int CreatePartFlags(int x, int y, int c, int flags);
void CreateLine(int x1, int y1, int x2, int y2, int c, Brush const &cBrush, int flags = -1);
void CreateLine(int x1, int y1, int x2, int y2, int c);
void CreateBox(int x1, int y1, int x2, int y2, int c, int flags = -1);
int FloodParts(int x, int y, int c, int cm, int flags = -1);
void GetGravityField(int x, int y, float particleGrav, float newtonGrav, float & pGravX, float & pGravY);
int GetParticleType(ByteString type);
void orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]);
void orbitalparts_set(int *block1, int *block2, int resblock1[], int resblock2[]);
int get_wavelength_bin(int *wm);
int get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny);
int get_normal_interp(int pt, float x0, float y0, float dx, float dy, float *nx, float *ny);
void clear_sim();
Simulation();
~Simulation();
// These don't really belong anywhere at the moment, so go here for loop edge mode
static int remainder_p(int x, int y);
static float remainder_p(float x, float y);
String ElementResolve(int type, int ctype) const;
String BasicParticleInfo(Particle const &sample_part) const;
struct CustomGOLData
{
int rule, colour1, colour2;
String nameString, ruleString;
inline bool operator <(const CustomGOLData &other) const
{
return rule < other.rule;
}
};
private:
std::vector<CustomGOLData> customGol;
public:
const CustomGOLData *GetCustomGOLByRule(int rule) const;
const std::vector<CustomGOLData> GetCustomGol() { return customGol; }
void SetCustomGOL(std::vector<CustomGOLData> newCustomGol);
private:
CoordStack& getCoordStackSingleton();
};