Initial minimal working tracerestrict implementation.

This is a port of the tracerestrict/routing restrictions feature
from TTDPatch.
At present this implements if tests (train length only),
and pathfinder deny and penalty actions.
This requires the use of YAPF. Note that restrictions are only evaluated
within the YAPF lookahead distance.
This commit is contained in:
Jonathan G Rennison
2015-07-22 00:28:53 +01:00
parent 13a726b18f
commit 5f1b148cf9
20 changed files with 1843 additions and 1 deletions

284
src/tracerestrict.h Normal file
View File

@@ -0,0 +1,284 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file tracerestrict.h Header file for Trace Restriction. */
#ifndef TRACERESTRICT_H
#define TRACERESTRICT_H
#include "stdafx.h"
#include "core/bitmath_func.hpp"
#include "core/enum_type.hpp"
#include "core/pool_type.hpp"
#include "command_func.h"
#include "rail_map.h"
#include "tile_type.h"
#include <map>
#include <vector>
struct Train;
/** Unique identifiers for a trace restrict nodes. */
typedef uint32 TraceRestrictProgramID;
struct TraceRestrictProgram;
typedef uint32 TraceRestrictRefId;
/** Type of the pool for trace restrict programs. */
typedef Pool<TraceRestrictProgram, TraceRestrictProgramID, 16, 256000> TraceRestrictProgramPool;
/** The actual pool for trace restrict nodes. */
extern TraceRestrictProgramPool _tracerestrictprogram_pool;
#define FOR_ALL_TRACE_RESTRICT_PROGRAMS_FROM(var, start) FOR_ALL_ITEMS_FROM(TraceRestrictProgram, tr_index, var, start)
#define FOR_ALL_TRACE_RESTRICT_PROGRAMS(var) FOR_ALL_TRACE_RESTRICT_PROGRAMS_FROM(var, 0)
struct TraceRestrictMappingItem {
TraceRestrictProgramID program_id;
TraceRestrictMappingItem() { }
TraceRestrictMappingItem(TraceRestrictProgramID program_id_)
: program_id(program_id_) { }
};
typedef std::map<TraceRestrictRefId, TraceRestrictMappingItem> TraceRestrictMapping;
extern TraceRestrictMapping _tracerestrictprogram_mapping;
void ClearTraceRestrictMapping();
/// Of the fields below, the type and cond flags seem the most likely
/// to need future expansion, hence the reserved bits are placed
/// immediately after them
enum TraceRestrictItemFlagAllocation {
TRIFA_TYPE_COUNT = 5,
TRIFA_TYPE_OFFSET = 0,
/* 3 bits reserved for future use */
TRIFA_COND_FLAGS_COUNT = 2,
TRIFA_COND_FLAGS_OFFSET = 8,
/* 3 bits reserved for future use */
TRIFA_COND_OP_COUNT = 3,
TRIFA_COND_OP_OFFSET = 13,
TRIFA_VALUE_COUNT = 16,
TRIFA_VALUE_OFFSET = 16,
};
enum TraceRestrictItemType {
TRIT_NULL = 0,
TRIT_PF_DENY = 1,
TRIT_PF_PENALTY = 2,
TRIT_COND_BEGIN = 8, ///< Start of conditional item types
TRIT_COND_ENDIF = 8, ///< This is an endif block or an else block
TRIT_COND_UNDEFINED = 9, ///< This condition has no type defined (evaluate as false)
TRIT_COND_TRAIN_LENGTH = 10, ///< Test train length
/* space up to 31 */
};
/* no flags set indicates end if for TRIT_COND_ENDIF, if otherwise */
enum TraceRestrictCondFlags {
TRCF_ELSE = 1 << 0,
TRCF_OR = 1 << 1,
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictCondFlags)
enum TraceRestictNullTypeSpecialValue {
TRNTSV_NULL = 0,
TRNTSV_START = 1,
TRNTSV_END = 2,
};
enum TraceRestrictCondOp {
TRCO_IS = 0,
TRCO_ISNOT = 1,
TRCO_LT = 2,
TRCO_LTE = 3,
TRCO_GT = 4,
TRCO_GTE = 5,
/* space up to 7 */
};
enum TraceRestrictProgramResultFlags {
TRPRF_DENY = 1 << 0,
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags)
struct TraceRestrictProgramResult {
uint32 penalty;
TraceRestrictProgramResultFlags flags;
TraceRestrictProgramResult()
: penalty(0), flags(static_cast<TraceRestrictProgramResultFlags>(0)) { }
};
typedef uint32 TraceRestrictItem;
struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrictprogram_pool> {
std::vector<TraceRestrictItem> items;
uint32 refcount;
TraceRestrictProgram()
: refcount(0) { }
void Execute(const Train *v, TraceRestrictProgramResult &out) const;
void IncrementRefCount() { refcount++; }
void DecrementRefCount();
static CommandCost Validate(const std::vector<TraceRestrictItem> &items);
CommandCost Validate() const { return TraceRestrictProgram::Validate(items); }
};
static inline TraceRestrictItemType GetTraceRestrictType(TraceRestrictItem item)
{
return static_cast<TraceRestrictItemType>(GB(item, TRIFA_TYPE_OFFSET, TRIFA_TYPE_COUNT));
}
static inline TraceRestrictCondFlags GetTraceRestrictCondFlags(TraceRestrictItem item)
{
return static_cast<TraceRestrictCondFlags>(GB(item, TRIFA_COND_FLAGS_OFFSET, TRIFA_COND_FLAGS_COUNT));
}
static inline TraceRestrictCondOp GetTraceRestrictCondOp(TraceRestrictItem item)
{
return static_cast<TraceRestrictCondOp>(GB(item, TRIFA_COND_OP_OFFSET, TRIFA_COND_OP_COUNT));
}
static inline uint16 GetTraceRestrictValue(TraceRestrictItem item)
{
return static_cast<uint16>(GB(item, TRIFA_VALUE_OFFSET, TRIFA_VALUE_COUNT));
}
static inline void SetTraceRestrictType(TraceRestrictItem &item, TraceRestrictItemType type)
{
SB(item, TRIFA_TYPE_OFFSET, TRIFA_TYPE_COUNT, type);
}
static inline void SetTraceRestrictCondOp(TraceRestrictItem &item, TraceRestrictCondOp condop)
{
SB(item, TRIFA_COND_OP_OFFSET, TRIFA_COND_OP_COUNT, condop);
}
void SetTraceRestrictTypeAndNormalise(TraceRestrictItem &item, TraceRestrictItemType type);
static inline void SetTraceRestrictValue(TraceRestrictItem &item, uint16 value)
{
SB(item, TRIFA_VALUE_OFFSET, TRIFA_VALUE_COUNT, value);
}
static inline bool IsTraceRestrictTypeConditional(TraceRestrictItemType type)
{
return type >= TRIT_COND_BEGIN;
}
static inline bool IsTraceRestrictConditional(TraceRestrictItem item)
{
return IsTraceRestrictTypeConditional(GetTraceRestrictType(item));
}
enum TraceRestrictConditionOpType {
TRCOT_NONE = 0, ///< takes no condition op
TRCOT_BINARY = 1, ///< takes "is" and "is not" condition ops
TRCOT_ALL = 2, ///< takes all condition ops (i.e. all relational ops)
};
enum TraceRestrictValueType {
TRVT_NONE = 0, ///< value field not used (set to 0)
TRVT_SPECIAL = 1, ///< special handling of value field
TRVT_INT = 2, ///< takes an integer value
TRVT_DENY = 3, ///< takes a value 0 = deny, 1 = allow (cancel previous deny)
};
struct TraceRestrictTypePropertySet {
TraceRestrictConditionOpType cond_type;
TraceRestrictValueType value_type;
};
static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceRestrictItem item)
{
TraceRestrictTypePropertySet out;
if (GetTraceRestrictType(item) == TRIT_NULL) {
out.cond_type = TRCOT_NONE;
out.value_type = TRVT_SPECIAL;
} else if (GetTraceRestrictType(item) == TRIT_COND_ENDIF ||
GetTraceRestrictType(item) == TRIT_COND_UNDEFINED) {
out.cond_type = TRCOT_NONE;
out.value_type = TRVT_NONE;
} else if (IsTraceRestrictConditional(item)) {
out.cond_type = TRCOT_ALL;
out.value_type = TRVT_INT;
} else {
out.cond_type = TRCOT_NONE;
if (GetTraceRestrictType(item) == TRIT_PF_PENALTY) {
out.value_type = TRVT_INT;
} else if (GetTraceRestrictType(item) == TRIT_PF_DENY) {
out.value_type = TRVT_DENY;
} else {
out.value_type = TRVT_NONE;
}
}
return out;
}
static inline TraceRestrictRefId MakeTraceRestrictRefId(TileIndex t, Track track)
{
return (t << 3) | track;
}
static inline TileIndex GetTraceRestrictRefIdTileIndex(TraceRestrictRefId ref)
{
return static_cast<TileIndex>(ref >> 3);
}
static inline Track GetTraceRestrictRefIdTrack(TraceRestrictRefId ref)
{
return static_cast<Track>(ref & 7);
}
void TraceRestrictCreateProgramMapping(TraceRestrictRefId ref, TraceRestrictProgram *prog);
void TraceRestrictRemoveProgramMapping(TraceRestrictRefId ref);
/// Gets the signal program for the tile identified by @p t and @p track.
/// An empty program will be constructed if none exists, and create_new is true
/// unless the pool is full
TraceRestrictProgram *GetTraceRestrictProgram(TraceRestrictRefId ref, bool create_new);
/// Notify that a signal is being removed
/// Remove any trace restrict items associated with it
void TraceRestrictNotifySignalRemoval(TileIndex tile, Track track);
/// Gets the signal program for the tile identified by @p t and @p track, or NULL
static inline const TraceRestrictProgram *GetExistingTraceRestrictProgram(TileIndex t, Track track)
{
if (IsRestrictedSignal(t)) {
return GetTraceRestrictProgram(MakeTraceRestrictRefId(t, track), false);
} else {
return NULL;
}
}
enum TraceRestrictDoCommandType {
TRDCT_INSERT_ITEM = 0,
TRDCT_MODIFY_ITEM = 1,
TRDCT_REMOVE_ITEM = 2,
};
void TraceRestrictDoCommandP(TileIndex tile, Track track, TraceRestrictDoCommandType type, uint32 offset, uint32 value, StringID error_msg);
CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
void ShowTraceRestrictProgramWindow(TileIndex tile, Track track);
#endif /* TRACERESTRICT_H */