第十一阶段 stage 1:污点代替没收、模块不设上限、出块 ×10
- 预测市场内幕单改为确定性记污点:结算或卖出时照常兑付,内幕份额对应的兑付记收款钱包污点;删除 PredictInsiderShare、PredictInsiderCatch - 操纵检出被查后照常兑付,预测兑付记钱包污点、永续盈利记 Poinbase 账户污点;删除 ManipFreezeDays - Wallet.AddTaintCapped:污点不超过钱包当时的价值,超出部分按 PredictFraudShare / PredictFraudCap 记诈骗罪证(TaintCrime.Commit) - 模块效果不设上限,只留算力、耗电、损耗乘数的下限(ModuleHashFloor / ModuleKjFloor / ModuleWearFloor) - BlockReward 100 → 1000,NpcHash0 360 → 3600 - 修正内幕卖出日志"只退本金"的错误说法;8 种语言文字与手册更新 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
45a6ec2f77
commit
bc23ae056b
18 files changed
+248
-205
No files matched your search
@@ -68,9 +68,8 @@ namespace Decentralized.Domain
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 矿架上游戏模块的效果。机器汇总的三项百分比(性能、效率、品质)各除以 <see cref="Tuning.ModuleRatio"/> 后生效,
|
||||
/// 并有上限,避免模块把挖矿收益放大到破坏经济:算力最多 +20%,省电最多 25%,损耗最多降 30%。
|
||||
/// 性能加成同时按比例提高损耗与暴毙率。负数(例如节能模块的负性能、超频模块的负效率)照常生效,耗电增加不设上限。
|
||||
/// 矿架上游戏模块的效果。机器汇总的三项百分比(性能、效率、品质)各除以 <see cref="Tuning.ModuleRatio"/> 后生效,不设上限(强力模块是玩家自己拿到的)。
|
||||
/// 性能加成同时按比例提高损耗与暴毙率。三个乘数各有防出错的下限:算力不低于 <see cref="Tuning.ModuleHashFloor"/>,耗电不低于 <see cref="Tuning.ModuleKjFloor"/>,损耗不低于 <see cref="Tuning.ModuleWearFloor"/>。
|
||||
/// </summary>
|
||||
public struct ModuleBonus
|
||||
{
|
||||
@@ -84,14 +83,17 @@ namespace Decentralized.Domain
|
||||
public static ModuleBonus From(int performance, int efficiency, int quality)
|
||||
{
|
||||
double r = Tuning.ModuleRatio * 100.0;
|
||||
double hash = Clamp(performance / r, -0.5, Tuning.ModuleHashCap);
|
||||
double save = Clamp(efficiency / r, -1.0, Tuning.ModuleKjCap);
|
||||
double wearCut = Clamp(quality / r, -1.0, Tuning.ModuleWearCap);
|
||||
double hash = performance / r, save = efficiency / r, wearCut = quality / r;
|
||||
double heat = 1 + Math.Max(0, hash);
|
||||
return new ModuleBonus { Hash = 1 + hash, Kj = 1 - save, Wear = (1 - wearCut) * heat, Death = heat };
|
||||
return new ModuleBonus
|
||||
{
|
||||
Hash = Math.Max(Tuning.ModuleHashFloor, 1 + hash),
|
||||
Kj = Math.Max(Tuning.ModuleKjFloor, 1 - save),
|
||||
Wear = Math.Max(Tuning.ModuleWearFloor, (1 - wearCut) * heat),
|
||||
Death = heat,
|
||||
};
|
||||
}
|
||||
|
||||
private static double Clamp(double v, double lo, double hi) => Math.Max(lo, Math.Min(hi, v));
|
||||
}
|
||||
|
||||
/// <summary>一张显卡或一台矿机的实例状态(存进物品标签)。</summary>
|
||||
|
||||
@@ -113,12 +113,13 @@ namespace Decentralized.Domain
|
||||
public bool Held;
|
||||
}
|
||||
|
||||
/// <summary>夜间结算发生的事。Kind:win / lose / void / caught。</summary>
|
||||
/// <summary>夜间结算发生的事。Kind:win / lose / void / insider(内幕份额记了污点)/ manip(被判操纵,整笔兑付记了污点)。
|
||||
/// Amount 是兑付或本金;Taint 是实际加上的污点,Over 是超出钱包价值、折成罪证的部分,Fraud 是罪证。</summary>
|
||||
public sealed class PredictEvent
|
||||
{
|
||||
public string Kind, Title;
|
||||
public PredictMarket Market;
|
||||
public double Amount, Fraud;
|
||||
public double Amount, Taint, Over, Fraud;
|
||||
}
|
||||
|
||||
/// <summary>候选盘口(接入层按游戏当前状态给出):先验概率按窗口算。</summary>
|
||||
@@ -181,29 +182,24 @@ namespace Decentralized.Domain
|
||||
}
|
||||
|
||||
/// <summary>全部卖出这个钱包在盘口里的持仓(盘口关闭前):收回 LMSR 的卖价减手续费,污点按比例退回,赚的部分是干净的。返回收回的 CRC。</summary>
|
||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, out double got) => SellAll(acct, m, day, null, out got, out _);
|
||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Func<string, double> price, out double got) => SellAll(acct, m, day, price, out got, out _, out _);
|
||||
|
||||
/// <summary>
|
||||
/// 全部卖出;内幕持仓(这个盘口合计)达到查处线、而且卖出有赚,按查处概率被查:本金和收益全部没收,收益的一半记罪证(fraud > 0)。
|
||||
/// 先买后卖、赶在结算前离场,同样会被查。
|
||||
/// 全部卖出;持仓里的内幕份额(下单时已经知道答案)对应的那部分卖出所得记污点(带上限,见 <see cref="Wallet.AddTaintCapped"/>),
|
||||
/// taint 是实际加上的污点,over 是超出钱包价值、没加进去的部分(由调用方按 <see cref="Wallet.OverflowFraud"/> 折成罪证)。先买后卖、赶在结算前离场也一样。
|
||||
/// </summary>
|
||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Rng rng, out double got, out double fraud)
|
||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Func<string, double> price, out double got, out double taint, out double over)
|
||||
{
|
||||
got = 0; fraud = 0;
|
||||
got = 0; taint = 0; over = 0;
|
||||
var pos = PosOf(m.Id, acct.Address);
|
||||
if (pos == null) return PredictResult.NoPosition;
|
||||
if (!m.IsOpen(day)) return PredictResult.Closed;
|
||||
double value = m.SellValue(pos.Yes, pos.Shares);
|
||||
got = value * (1 - Tuning.PredictFee);
|
||||
bool insider = PosAll(m.Id).Sum(x => x.Insider) >= Tuning.PredictInsiderShare * m.ShareCap;
|
||||
if (pos.Yes) m.QYes -= pos.Shares; else m.QNo -= pos.Shares;
|
||||
Positions.Remove(pos);
|
||||
if (rng != null && insider && pos.Insider > 0 && got > pos.Cost && rng.Chance(Math.Min(1, Tuning.PredictInsiderCatch * StoryMods.Current.Enforce(day))))
|
||||
{
|
||||
fraud = Math.Min(Tuning.PredictFraudCap, (got - pos.Cost) * Tuning.PredictFraudShare);
|
||||
got = 0;
|
||||
}
|
||||
Pay(acct, pos, got);
|
||||
over = MarkInsider(acct, pos, got, price, out taint);
|
||||
return PredictResult.Ok;
|
||||
}
|
||||
|
||||
@@ -213,11 +209,22 @@ namespace Decentralized.Domain
|
||||
acct.Add(Assets.CRC, payout); acct.Taint += pos.Taint * keep; acct.Basis += pos.Basis * keep;
|
||||
}
|
||||
|
||||
/// <summary>内幕份额对应的兑付记污点(带上限)。taint 是实际加上的污点,返回超出钱包价值、没加进去的部分。</summary>
|
||||
private static double MarkInsider(Wallet acct, PredictPos pos, double payout, Func<string, double> price, out double taint)
|
||||
{
|
||||
taint = 0;
|
||||
if (pos.Insider <= 0 || pos.Shares <= 0 || payout <= 0) return 0;
|
||||
double amount = payout * Math.Min(1, pos.Insider / pos.Shares);
|
||||
double over = acct.AddTaintCapped(amount, price);
|
||||
taint = amount - over;
|
||||
return over;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 夜间:先登记今晚的观测,再结算 ToDay 到了的盘口(赢的钱回到下注的钱包,wallet 按地址找)。outcome 由接入层给出(事件 / 派系读观测,纯度和行情读游戏数值),null 表示拿不到数据。
|
||||
/// 赢家每份兑付 1 信用点;内幕持仓达到份额上限的 <see cref="Tuning.PredictInsiderShare"/> 后,有概率被查:本金和收益全部没收,收益的一半记罪证。
|
||||
/// 赢家每份兑付 1 信用点,照常兑付;内幕份额对应的兑付记污点,行情盘被判操纵时整笔兑付记污点(都带上限,超出钱包价值的部分折成罪证)。
|
||||
/// </summary>
|
||||
public List<PredictEvent> Night(int day, IEnumerable<string> activeNow, Func<PredictMarket, bool?> outcome, Func<string, Wallet> wallet, Rng rng, double push = 0)
|
||||
public List<PredictEvent> Night(int day, IEnumerable<string> activeNow, Func<PredictMarket, bool?> outcome, Func<string, Wallet> wallet, Func<string, double> price, Rng rng, double push = 0)
|
||||
{
|
||||
var now = activeNow.Distinct().ToList();
|
||||
if (Prev != null) Started[day] = now.Where(x => !Prev.Contains(x)).ToList();
|
||||
@@ -243,14 +250,6 @@ namespace Decentralized.Domain
|
||||
if (!Stats.TryGetValue(sk, out var st)) Stats[sk] = st = new PredictStat();
|
||||
st.Count++; st.SumP0 += m.P0; if (res.Value) st.Hits++;
|
||||
var winners = all.Where(x => x.Yes == res.Value).ToList();
|
||||
// 操纵:行情盘上,赢家的方向和玩家推价的方向一致时按推价幅度被查——本金和收益都没收,收益的一半记罪证
|
||||
if (m.Kind == PredictKind.Price && winners.Count > 0 && winners.Any(x => x.Yes ? push > 0 : push < 0) && rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(day))))
|
||||
{
|
||||
double profitM = winners.Sum(x => x.Shares) - cost;
|
||||
evs.Add(new PredictEvent { Kind = "manip", Title = m.Title, Market = m, Amount = cost, Fraud = Math.Min(Tuning.PredictFraudCap, Math.Max(0, profitM) * Tuning.PredictFraudShare) });
|
||||
Record(day, m, m.Outcome, -cost, true);
|
||||
continue;
|
||||
}
|
||||
if (all.Count > 0 && winners.Count == 0)
|
||||
{
|
||||
evs.Add(new PredictEvent { Kind = "lose", Title = m.Title, Market = m, Amount = cost });
|
||||
@@ -259,19 +258,28 @@ namespace Decentralized.Domain
|
||||
else if (winners.Count > 0)
|
||||
{
|
||||
double payout = winners.Sum(x => x.Shares), profit = payout - cost;
|
||||
// 内幕持仓按盘口合计(拆到几个钱包里也一样)
|
||||
if (all.Sum(x => x.Insider) >= Tuning.PredictInsiderShare * m.ShareCap && rng.Chance(Math.Min(1, Tuning.PredictInsiderCatch * StoryMods.Current.Enforce(day))))
|
||||
// 操纵:行情盘上,赢家的方向和玩家推价的方向一致时按推价幅度被查——照常兑付,整笔兑付记污点
|
||||
bool manip = m.Kind == PredictKind.Price && winners.Any(x => x.Yes ? push > 0 : push < 0) && rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(day)));
|
||||
double taint = 0, over = 0;
|
||||
foreach (var pos in winners)
|
||||
{
|
||||
// 查实:本金和收益全部没收
|
||||
evs.Add(new PredictEvent { Kind = "caught", Title = m.Title, Market = m, Amount = payout, Fraud = Math.Min(Tuning.PredictFraudCap, Math.Max(0, profit) * Tuning.PredictFraudShare) });
|
||||
Record(day, m, m.Outcome, -cost, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var pos in winners) Pay(wallet(pos.Wallet), pos, pos.Shares);
|
||||
evs.Add(new PredictEvent { Kind = "win", Title = m.Title, Market = m, Amount = payout });
|
||||
Record(day, m, m.Outcome, profit, true);
|
||||
var w = wallet(pos.Wallet);
|
||||
Pay(w, pos, pos.Shares);
|
||||
if (manip)
|
||||
{
|
||||
double o = w.AddTaintCapped(pos.Shares, price);
|
||||
taint += pos.Shares - o; over += o;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 内幕份额(下单时已经知道答案)对应的兑付记污点,每个钱包各算各的
|
||||
over += MarkInsider(w, pos, pos.Shares, price, out double t);
|
||||
taint += t;
|
||||
}
|
||||
}
|
||||
string kind = manip ? "manip" : taint + over > 1e-9 ? "insider" : "win";
|
||||
evs.Add(new PredictEvent { Kind = kind, Title = m.Title, Market = m, Amount = payout, Taint = taint, Over = over, Fraud = Wallet.OverflowFraud(over) });
|
||||
Record(day, m, m.Outcome, profit, true);
|
||||
}
|
||||
else Record(day, m, m.Outcome, 0, false);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Decentralized.Domain
|
||||
|
||||
// 挖矿
|
||||
public const double PscStartPrice = 100;
|
||||
public const double BlockReward = 100;
|
||||
public const double BlockReward = 1000;
|
||||
public const int HalvingDays = 90;
|
||||
/// <summary>减半对币价的传导:每次减半在区间内随机一个指数,价格锚上移 2^指数 倍(0.15–0.85 即约 +11% 到 +80%)。
|
||||
/// 参考比特币:每次减半后的涨幅差别很大,市场也已部分预期到,所以既不固定也不翻倍。</summary>
|
||||
@@ -20,15 +20,15 @@ namespace Decentralized.Domain
|
||||
public const double HalvingRamp = 0.08;
|
||||
/// <summary>价格锚向目标的逐晚靠拢比例(约 7 天完成大半)。</summary>
|
||||
public const double SupplyAdjust = 0.15;
|
||||
public const double NpcHash0 = 360;
|
||||
public const double NpcHash0 = 3600;
|
||||
public const double NpcKjPerH = 2.4;
|
||||
public const double ElecPrice = 1.5;
|
||||
public const double NpcTargetRatio = 3.5;
|
||||
public const double NpcAdj = 0.05;
|
||||
public const double PoolFee = 0.03;
|
||||
public const int RigPrice = 400, RigKj = 2;
|
||||
/// <summary>矿架上模块百分比的折算系数(原版机器用 2–4),以及各项上限。</summary>
|
||||
public const double ModuleRatio = 4, ModuleHashCap = 0.20, ModuleKjCap = 0.25, ModuleWearCap = 0.30;
|
||||
/// <summary>矿架上模块百分比的折算系数(原版机器用 2–4)。模块效果不设上限,只有防出错的下限:算力、耗电、每日损耗三个乘数各自不低于下面的值。</summary>
|
||||
public const double ModuleRatio = 4, ModuleHashFloor = 0, ModuleKjFloor = 0.2, ModuleWearFloor = 0;
|
||||
public const double DeathBase = 0.001, DeathWorn = 0.03, FakeDeathFactor = 2;
|
||||
public const double RefurbishHealth = 30;
|
||||
|
||||
@@ -244,14 +244,14 @@ namespace Decentralized.Domain
|
||||
public const double EraKjMult = 0.5;
|
||||
|
||||
/// <summary>预测市场:游戏第几天起开放;手续费;单盘额度 = 基础 + 每天增量 × 天数;所有钱包在单盘合计的份额上限(额度的倍数);
|
||||
/// 同时开放的盘口数量范围、每天最多新开几个;内幕持仓达到上限份额的多少比例后结算被查的概率,查实后收益记罪证的比例与上限;
|
||||
/// 同时开放的盘口数量范围、每天最多新开几个;污点超出钱包价值的部分折成诈骗罪证的比例与单次上限(内幕、操纵记污点时通用);
|
||||
/// 派系行动的日均开始概率(先验);先验概率的夹紧范围;结算记录保留条数。</summary>
|
||||
public const int PredictUnlockDay = 8;
|
||||
public const double PredictFee = 0.01, PredictLoss0 = 800, PredictLossPerDay = 25, PredictCap = 2;
|
||||
/// <summary>预测盘的流动性:LMSR 的 b = 倍数 × 单盘额度 / ln 2,与先验无关(低先验盘不再更浅)。单盘额度只决定份额上限和消息价。</summary>
|
||||
public const double PredictDepth = 1.8;
|
||||
public const int PredictOpenMin = 3, PredictOpenMax = 6, PredictNewPerDay = 2;
|
||||
public const double PredictInsiderShare = 0.4, PredictInsiderCatch = 0.7, PredictFraudShare = 0.5, PredictFraudCap = 400;
|
||||
public const double PredictFraudShare = 0.5, PredictFraudCap = 400;
|
||||
public const double PredictFactionDaily = 0.06, PredictPMin = 0.03, PredictPMax = 0.97;
|
||||
public const int PredictHistory = 8;
|
||||
/// <summary>gas 盘的公开价里"不知道相位"的权重:越大,数清七天周期的玩家越赚。金融审查(agy_fin/subsim)发现 0.5 时 gas 盘胜率 96%、每周净赚约 1,400,调到 0.15。</summary>
|
||||
@@ -265,9 +265,8 @@ namespace Decentralized.Domain
|
||||
public static readonly double[] IntelTipPrice = { 0.02, 0.05, 0.12 }, IntelTipAcc = { 0.60, 0.80, 0.95 };
|
||||
public const int IntelRep = 20;
|
||||
/// <summary>操纵检出:玩家自己的大单把价格推离"没有你时的水平"的对数幅度(取绝对值)低于 ManipFree 不查;
|
||||
/// 超过后被查概率 = ManipBase + ManipSlope × (幅度 − ManipFree),封顶 ManipMax;被查后永续账户冻结几天。</summary>
|
||||
/// 超过后被查概率 = ManipBase + ManipSlope × (幅度 − ManipFree),封顶 ManipMax;被查后照常兑付,赚到的钱记污点。</summary>
|
||||
public const double ManipFree = 0.16, ManipBase = 0.25, ManipSlope = 3, ManipMax = 0.95;
|
||||
public const int ManipFreezeDays = 3;
|
||||
|
||||
/// <summary>高息理财(庞氏):第几天起开放、开张的宣传费(CRC)、可选日息、每晚新存入的基数(随天数)和对日息的敏感指数、
|
||||
/// 池子上限(随天数)、每晚被取走的比例、每晚被举报概率(基础 + 日息系数 + 池子占上限的比例系数)、卷走或崩盘时记的罪证。</summary>
|
||||
|
||||
@@ -266,7 +266,6 @@ namespace Decentralized.Domain
|
||||
["LedgerShow"] = Tuning.LedgerShow,
|
||||
["ManipBase"] = Tuning.ManipBase,
|
||||
["ManipFree"] = Tuning.ManipFree,
|
||||
["ManipFreezeDays"] = Tuning.ManipFreezeDays,
|
||||
["ManipMax"] = Tuning.ManipMax,
|
||||
["ManipSlope"] = Tuning.ManipSlope,
|
||||
["MixerCleanRate"] = Tuning.MixerCleanRate,
|
||||
@@ -278,10 +277,10 @@ namespace Decentralized.Domain
|
||||
["MixerSanctionChance"] = Tuning.MixerSanctionChance,
|
||||
["MixerSanctionDays"] = Tuning.MixerSanctionDays,
|
||||
["MixerUnlockPrice"] = Tuning.MixerUnlockPrice,
|
||||
["ModuleHashCap"] = Tuning.ModuleHashCap,
|
||||
["ModuleKjCap"] = Tuning.ModuleKjCap,
|
||||
["ModuleHashFloor"] = Tuning.ModuleHashFloor,
|
||||
["ModuleKjFloor"] = Tuning.ModuleKjFloor,
|
||||
["ModuleRatio"] = Tuning.ModuleRatio,
|
||||
["ModuleWearCap"] = Tuning.ModuleWearCap,
|
||||
["ModuleWearFloor"] = Tuning.ModuleWearFloor,
|
||||
["NpcAdj"] = Tuning.NpcAdj,
|
||||
["NpcHash0"] = Tuning.NpcHash0,
|
||||
["NpcKjPerH"] = Tuning.NpcKjPerH,
|
||||
@@ -342,8 +341,6 @@ namespace Decentralized.Domain
|
||||
["PredictFraudShare"] = Tuning.PredictFraudShare,
|
||||
["PredictGasBlind"] = Tuning.PredictGasBlind,
|
||||
["PredictHistory"] = Tuning.PredictHistory,
|
||||
["PredictInsiderCatch"] = Tuning.PredictInsiderCatch,
|
||||
["PredictInsiderShare"] = Tuning.PredictInsiderShare,
|
||||
["PredictLoss0"] = Tuning.PredictLoss0,
|
||||
["PredictLossPerDay"] = Tuning.PredictLossPerDay,
|
||||
["PredictMoveLog"] = Tuning.PredictMoveLog,
|
||||
|
||||
@@ -118,6 +118,21 @@ namespace Decentralized.Domain
|
||||
|
||||
public double Value(Func<string, double> price) => Balances.Sum(kv => kv.Value * price(kv.Key));
|
||||
|
||||
/// <summary>
|
||||
/// 加污点,加完不超过钱包当时的价值(只在加的这一刻检查,之后币价涨跌不再调整)。
|
||||
/// 返回加不进去的部分(超出额),由调用方按 <see cref="OverflowFraud"/> 折成罪证。
|
||||
/// </summary>
|
||||
public double AddTaintCapped(double amount, Func<string, double> price)
|
||||
{
|
||||
if (amount <= 0) return 0;
|
||||
double add = Math.Min(amount, Math.Max(0, Value(price) - Taint));
|
||||
Taint += add;
|
||||
return amount - add;
|
||||
}
|
||||
|
||||
/// <summary>污点超出钱包价值的部分折成的诈骗罪证:超出额 × <see cref="Tuning.PredictFraudShare"/>,单次封顶 <see cref="Tuning.PredictFraudCap"/>。</summary>
|
||||
public static double OverflowFraud(double overflow) => Math.Min(Tuning.PredictFraudCap, Math.Max(0, overflow) * Tuning.PredictFraudShare);
|
||||
|
||||
/// <summary>
|
||||
/// 转出:taint 和 basis 按转出价值占地址总价值的比例带走;被标记的地址转出可追踪的币,收款地址也被标记。
|
||||
/// Ponero 等不可追踪资产转入时,污点和标记都不随之进入目标地址。
|
||||
|
||||
Reference in new issue
Block a user