/// <summary> /// Removes this platform from the world. /// </summary> public override void remove() { World world = World.world; onHostDisconnected(); foreach (YardRailRoad[] yrrs in lanes) { if (yrrs != null) { foreach (YardRailRoad yrr in yrrs) { // canRemove must be true before this method is called. Debug.Assert(yrr.voxel.car == null); Location loc = yrr.location; yrr.voxel.railRoad = null; new SingleRailRoad( TrafficVoxel.getOrCreate(loc), RailPattern.get(direction, direction.opposite)); world.onVoxelUpdated(loc); } } } // remove the platform itself foreach (FatPlatformVoxel pv in voxels) { world.remove(pv.location); world.onVoxelUpdated(pv.location); } base.remove(); }
/// <summary> /// Builds normal RR between two specified locations /// </summary> /// <returns>false if the operation was unsuccessful</returns> public static bool build(Location here, Location there) { // ensure that nothing is on our way between "from" and "to" World world = World.world; int cost; if (comupteRoute(here, there, out cost) == null) { return(false); } Direction d = here.getDirectionTo(there); while (true) { TrafficVoxel v = TrafficVoxel.getOrCreate(here); if (v == null) { Voxel vv = World.world[here]; Debug.Assert(vv.entity.isSilentlyReclaimable); vv.entity.remove(); v = TrafficVoxel.getOrCreate(here); } Direction dd; if (here != there) { dd = here.getDirectionTo(there); } else { dd = d; } if (v.railRoad != null) { v.railRoad.attach(here == there?d.opposite:d); World.world.onVoxelUpdated(here); } else { v.railRoad = new SingleRailRoad(v, RailPattern.get(d.opposite, dd)); // if this RR is elevated, elect a bridge support. // if((++cycle%2)==0) BridgePierVoxel.electBridgeSupport(here, typeof(BridgePierVoxel.DefaultImpl), v); } if (here == there) { break; } d = dd; here = here.toward(there); } accounting.AccountGenre.RAIL_SERVICE.spend(cost); // charge the cost return(true); }
// for junction rail private static RailPattern createJunction(int imageIndexX, int angle1, int angle2, int angle3offset) { RailPattern p = new RailPattern(12 + imageIndexX, imageIndexX, 1, angle1, angle2, new Size(32, 16), 0); p.dir[(angle2 + angle3offset + 8) % 8] = true; return(p); }
/// <summary> /// Creates a new slope. A slope consists of four consective /// blocks of railroads. The base parameter specifies the location /// of the lowest railroad and the direction parameter /// specifies the direction to climb. /// /// The caller must use the canCreateSlope method to check /// if this method can be invoked. /// </summary> public static void createSlope(Location _base, Direction dir) { Debug.Assert(canCreateSlope(_base, dir)); // charge the cost before we alter something accounting.AccountGenre.RAIL_SERVICE.spend(calcCostOfNewSlope(_base, dir)); SlopeEntity entity = new SlopeEntity(_base, dir); for (int i = 0; i < 4; i++) { if (_base.z < World.world.getGroundLevel(_base)) { new SlopeRailRoad(entity, TrafficVoxel.getOrCreate( _base.x, _base.y, _base.z + (i / 2)), RailPattern.getUGSlope(dir, i)); if (i < 2) { // space filler new SlopeFillerVoxel(entity, _base.x, _base.y, _base.z + 1, i); } else { new SlopeSupportVoxel(entity, _base.x, _base.y, _base.z, i, RailPattern.slopeWalls[dir.index + i - 2]); } } else { new SlopeRailRoad(entity, TrafficVoxel.getOrCreate( _base.x, _base.y, _base.z + (i / 2)), RailPattern.getSlope(dir, i)); if (i < 2) { // space filler new SlopeFillerVoxel(entity, _base.x, _base.y, _base.z + 1, i); } else { new SlopeSupportVoxel(entity, _base.x, _base.y, _base.z, i, RailPattern.slopeSupports[dir.index + (i - 2)]); } } Type bridgeStyle; if (dir == Direction.NORTH || dir == Direction.EAST) { bridgeStyle = typeof(BridgePierVoxel.DefaultImpl); } else { bridgeStyle = typeof(BridgePierVoxel.SlopeNEImpl); } BridgePierVoxel.electBridgeSupport(_base, bridgeStyle, entity); _base += dir; } }
// for angle rail private static RailPattern createSlope(Picture pic, int baseIndexX, int imageIndexX, int upDir, int zdiff, int zangle, bool isVisible) { RailPattern p = new RailPattern(pic, baseIndexX + imageIndexX, isVisible?imageIndexX:12, isVisible?2:0, upDir, (upDir + 4) % 8, isVisible?new Size(32, 32):new Size(1, 1), 16); p._climbDir = Direction.get(upDir); p._level = imageIndexX % 4; p._zdiff = zdiff; p._zangle = Direction.get(zangle); return(p); }
/// <summary> /// Removes this platform from the world. /// </summary> public override void remove() { World world = World.world; onHostDisconnected(); Location loc = this.location; for (int i = 0; i < length; i++, loc += direction) { new SingleRailRoad( TrafficVoxel.get(loc), RailPattern.get(direction, direction.opposite)); } base.remove(); }
/// <summary> /// Computes the route of RRs between specified two points. /// </summary> /// <returns> /// null if it is impossible to build the route between two. /// Otherwise returns a map from Location to RailPattern. /// </returns> /// <param name="cost">The total cost of construction will be returned here</param> public static IDictionary comupteRoute(Location from, Location to, out int cost) { cost = 0; int c; Hashtable route = new Hashtable(); if (from == to) { return(route); } Direction dir = null; for (Location loc = from; loc != to; dir = loc.getDirectionTo(to).opposite, loc = loc.toward(to)) { Direction dd = loc.getDirectionTo(to); c = calcRailRoadCost(loc, dir, dd); cost += c; if (c == 0) { return(null); } route.Add(loc, RailPattern.get(dir != null?dir:dd.opposite, dd)); } c = calcRailRoadCost(to, dir, null); cost += c; if (c == 0) { return(null); } route.Add(to, RailPattern.get(dir, dir.opposite)); return(route); }
public override bool attach(Direction newDir) { if (hasRail(newDir)) { return(true); // already added } Direction d1 = dir1, d2 = dir2; if (isWellConnected) { Debug.Assert(is1or3or4(Direction.angle(d1, newDir)) && is1or3or4(Direction.angle(d2, newDir))); // if the line is already well connected, make it a junction TrafficVoxel v = voxel; v.railRoad = new JunctionRailRoad(v, RailPattern.getJunction(d1, d2, newDir)); World.world.onVoxelUpdated(voxel); return(true); } else { // if the line is not well connected, change the // direction if (Direction.angle(d1, newDir) >= 3) { pattern = RailPattern.get(d1, newDir); World.world.onVoxelUpdated(voxel); return(true); } if (Direction.angle(d2, newDir) >= 3) { pattern = RailPattern.get(d2, newDir); World.world.onVoxelUpdated(voxel); return(true); } } return(false); // unable to attach this. }
public override void build(Location here, Location to) { Debug.Assert(canBeBuilt(here, to)); Direction d = here.getDirectionTo(to); while (true) { if (RailRoad.get(here) == null) { MountainVoxel mv = World.world[here] as MountainVoxel; if (mv != null) { // build a tunnel byte[] heights = new byte[4]; for (int i = 0; i < 4; i++) { heights[i] = (byte)mv.getHeight(Direction.get(i * 2 + 1)); } World.world.remove(here); // remove this mountain create(TrafficVoxel.getOrCreate(here), d, heights); } else { // build a normal tunnel new SingleRailRoad(TrafficVoxel.getOrCreate(here), RailPattern.get(d, d.opposite)); } } if (here == to) { return; } here = here.toward(to); } }
/// <summary> /// If this RR has two RRs with specified direction, /// remove it completely. If one RR matches, change /// it to a single RR. /// </summary> public override void detach(Direction d1, Direction d2) { if (hasRail(d1) && hasRail(d2)) { voxel.railRoad = null; return; } if (hasRail(d1) || hasRail(d2)) { // this needs to be changed to a single RR. Direction a = null, b = null; // two directions of such a single RR. foreach (Direction x in Direction.directions) { if (hasRail(x) && x != d1 && x != d2) { if (a == null) { a = x; } else { b = x; } } } Debug.Assert(a != null && b != null); Location loc = location; TrafficVoxel v = voxel; // these references can be lost, so use local variables. // replace the railroad new SingleRailRoad(v, RailPattern.get(a, b)); World.world.onVoxelUpdated(loc); return; } }
public SingleRailRoad(TrafficVoxel tv, RailPattern p) : base(tv, p) { }
public JunctionRailRoad(TrafficVoxel tv, RailPattern p) : base(tv, p) { }
protected RailRoad(TrafficVoxel tv, RailPattern pattern) { this.voxel = tv; this.pattern = pattern; voxel.railRoad = this; }
public SpecialPurposeRailRoad(TrafficVoxel voxel, Direction d) : base(voxel, RailPattern.get(d, d.opposite)) { }
private SlopeRailRoad(SlopeEntity e, TrafficVoxel v, RailPattern rp) : base(v, rp) { entity = e; }