00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef PROGRAMMABLE_SIGNALS_H
00013 #define PROGRAMMABLE_SIGNALS_H
00014 #include "rail_map.h"
00015 #include "core/smallvec_type.hpp"
00016 #include <map>
00017
00019
00020
00026 struct SignalVM;
00027
00028 class SignalInstruction;
00029 class SignalSpecial;
00030 typedef SmallVector<SignalInstruction*, 4> InstructionList;
00031
00033 struct SignalProgram {
00034 SignalProgram(TileIndex tile, Track track, bool raw = false);
00035 ~SignalProgram();
00036 void DebugPrintProgram();
00037
00038 TileIndex tile;
00039 Track track;
00040
00041 SignalSpecial *first_instruction;
00042 SignalSpecial *last_instruction;
00043 InstructionList instructions;
00044 };
00045
00053 enum SignalOpcode {
00054 PSO_FIRST = 0,
00055 PSO_LAST = 1,
00056 PSO_IF = 2,
00057 PSO_IF_ELSE = 3,
00058 PSO_IF_ENDIF = 4,
00059 PSO_SET_SIGNAL = 5,
00060
00061 PSO_END,
00062 PSO_INVALID = 0xFF
00063 };
00064 template <> struct EnumPropsT<SignalOpcode> : MakeEnumPropsT<SignalOpcode, byte, PSO_FIRST, PSO_END, PSO_INVALID, 8> {};
00065
00067 class SignalInstruction {
00068 public:
00069
00070 inline SignalOpcode Opcode() const { return this->opcode; }
00071
00072
00073
00074 inline SignalInstruction *Previous() const { return this->previous; }
00075
00076
00077 inline int Id() const
00078
00079 { return program->instructions.FindIndex(const_cast<SignalInstruction*>(this)); }
00080
00081
00082 virtual void Insert(SignalInstruction *before_insn);
00083
00084
00085 virtual void Evaluate(SignalVM &vm) = 0;
00086
00087
00088
00089
00090
00091
00092
00093 virtual void Remove() = 0;
00094
00095
00096
00097 inline SignalInstruction *&GetPrevHandle()
00098 { return previous; }
00099
00100
00101
00102 inline void SetPrevious(SignalInstruction *prev)
00103 { previous = prev; }
00104
00105
00106 virtual void SetNext(SignalInstruction *next_insn) = 0;
00107
00108 protected:
00109
00110
00111
00112 SignalInstruction(SignalProgram *prog, SignalOpcode op) ;
00113 ~SignalInstruction();
00114
00115 const SignalOpcode opcode;
00116 SignalInstruction *previous;
00117 SignalProgram *program;
00118 };
00119
00126 enum SignalConditionCode {
00127 PSC_ALWAYS = 0,
00128 PSC_NEVER = 1,
00129 PSC_NUM_GREEN = 2,
00130 PSC_NUM_RED = 3,
00131 PSC_SIGNAL_STATE = 4,
00132
00133 PSC_MAX = PSC_SIGNAL_STATE
00134 };
00135
00136 class SignalCondition {
00137 public:
00138
00139 inline SignalConditionCode ConditionCode() const { return this->cond_code; }
00140
00141
00142 virtual bool Evaluate(SignalVM& vm) = 0;
00143
00144
00145 virtual ~SignalCondition();
00146
00147 protected:
00148 SignalCondition(SignalConditionCode code) : cond_code(code) {}
00149
00150 const SignalConditionCode cond_code;
00151 };
00152
00153
00154
00155
00160 class SignalSimpleCondition: public SignalCondition {
00161 public:
00162 SignalSimpleCondition(SignalConditionCode code);
00163 virtual bool Evaluate(SignalVM& vm);
00164 };
00165
00167 enum SignalComparator {
00168 SGC_EQUALS = 0,
00169 SGC_NOT_EQUALS = 1,
00170 SGC_LESS_THAN = 2,
00171 SGC_LESS_THAN_EQUALS = 3,
00172 SGC_MORE_THAN = 4,
00173 SGC_MORE_THAN_EQUALS = 5,
00174 SGC_IS_TRUE = 6,
00175 SGC_IS_FALSE = 7,
00176
00177 SGC_LAST = SGC_IS_FALSE
00178 };
00179
00181 enum SignalConditionField {
00182 SCF_COMPARATOR = 0,
00183 SCF_VALUE = 1,
00184 };
00185
00193 class SignalVariableCondition: public SignalCondition {
00194 public:
00195
00196
00197 SignalVariableCondition(SignalConditionCode code);
00198
00199 SignalComparator comparator;
00200 uint32 value;
00201
00202
00203 virtual bool Evaluate(SignalVM &vm);
00204 };
00205
00207 class SignalStateCondition: public SignalCondition {
00208 public:
00209 SignalStateCondition(SignalReference this_sig, TileIndex sig_tile,
00210 Trackdir sig_track);
00211
00212 void SetSignal(TileIndex tile, Trackdir track);
00213 bool IsSignalValid();
00214 void Invalidate();
00215
00216 virtual bool Evaluate(SignalVM& vm);
00217 virtual ~SignalStateCondition();
00218
00219 SignalReference this_sig;
00220 TileIndex sig_tile;
00221 Trackdir sig_track;
00222 SignalState state;
00223 };
00224
00225
00226
00227
00241 class SignalSpecial: public SignalInstruction {
00242 public:
00250 SignalSpecial(SignalProgram *prog, SignalOpcode op);
00251
00257 virtual void Evaluate(SignalVM &vm);
00258
00263 static void link(SignalSpecial *first, SignalSpecial *last);
00264
00273 virtual void Remove();
00274
00279 SignalInstruction *next;
00280
00281 virtual void SetNext(SignalInstruction *next_insn);
00282 };
00283
00290 class SignalIf: public SignalInstruction {
00291 public:
00304 class PseudoInstruction: public SignalInstruction {
00305 public:
00310 PseudoInstruction(SignalProgram *prog, SignalIf *block, SignalOpcode op);
00311
00317 PseudoInstruction(SignalProgram *prog, SignalOpcode op);
00318
00323 virtual void Remove();
00324
00329 virtual void Evaluate(SignalVM &vm);
00330
00332 SignalIf *block;
00333 virtual void SetNext(SignalInstruction *next_insn);
00334 };
00335
00336 public:
00342 SignalIf(SignalProgram *prog, bool raw = false);
00343
00345 void SetCondition(SignalCondition *cond);
00346
00348 virtual void Evaluate(SignalVM &vm);
00349
00350 virtual void Insert(SignalInstruction *before_insn);
00351
00353 virtual void Remove();
00354
00355 SignalCondition *condition;
00356 SignalInstruction *if_true;
00357 SignalInstruction *if_false;
00358 SignalInstruction *after;
00359
00360 virtual void SetNext(SignalInstruction *next_insn);
00361 };
00362
00364 class SignalSet: public SignalInstruction {
00365 public:
00366
00367 SignalSet(SignalProgram *prog, SignalState = SIGNAL_STATE_RED);
00368
00369 virtual void Evaluate(SignalVM &vm);
00370 virtual void Remove();
00371
00372
00373 SignalState to_state;
00374
00375
00376 SignalInstruction *next;
00377
00378 virtual void SetNext(SignalInstruction *next_insn);
00379 };
00380
00381
00382 typedef std::map<SignalReference, SignalProgram*> ProgramList;
00383
00384
00385 extern ProgramList _signal_programs;
00386
00387
00388 typedef std::map<SignalReference, uint16> SpeedLimits;
00389
00390
00391 extern SpeedLimits _speedlimits;
00392
00393
00394 static inline bool HasProgrammableSignals(SignalReference ref)
00395 {
00396 return IsTileType(ref.tile, MP_RAILWAY) && GetRailTileType(ref.tile) == RAIL_TILE_SIGNALS
00397 && IsPresignalProgrammable(ref.tile, ref.track);
00398 }
00399
00400
00401 static inline bool HasSpeedSignals(SignalReference ref)
00402 {
00403 return GetRailTileType(ref.tile) == RAIL_TILE_SIGNALS
00404 && IsSpeedSignal(ref.tile, ref.track);
00405 }
00406
00407
00408
00409 void ShowSignalProgramWindow(SignalReference ref);
00410
00411
00412
00413 void ShowSpeedSignalWindow(SignalReference ref);
00414
00415
00416
00417 SignalProgram *GetSignalProgram(SignalReference ref);
00418
00419
00420 uint16 GetSignalSpeed(SignalReference ref);
00421
00422
00423 void FreeSignalProgram(SignalReference ref);
00424
00425
00426 void FreeSignalPrograms();
00427
00428
00429 void FreeSignalSpeed(SignalReference ref);
00430
00431
00432 void FreeSignalSpeeds();
00433
00434
00435 SignalState RunSignalProgram(SignalReference ref, uint num_exits, uint num_green);
00436
00437
00438 void RemoveProgramDependencies(SignalReference by, SignalReference on);
00440
00441 #endif