Пример #1
0
        /// <summary>
        /// モード設定の1ブロックの文字列から設定を抽出
        /// </summary>
        /// <param name="modeLines"></param>
        private Mode(List <string> modeLines)
        {
            Name    = ApplicationUtil.ExtractModProperty(modeLines, "#mode");
            Year    = int.Parse(ApplicationUtil.ExtractModProperty(modeLines, "year"));
            Money   = long.Parse(ApplicationUtil.ExtractModProperty(modeLines, "money"));
            Message = ApplicationUtil.ExtractModProperty(modeLines, "message").Replace(',', '\n');
            MYear   = int.Parse(ApplicationUtil.ExtractModProperty(modeLines, "myear"));

            DefautltCompositions = ApplicationUtil.ExtractModProperties(modeLines, "car").Select(value =>
            {
                string[] arr     = value.Split(",");
                int ck           = int.Parse(arr[2]);       //編成規格
                bool isLinear    = (ck & 32) > 0;
                bool isDiesel    = (ck & 16) > 0;
                bool isElectric  = (ck & 8) > 0;
                bool isSteam     = (ck & 4) > 0;
                bool isNarrow    = (ck & 1) > 0;
                bool isRegular   = (ck & 2) > 0;
                bool isPendulum  = (ck & 64) > 0;
                bool isFreeGauge = (ck & 128) > 0;

                RailTypeEnum railType = isLinear ? RailTypeEnum.LinearMotor : RailTypeEnum.Iron;

                CarGaugeEnum?carGauge =
                    isLinear ? (CarGaugeEnum?)null :
                    isNarrow ? CarGaugeEnum.Narrow :
                    isRegular ? CarGaugeEnum.Regular :
                    isFreeGauge ? CarGaugeEnum.FreeGauge :
                    throw new ArgumentException("軌間が未定義です");

                PowerEnum powerSource =
                    isLinear ? PowerEnum.LinearMotor :
                    isElectric ? PowerEnum.Electricity :
                    isDiesel ? PowerEnum.Diesel :
                    isSteam ? PowerEnum.Steam :
                    throw new ArgumentException("動力源が未指定です");

                return(new DefautltComposition
                {
                    Name = arr[0],
                    BestSpeed = int.Parse(arr[1]),
                    CarCount = int.Parse(arr[3]),
                    HeldUnits = int.Parse(arr[4]),
                    Price = int.Parse(arr[5]),
                    seat = LogicUtil.ConvertSeatModToInternalId(int.Parse(arr[6])),
                    Gauge = carGauge,
                    Power = powerSource,
                    Tilt = isPendulum ? CarTiltEnum.Pendulum : CarTiltEnum.None,
                    Type = railType
                });
            }).ToList();
        }
Пример #2
0
        /// <summary>
        /// モード設定文字列からモードオブジェクト作成
        /// </summary>
        /// <param name="modeLines"></param>
        /// <returns></returns>
        private static Mode CreateMode(List <string> modeLines)
        {
            Mode mode = new Mode();

            //ゲーム設定
            mode.Name          = ExtractModProperty(modeLines, "#mode");
            mode.Year          = int.Parse(ExtractModProperty(modeLines, "year"));
            mode.Money         = long.Parse(ExtractModProperty(modeLines, "money"));
            mode.Message       = ExtractModProperty(modeLines, "message").Replace(',', '\n');
            mode.MYear         = int.Parse(ExtractModProperty(modeLines, "myear"));
            mode.genkaiJoki    = ParseIntOrNull(ExtractModProperty(modeLines, "steam")) ?? 40;
            mode.genkaiDenki   = ParseIntOrNull(ExtractModProperty(modeLines, "elect"));
            mode.genkaiKidosha = ParseIntOrNull(ExtractModProperty(modeLines, "diesel"));
            mode.genkaiLinear  = ParseIntOrNull(ExtractModProperty(modeLines, "linear"));
            var tecno = ParseIntOrNull(ExtractModProperty(modeLines, "tecno"));

            if (tecno.HasValue)
            {
                int tecnoV = tecno.Value;
                if ((tecnoV & 256) > 0)                 //動的信号
                {
                    mode.isDevelopedDynamicSignal    = true;
                    mode.isDevelopedFreeGauge        = true;
                    mode.isDevelopedMachineTilt      = true;
                    mode.isDevelopedDualSeat         = true;
                    mode.isDevelopedRetructableLong  = true;
                    mode.isDevelopedRichCross        = true;
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 4) > 0)                 //フリーゲージトレイン
                {
                    mode.isDevelopedFreeGauge        = true;
                    mode.isDevelopedMachineTilt      = true;
                    mode.isDevelopedDualSeat         = true;
                    mode.isDevelopedRetructableLong  = true;
                    mode.isDevelopedRichCross        = true;
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 512) > 0)                 //機械式車体傾斜装置
                {
                    mode.isDevelopedMachineTilt      = true;
                    mode.isDevelopedDualSeat         = true;
                    mode.isDevelopedRetructableLong  = true;
                    mode.isDevelopedRichCross        = true;
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 8) > 0)                 //デュアルシート
                {
                    mode.isDevelopedDualSeat         = true;
                    mode.isDevelopedRetructableLong  = true;
                    mode.isDevelopedRichCross        = true;
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 32) > 0)                 //収納式ロングシート
                {
                    mode.isDevelopedRetructableLong  = true;
                    mode.isDevelopedRichCross        = true;
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 16) > 0)                 //豪華クロスシート
                {
                    mode.isDevelopedRichCross        = true;
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 1) > 0)                 //振り子式車体傾斜装置
                {
                    mode.isDevelopedCarTiltPendulum  = true;
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 128) > 0)                 //自動改札機
                {
                    mode.isDevelopedAutoGate         = true;
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 64) > 0)                 //転換クロスシート
                {
                    mode.isDevelopedConvertibleCross = true;
                    mode.isDevelopedBlockingSignal   = true;
                }
                else if ((tecnoV & 2) > 0)                 //閉塞信号
                {
                    mode.isDevelopedBlockingSignal = true;
                }
            }
            int[] people = ExtractModProperty(modeLines, "people")?.Split(",").Select(it => int.Parse(it)).Take(2).ToArray() ?? new int[] { 1, 1 };
            if (people.Count() == 2)
            {
                mode.peopleNume  = people[0];
                mode.peopleDenom = people[1];
            }


            //デフォルト編成
            mode.DefautltCompositions = ExtractModProperties(modeLines, "car").Select(value =>
            {
                string[] arr     = value.Split(",");
                int ck           = int.Parse(arr[2]);       //編成規格
                bool isLinear    = (ck & 32) > 0;
                bool isDiesel    = (ck & 16) > 0;
                bool isElectric  = (ck & 8) > 0;
                bool isSteam     = (ck & 4) > 0;
                bool isNarrow    = (ck & 1) > 0;
                bool isRegular   = (ck & 2) > 0;
                bool isPendulum  = (ck & 64) > 0;
                bool isFreeGauge = (ck & 128) > 0;

                RailTypeEnum railType = isLinear ? RailTypeEnum.LinearMotor : RailTypeEnum.Iron;

                CarGaugeEnum?carGauge =
                    isLinear ? (CarGaugeEnum?)null :
                    isNarrow ? CarGaugeEnum.Narrow :
                    isRegular ? CarGaugeEnum.Regular :
                    isFreeGauge ? CarGaugeEnum.FreeGauge :
                    throw new ArgumentException("軌間が未定義です");

                PowerEnum powerSource =
                    isLinear ? PowerEnum.LinearMotor :
                    isElectric ? PowerEnum.Electricity :
                    isDiesel ? PowerEnum.Diesel :
                    isSteam ? PowerEnum.Steam :
                    throw new ArgumentException("動力源が未指定です");

                return(new DefautltComposition
                {
                    Name = arr[0],
                    BestSpeed = int.Parse(arr[1]),
                    CarCount = int.Parse(arr[3]),
                    HeldUnits = int.Parse(arr[4]),
                    Price = int.Parse(arr[5]),
                    seat = LogicUtil.ConvertSeatModToInternalId(int.Parse(arr[6])),
                    Gauge = carGauge,
                    Power = powerSource,
                    Tilt = isPendulum ? CarTiltEnum.Pendulum : CarTiltEnum.None,
                    Type = railType
                });
            }).ToList();

            //路線
            List <LineDefaultSetting> lineDefaultSettings = new List <LineDefaultSetting>();

            bool[] ltn  = ExtractModProperty(modeLines, "ltn")?.Split(",").Select(flg => int.Parse(flg) != 0).ToArray() ?? new bool[0];
            int[]  lk   = ExtractModProperty(modeLines, "lk")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[ltn.Length];
            int[]  lbs  = ExtractModProperty(modeLines, "lbs")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[ltn.Length];
            int[]  las  = ExtractModProperty(modeLines, "las")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[ltn.Length];
            int[]  lwe  = ExtractModProperty(modeLines, "lwe")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? Enumerable.Repeat(GameConstants.RetentionRateDefault, ltn.Length).ToArray();
            int[]  lts  = ExtractModProperty(modeLines, "lts")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[ltn.Length];
            int[]  ulc  = ExtractModProperty(modeLines, "ulc")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? null;
            int[]  ulcr = ExtractModProperty(modeLines, "ulcr")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[ltn.Length];
            for (int i = 0; i < ltn.Length; i++)
            {
                LineDefaultSetting setting = new LineDefaultSetting();

                setting.IsExist = ltn[i];
                if (setting.IsExist)
                {
                    if (i < lk.Length)
                    {
                        setting.Type          = (lk[i] & 4) > 0 ? RailTypeEnum.LinearMotor : RailTypeEnum.Iron;
                        setting.gauge         = (lk[i] & 1) > 0 ? RailGaugeEnum.Regular : RailGaugeEnum.Narrow;
                        setting.IsElectrified = (lk[i] & 2) > 0;
                    }
                    if (i < lbs.Length)
                    {
                        setting.bestSpeed = lbs[i];
                    }
                    if (i < las.Length)
                    {
                        setting.LaneNum = las[i];
                    }
                    if (i < lwe.Length)
                    {
                        setting.retentionRate = lwe[i];
                    }
                    if (i < lts.Length)
                    {
                        setting.taihisen = (TaihisenEnum)lts[i];
                    }
                    if (ulc != null)
                    {
                        setting.useComposition = mode.DefautltCompositions[ulc[i] - 1];
                    }
                    if (i < ulcr.Length)
                    {
                        setting.runningPerDay = ulcr[i];
                    }
                }
                lineDefaultSettings.Add(setting);
            }
            mode.LineSettings = lineDefaultSettings;

            //運行系統
            List <KeitoDefaultSetting> keitoDefaultSettings = new List <KeitoDefaultSetting>();

            int[] udc  = ExtractModProperty(modeLines, "udc")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[0];
            int[] udcr = ExtractModProperty(modeLines, "udcr")?.Split(",").Select(value => int.Parse(value)).ToArray() ?? new int[udc.Length];
            for (int i = 0; i < udc.Length; i++)
            {
                KeitoDefaultSetting setting = new KeitoDefaultSetting()
                {
                    useComposition = mode.DefautltCompositions[udc[i] - 1],
                    runningPerDay  = udcr[i]
                };
                keitoDefaultSettings.Add(setting);
            }
            mode.KeitoDefaultSettings = keitoDefaultSettings;

            //目標
            mode.goalLineMake    = (LineGoalTargetEnum?)ParseIntOrNull(ExtractModProperty(modeLines, "mmake"));
            mode.goalTechDevelop = ExtractModProperties(modeLines, "mtec").ToDictionary(
                value => (PowerEnum)(int.Parse(value.Split(",")[0]) - 1),
                value => int.Parse(value.Split(",")[1]));
            string[] mlbsValues = ExtractModProperty(modeLines, "mlbs")?.Split(",") ?? null;
            if (mlbsValues != null)
            {
                mode.goalLineBestSpeed = ((LineGoalTargetEnum?)ParseIntOrNull(mlbsValues[0]), int.Parse(mlbsValues[1]));
            }
            string[] mmanegeValues = ExtractModProperty(modeLines, "mmanage")?.Split(",") ?? null;
            if (mmanegeValues != null)
            {
                mode.goalLineManage = (LineGoalTargetEnum?)ParseIntOrNull(mmanegeValues[0]);
            }
            mode.goalMoney    = ParseIntOrNull(ExtractModProperty(modeLines, "mmoney"));
            mode.gameoverYear = int.Parse(ExtractModProperty(modeLines, "myear"));

            return(mode);
        }
Пример #3
0
        /// <summary>
        /// 路線建造コスト計算ロジック
        /// </summary>
        /// <param name="bestSpeed"></param>
        /// <param name="laneSu"></param>
        /// <param name="distance"></param>
        /// <param name="railType"></param>
        /// <param name="railGauge"></param>
        /// <param name="isElectrified"></param>
        /// <param name="taihisen"></param>
        /// <param name="lineProperty"></param>
        /// <param name="gameInfo"></param>
        /// <returns></returns>
        public static long CalcLineConstructionCost(
            int bestSpeed, int laneSu, int distance,
            RailTypeEnum railType, RailGaugeEnum?railGauge, bool?isElectrified,
            TaihisenEnum taihisen, LinePropertyType lineProperty,
            GameInfo gameInfo)
        {
            if (gameInfo is null)
            {
                throw new ArgumentNullException(nameof(gameInfo));
            }

            int railCostKeisu = gameInfo.LineMakeCost, year = gameInfo.Year, basicYear = gameInfo.BasicYear, economicIndex = gameInfo.CalcEconomicIndex();

            long railCost;
            long taihiCost;
            int  taihiKeisu;

            if (laneSu == 3)
            {
                laneSu = 4;
            }
            switch (lineProperty)
            {
            case LinePropertyType.JapaneseInterCity:
                railCost   = (bestSpeed + 40) * (laneSu + 1) * (distance + 10) * 4;
                taihiKeisu = 400;
                break;

            case LinePropertyType.Surburb:
                railCost   = (bestSpeed + 40) * (laneSu) * (distance + 1) * 6;
                taihiKeisu = 500;
                break;

            case LinePropertyType.Outskirts:
                railCost   = (bestSpeed + 40) * (laneSu) * (distance + 1) * 8;
                taihiKeisu = 700;
                break;

            case LinePropertyType.Plain:
                railCost   = (bestSpeed + 200) * (laneSu + 1) * (distance + 10) * 4 / 3;
                taihiKeisu = 300;
                break;

            case LinePropertyType.Mountain:
                if (bestSpeed > 80)
                {
                    railCost   = (bestSpeed + 200) * (laneSu + 1) * (distance + 10) * 4;
                    taihiKeisu = 500;
                }
                else
                {
                    railCost   = (bestSpeed + 40) * (laneSu + 1) * (distance + 10) * 4;
                    taihiKeisu = 400;
                }
                break;

            case LinePropertyType.Alpine:
                if (bestSpeed > 60)
                {
                    railCost   = (bestSpeed + 200) * (laneSu + 1) * (distance + 10) * 5;
                    taihiKeisu = 550;
                }
                else
                {
                    railCost   = (bestSpeed + 30) * (laneSu + 1) * (distance + 10) * 5;
                    taihiKeisu = 450;
                }
                break;

            case LinePropertyType.Sea:
                if (bestSpeed > 40)
                {
                    railCost   = (bestSpeed + 500) * (laneSu + 1) * (distance + 10) * 5;
                    taihiKeisu = 800;
                }
                else
                {
                    railCost   = 240 * (laneSu + 1) * (distance + 10) * 5;
                    taihiKeisu = 500;
                }
                break;

            case LinePropertyType.RussianPlain:
                railCost   = (bestSpeed + 500) * (laneSu + 1) / 7 * (distance + 20) * 4;
                taihiKeisu = 200;
                break;

            case LinePropertyType.Underground:
                if (bestSpeed > 40)
                {
                    railCost   = (bestSpeed + 200) * (laneSu + 1) * (distance + 10) * 8;
                    taihiKeisu = 200;
                }
                else
                {
                    railCost   = 240 * (laneSu + 1) * (distance + 10);
                    taihiKeisu = 500;
                }
                break;

            default:
                throw new ArgumentException($"引数の内容が誤りです 内容:{lineProperty}", nameof(lineProperty));
            }

            //標準軌、リニア
            if (railType == RailTypeEnum.LinearMotor || railGauge == RailGaugeEnum.Regular)
            {
                railCost = railCost * 6 / 5;
            }

            //電化(リニアは電化)
            if (railType == RailTypeEnum.LinearMotor || isElectrified.GetValueOrDefault(true))
            {
                railCost = railCost * 3 / 2;
            }

            //リニア地下鉄(都営大江戸線、福岡市営地下鉄七隈線みたいな)
            if (lineProperty == LinePropertyType.Underground && railType == RailTypeEnum.LinearMotor && bestSpeed < 200)
            {
                railCost /= 2;
            }

            switch (taihisen)
            {
            case TaihisenEnum.None:
                taihiCost = 0;
                break;

            case TaihisenEnum.Every100km:
                taihiCost = (distance / 100 + 1) * taihiKeisu * laneSu;
                break;

            case TaihisenEnum.Every50km:
                taihiCost = (distance / 50 + 1) * taihiKeisu * laneSu;
                break;

            case TaihisenEnum.Every20km:
                taihiCost = (distance / 20 + 1) * taihiKeisu * laneSu;
                break;

            case TaihisenEnum.Every10km:
                taihiCost = (distance / 10 + 1) * taihiKeisu * laneSu;
                break;

            case TaihisenEnum.Every5km:
                taihiCost = (distance / 5 + 1) * taihiKeisu * laneSu;
                break;

            case TaihisenEnum.Every2km:
                taihiCost = (distance / 2 + 1) * taihiKeisu * laneSu;
                break;

            default:
                throw new ArgumentException($"引数の内容が誤りです 内容:{taihisen}", nameof(taihisen));
            }

            var totalCost = railCost + taihiCost;

            return(totalCost / 100 * railCostKeisu / 188 * (year / 10 - basicYear / 10 + 188) / 10 * economicIndex / 10);
        }