升级改为四选一并重做赌徒与方块改造机制

This commit is contained in:
2026-04-25 12:19:37 +08:00
parent 4bcc62f01a
commit 332573a28c
6 changed files with 1349 additions and 102 deletions
+160 -70
View File
@@ -38,7 +38,7 @@ enum UpgradeId
UPGRADE_EXPLOSIVE_PIECE = 9,
UPGRADE_STABLE_STRUCTURE = 10,
UPGRADE_DOUBLE_GROWTH = 11,
UPGRADE_LUCKY_ROLL = 12,
UPGRADE_PIECE_TUNING = 12,
UPGRADE_GAMBLER = 13
};
@@ -56,8 +56,8 @@ static const UpgradeEntry kUpgradePool[] =
{ UPGRADE_EXPLOSIVE_PIECE, -1, true, _T("\u7206\u7834\u65b9\u5757"), _T("\u7279\u6b8a"), _T("\u63d0\u9ad8\u7206\u7834\u65b9\u5757\u51fa\u73b0\u6982\u7387\uff0c\u843d\u5730\u65f6\u89e6\u53d1 3x3 \u6e05\u9664\u3002") },
{ UPGRADE_STABLE_STRUCTURE, -1, true, _T("\u7a33\u5b9a\u7ed3\u6784"), _T("\u7279\u6b8a"), _T("\u843d\u5730\u540e\u5c0f\u6982\u7387\u81ea\u52a8\u586b\u8865\u90bb\u8fd1\u7a7a\u6d1e\uff0c\u63d0\u9ad8\u76d8\u9762\u7ed3\u6784\u7a33\u5b9a\u6027\u3002") },
{ UPGRADE_DOUBLE_GROWTH, -1, true, _T("\u53cc\u500d\u6210\u957f"), _T("\u7279\u6b8a"), _T("\u989d\u5916\u63d0\u9ad8\u6d88\u884c\u5f97\u5206\u4e0e EXP \u6536\u76ca\uff0c\u6bcf\u5c42\u518d\u8ffd\u52a0 15%\u3002") },
{ UPGRADE_LUCKY_ROLL, -1, true, _T("\u65b9\u5757\u6539\u8fd0"), _T("\u7279\u6b8a"), _T("\u4f18\u5316 Next \u961f\u5217\uff0c\u964d\u4f4e\u8fde\u7eed\u91cd\u590d\u65b9\u5757\u51fa\u73b0\u7684\u6982\u7387\u3002") },
{ UPGRADE_GAMBLER, -1, true, _T("\u8d4c\u5f92"), _T("\u7279\u6b8a"), _T("\u6d88\u884c\u6536\u76ca\u4f1a\u989d\u5916\u968f\u673a\u6ce2\u52a8\uff0c\u5c42\u6570\u8d8a\u9ad8\u6ce2\u52a8\u8d8a\u5927\u3002") }
{ UPGRADE_PIECE_TUNING, -1, true, _T("\u65b9\u5757\u6539\u9020"), _T("\u7279\u6b8a"), _T("\u9009\u62e9\u4e00\u79cd\u65b9\u5757\uff0c\u964d\u4f4e\u5176\u540e\u7eed\u51fa\u73b0\u6982\u7387\u3002") },
{ UPGRADE_GAMBLER, -1, true, _T("\u8d4c\u5f92"), _T("\u7279\u6b8a"), _T("\u9009\u62e9\u5f3a\u5316\u65f6\uff0c\u6709\u6982\u7387\u53cc\u500d\u751f\u6548\uff0c\u4e5f\u6709\u6982\u7387\u5b8c\u5168\u843d\u7a7a\u3002") }
};
static constexpr int kUpgradePoolSize = sizeof(kUpgradePool) / sizeof(kUpgradePool[0]);
@@ -215,8 +215,11 @@ static void ResetPlayerStats(PlayerStats& stats, bool useRogueRules)
stats.explosiveLevel = 0;
stats.stableStructureLevel = 0;
stats.doubleGrowthLevel = 0;
stats.luckyRollLevel = 0;
stats.gamblerLevel = 0;
for (int i = 0; i < 7; i++)
{
stats.pieceTuningLevels[i] = 0;
}
}
static int GetNextPreviewLimit()
@@ -267,8 +270,6 @@ static int GetUpgradeCurrentLevel(int upgradeId)
return rogueStats.stableStructureLevel;
case UPGRADE_DOUBLE_GROWTH:
return rogueStats.doubleGrowthLevel;
case UPGRADE_LUCKY_ROLL:
return rogueStats.luckyRollLevel;
case UPGRADE_GAMBLER:
return rogueStats.gamblerLevel;
default:
@@ -276,6 +277,27 @@ static int GetUpgradeCurrentLevel(int upgradeId)
}
}
static const TCHAR* GetPieceShortName(int pieceType)
{
static const TCHAR* kPieceNames[7] =
{
_T("I"),
_T("T"),
_T("L"),
_T("J"),
_T("O"),
_T("S"),
_T("Z")
};
if (pieceType < 0 || pieceType >= 7)
{
return _T("?");
}
return kPieceNames[pieceType];
}
static bool IsUpgradeSelectable(const UpgradeEntry& entry)
{
if (entry.repeatable)
@@ -390,42 +412,37 @@ static int ClearExplosiveAreaAt(int centerY, int centerX)
static int RollNextPieceType()
{
int candidate = rand() % 7;
int weights[7] = { 100, 100, 100, 100, 100, 100, 100 };
if (currentMode != MODE_ROGUE || rogueStats.luckyRollLevel <= 0)
if (currentMode == MODE_ROGUE)
{
return candidate;
}
int rerollCount = rogueStats.luckyRollLevel;
if (rerollCount > 3)
{
rerollCount = 3;
}
for (int attempt = 0; attempt < rerollCount; attempt++)
{
bool matchesCurrent = (candidate == type);
bool matchesQueue = false;
for (int i = 0; i < 3; i++)
for (int i = 0; i < 7; i++)
{
if (nextTypes[i] == candidate)
weights[i] -= rogueStats.pieceTuningLevels[i] * 20;
if (weights[i] < 20)
{
matchesQueue = true;
break;
weights[i] = 20;
}
}
if (!matchesCurrent && !matchesQueue)
{
break;
}
candidate = rand() % 7;
}
return candidate;
int totalWeight = 0;
for (int i = 0; i < 7; i++)
{
totalWeight += weights[i];
}
int roll = rand() % totalWeight;
for (int i = 0; i < 7; i++)
{
if (roll < weights[i])
{
return i;
}
roll -= weights[i];
}
return rand() % 7;
}
static int TryStabilizeBoard()
@@ -544,7 +561,7 @@ static void FillUpgradeOptions()
}
}
int optionCount = selectableCount < 3 ? selectableCount : 3;
int optionCount = selectableCount < 4 ? selectableCount : 4;
upgradeUiState.optionCount = optionCount;
upgradeUiState.selectedIndex = 0;
@@ -556,10 +573,45 @@ static void FillUpgradeOptions()
upgradeUiState.options[i].id = pickedEntry.id;
upgradeUiState.options[i].currentLevel = GetUpgradeCurrentLevel(pickedEntry.id);
upgradeUiState.options[i].targetPieceType = -1;
upgradeUiState.options[i].name = pickedEntry.name;
upgradeUiState.options[i].category = pickedEntry.category;
upgradeUiState.options[i].description = pickedEntry.description;
if (pickedEntry.id == UPGRADE_PIECE_TUNING)
{
int targetPieceType = rand() % 7;
bool duplicatedPiece = true;
int guard = 0;
while (duplicatedPiece && guard < 16)
{
duplicatedPiece = false;
for (int optionIndex = 0; optionIndex < i; optionIndex++)
{
if (upgradeUiState.options[optionIndex].id == UPGRADE_PIECE_TUNING &&
upgradeUiState.options[optionIndex].targetPieceType == targetPieceType)
{
duplicatedPiece = true;
targetPieceType = (targetPieceType + 1) % 7;
break;
}
}
guard++;
}
upgradeUiState.options[i].targetPieceType = targetPieceType;
upgradeUiState.options[i].currentLevel = rogueStats.pieceTuningLevels[targetPieceType];
upgradeUiState.options[i].name = _T("\u65b9\u5757\u6539\u9020");
static TCHAR tuningDescriptions[4][64];
_stprintf_s(
tuningDescriptions[i],
_T("\u964d\u4f4e %s \u65b9\u5757\u7684\u51fa\u73b0\u6982\u7387\u3002"),
GetPieceShortName(targetPieceType));
upgradeUiState.options[i].description = tuningDescriptions[i];
}
selectableIndexes[pickSlot] = selectableIndexes[selectableCount - 1];
selectableCount--;
}
@@ -570,77 +622,80 @@ static int GetRogueFallInterval()
return 500 + rogueStats.slowFallStacks * 80;
}
static void ApplyUpgradeById(int upgradeId)
static void ApplyUpgradeById(int upgradeId, int targetPieceType, int applyCount)
{
if (applyCount <= 0)
{
return;
}
switch (upgradeId)
{
case UPGRADE_SCORE_MULTIPLIER:
rogueStats.scoreMultiplierPercent += 20;
rogueStats.scoreUpgradeLevel++;
rogueStats.scoreMultiplierPercent += 20 * applyCount;
rogueStats.scoreUpgradeLevel += applyCount;
break;
case UPGRADE_COMBO_BONUS:
rogueStats.comboBonusStacks++;
rogueStats.comboBonusStacks += applyCount;
break;
case UPGRADE_EXP_MULTIPLIER:
rogueStats.expMultiplierPercent += 25;
rogueStats.expUpgradeLevel++;
rogueStats.expMultiplierPercent += 25 * applyCount;
rogueStats.expUpgradeLevel += applyCount;
break;
case UPGRADE_SLOW_FALL:
rogueStats.slowFallStacks++;
rogueStats.slowFallStacks += applyCount;
currentFallInterval = GetRogueFallInterval();
break;
case UPGRADE_PREVIEW_PLUS_ONE:
if (rogueStats.previewCount < 3)
for (int i = 0; i < applyCount; i++)
{
rogueStats.previewCount++;
if (rogueStats.previewCount < 3)
{
rogueStats.previewCount++;
}
}
rogueStats.previewUpgradeLevel = rogueStats.previewCount - 1;
break;
case UPGRADE_LAST_CHANCE:
rogueStats.lastChanceCount = 1;
rogueStats.lastChanceUpgradeLevel = 1;
rogueStats.lastChanceCount += applyCount;
rogueStats.lastChanceUpgradeLevel += applyCount;
break;
case UPGRADE_HOLD_UNLOCK:
rogueStats.holdUnlocked = 1;
break;
case UPGRADE_PRESSURE_RELIEF:
{
rogueStats.pressureReliefLevel++;
int topOccupiedRow = GetTopOccupiedRow();
if (topOccupiedRow >= 0)
rogueStats.pressureReliefLevel += applyCount;
for (int i = 0; i < applyCount; i++)
{
DeleteOneLine(topOccupiedRow);
SetFeedbackMessage(_T("\u51cf\u538b\u751f\u6548"), _T("\u5df2\u7acb\u5373\u6e05\u9664\u5f53\u524d\u6700\u9ad8\u5360\u7528\u884c\u3002"), 12);
}
else
{
SetFeedbackMessage(_T("\u51cf\u538b\u751f\u6548"), _T("\u5f53\u524d\u76d8\u9762\u8fd8\u5f88\u7a7a\uff0c\u672c\u6b21\u6ca1\u6709\u989d\u5916\u6e05\u9664\u884c\u3002"), 12);
int topOccupiedRow = GetTopOccupiedRow();
if (topOccupiedRow >= 0)
{
DeleteOneLine(topOccupiedRow);
}
}
break;
}
case UPGRADE_SWEEPER:
rogueStats.sweeperLevel++;
SetFeedbackMessage(_T("\u6e05\u626b\u8005\u5df2\u52a0\u5165"), _T("\u7d2f\u8ba1\u6d88\u884c\u540e\u5c06\u81ea\u52a8\u6e05\u7406\u5e95\u90e8\u79ef\u538b\u3002"), 12);
rogueStats.sweeperLevel += applyCount;
break;
case UPGRADE_EXPLOSIVE_PIECE:
rogueStats.explosiveLevel++;
SetFeedbackMessage(_T("\u7206\u7834\u65b9\u5757\u5df2\u5f3a\u5316"), _T("\u540e\u7eed\u5c06\u6709\u66f4\u9ad8\u6982\u7387\u51fa\u73b0\u7206\u7834\u65b9\u5757\u3002"), 12);
rogueStats.explosiveLevel += applyCount;
break;
case UPGRADE_STABLE_STRUCTURE:
rogueStats.stableStructureLevel++;
SetFeedbackMessage(_T("\u7a33\u5b9a\u7ed3\u6784\u5df2\u5f3a\u5316"), _T("\u540e\u7eed\u843d\u5730\u7ed3\u7b97\u65f6\u5c06\u6709\u6982\u7387\u81ea\u52a8\u8865\u6d1e\u3002"), 12);
rogueStats.stableStructureLevel += applyCount;
break;
case UPGRADE_DOUBLE_GROWTH:
rogueStats.doubleGrowthLevel++;
SetFeedbackMessage(_T("\u53cc\u500d\u6210\u957f\u5df2\u53e0\u52a0"), _T("\u540e\u7eed\u6d88\u884c\u7684\u5f97\u5206\u548c EXP \u6536\u76ca\u4f1a\u66f4\u9ad8\u3002"), 12);
rogueStats.doubleGrowthLevel += applyCount;
break;
case UPGRADE_LUCKY_ROLL:
rogueStats.luckyRollLevel++;
SetFeedbackMessage(_T("\u65b9\u5757\u6539\u8fd0\u5df2\u5f3a\u5316"), _T("Next \u961f\u5217\u4f1a\u66f4\u5c11\u51fa\u73b0\u8fde\u7eed\u91cd\u590d\u5757\u578b\u3002"), 12);
case UPGRADE_PIECE_TUNING:
if (targetPieceType >= 0 && targetPieceType < 7)
{
rogueStats.pieceTuningLevels[targetPieceType] += applyCount;
}
break;
case UPGRADE_GAMBLER:
rogueStats.gamblerLevel++;
SetFeedbackMessage(_T("\u8d4c\u5f92\u5df2\u53e0\u52a0"), _T("\u540e\u7eed\u6d88\u884c\u7684\u5206\u6570\u548c EXP \u4f1a\u989d\u5916\u968f\u673a\u6ce2\u52a8\u3002"), 12);
rogueStats.gamblerLevel += applyCount;
break;
default:
break;
@@ -1272,12 +1327,47 @@ void ConfirmUpgradeSelection()
}
UpgradeOption selectedOption = upgradeUiState.options[upgradeUiState.selectedIndex];
ApplyUpgradeById(selectedOption.id);
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(" \u8d4c\u5f92\uff1a\u53cc\u500d"));
}
else if (roll >= 100 - gamblerChance)
{
applyCount = 0;
_stprintf_s(gamblerSuffix, _T(" \u8d4c\u5f92\uff1a\u843d\u7a7a"));
}
}
ApplyUpgradeById(selectedOption.id, selectedOption.targetPieceType, applyCount);
upgradeUiState.totalChosenCount++;
TCHAR feedbackTitle[64];
TCHAR feedbackDetail[128];
_stprintf_s(feedbackTitle, _T("\u5df2\u83b7\u5f97\uff1a%s"), selectedOption.name);
_stprintf_s(feedbackDetail, _T("%s"), selectedOption.description);
if (selectedOption.id == UPGRADE_PIECE_TUNING && selectedOption.targetPieceType >= 0)
{
_stprintf_s(
feedbackDetail,
_T("\u964d\u4f4e %s \u65b9\u5757\u51fa\u73b0\u6982\u7387%s"),
GetPieceShortName(selectedOption.targetPieceType),
gamblerSuffix);
}
else
{
_stprintf_s(feedbackDetail, _T("%s%s"), selectedOption.description, gamblerSuffix);
}
SetFeedbackMessage(feedbackTitle, feedbackDetail, 12);
if (upgradeUiState.pendingCount > 0)