第十一阶段 stage 3:自营混币器

- Domain/OwnMixer:注资开张、NPC 客户存入、按匿名集洗污点出款(和普通混币器同一套抽象,匿名集主要是本金和收入)、手续费收入取回全额带污点、本金带自己的污点;客流按"费率 + 出款剩下的污点"和 Tumbler 比,乘黑市声望;风声累积按概率查封(全部没收、记 FENCING、停业)、便衣存入(记 FENCING)、卷款跑路(全额污点、记 FRAUD、黑市声望下降、永久关闭)
- 灰网页"自营混币器"标签(买下场外换币台就有;TerminalWindow 拆成 partial,页面在 TerminalWindow.OwnMix.cs):状态、费率、口碑、风声、匿名集、各币种本金/收入/客户在途;费率、开张/暂停、注资(账单转账)、取回、卷款跑路(合约签名)
- 夜间结算、日志、报纸新闻;浏览器显示"自营混币器"地址名
- Tuning.OwnMix*(research/mixsim 标定),单元测试,手册与 8 种语言
- 实测:注资 20 PSC 开张,三晚各一笔存入、一次便衣

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Opus 5.5 committed 2026-11-08 16:14:28 +08:00
1 parent 9d95e1f760
commit 71002cbced
17 files changed
+820 -16

No files matched your search

+26
View File
@@ -104,6 +104,31 @@ namespace Decentralized
}
}
/// <summary>自营混币器的夜间:客户存入、出款、便衣、查封。对手是 Tumbler 的混币器(关停或被制裁时不算对手)。</summary>
private static void OwnMixNight(SaveData d, int day, PlayerStore ps)
{
var m = d.OwnMix;
bool rivalOpen = !d.Story.MixerClosed && !d.Mixer.Sanctioned(day);
double rivalRemain = Math.Pow(1 - Mixer.RoundRate(Tuning.OwnMixTicket), Tuning.OwnMixAvgRounds);
var evs = m.Night(day, Session.Price, StoreReputation.GetBMReputation(), Mixer.Fee, rivalRemain, rivalOpen, StoryMods.Current.Sanction(day), ActiveEvents().Contains(MarketEvent.Crackdown), d.Rng);
foreach (var e in evs)
{
if (e.Kind == "deposit") ps.AddNightLog(L.T("nightlog.ownmix.in", e.Count, Fmt.Credits(e.Value), Fmt.Credits(e.Value * m.Fee)));
else if (e.Kind == "sting")
{
ps.secData.CommitCrime("FENCING", (int)Math.Round(e.Crime));
ps.AddNightLog(L.T("nightlog.ownmix.sting"), "cc7755");
}
else if (e.Kind == "seized")
{
ps.secData.CommitCrime("FENCING", (int)Math.Round(e.Crime));
ps.AddNightLog(L.T("nightlog.ownmix.seized", Fmt.Credits(e.Value)), "cc7755");
News.Show("pd_news_ownmix_seized_" + day, L.T("news.ownmix.seized.title"), L.T("news.ownmix.seized.desc"), 4, 8);
}
Log.Info($"自营混币器 {e.Kind}:{e.Value:0}({e.Count} 笔),比例 {e.Ratio:0.00},罪证 {e.Crime:0},口碑 {m.Rating:0.00},风声 {m.Heat:0.00}");
}
}
private static void OnSleepEarly()
{
Session.TonightCards.Clear();
@@ -276,6 +301,7 @@ namespace Decentralized
var ps = PlayerStore.Instance;
if (mined > 0) ps.AddNightLog(L.T("nightlog.mined", Fmt.Num(mined)));
if (Unlock.OtcUnlocked) OwnMixNight(d, day, ps);
var mixBefore = d.SnapshotAll();
var mixed = d.Mixer.Night(d.WalletAt, day, Session.Price, d.Rng);
d.ChainDiffAll(mixBefore, d.Address("mixer"));