@ -450,7 +450,6 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
break ;
}
case TRIT_COND_TRAIN_STATUS : {
bool has_status = false ;
switch ( static_cast < TraceRestrictTrainStatusValueField > ( GetTraceRestrictValue ( item ) ) ) {
@ -956,11 +955,21 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
TraceRestrictItem item = items [ i ] ;
TraceRestrictItemType type = GetTraceRestrictType ( item ) ;
auto validation_error = [ i ] ( StringID str ) - > CommandCost {
CommandCost result ( str ) ;
result . SetResultData ( ( 1 < < 31 ) | ( uint ) i ) ;
return result ;
} ;
auto unknown_instruction = [ & ] ( ) {
return validation_error ( STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION ) ;
} ;
// check multi-word instructions
if ( IsTraceRestrictDoubleItem ( item ) ) {
i + + ;
if ( i > = size ) {
return_cmd_error ( STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE ) ; // instruction ran off end
return validation _error( STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE ) ; // instruction ran off end
}
}
@ -969,12 +978,12 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
if ( type = = TRIT_COND_ENDIF ) {
if ( condstack . empty ( ) ) {
return_cmd _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_NO_IF ) ; // else/endif with no starting if
return validation _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_NO_IF ) ; // else/endif with no starting if
}
if ( condflags & TRCF_ELSE ) {
// else
if ( condstack . back ( ) & TRCSF_SEEN_ELSE ) {
return_cmd _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE ) ; // Two else clauses
return validation _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE ) ; // Two else clauses
}
HandleCondition ( condstack , condflags , true ) ;
condstack . back ( ) | = TRCSF_SEEN_ELSE ;
@ -985,15 +994,221 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
} else {
if ( condflags & ( TRCF_OR | TRCF_ELSE ) ) { // elif/orif
if ( condstack . empty ( ) ) {
return_cmd _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_ELIF_NO_IF ) ; // Pre-empt assertions in HandleCondition
return validation _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_ELIF_NO_IF ) ; // Pre-empt assertions in HandleCondition
}
if ( condstack . back ( ) & TRCSF_SEEN_ELSE ) {
return_cmd _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE ) ; // else clause followed by elif/orif
return validation _error( STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE ) ; // else clause followed by elif/orif
}
}
HandleCondition ( condstack , condflags , true ) ;
}
const TraceRestrictCondOp condop = GetTraceRestrictCondOp ( item ) ;
auto invalid_condition = [ & ] ( ) - > bool {
switch ( condop ) {
case TRCO_IS :
case TRCO_ISNOT :
case TRCO_LT :
case TRCO_LTE :
case TRCO_GT :
case TRCO_GTE :
return false ;
default :
return true ;
}
} ;
auto invalid_binary_condition = [ & ] ( ) - > bool {
switch ( condop ) {
case TRCO_IS :
case TRCO_ISNOT :
return false ;
default :
return true ;
}
} ;
auto invalid_order_condition = [ & ] ( ) - > bool {
if ( invalid_binary_condition ( ) ) return true ;
switch ( static_cast < TraceRestrictOrderCondAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TROCAF_STATION :
case TROCAF_WAYPOINT :
case TROCAF_DEPOT :
return false ;
default :
return true ;
}
} ;
/* Validation action instruction */
switch ( GetTraceRestrictType ( item ) ) {
case TRIT_COND_ENDIF :
case TRIT_COND_UNDEFINED :
break ;
case TRIT_COND_TRAIN_LENGTH :
case TRIT_COND_MAX_SPEED :
case TRIT_COND_LOAD_PERCENT :
case TRIT_COND_COUNTER_VALUE :
case TRIT_COND_RESERVED_TILES :
if ( invalid_condition ( ) ) return unknown_instruction ( ) ;
break ;
case TRIT_COND_CARGO :
case TRIT_COND_TRAIN_GROUP :
case TRIT_COND_TRAIN_IN_SLOT :
case TRIT_COND_TRAIN_OWNER :
case TRIT_COND_RESERVATION_THROUGH :
if ( invalid_binary_condition ( ) ) return unknown_instruction ( ) ;
break ;
case TRIT_COND_CURRENT_ORDER :
case TRIT_COND_NEXT_ORDER :
case TRIT_COND_LAST_STATION :
if ( invalid_order_condition ( ) ) return unknown_instruction ( ) ;
break ;
case TRIT_COND_ENTRY_DIRECTION :
if ( invalid_binary_condition ( ) ) return unknown_instruction ( ) ;
switch ( GetTraceRestrictValue ( item ) ) {
case TRNTSV_NE :
case TRNTSV_SE :
case TRNTSV_SW :
case TRNTSV_NW :
case TRDTSV_FRONT :
case TRDTSV_BACK :
case TRDTSV_TUNBRIDGE_ENTER :
case TRDTSV_TUNBRIDGE_EXIT :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_PBS_ENTRY_SIGNAL :
if ( invalid_binary_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictPBSEntrySignalAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRPESAF_VEH_POS :
case TRPESAF_RES_END :
case TRPESAF_RES_END_TILE :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_PHYS_PROP :
if ( invalid_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictPhysPropCondAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRPPCAF_WEIGHT :
case TRPPCAF_POWER :
case TRPPCAF_MAX_TE :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_PHYS_RATIO :
if ( invalid_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictPhysPropRatioCondAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRPPRCAF_POWER_WEIGHT :
case TRPPRCAF_MAX_TE_WEIGHT :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_TIME_DATE_VALUE :
if ( invalid_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictTimeDateValueField > ( GetTraceRestrictValue ( item ) ) ) {
case TRTDVF_MINUTE :
case TRTDVF_HOUR :
case TRTDVF_HOUR_MINUTE :
case TRTDVF_DAY :
case TRTDVF_MONTH :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_CATEGORY :
if ( invalid_binary_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictCatgeoryCondAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRCCAF_ENGINE_CLASS :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_TARGET_DIRECTION :
if ( invalid_binary_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictTargetDirectionCondAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRTDCAF_CURRENT_ORDER :
case TRTDCAF_NEXT_ORDER :
break ;
default :
return unknown_instruction ( ) ;
}
switch ( GetTraceRestrictValue ( item ) ) {
case DIAGDIR_NE :
case DIAGDIR_SE :
case DIAGDIR_SW :
case DIAGDIR_NW :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_TRAIN_STATUS :
if ( invalid_binary_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictTrainStatusValueField > ( GetTraceRestrictValue ( item ) ) ) {
case TRTSVF_EMPTY :
case TRTSVF_FULL :
case TRTSVF_BROKEN_DOWN :
case TRTSVF_NEEDS_REPAIR :
case TRTSVF_REVERSING :
case TRTSVF_HEADING_TO_STATION_WAYPOINT :
case TRTSVF_HEADING_TO_DEPOT :
case TRTSVF_LOADING :
case TRTSVF_WAITING :
case TRTSVF_LOST :
case TRTSVF_REQUIRES_SERVICE :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COND_SLOT_OCCUPANCY :
if ( invalid_condition ( ) ) return unknown_instruction ( ) ;
switch ( static_cast < TraceRestrictSlotOccupancyCondAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRSOCAF_OCCUPANTS :
case TRSOCAF_REMAINING :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
default :
return unknown_instruction ( ) ;
}
/* Determine actions_used_flags */
switch ( GetTraceRestrictType ( item ) ) {
case TRIT_COND_ENDIF :
case TRIT_COND_UNDEFINED :
@ -1043,13 +1258,29 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
break ;
default :
return_cmd_error ( STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION ) ;
/* Validation has already been done, above */
NOT_REACHED ( ) ;
}
} else {
switch ( GetTraceRestrictType ( item ) ) {
case TRIT_PF_DENY :
actions_used_flags | = TRPAUF_PF ;
break ;
case TRIT_PF_PENALTY :
actions_used_flags | = TRPAUF_PF ;
switch ( static_cast < TraceRestrictPathfinderPenaltyAuxField > ( GetTraceRestrictAuxField ( item ) ) ) {
case TRPPAF_VALUE :
break ;
case TRPPAF_PRESET :
if ( GetTraceRestrictValue ( item ) > = TRPPPI_END ) return unknown_instruction ( ) ;
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_RESERVE_THROUGH :
@ -1078,8 +1309,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
break ;
default :
NOT_REACHED ( ) ;
break ;
return unknown_instruction ( ) ;
}
break ;
@ -1123,8 +1353,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
break ;
default :
NOT_REACHED ( ) ;
break ;
return unknown_instruction ( ) ;
}
break ;
@ -1139,8 +1368,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
break ;
default :
NOT_REACHED ( ) ;
break ;
return unknown_instruction ( ) ;
}
break ;
@ -1150,26 +1378,72 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
case TRIT_NEWS_CONTROL :
actions_used_flags | = TRPAUF_TRAIN_NOT_STUCK ;
switch ( static_cast < TraceRestrictNewsControlField > ( GetTraceRestrictValue ( item ) ) ) {
case TRNCF_TRAIN_NOT_STUCK :
case TRNCF_CANCEL_TRAIN_NOT_STUCK :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_COUNTER :
actions_used_flags | = TRPAUF_CHANGE_COUNTER ;
switch ( static_cast < TraceRestrictCounterCondOpField > ( GetTraceRestrictCondOp ( item ) ) ) {
case TRCCOF_INCREASE :
case TRCCOF_DECREASE :
case TRCCOF_SET :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_PF_PENALTY_CONTROL :
actions_used_flags | = TRPAUF_NO_PBS_BACK_PENALTY ;
switch ( static_cast < TraceRestrictPfPenaltyControlField > ( GetTraceRestrictValue ( item ) ) ) {
case TRPPCF_NO_PBS_BACK_PENALTY :
case TRPPCF_CANCEL_NO_PBS_BACK_PENALTY :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_SPEED_ADAPTATION_CONTROL :
actions_used_flags | = TRPAUF_SPEED_ADAPTATION ;
switch ( static_cast < TraceRestrictSpeedAdaptationControlField > ( GetTraceRestrictValue ( item ) ) ) {
case TRSACF_SPEED_ADAPT_EXEMPT :
case TRSACF_REMOVE_SPEED_ADAPT_EXEMPT :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
case TRIT_SIGNAL_MODE_CONTROL :
actions_used_flags | = TRPAUF_CMB_SIGNAL_MODE_CTRL ;
switch ( static_cast < TraceRestrictSignalModeControlField > ( GetTraceRestrictValue ( item ) ) ) {
case TRSMCF_NORMAL_ASPECT :
case TRSMCF_SHUNT_ASPECT :
break ;
default :
return unknown_instruction ( ) ;
}
break ;
default :
return_cmd_error ( STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION ) ;
return unknown_instruction ( ) ;
}
}
}