diff --git a/src/source/Tetris.cpp b/src/source/Tetris.cpp index a802fe7..6c9832d 100644 --- a/src/source/Tetris.cpp +++ b/src/source/Tetris.cpp @@ -1327,6 +1327,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case 'C': case VK_SHIFT: + case VK_LSHIFT: + case VK_RSHIFT: HoldCurrentPiece(); break; case 'Z': diff --git a/src/source/TetrisRender.cpp b/src/source/TetrisRender.cpp index 184b9d4..bd8e51d 100644 --- a/src/source/TetrisRender.cpp +++ b/src/source/TetrisRender.cpp @@ -702,7 +702,7 @@ void TDrawScreen(HDC hdc, HWND hWnd) _T("连锁火花:消行后追加随机破坏\r\n连环炸弹:爆破扩大为 5x5\r\n雷霆四消:三消/四消额外轰击\r\n雷霆棱镜:三消/四消追加激光"), _T("狂热节拍:累计12行进入狂热\r\n怒火连段:连击越高倍率越高\r\n无尽狂热:狂热中消行延时\r\n高压悬赏:更快但收益更高\r\n豪赌四消 / 极限玩家:偏向四消爆发"), _T("双重抉择:升级可多选1个\r\n命运轮盘:6选2但含诅咒\r\n升级冲击波:升级后清底2行\r\n进化冲击:升级后清底3行\r\n成长核心:永久得分/EXP +15%"), - _T("操控大师:Hold 后减速并预览+1\r\n方块风暴:接下来5个全 I 块\r\n稳定结构:概率填局部小洞\r\n虚空核心:黑洞生成彩虹,彩虹生效追加小黑洞\r\n赌徒契约:强化可能翻倍或落空") + _T("操控大师:Hold 后减速并预览+1\r\n方块风暴:接下来5个全 I 块\r\n稳定结构:概率填局部小洞\r\n虚空核心:黑洞生成彩虹,彩虹生效追加小黑洞\r\n赌徒契约:强化20%翻倍/20%落空,收益波动") }; int columnGap = SS(18); diff --git a/src/source/TetrisRogue.cpp b/src/source/TetrisRogue.cpp index 6a48d44..c50e6fe 100644 --- a/src/source/TetrisRogue.cpp +++ b/src/source/TetrisRogue.cpp @@ -94,7 +94,7 @@ static const UpgradeEntry kUpgradePool[] = { UPGRADE_STABLE_STRUCTURE, -1, 72, true, _T("稳定结构"), _T("特殊"), _T("落地后有小概率填补邻近空洞,让阵型更加稳固。") }, { UPGRADE_DOUBLE_GROWTH, 1, 84, false, _T("成长核心"), _T("成长"), _T("永久获得 +15% 得分与 +15% EXP;每局只能选择一次。") }, { UPGRADE_PIECE_TUNING, -1, 64, true, _T("方块改造"), _T("特殊"), _T("固定提高 I 方块的生成概率。") }, - { UPGRADE_GAMBLER, -1, 64, true, _T("赌徒契约"), _T("特殊"), _T("选择强化时,有概率效果翻倍,也有概率本次落空。") } + { UPGRADE_GAMBLER, -1, 64, true, _T("赌徒契约"), _T("风险"), _T("后续强化 20% 翻倍 / 20% 落空,每级+5%;消行收益随机波动。") } }; static constexpr int kUpgradePoolSize = sizeof(kUpgradePool) / sizeof(kUpgradePool[0]); @@ -116,6 +116,8 @@ static int GetUpgradeBaseRarity(int upgradeId); static int GetUpgradeDynamicWeight(const UpgradeEntry& entry); static const TCHAR* GetPieceShortName(int pieceType); static bool IsUpgradeSelectable(const UpgradeEntry& entry); +static int GetGamblerRollChancePercent(); +static int RollGamblerApplyCount(TCHAR* suffix, int suffixCapacity, bool compactText); static int GetTopOccupiedRow(); static int GetSweeperThreshold(); static bool RollExplosivePiece(); @@ -624,6 +626,58 @@ static bool IsUpgradeSelectable(const UpgradeEntry& entry) return GetUpgradeCurrentLevel(entry.id) < entry.maxLevel; } +/** + * @brief 计算赌徒契约触发翻倍或落空的单边概率。 + */ +static int GetGamblerRollChancePercent() +{ + if (currentMode != MODE_ROGUE || rogueStats.gamblerLevel <= 0) + { + return 0; + } + + int gamblerChance = 20 + (rogueStats.gamblerLevel - 1) * 5; + return gamblerChance > 40 ? 40 : gamblerChance; +} + +/** + * @brief 根据赌徒契约掷骰决定本次强化应用次数。 + */ +static int RollGamblerApplyCount(TCHAR* suffix, int suffixCapacity, bool compactText) +{ + if (suffix != nullptr && suffixCapacity > 0) + { + suffix[0] = _T('\0'); + } + + int gamblerChance = GetGamblerRollChancePercent(); + if (gamblerChance <= 0) + { + return 1; + } + + int roll = rand() % 100; + if (roll < gamblerChance) + { + if (suffix != nullptr && suffixCapacity > 0) + { + _stprintf_s(suffix, suffixCapacity, compactText ? _T("(赌徒翻倍)") : _T(" 赌徒命中:效果翻倍")); + } + return 2; + } + + if (roll >= 100 - gamblerChance) + { + if (suffix != nullptr && suffixCapacity > 0) + { + _stprintf_s(suffix, suffixCapacity, compactText ? _T("(赌徒落空)") : _T(" 赌徒失手:本次落空")); + } + return 0; + } + + return 1; +} + /** * @brief 查找棋盘中最高的已占用行,用于评估局势压力。 */ @@ -1580,6 +1634,7 @@ static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount) break; case UPGRADE_HOLD_UNLOCK: rogueStats.holdUnlocked = 1; + holdUsedThisTurn = false; break; case UPGRADE_PRESSURE_RELIEF: { @@ -2258,29 +2313,8 @@ void ConfirmUpgradeSelection() } UpgradeOption selectedOption = upgradeUiState.options[optionIndex]; - int applyCount = 1; TCHAR gamblerSuffix[64] = _T(""); - - if (currentMode == MODE_ROGUE && rogueStats.gamblerLevel > 0) - { - int gamblerChance = 20 + (rogueStats.gamblerLevel - 1) * 5; - if (gamblerChance > 40) - { - gamblerChance = 40; - } - - int roll = rand() % 100; - if (roll < gamblerChance) - { - applyCount = 2; - _stprintf_s(gamblerSuffix, _T("(翻倍)")); - } - else if (roll >= 100 - gamblerChance) - { - applyCount = 0; - _stprintf_s(gamblerSuffix, _T("(落空)")); - } - } + int applyCount = RollGamblerApplyCount(gamblerSuffix, 64, true); ApplyUpgradeById(selectedOption.id, selectedOption.targetPieceType, applyCount); upgradeUiState.totalChosenCount++; @@ -2336,29 +2370,8 @@ void ConfirmUpgradeSelection() } UpgradeOption selectedOption = upgradeUiState.options[upgradeUiState.selectedIndex]; - int applyCount = 1; TCHAR gamblerSuffix[64] = _T(""); - - if (currentMode == MODE_ROGUE && rogueStats.gamblerLevel > 0) - { - int gamblerChance = 20 + (rogueStats.gamblerLevel - 1) * 5; - if (gamblerChance > 40) - { - gamblerChance = 40; - } - - int roll = rand() % 100; - if (roll < gamblerChance) - { - applyCount = 2; - _stprintf_s(gamblerSuffix, _T(" 赌徒命中:效果翻倍")); - } - else if (roll >= 100 - gamblerChance) - { - applyCount = 0; - _stprintf_s(gamblerSuffix, _T(" 赌徒失手:本次落空")); - } - } + int applyCount = RollGamblerApplyCount(gamblerSuffix, 64, false); ApplyUpgradeById(selectedOption.id, selectedOption.targetPieceType, applyCount); upgradeUiState.totalChosenCount++;