mirror of
https://github.com/AHA705/Monopoly-Poker-Helper.git
synced 2026-10-07 22:56:34 +01:00
Initial commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BepInExDir>C:\Program Files (x86)\Steam\steamapps\common\Monopoly Poker\BepInEx\core</BepInExDir>
|
||||
<InteropDir>C:\Program Files (x86)\Steam\steamapps\common\Monopoly Poker\BepInEx\interop</InteropDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- BepInEx 6 core + Unity interop references -->
|
||||
<ItemGroup>
|
||||
<Reference Include="BepInEx.Core">
|
||||
<HintPath>$(BepInExDir)\BepInEx.Core.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="BepInEx.Unity.IL2CPP">
|
||||
<HintPath>$(BepInExDir)\BepInEx.Unity.IL2CPP.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>$(BepInExDir)\0Harmony.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppInterop.Runtime">
|
||||
<HintPath>$(BepInExDir)\Il2CppInterop.Runtime.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>$(InteropDir)\UnityEngine.CoreModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>$(InteropDir)\Assembly-CSharp.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2Cppmscorlib">
|
||||
<HintPath>$(InteropDir)\Il2Cppmscorlib.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Il2CppSystem.Core">
|
||||
<HintPath>$(InteropDir)\Il2CppSystem.Core.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,216 @@
|
||||
using BepInEx;
|
||||
using BepInEx.Unity.IL2CPP;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AutoBlackjack;
|
||||
|
||||
/// <summary>
|
||||
/// Manages JSON database for tracking blackjack statistics.
|
||||
/// Tracks: bet amount, date/time, chip balance, and round outcome.
|
||||
///
|
||||
/// Logger doesnt work
|
||||
/// </summary>
|
||||
public class BlackjackStatsJsonDatabase : IDisposable
|
||||
{
|
||||
private readonly string _jsonPath;
|
||||
private List<BlackjackRoundRecord> _records;
|
||||
private bool _disposed;
|
||||
|
||||
public BlackjackStatsJsonDatabase(string jsonPath)
|
||||
{
|
||||
_jsonPath = jsonPath;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Ensure directory exists
|
||||
string directory = Path.GetDirectoryName(_jsonPath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// Load existing records or create new list
|
||||
if (File.Exists(_jsonPath))
|
||||
{
|
||||
string jsonContent = File.ReadAllText(_jsonPath);
|
||||
_records = JsonSerializer.Deserialize<List<BlackjackRoundRecord>>(jsonContent)
|
||||
?? new List<BlackjackRoundRecord>();
|
||||
//Log.LogInfo($"Loaded {_records.Count} records from JSON database");
|
||||
}
|
||||
else
|
||||
{
|
||||
_records = new List<BlackjackRoundRecord>();
|
||||
SaveToFile();
|
||||
//Log.LogInfo($"Created new JSON database at: {_jsonPath}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Log.Error($"Failed to initialize JSON database: {ex}");
|
||||
_records = new List<BlackjackRoundRecord>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a blackjack round with statistics.
|
||||
/// </summary>
|
||||
public void LogRound(long betAmount, long chipBalance, string outcome = null,
|
||||
int playerTotal = 0, int dealerUpcard = 0, string action = null, long profit = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var record = new BlackjackRoundRecord
|
||||
{
|
||||
Id = _records.Count > 0 ? _records[^1].Id + 1 : 1,
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
BetAmount = betAmount,
|
||||
ChipBalance = chipBalance,
|
||||
Outcome = outcome ?? "",
|
||||
PlayerTotal = playerTotal,
|
||||
DealerUpcard = dealerUpcard,
|
||||
Action = action ?? "",
|
||||
Profit = profit
|
||||
};
|
||||
|
||||
_records.Add(record);
|
||||
SaveToFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Log.Error($"Failed to log round to JSON database: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save records to JSON file.
|
||||
/// </summary>
|
||||
private void SaveToFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
string jsonContent = JsonSerializer.Serialize(_records, options);
|
||||
File.WriteAllText(_jsonPath, jsonContent);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Log.Error($"Failed to save JSON database: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get total number of rounds played.
|
||||
/// </summary>
|
||||
public long GetTotalRounds()
|
||||
{
|
||||
return _records?.Count ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get total profit/loss across all rounds.
|
||||
/// </summary>
|
||||
public long GetTotalProfit()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_records == null || _records.Count == 0)
|
||||
return 0;
|
||||
|
||||
long total = 0;
|
||||
foreach (var record in _records)
|
||||
{
|
||||
total += record.Profit;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Log.Error($"Failed to get total profit: {ex}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get statistics summary.
|
||||
/// </summary>
|
||||
public void LogStatsSummary()
|
||||
{
|
||||
try
|
||||
{
|
||||
long totalRounds = GetTotalRounds();
|
||||
long totalProfit = GetTotalProfit();
|
||||
|
||||
//Log.Info("=== Blackjack Stats Summary (JSON) ===");
|
||||
//Log.Info($"Total Rounds: {totalRounds}");
|
||||
//Log.Info($"Total Profit: {totalProfit:+#;-#;0} chips");
|
||||
//if (totalRounds > 0)
|
||||
//Log.Info($"Average Profit per Round: {(double)totalProfit / totalRounds:F2} chips");
|
||||
//Log.Info("=======================================");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Log.Error($"Failed to log stats summary: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
try
|
||||
{
|
||||
SaveToFile();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Log.Error($"Error disposing JSON database: {ex}");
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single blackjack round record.
|
||||
/// </summary>
|
||||
public class BlackjackRoundRecord
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("date")]
|
||||
public string Date { get; set; }
|
||||
|
||||
[JsonPropertyName("betAmount")]
|
||||
public long BetAmount { get; set; }
|
||||
|
||||
[JsonPropertyName("chipBalance")]
|
||||
public long ChipBalance { get; set; }
|
||||
|
||||
[JsonPropertyName("outcome")]
|
||||
public string Outcome { get; set; }
|
||||
|
||||
[JsonPropertyName("playerTotal")]
|
||||
public int PlayerTotal { get; set; }
|
||||
|
||||
[JsonPropertyName("dealerUpcard")]
|
||||
public int DealerUpcard { get; set; }
|
||||
|
||||
[JsonPropertyName("action")]
|
||||
public string Action { get; set; }
|
||||
|
||||
[JsonPropertyName("profit")]
|
||||
public long Profit { get; set; }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
Strategy:
|
||||
|
||||
Bet sizing (Hi-Lo count-based):
|
||||
True Count ≤ 1: minimum bet
|
||||
True Count 2: 2× minimum
|
||||
True Count 3: 4× minimum
|
||||
True Count 4: 6× minimum
|
||||
True Count ≥ 5: maximum bet
|
||||
|
||||
Card Counting (Hi-Lo):
|
||||
Cards 2-6: +1
|
||||
Cards 7-9: 0
|
||||
Cards 10, J, Q, K, A: -1
|
||||
True Count = Running Count / Estimated Decks Remaining
|
||||
Assumes 6-deck shoe. Running count persists across rounds.
|
||||
All visible cards (all players + dealer) are scanned at decision time.
|
||||
Dealer reveal is also counted (Hook 4) for next-round accuracy.
|
||||
|
||||
Illustrious 18 Deviations (applied when True Count thresholds met):
|
||||
16 vs 10: STAND when TC ≥ 0 (basic says HIT)
|
||||
16 vs 9: STAND when TC ≥ 5 (basic says HIT)
|
||||
15 vs 10: STAND when TC ≥ 4 (basic says HIT)
|
||||
12 vs 3: STAND when TC ≥ 2 (basic says HIT)
|
||||
12 vs 2: STAND when TC ≥ 3 (basic says HIT)
|
||||
10 vs 10: DOUBLE when TC ≥ 4 (basic says HIT)
|
||||
10 vs A: DOUBLE when TC ≥ 4 (basic says HIT)
|
||||
9 vs 2: DOUBLE when TC ≥ 1 (basic says HIT)
|
||||
9 vs 7: DOUBLE when TC ≥ 3 (basic says HIT)
|
||||
|
||||
Soft totals: A soft total is any hand that has an Ace as one of the first two cards, the ace counts as 11 to start.
|
||||
|
||||
Soft 20 (A,9) always stands.
|
||||
Soft 19 (A,8) doubles against dealer 6, otherwise stand.
|
||||
Soft 18 (A,7) doubles against dealer 2 through 6, and hits against 9 through Ace, otherwise stand.
|
||||
Soft 17 (A,6) doubles against dealer 3 through 6, otherwise hit.
|
||||
Soft 16 (A,5) doubles against dealer 4 through 6, otherwise hit.
|
||||
Soft 15 (A,4) doubles against dealer 4 through 6, otherwise hit.
|
||||
Soft 14 (A,3) doubles against dealer 5 through 6, otherwise hit.
|
||||
Soft 13 (A,2) doubles against dealer 5 through 6, otherwise hit.
|
||||
|
||||
Hard totals: A hard total is any hand that does not start with an ace in it, or it has been dealt an ace that can only be counted as 1 instead of 11.
|
||||
|
||||
17 and up always stands.
|
||||
16 stands against dealer 2 through 6, otherwise hit.
|
||||
15 stands against dealer 2 through 6, otherwise hit.
|
||||
14 stands against dealer 2 through 6, otherwise hit.
|
||||
13 stands against dealer 2 through 6, otherwise hit.
|
||||
12 stands against dealer 4 through 6, otherwise hit.
|
||||
11 always doubles.
|
||||
10 doubles against dealer 2 through 9 otherwise hit.
|
||||
9 doubles against dealer 3 through 6 otherwise hit.
|
||||
8 always hits.
|
||||
|
||||
Splits:
|
||||
Aces : always split
|
||||
10 : always stand
|
||||
9 : split vs dealer 2-9 except 7, else stand
|
||||
8 : always split
|
||||
7 : split vs dealer 2-7, else hit
|
||||
6 : split vs dealer 2-6, else hit
|
||||
5 : double vs dealer 2-9, else hit
|
||||
4 : split vs dealer 5-6, else hit
|
||||
1-3 : split vs dealer 2-7, else hit
|
||||
Reference in New Issue
Block a user