Domain core: seeded RNG, asset registry, wallets, AMM pairs, mining
Pure logic layer with no game references: xoshiro128** RNG with savable state, asset registry (PSC, CRC, CRT, CRA, SPARK, Ponero), wallets whose taint and cost basis move with transfers, constant-product pools with nightly reversion, and mining (Probidia/PMD GPUs, RatDigg ASICs, network hash response, halving, wear and sudden death). 35 checks pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
ce3bed1467
14 files changed
+702
No files matched your search
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Decentralized.Domain
|
||||
{
|
||||
/// <summary>显卡或矿机的型号。算力内部单位 H(1 H = 10 MH/s),耗电单位 kJ/天。</summary>
|
||||
public sealed class HardwareSpec
|
||||
{
|
||||
public string Model;
|
||||
public string Brand;
|
||||
public double Hash;
|
||||
public double Kj;
|
||||
public int Price;
|
||||
/// <summary>暴毙概率的品牌系数。</summary>
|
||||
public double DeathFactor;
|
||||
/// <summary>每天损耗的系数。</summary>
|
||||
public double WearFactor;
|
||||
/// <summary>矿机(ASIC):独立机器;false 为插在矿架上的显卡。</summary>
|
||||
public bool Asic;
|
||||
|
||||
/// <summary>显示用算力:显卡 MH/s,矿机 GH/s。</summary>
|
||||
public double DisplayHash => Asic ? Hash * 10 / 1000 : Hash * 10;
|
||||
}
|
||||
|
||||
public static class Hardware
|
||||
{
|
||||
public const string Probidia = "Probidia", Pmd = "PMD", RatDigg = "RatDigg";
|
||||
|
||||
public static readonly IReadOnlyDictionary<string, HardwareSpec> Specs = new[]
|
||||
{
|
||||
Gpu("RZX50", Probidia, 1.0, 4, 120), Gpu("RZX60", Probidia, 1.5, 5, 180), Gpu("RZX70", Probidia, 5.0, 12, 450),
|
||||
Gpu("RZX80Ti", Probidia, 8.0, 18, 750), Gpu("RZX90", Probidia, 20.0, 30, 2800),
|
||||
Gpu("RZ470", Pmd, 0.8, 2.5, 90), Gpu("RZ580", Pmd, 1.2, 3, 140), Gpu("RZ6800", Pmd, 4.0, 8, 380),
|
||||
Gpu("RZ7900", Pmd, 15.0, 20, 2200),
|
||||
Asic("M1", 50, 60, 6000), Asic("M2", 120, 110, 15000), Asic("M3", 300, 220, 40000),
|
||||
}.ToDictionary(s => s.Model);
|
||||
|
||||
private static HardwareSpec Gpu(string model, string brand, double h, double kj, int price) => new HardwareSpec
|
||||
{
|
||||
Model = model, Brand = brand, Hash = h, Kj = kj, Price = price,
|
||||
DeathFactor = brand == Probidia ? 0.7 : 1.0, WearFactor = brand == Probidia ? 1.0 : 1.2,
|
||||
};
|
||||
|
||||
private static HardwareSpec Asic(string model, double h, double kj, int price) => new HardwareSpec
|
||||
{
|
||||
Model = model, Brand = RatDigg, Hash = h, Kj = kj, Price = price, DeathFactor = 0.5, WearFactor = 0.8, Asic = true,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>一张显卡或一台矿机的实例状态(存进物品标签)。</summary>
|
||||
public sealed class Unit
|
||||
{
|
||||
public string Model;
|
||||
/// <summary>假卡:标着 Model,芯片实为 FakeOf。</summary>
|
||||
public string FakeOf;
|
||||
public double Health = 100;
|
||||
public bool Dead;
|
||||
public bool Refurbished;
|
||||
|
||||
public HardwareSpec Label => Hardware.Specs[Model];
|
||||
public HardwareSpec Chip => Hardware.Specs[FakeOf ?? Model];
|
||||
|
||||
/// <summary>当前算力:健康 ≥ 50 时满算力,低于 50 线性降到健康 0 时的 60%。</summary>
|
||||
public double Hash(bool overclock)
|
||||
{
|
||||
if (Dead) return 0;
|
||||
double h = Chip.Hash * (Health >= 50 ? 1.0 : 0.6 + 0.4 * Health / 50);
|
||||
return overclock ? h * Tuning.OcHash : h;
|
||||
}
|
||||
|
||||
public double Kj(bool overclock) => Dead ? 0 : Chip.Kj * (overclock ? Tuning.OcKj : 1);
|
||||
|
||||
/// <summary>今晚的暴毙概率。</summary>
|
||||
public double DeathChance(bool overclock)
|
||||
{
|
||||
double p = Tuning.DeathBase + Tuning.DeathWorn * Math.Pow(1 - Health / 100, 2);
|
||||
p *= Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * (overclock ? Tuning.OcDeath : 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>一夜的损耗与暴毙判定;返回是否在今晚暴毙。</summary>
|
||||
public bool Night(bool overclock, Rng rng)
|
||||
{
|
||||
if (Dead) return false;
|
||||
Health = Math.Max(0, Health - Label.WearFactor * (overclock ? Tuning.OcWear : 1));
|
||||
if (rng.Chance(DeathChance(overclock)))
|
||||
{
|
||||
Dead = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>翻新:每张卡一次,健康 +30。</summary>
|
||||
public bool Refurbish()
|
||||
{
|
||||
if (Dead || Refurbished) return false;
|
||||
Refurbished = true;
|
||||
Health = Math.Min(100, Health + Tuning.RefurbishHealth);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>全网:NPC 背景算力、出块奖励与减半。</summary>
|
||||
public sealed class Network
|
||||
{
|
||||
public double NpcHash = Tuning.NpcHash0;
|
||||
public double Reward = Tuning.BlockReward;
|
||||
/// <summary>停电、动荡等事件对 NPC 算力的可用比例。</summary>
|
||||
public double Availability = 1.0;
|
||||
|
||||
/// <summary>按算力分得今晚的出块(已扣矿池抽成)。</summary>
|
||||
public double Mine(double playerHash)
|
||||
{
|
||||
if (playerHash <= 0) return 0;
|
||||
double total = NpcHash * Availability + playerHash;
|
||||
return Reward * playerHash / total * (1 - Tuning.PoolFee);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 夜间:第 HalvingDays 天的倍数时减半;NPC 矿工按"每 H 收益 / 电费"与目标比的偏离扩张或关机,每晚最多 ±5%。
|
||||
/// </summary>
|
||||
public void Night(int day, double price, double playerHash)
|
||||
{
|
||||
if (day > 0 && day % Tuning.HalvingDays == 0) Reward /= 2;
|
||||
double total = NpcHash * Availability + playerHash;
|
||||
double perH = Reward * price / total;
|
||||
double ratio = perH / (Tuning.NpcKjPerH * Tuning.ElecPrice);
|
||||
double adj = Math.Max(-Tuning.NpcAdj, Math.Min(Tuning.NpcAdj, Tuning.NpcAdj * (ratio / Tuning.NpcTargetRatio - 1)));
|
||||
NpcHash *= 1 + adj;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user