You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
GoToJailTile menggunakan (uses) JailTile::sendToJail().
2. Deskripsi Kelas
2.1. Kelas GameUI
GameUI adalah pintu masuk utama seluruh interaksi antara pemain manusia dan sistem permainan. Kelas ini bertanggung jawab untuk tampilan menu awal, pengambilan input perintah dari pemain pada setiap giliran, dan penyampaian pesan hasil aksi kembali ke layar. GameUI tidak boleh menyentuh logika permainan sama sekali, hanya meneruskan input ke GameEngine melalui processCommand() dan menampilkan hasilnya. Dengan demikian, seluruh logika di Core Layer bebas dari kode I/O. GameUI memiliki CommandParser untuk mengubah string mentah menjadi Command terstruktur, dan BoardRenderer untuk menampilkan papan.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
CommandParser
parser
Parser yang mengubah input string mentah menjadi objek Command
-
BoardRenderer
renderer
Renderer yang menangani tampilan papan permainan di terminal
-
GameEngine*
engine
Pointer ke GameEngine sebagai pusat logika permainan
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
showMainMenu()
Menampilkan menu utama: pilihan New Game atau Load Game
+
void
showTurnMenu(const Player& p)
Menampilkan menu giliran: daftar perintah yang tersedia untuk pemain aktif
+
std::string
promptCommand()
Meminta input perintah dari pemain dan mengembalikan string mentah
+
void
showMessage(const std::string& msg)
Menampilkan pesan hasil aksi atau notifikasi ke layar
+
void
run()
Loop utama UI: terus meminta input dan meneruskan ke GameEngine hingga game selesai
-
void
displayWelcome()
Menampilkan layar sambutan saat program pertama kali dijalankan
Relasi dengan Kelas Lain
has-aCommandParser : untuk parsing input perintah pemain
has-aBoardRenderer : untuk render tampilan papan ke layar
usesGameEngine : meneruskan Command hasil parsing ke processCommand()
2.2. Kelas CommandParser
CommandParser mengurai (parse) string input mentah yang diketik pemain menjadi objek Command yang terstruktur dan mudah diproses GameEngine. Pemisahan parser ke kelas tersendiri memastikan GameUI tidak perlu mengurus logika string manipulation dan GameEngine tidak perlu mengurus format raw input. Method parse() mengidentifikasi CommandType dari kata pertama input (misalnya 'LEMPAR_DADU' → CommandType::ROLL_DICE) dan mengekstrak sisa kata sebagai argumen ke vector<string>. Validasi format awal dilakukan di sini, sedangkan validasi semantik (misalnya kode properti valid atau tidak) tetap dilakukan di layer Core.
Method
Visibilitas
Tipe
Nama
Keterangan
+
Command
parse(const std::string& raw)
Mengurai string input mentah menjadi objek Command berisi type dan args
-
CommandType
resolveType(const std::string& token)
Memetakan string perintah ke nilai enum CommandType yang sesuai
-
std::vector<std::string>
tokenize(const std::string& raw)
Memecah string input berdasarkan spasi menjadi token-token kata
Relasi dengan Kelas Lain
producesCommand : hasil parsing dikembalikan sebagai objek Command
digunakan olehGameUI : dipanggil setiap kali pemain mengetik perintah
2.3. Kelas BoardRenderer
BoardRenderer adalah kelas khusus yang bertanggung jawab merender papan permainan ke layar terminal dalam format ASCII dengan warna ANSI. Ia menerima referensi ke Board (untuk mendapatkan semua tile dan posisinya) serta vector<Player> (untuk mengetahui posisi semua bidak dan kepemilikan properti). Kelas ini menangani seluruh detail visual: kode warna per kategori tile, simbol bangunan (^/*/H), indikator bidak pemain (angka dalam kurung), status penjara, legenda, dan indikator turn. Dengan memisahkan renderer ke kelas tersendiri, kelas Board bebas dari tanggung jawab tampilan.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
cellWidth
Lebar satu sel papan dalam karakter (default: 10)
-
int
sideLength
Jumlah sel per sisi papan (default: 11 untuk papan 40 petak)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
render(const Board& b, const std::vector<Player>& ps, int turn, int maxTurn)
Merender seluruh papan permainan beserta semua informasi status ke layar
Menghasilkan string token pemain yang berada di tile tersebut
Relasi dengan Kelas Lain
usesBoard : membaca tile untuk membangun tampilan papan
usesvector<Player> : membaca posisi dan data pemain untuk tampilan bidak
digunakan olehGameUI : dipanggil saat perintah CETAK_PAPAN
2.4. Kelas GameEngine
GameEngine adalah pusat orkestrasi permainan yang mengelola alur besar. Class tidak menangani detail bisnis secara langsung, melainkan mendelegasikan ke manager yang tepat. GameEngine menyimpan state global (board, players, turn), menggunakan TurnManager untuk mengatur urutan giliran, memanggil handleLanding() yang mendispatch ke PropertyManager/CardManager/BankruptcyManager bergantung tile yang diinjak, dan mencatat setiap aksi ke TransactionLogger. GameEngine menjadi titik temu antara UI Layer (menerima Command) dan semua manager di Core Layer.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
Board
board
Papan permainan berisi semua tile
-
std::vector<Player>
players
Daftar seluruh pemain aktif dan bangkrut
-
TurnManager
turnManager
Mengelola urutan dan nomor giliran
-
Bank
bank
Entitas bank untuk transaksi ke/dari bank
-
Dice
dice
Dadu untuk pergerakan pemain
-
AuctionManager
auctionManager
Menjalankan mekanisme lelang properti
-
BankruptcyManager
bankruptcyManager
Menangani proses kebangkrutan
-
PropertyManager
propertyManager
Mengelola logika kepemilikan dan bangunan properti
-
CardManager
cardManager
Mengelola semua deck dan penggunaan kartu
-
EffectManager
effectManager
Mengelola efek sementara lintas giliran
-
TransactionLogger
logger
Mencatat semua kejadian signifikan permainan
-
bool
gameOver
Flag penanda permainan telah berakhir
-
int
maxTurn
Batas maksimum giliran dari konfigurasi (0 = mode bankruptcy only)
-
int
goSalary
Gaji yang didapat pemain saat melewati/berhenti di GO
dikonfigurasi olehConfigLoader : saat inisialisasi
diakses olehSaveLoadManager : untuk simpan/muat state
2.5. Kelas TurnManager
TurnManager memisahkan logika pengaturan giliran dari GameEngine agar tanggung jawab lebih bersih dan terfokus. Ia menyimpan urutan giliran (turnOrder) yang ditentukan secara acak saat awal permainan, melacak index pemain aktif (currentIndex), dan menghitung nomor turn global (currentTurnNumber). Method grantExtraTurn() dipanggil saat pemain melempar double agar giliran tidak berpindah. GameEngine hanya perlu bertanya siapa yang bermain sekarang dan berikutnya tanpa mengelola detail urutan sendiri. TurnManager juga bertanggung jawab mengecualikan pemain yang sudah bangkrut dari urutan giliran.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::vector<int>
turnOrder
Urutan index pemain yang bermain (hasil pengacakan awal)
-
int
currentIndex
Index di dalam turnOrder yang menunjuk pemain aktif saat ini
-
int
currentTurnNumber
Nomor turn saat ini (bertambah setelah semua pemain selesai satu putaran)
-
bool
extraTurnGranted
Flag bahwa giliran tambahan (karena double) telah diberikan
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
initializeOrder(int nPlayers)
Mengacak urutan giliran untuk sejumlah nPlayers pemain
+
int
getCurrentPlayerIndex()
Mengembalikan index pemain (dalam vector players di GameEngine) yang sedang giliran
+
void
nextPlayer()
Berpindah ke pemain berikutnya dalam turnOrder, melewati pemain bangkrut
+
void
grantExtraTurn()
Memberikan giliran tambahan kepada pemain saat ini (tidak berpindah ke berikutnya)
+
int
getTurnNumber()
Mengembalikan nomor turn saat ini
+
void
removePlayer(int playerIndex)
Menghapus pemain yang bangkrut dari urutan giliran
+
void
resetExtraTurn()
Mereset flag extra turn setelah giliran tambahan dieksekusi
+
bool
hasExtraTurn()
Mengecek apakah pemain aktif memiliki giliran tambahan yang belum digunakan
Relasi dengan Kelas Lain
digunakan olehGameEngine : dipanggil untuk navigasi urutan giliran
Tidak memiliki dependency ke kelas lain secara langsung
2.6. Kelas Board
Board merepresentasikan papan permainan sebagai koleksi Tile yang tersusun membentuk jalur melingkar. Ia menyimpan tile dalam vector<unique_ptr<Tile>> untuk kepemilikan memori yang aman dan polimorfis, serta map<string, int> untuk akses cepat tile berdasarkan kode huruf. Board menyediakan antarmuka akses tile (by index atau by code) dan membantu kalkulasi movement wrap-around (posisi % size). Board tidak memiliki logika permainan, hanya struktur data papan yang bersih.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::vector<std::unique_ptr<Tile>>
tiles
Koleksi semua tile papan dengan kepemilikan polimorfis
-
std::map<std::string, int>
codeToIndex
Pemetaan kode tile (misalnya "JKT") ke indeks dalam vector tiles
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
addTile(std::unique_ptr<Tile> tile)
Menambahkan tile ke papan saat inisialisasi
+
Tile&
getTileByIndex(int idx)
Mengakses tile berdasarkan posisi index (dengan wrap-around % size())
+
Tile&
getTileByCode(const std::string& code)
Mengakses tile berdasarkan kode huruf uniknya
+
int
size() const
Mengembalikan jumlah total tile di papan
+
int
getIndexOf(const std::string& code) const
Mengembalikan index numerik dari kode tile tertentu
+
int
distanceTo(int from, int to) const
Menghitung jarak searah jarum jam dari posisi from ke to
Relasi dengan Kelas Lain
has-manyTile (unique_ptr) : kepemilikan dan akses polimorfis semua tile
digunakan olehGameEngine : untuk navigasi dan resolusi landing
digunakan olehBoardRenderer : untuk iterasi tile dalam rendering tampilan
digunakan oleh berbagai Manager : untuk pencarian tile spesifik
2.7. Kelas Player
Player merepresentasikan kondisi lengkap seorang pemain: uang tunai, posisi di papan, properti yang dimiliki, kartu di tangan, status permainan, dan flag efek sementara. Kelas ini mengimplementasikan operator overloading sesuai spesifikasi: operator+= dan operator-= untuk operasi uang (menambah/memotong saldo), operator> dan operator< untuk perbandingan kekayaan total antar pemain saat menentukan pemenang. Player bersifat semi-pasif: menyimpan data dan menyediakan operasi dasar, sedangkan logika kapan harus memotong uang atau kapan bangkrut dikelola oleh manager terkait.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::string
username
Nama unik pemain sebagai identifikasi dalam permainan
-
int
money
Jumlah uang tunai pemain saat ini
-
int
position
Posisi bidak pemain (index tile di Board, 0-based)
-
PlayerStatus
status
Status pemain: ACTIVE, JAILED, atau BANKRUPT
-
std::vector<Property*>
ownedProperties
Daftar pointer ke properti yang dimiliki pemain
-
std::vector<std::shared_ptr<SkillCard>>
handCards
Kartu kemampuan di tangan pemain (maks 3)
-
bool
hasUsedSkillThisTurn
Flag apakah pemain sudah menggunakan kartu skill pada giliran ini
-
bool
shieldActive
Flag apakah ShieldCard aktif pada giliran ini
-
int
jailTurns
Jumlah giliran yang sudah dihabiskan di penjara (maks 3 sebelum wajib bayar)
-
int
consecutiveDoubles
Jumlah double berturut-turut dalam satu giliran (reset tiap giliran)
-
int
discountPercent
Persentase diskon aktif (dari DiscountCard, 0 = tidak aktif)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
move(int steps, int boardSize)
Memindahkan posisi bidak maju sejumlah steps dengan wrap-around
+
void
setPosition(int pos)
Memindahkan bidak langsung ke posisi tertentu (teleport/jail)
+
void
addMoney(int amount)
Menambah uang tunai pemain
+
void
deductMoney(int amount)
Mengurangi uang tunai pemain (tidak negatif, validasi di caller)
+
bool
canAfford(int amount) const
Mengecek apakah saldo cukup untuk membayar sejumlah amount
+
void
addProperty(Property* prop)
Menambahkan properti ke daftar kepemilikan
+
void
removeProperty(Property* prop)
Menghapus properti dari daftar kepemilikan
+
void
addCard(std::shared_ptr<SkillCard> card)
Menambahkan kartu skill ke tangan (validasi jumlah di CardManager)
+
void
removeCard(int idx)
Membuang kartu skill pada index tertentu dari tangan
+
bool
isBankrupt() const
Mengembalikan true jika status == BANKRUPT
+
bool
isJailed() const
Mengembalikan true jika status == JAILED
+
int
getTotalWealth() const
Menghitung total kekayaan: uang + harga beli semua properti + nilai bangunan
+
int
countProperties() const
Mengembalikan jumlah properti yang dimiliki (untuk tie-breaking)
+
int
countCards() const
Mengembalikan jumlah kartu di tangan (untuk tie-breaking)
Membandingkan total kekayaan: true jika kekayaan ini > other
+
bool
operator<(const Player& other) const
Membandingkan total kekayaan: true jika kekayaan ini < other
Relasi dengan Kelas Lain
owns* Property (pointer) : daftar properti milik pemain
holds* SkillCard (shared_ptr) : kartu kemampuan di tangan
digunakan oleh hampir semua Manager : sebagai subjek aksi
digunakan olehBoardRenderer : untuk tampilan posisi dan informasi
2.8. Kelas Bank
Bank mengabstraksikan semua transaksi yang melibatkan entitas Bank sebagai pihak yang membayar atau menerima uang. Dengan kelas ini, seluruh transfer uang ke/dari bank tidak tersebar hardcoded di berbagai manager, cukup memanggil metode Bank yang tepat. Hal ini menjaga Single Responsibility: Player mengurus uang pemain, Bank mengurus aliran dari/ke bank. Bank tidak menyimpan saldo sendiri (bank diasumsikan memiliki dana tak terbatas sesuai aturan Monopoli), sehingga atributnya minimal.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
goSalary
Jumlah gaji GO yang dibayarkan ke pemain (dari konfigurasi)
-
int
jailFine
Besar denda keluar penjara (dari konfigurasi)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
paySalary(Player& p, int amount)
Memberikan gaji GO kepada pemain (Player += amount)
+
void
collectTax(Player& p, int amount)
Memungut pajak dari pemain ke bank (Player -= amount)
+
void
collectJailFine(Player& p)
Memungut denda keluar penjara dari pemain
+
void
payMortgage(Player& p, int value)
Memberikan uang nilai gadai ke pemain
+
void
collectRedemption(Player& p, int price)
Memungut harga tebus properti dari pemain
+
void
collectSalePrice(Player& p, int price)
Menerima pembayaran properti yang dijual pemain ke bank
+
void
payPropertySale(Player& p, int value)
Membayar nilai jual properti ke pemain saat menjual ke bank
Relasi dengan Kelas Lain
usesPlayer : sebagai pihak yang menerima atau membayar
digunakan olehPropertyManager, BankruptcyManager, EffectManager, dan Tile : untuk transaksi bank
2.9. Kelas Dice
Dice mengenkapsulasi logika kedua dadu permainan agar tidak tersebar di GameEngine. Ia menyimpan hasil lemparan terakhir (die1, die2) dan mendukung dua mode: rollRandom() untuk lemparan acak (perintah LEMPAR_DADU) dan setManual(x, y) untuk lemparan manual (perintah ATUR_DADU). isDouble() digunakan GameEngine untuk mendeteksi giliran tambahan atau kondisi tiga-double-berturut yang mengirim pemain ke penjara.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
die1
Nilai dadu pertama dari lemparan terakhir
-
int
die2
Nilai dadu kedua dari lemparan terakhir
-
int
faces
Jumlah sisi dadu (default: 6)
Method
Visibilitas
Tipe
Nama
Keterangan
+
std::pair<int,int>
rollRandom()
Mengacak nilai kedua dadu (1–6), menyimpan ke die1/die2, mengembalikan pair
+
std::pair<int,int>
setManual(int x, int y)
Mengatur nilai dadu secara manual, memvalidasi rentang 1–6
+
bool
isDouble() const
Mengembalikan true jika die1 == die2
+
int
getTotal() const
Mengembalikan die1 + die2 (total langkah atau faktor pengali utility)
+
int
getDie1() const
Getter nilai dadu pertama
+
int
getDie2() const
Getter nilai dadu kedua
Relasi dengan Kelas Lain
digunakan olehGameEngine : dipanggil saat LEMPAR_DADU dan ATUR_DADU
digunakan olehUtilityProperty::calculateRent via GameContext, total dadu sebagai faktor pengali
2.10. Kelas Tile (Abstract Base Class)
Tile adalah kelas abstrak yang menjadi dasar semua petak pada papan permainan. Ia mendefinisikan interface umum yang wajib diimplementasikan setiap petak konkret: virtual method onLand() yang dipanggil GameEngine setiap kali pemain mendarat. Dengan polimorfisme, GameEngine cukup memanggil tile.onLand(player, game) tanpa perlu tahu tipe konkret tile; masing-masing subclass menjalankan perilaku yang sesuai. Tile menyimpan index posisi di papan, kode unik, dan nama lengkap yang digunakan oleh BoardRenderer.
Atribut
Visibilitas
Tipe
Nama
Keterangan
#
int
index
Posisi tile dalam papan (0-based index)
#
std::string
code
Kode huruf unik tile (misal "JKT", "BDG", "GO")
#
std::string
name
Nama lengkap tile untuk tampilan
Method
Visibilitas
Tipe
Nama
Keterangan
+
virtual ~Tile()
~Tile()
Virtual destructor untuk keamanan penghapusan polimorfis
+
virtual void
onLand(Player& p, GameEngine& game) = 0
Pure virtual: dipanggil saat pemain mendarat di tile ini
+
virtual bool
isProperty() const
Mengembalikan false secara default; dioverride oleh PropertyTile
+
virtual std::string
getDisplayInfo() const
Mengembalikan string info singkat tile untuk BoardRenderer
+
int
getIndex() const
Getter index posisi tile
+
std::string
getCode() const
Getter kode huruf tile
+
std::string
getName() const
Getter nama lengkap tile
Relasi dengan Kelas Lain
parent dari semua tile konkret (PropertyTile, GoTile, JailTile, GoToJailTile, TaxTile, FestivalTile, CardTile, FreeParkingTile)
dimiliki olehBoard : via vector<unique_ptr<Tile>>
digunakan olehGameEngine : dipanggil onLand() saat pemain mendarat
2.11. Kelas PropertyTile
PropertyTile adalah petak yang berasosiasi dengan satu objek Property (Street, Railroad, atau Utility). Saat onLand() dipanggil, PropertyTile mendelegasikan seluruh logika ke PropertyManager di GameEngine: jika properti berstatus BANK, menawarkan pembelian atau akuisisi otomatis; jika berstatus OWNED milik pemain lain, membayar sewa. PropertyTile hanya menjadi jembatan antara posisi di papan (Tile) dan data aset (Property). Satu PropertyTile memiliki tepat satu Property.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::shared_ptr<Property>
property
Properti yang berasosiasi dengan tile ini (Street/Railroad/Utility)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Mendispatch ke PropertyManager berdasarkan status properti (BANK/OWNED/MORTGAGED)
+
bool
isProperty() const
Override: mengembalikan true
+
Property&
getProperty()
Getter referensi ke objek Property yang dipegang
+
const Property&
getProperty() const
Getter const untuk akses read-only ke Property
Relasi dengan Kelas Lain
extendsTile : mewarisi index, code, name, dan interface onLand()
has-aProperty (shared_ptr) : kepemilikan data aset properti
GoTile merepresentasikan petak Mulai (GO), titik awal permainan dan sumber pendapatan tetap. Saat onLand() dipanggil (pemain berhenti tepat di GO), GoTile memanggil Bank::paySalary() untuk memberikan gaji. Deteksi pemain melewati GO (tidak berhenti) dilakukan di GameEngine::moveCurrentPlayer() secara terpisah, bukan di onLand(). GoTile menyimpan nilai gaji yang dibaca dari konfigurasi.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
salary
Jumlah gaji yang diterima pemain saat berhenti di petak GO
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Memanggil Bank::paySalary(p, salary) dan mencatat ke TransactionLogger
+
std::string
getDisplayInfo() const
Mengembalikan `"GO
Relasi dengan Kelas Lain
extendsTile
usesBank (via GameEngine) : untuk membayarkan gaji GO
2.13. Kelas JailTile
JailTile merepresentasikan petak Penjara yang memiliki dua fungsi berbeda berdasarkan cara pemain tiba: (1) Hanya Mampir (Visiting): jika pemain tiba dari lemparan dadu normal, tidak ada aksi apapun; (2) Dalam Penjara: jika pemain dikirim oleh GoToJailTile atau kartu/mekanisme lain, status pemain diubah menjadi JAILED. Logika handling giliran pemain di penjara (coba double, bayar denda, atau paksa keluar di giliran ke-4) ditangani oleh GameEngine::handleJailTurn().
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Jika p.isJailed() false: tampilkan pesan "Hanya Mampir". Jika true: sudah ditangani oleh handleJailTurn()
+
void
sendToJail(Player& p)
Mengatur posisi dan status pemain menjadi di penjara (dipanggil dari GoToJailTile dan kartu)
+
std::string
getDisplayInfo() const
Mengembalikan info jumlah tahanan dan pengunjung saat ini
Relasi dengan Kelas Lain
extendsTile
dipanggilsendToJail() oleh GoToJailTile dan GoToJailCard
Logika giliran penjara dikelola oleh GameEngine
2.14. Kelas GoToJailTile
GoToJailTile adalah petak jebakan; saat pemain mendarat di sini, bidak langsung dipindahkan ke JailTile dengan status JAILED tanpa melewati GO (tidak mendapat gaji). Giliran pemain berakhir seketika setelah landing di tile ini. onLand() memanggil JailTile::sendToJail() dan memberitahu GameEngine untuk mengakhiri giliran.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Memanggil sendToJail(p), mengakhiri giliran pemain, tidak memberikan gaji GO
+
std::string
getDisplayInfo() const
Mengembalikan "Pergi ke Penjara!"
Relasi dengan Kelas Lain
extendsTile
usesJailTile::sendToJail() : untuk mengirim pemain ke penjara
usesGameEngine : untuk mengakhiri giliran secara paksa
2.15. Kelas TaxTile
TaxTile merepresentasikan kedua petak pajak: Pajak Penghasilan (PPH) dan Pajak Barang Mewah (PBM). Tipe pajak ditentukan oleh atribut TaxType. Untuk PPH, pemain diberi pilihan membayar flat atau persentase dari total kekayaan sebelum menghitung kekayaannya. Untuk PBM, langsung dipotong nilai flat. Jika pemain tidak mampu membayar, TaxTile memicu BankruptcyManager::handleDebt() dengan Bank sebagai kreditor.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
TaxType
type
Jenis pajak: PPH (Pajak Penghasilan) atau PBM (Pajak Barang Mewah)
-
int
flatAmount
Jumlah pajak flat (PPH flat atau PBM)
-
int
percentage
Persentase untuk PPH (0 untuk PBM)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Menampilkan pilihan dan memproses pembayaran pajak sesuai tipe
-
void
handlePPH(Player& p, GameEngine& game)
Menangani logika PPH: tampil pilihan, hitung, potong, atau trigger bankruptcy
-
void
handlePBM(Player& p, GameEngine& game)
Langsung memotong PBM flat; jika gagal trigger bankruptcy
+
std::string
getDisplayInfo() const
Mengembalikan info jenis dan besar pajak
Relasi dengan Kelas Lain
extendsTile
usesBankruptcyManager (via GameEngine) : jika pemain tidak mampu membayar
usesBank (via GameEngine) : untuk menerima pembayaran pajak
2.16. Kelas FestivalTile
FestivalTile memicu efek festival yang melipatgandakan sewa properti milik pemain. Saat onLand(), pemain diminta memilih salah satu properti miliknya. FestivalTile mendelegasikan seluruh logika penerapan dan penguatan efek ke EffectManager::applyFestival(). EffectManager yang mengelola festivalMultiplier (1/2/4/8) dan festivalDuration (0–3) pada objek Property yang dipilih.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Menampilkan daftar properti pemain, meminta pilihan, mendelegasikan ke EffectManager
+
std::string
getDisplayInfo() const
Mengembalikan "Festival : Pilih properti untuk digandakan sewanya"
Relasi dengan Kelas Lain
extendsTile
usesEffectManager (via GameEngine) : untuk menerapkan/memperkuat efek festival pada properti
2.17. Kelas CardTile
CardTile merepresentasikan petak Kesempatan atau Dana Umum. Atribut drawType menentukan dari deck mana kartu ditarik. Saat onLand(), CardTile memanggil CardManager::drawChanceCard() atau drawCommunityCard() sesuai tipe, yang kemudian mengeksekusi efek kartu secara langsung pada pemain.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
CardDrawType
drawType
Tipe kartu: CHANCE (Kesempatan) atau COMMUNITY (Dana Umum)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
Memanggil CardManager sesuai drawType untuk mengambil dan mengeksekusi kartu
+
std::string
getDisplayInfo() const
Mengembalikan "Kesempatan" atau "Dana Umum"
Relasi dengan Kelas Lain
extendsTile
usesCardManager (via GameEngine) : untuk menarik dan mengeksekusi kartu
2.18. Kelas FreeParkingTile
FreeParkingTile merepresentasikan petak Bebas Parkir, rest area tanpa aksi apapun. onLand() tidak melakukan apapun (no-op). Kelas ini tetap dibuat sebagai kelas tersendiri (bukan case dalam switch) untuk menghormati prinsip Open/Closed dan polimorfisme: setiap tile adalah objek dengan perilaku masing-masing.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onLand(Player& p, GameEngine& game)
No-op: tidak ada aksi saat mendarat di Bebas Parkir
+
std::string
getDisplayInfo() const
Mengembalikan "Bebas Parkir, Tidak ada aksi"
Relasi dengan Kelas Lain
extendsTile
2.19. Kelas Property (Abstract Base Class)
Property merepresentasikan aset properti yang dapat dimiliki pemain, sengaja dipisahkan dari Tile karena data kepemilikan (owner, status, bangunan, efek festival) harus tetap ada dan konsisten meski pemain berpindah posisi. Property mendefinisikan interface abstrak calculateRent() yang diimplementasikan berbeda oleh setiap subclass. Atribut festivalMultiplier dan festivalDuration dikelola oleh EffectManager. Enum OwnershipStatus (BANK/OWNED/MORTGAGED) menentukan apakah sewa berlaku.
Atribut
Visibilitas
Tipe
Nama
Keterangan
#
std::string
code
Kode huruf unik properti (sama dengan kode tile terkait)
#
std::string
name
Nama lengkap properti
#
PropertyType
type
Jenis: STREET, RAILROAD, atau UTILITY
#
Player*
owner
Pointer ke pemilik (nullptr jika berstatus BANK)
#
OwnershipStatus
status
Status: BANK, OWNED, atau MORTGAGED
#
int
purchasePrice
Harga beli properti dari konfigurasi
#
int
mortgageValue
Nilai gadai properti dari konfigurasi
#
int
festivalMultiplier
Pengganda sewa festival: 1 (tidak aktif), 2, 4, atau 8
#
int
festivalDuration
Sisa durasi efek festival: 0 = tidak aktif, 1–3 = aktif
Method
Visibilitas
Tipe
Nama
Keterangan
+
virtual ~Property()
~Property()
Virtual destructor untuk penghapusan polimorfis yang aman
+
virtual int
calculateRent(const GameContext& ctx) const = 0
Pure virtual: menghitung sewa berdasarkan kondisi saat ini (polimorfis)
+
virtual bool
canBuild() const
Mengembalikan false secara default; dioverride oleh StreetProperty
+
virtual int
getSellValue() const
Nilai jual ke bank: purchasePrice + setengah harga bangunan (jika ada)
+
bool
isOwned() const
True jika status == OWNED
+
bool
isMortgaged() const
True jika status == MORTGAGED
+
bool
isBank() const
True jika status == BANK (belum dimiliki siapapun)
+
void
setOwner(Player* p)
Mengatur pemilik baru dan status OWNED (nullptr untuk BANK)
+
void
setStatus(OwnershipStatus s)
Mengatur status langsung (untuk mortgage/redeem/bankruptcy)
diakses olehPropertyManager, BankruptcyManager, EffectManager : untuk logika bisnis
2.20. Kelas StreetProperty
StreetProperty adalah jenis properti paling umum dalam permainan, dengan sistem bangunan dan monopoli color group. Selain atribut dari Property, ia menyimpan colorGroup, harga bangunan (houseCost, hotelCost), tabel sewa per level (rentLevels[0..5]: tanah kosong hingga hotel), dan level bangunan saat ini (BuildingLevel). calculateRent() mengecek status monopoli (jika owner monopoli dan belum ada bangunan, sewa × 2) lalu mengambil nilai dari rentLevels sesuai buildingLevel, kemudian mengalikan dengan festivalMultiplier. Pembangunan rumah/hotel hanya boleh saat pemain monopoli color group dengan pemerataan antar petak.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::string
colorGroup
Kelompok warna properti (misal "BIRU_TUA", "HIJAU")
-
int
houseCost
Harga membangun satu rumah dari konfigurasi
-
int
hotelCost
Harga upgrade dari 4 rumah ke hotel dari konfigurasi
Level bangunan saat ini: NONE(0), HOUSE_1–4, HOTEL
Method
Visibilitas
Tipe
Nama
Keterangan
+
int
calculateRent(const GameContext& ctx) const
Menghitung sewa: cek monopoli × 2 jika no-build, atau rentLevels[lvl] × festivalMultiplier
+
bool
canBuild() const
True jika owner memonopoli color group dan properti tidak digadaikan
+
int
getSellValue() const
purchasePrice + (jumlahBangunan × houseCost/2) atau (hotelCost/2) jika hotel
+
void
buildHouse()
Menaikkan buildingLevel satu level (NONE→HOUSE_1→...→HOUSE_4); validasi di PropertyManager
+
void
buildHotel()
Mengupgrade dari HOUSE_4 ke HOTEL; validasi semua petak group sudah HOUSE_4
+
void
demolishBuildings()
Mereset buildingLevel ke NONE dan mengembalikan nilai bangunan ke bank (DemolitionCard/Bankruptcy)
+
int
getBuildingSellValue() const
Nilai jual bangunan ke bank (setengah harga beli bangunan)
+
std::string
getColorGroup() const
Getter nama color group
+
BuildingLevel
getBuildingLevel() const
Getter level bangunan saat ini
+
int
getHouseCost() const
Getter harga rumah
+
int
getHotelCost() const
Getter harga hotel
Relasi dengan Kelas Lain
extendsProperty : mewarisi semua atribut dan method dasar properti
dikelola olehPropertyManager : untuk beli, sewa, bangun, gadai, tebus
2.21. Kelas RailroadProperty
RailroadProperty merepresentasikan empat stasiun kereta dalam permainan. Berbeda dengan Street, Railroad diperoleh secara otomatis tanpa proses beli (pemain pertama yang menginjak langsung menjadi pemilik). calculateRent() menghitung sewa berdasarkan jumlah Railroad yang dimiliki pemilik saat ini, nilainya dibaca dari konfigurasi railroad.txt via GameContext. Semakin banyak Railroad yang dimiliki, sewa semakin tinggi.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::map<int,int>
rentByCount
Pemetaan jumlah railroad yang dimiliki → biaya sewa (dari config)
Method
Visibilitas
Tipe
Nama
Keterangan
+
int
calculateRent(const GameContext& ctx) const
Hitung jumlah railroad milik owner lewat ctx, lookup di rentByCount
+
bool
canBuild() const
Selalu false, Railroad tidak dapat dibangun
+
int
getSellValue() const
purchasePrice (tidak ada bangunan, nilai jual = harga beli)
Relasi dengan Kelas Lain
extendsProperty
usesGameContext : untuk mengakses daftar properti pemilik guna menghitung jumlah railroad
2.22. Kelas UtilityProperty
UtilityProperty merepresentasikan PLN dan PAM. Seperti Railroad, Utility diperoleh otomatis tanpa beli. calculateRent() mengalikan total angka dadu pemain yang mendarat (dari GameContext::diceTotal) dengan faktor pengali sesuai jumlah Utility yang dimiliki pemilik (dari konfigurasi utility.txt). Satu utility: faktor 4; dua utility: faktor 10.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::map<int,int>
multiplierByCount
Pemetaan jumlah utility yang dimiliki → faktor pengali (dari config)
Method
Visibilitas
Tipe
Nama
Keterangan
+
int
calculateRent(const GameContext& ctx) const
ctx.diceTotal × multiplierByCount[jumlah utility milik owner]
+
bool
canBuild() const
Selalu false, Utility tidak dapat dibangun
+
int
getSellValue() const
purchasePrice (tidak ada bangunan)
Relasi dengan Kelas Lain
extendsProperty
usesGameContext : untuk diceTotal dan daftar properti pemilik
2.23. Kelas Card
Kelas abstrak yang mendefinisikan interface universal semua kartu. Setiap kartu memiliki deskripsi teks dan method apply() yang dipanggil saat kartu dieksekusi. apply() menerima referensi Player dan GameEngine agar kartu dapat memicu efek seperti memindahkan pemain, berinteraksi dengan bank, atau mempengaruhi pemain lain.
Atribut
Visibilitas
Tipe
Nama
Keterangan
#
std::string
description
Teks deskripsi efek kartu yang ditampilkan saat kartu ditarik
Method
Visibilitas
Tipe
Nama
Keterangan
+
virtual ~Card()
~Card()
Virtual destructor untuk penghapusan polimorfis
+
virtual void
apply(Player& p, GameEngine& game) = 0
Pure virtual: menerapkan efek kartu pada pemain dan game state
+
std::string
getDescription() const
Getter deskripsi kartu
Relasi dengan Kelas Lain
parent dariActionCard dan SkillCard
dikelola dalamDeck<T> oleh CardManager
2.24. Kelas ActionCard
ActionCard adalah kelas menengah untuk kartu Kesempatan dan Dana Umum. Kelas ini tidak menambah atribut baru namun berfungsi sebagai tipe yang dapat digunakan sebagai parameter template Deck<ActionCard> sehingga chanceDeck dan communityDeck terpisah secara tipe dari skillDeck. Semua kartu konkret Kesempatan dan Dana Umum extends ActionCard.
Method
Visibilitas
Tipe
Nama
Keterangan
+
virtual void
apply(Player& p, GameEngine& game) = 0
Masih pure virtual, setiap kartu konkret wajib mengimplementasikan
Relasi dengan Kelas Lain
extendsCard
parent dari semua kartu Kesempatan dan Dana Umum konkret
digunakan sebagai parameter template Deck<ActionCard>
2.25. Kelas GoToNearestRailroadCard
Kartu Kesempatan yang memindahkan pemain ke stasiun kereta terdekat dari posisi saat ini (searah jarum jam). apply() mencari tile Railroad terdekat menggunakan Board::distanceTo(), memindahkan pemain, memberikan gaji GO jika melewatinya, lalu memicu onLand() tile Railroad yang dituju (akuisisi otomatis atau bayar sewa).
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Cari Railroad terdekat, pindahkan pemain, proses landing di Railroad
Relasi dengan Kelas Lain
extendsActionCard
usesBoard (via GameEngine) untuk mencari railroad terdekat
2.26. Kelas MoveBackCard
Kartu Kesempatan yang memundurkan posisi pemain sebanyak 3 petak dari posisi saat ini. Pemain tidak mendapatkan gaji GO jika mundur melewati petak GO. Setelah pindah, onLand() tile tujuan dipicu.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
steps
Jumlah petak yang harus dimundurkan (default: 3)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Mundurkan posisi pemain steps petak, proses landing di tile baru
Relasi dengan Kelas Lain
extendsActionCard
2.27. Kelas GoToJailCard
Kartu Kesempatan yang mengirim pemain langsung ke penjara. apply() memanggil JailTile::sendToJail dan mengakhiri giliran pemain tanpa memberikan gaji GO meski melewati petak GO.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Kirim pemain ke penjara, akhiri giliran
Relasi dengan Kelas Lain
extendsActionCard
usesJailTile::sendToJail() (via GameEngine)
2.28. Kelas BirthdayCard
Kartu Dana Umum yang meminta setiap pemain lain membayar M100 kepada pemain aktif. apply() mengiterasi semua pemain aktif lain, memotong M100 dari masing-masing (atau memicu bankruptcy jika tidak mampu), dan menambahkan total ke pemain aktif.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
amountPerPlayer
Jumlah uang yang diterima dari setiap pemain lain (default: 100)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Iterasi pemain aktif lain, transfer amountPerPlayer ke pemain aktif
Relasi dengan Kelas Lain
extendsActionCard
uses semua Player aktif lain (via GameEngine)
2.29. Kelas DoctorFeeCard
Kartu Dana Umum yang membebankan biaya dokter sebesar M700 kepada pemain ke Bank. Jika pemain tidak mampu membayar, memicu BankruptcyManager::handleDebt() dengan Bank sebagai kreditor. ShieldCard aktif akan membatalkan efek kartu ini.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
fee
Besar biaya dokter (default: 700)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Potong fee dari pemain ke bank; jika tidak mampu, trigger BankruptcyManager; cek shield terlebih dahulu
Relasi dengan Kelas Lain
extendsActionCard
usesBankruptcyManager (via GameEngine)
2.30. Kelas ElectionCard
Kartu Dana Umum yang mengharuskan pemain membayar M200 kepada setiap pemain lain. apply() mengiterasi semua pemain aktif, memindahkan M200 dari pemain aktif ke setiap pemain lain. Jika tidak mampu membayar salah satu, memicu bankruptcy.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
int
amountPerPlayer
Jumlah yang harus dibayar ke setiap pemain lain (default: 200)
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Transfer amountPerPlayer dari pemain aktif ke setiap pemain lain
Relasi dengan Kelas Lain
extendsActionCard
uses semua Player aktif lain (via GameEngine)
2.31. Kelas SkillCard
SkillCard adalah kelas untuk kartu kemampuan spesial yang dipegang pemain di tangan (maksimal 3 kartu). Berbeda dengan ActionCard, SkillCard hanya bisa digunakan sebelum melempar dadu dan bersifat sekali pakai. Atribut value menyimpan parameter kartu (jumlah langkah untuk MoveCard, persentase diskon untuk DiscountCard), dan duration menyimpan sisa masa berlaku. Tipe SkillCard digunakan sebagai parameter Deck<SkillCard> di CardManager.
Atribut
Visibilitas
Tipe
Nama
Keterangan
#
int
value
Parameter nilai kartu: langkah (Move), persentase (Discount), atau 0 (kartu tanpa nilai)
#
int
duration
Sisa durasi berlakunya kartu (hanya relevan untuk DiscountCard)
Method
Visibilitas
Tipe
Nama
Keterangan
+
virtual void
apply(Player& p, GameEngine& game) = 0
Pure virtual: efek spesifik setiap kartu kemampuan
+
virtual bool
canUseBeforeRoll() const
Mengembalikan true, semua SkillCard hanya bisa dipakai sebelum dadu
+
int
getValue() const
Getter nilai parameter kartu
+
int
getDuration() const
Getter sisa durasi
+
void
setDuration(int d)
Setter sisa durasi (digunakan EffectManager)
+
virtual std::string
getTypeName() const = 0
Mengembalikan nama tipe kartu (untuk save/load dan display)
digunakan sebagai parameter template Deck<SkillCard>
disimpan dalamPlayer::handCards
2.32. Kelas MoveCard
Kartu kemampuan yang memindahkan pemain maju sejumlah petak. Nilai langkah (value) ditentukan secara acak saat kartu pertama kali didistribusikan ke pemain. apply() memanggil GameEngine::moveCurrentPlayer(value) yang juga menangani deteksi lewat GO dan landing di tile baru.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Pindahkan pemain maju value petak, proses landing normal
+
std::string
getTypeName() const
Mengembalikan "MoveCard"
Relasi dengan Kelas Lain
extendsSkillCard
2.33. Kelas DiscountCard
Kartu kemampuan yang memberikan diskon persentase acak selama 1 giliran. Persentase (value) ditentukan saat kartu didistribusikan. apply() mengaktifkan discountPercent pada Player dan duration. EffectManager::onTurnEnd() mengurangi duration dan mereset diskon saat habis. Diskon diterapkan pada transaksi pembelian properti dalam giliran aktif.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Set p.discountPercent = value dan duration = 1
+
std::string
getTypeName() const
Mengembalikan "DiscountCard"
Relasi dengan Kelas Lain
extendsSkillCard
Efeknya dikelola oleh EffectManager
2.34. Kelas ShieldCard
Kartu kemampuan yang melindungi pemain dari semua tagihan dan sanksi merugikan selama 1 giliran. apply() mengaktifkan p.shieldActive. Setiap kali ada potongan uang (sewa, pajak, biaya kartu), sistem mengecek shieldActive terlebih dahulu; jika true, tagihan dibatalkan. EffectManager::onTurnEnd() mereset shieldActive ke false.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Set p.shieldActive = true untuk giliran ini
+
std::string
getTypeName() const
Mengembalikan "ShieldCard"
Relasi dengan Kelas Lain
extendsSkillCard
Efeknya diperiksa di PropertyManager, TaxTile, CardTile sebelum memotong uang
2.35. Kelas TeleportCard
Kartu kemampuan yang memberikan pemain kebebasan berpindah ke petak manapun. apply() meminta pemain memasukkan kode tile tujuan, lalu memanggil GameEngine::handleLanding() di tile tersebut tanpa memberikan gaji GO. Validasi kode tile dilakukan sebelum pemindahan.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Minta input kode tile, validasi, teleport pemain, proses landing di tujuan
+
std::string
getTypeName() const
Mengembalikan "TeleportCard"
Relasi dengan Kelas Lain
extendsSkillCard
usesGameEngine untuk validasi tile dan teleport
2.36. Kelas LassoCard
Kartu kemampuan yang menarik satu pemain lawan yang posisinya di depan pemain aktif ke posisi pemain aktif saat ini. apply() menampilkan daftar pemain yang posisinya di depan, meminta pilihan, lalu memindahkan posisi lawan ke posisi pemain aktif. Pemain yang ditarik tidak memproses landing di posisi baru.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Tampilkan kandidat lawan, minta pilihan, pindahkan posisi lawan ke posisi pemain aktif
+
std::string
getTypeName() const
Mengembalikan "LassoCard"
Relasi dengan Kelas Lain
extendsSkillCard
usesPlayer lain dan Board
2.37. Kelas DemolitionCard
Kartu kemampuan yang menghancurkan bangunan pada satu properti milik pemain lawan. apply() menampilkan daftar properti lawan yang memiliki bangunan, meminta pilihan, lalu memanggil StreetProperty::demolishBuildings() untuk menghancurkan semua bangunan di properti tersebut. Nilai bangunan dikembalikan ke bank.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
apply(Player& p, GameEngine& game)
Tampilkan properti lawan berisi bangunan, pilih, demolish bangunan, kembalikan nilai ke bank
+
std::string
getTypeName() const
Mengembalikan "DemolitionCard"
Relasi dengan Kelas Lain
extendsSkillCard
usesStreetProperty::demolishBuildings()
2.38. Kelas Deck<T>
Deck<T> adalah generic class template yang mengelola tumpukan kartu untuk semua jenis kartu (T = ActionCard atau SkillCard). Ia memisahkan drawPile (kartu siap diambil) dan discardPile (kartu sudah dipakai). Saat drawPile habis, refillFromDiscardIfNeeded() memindahkan isi discardPile ke drawPile dan mengocoknya ulang. Penggunaan template menghindari duplikasi kode untuk setiap jenis deck.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::vector<std::shared_ptr<T>>
drawPile
Tumpukan kartu yang siap untuk diambil
-
std::vector<std::shared_ptr<T>>
discardPile
Tumpukan kartu yang sudah digunakan dan menunggu dikocok ulang
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
shuffle()
Mengocok drawPile secara acak menggunakan std::shuffle
+
std::shared_ptr<T>
draw()
Mengambil kartu teratas dari drawPile; panggil refill jika kosong
+
void
discard(std::shared_ptr<T> card)
Memindahkan kartu ke discardPile setelah digunakan
+
void
refillFromDiscardIfNeeded()
Jika drawPile kosong: pindahkan discardPile ke drawPile dan kocok ulang
+
int
size() const
Mengembalikan jumlah kartu di drawPile
+
void
addCard(std::shared_ptr<T> card)
Menambahkan kartu ke drawPile (digunakan saat inisialisasi)
+
std::vector<std::shared_ptr<T>>
getAllCards() const
Mengembalikan semua kartu (drawPile + discardPile) untuk save/load
Relasi dengan Kelas Lain
Parameter T: ActionCard atau SkillCard
dimiliki olehCardManager: tiga instance chanceDeck, communityDeck, skillDeck
2.39. Kelas PropertyManager
PropertyManager mengeksekusi semua logika terkait kepemilikan properti agar tidak menumpuk di GameEngine. Ia menangani seluruh siklus kepemilikan, yaitu penawaran beli Street, akuisisi otomatis Railroad/Utility, pembayaran sewa (dengan polimorfisme calculateRent()), pembangunan rumah/hotel dengan validasi pemerataan, serta gadai dan tebus. Semua transaksi uang diteruskan ke Bank, dan setiap aksi dicatat ke TransactionLogger.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
Bank&
bank
Referensi ke Bank untuk semua transaksi uang properti
-
AuctionManager&
auctionManager
Referensi ke AuctionManager untuk memicu lelang saat perlu
-
BankruptcyManager&
bankruptcyManager
Referensi ke BankruptcyManager untuk memicu proses bankruptcy
-
TransactionLogger&
logger
Referensi ke logger untuk mencatat semua transaksi properti
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
tryBuyStreet(Player& p, StreetProperty& prop)
Tampilkan akta, minta konfirmasi; jika beli: transfer uang dan kepemilikan; jika tidak: trigger lelang
Mengembalikan daftar Street dalam color group yang memenuhi syarat pemerataan untuk dibangun
+
int
countRailroadsOwned(const Player& p) const
Menghitung jumlah Railroad milik pemain (untuk GameContext)
+
int
countUtilitiesOwned(const Player& p) const
Menghitung jumlah Utility milik pemain (untuk GameContext)
Relasi dengan Kelas Lain
usesBank untuk semua transaksi uang properti
usesAuctionManager untuk memicu lelang saat pemain menolak beli atau tidak mampu
usesBankruptcyManager untuk memicu bankruptcy jika sewa tidak mampu dibayar
usesTransactionLogger untuk mencatat beli, sewa, bangun, gadai, tebus
digunakan olehGameEngine: dipanggil dari handleLanding() dan processCommand()
2.40. Kelas AuctionManager
AuctionManager menjalankan mekanisme lelang properti yang terdiri dari putaran bidding antar pemain aktif. runAuction() mengatur urutan bid/pass mulai dari pemain setelah trigger player, memvalidasi bahwa bid tidak melebihi saldo pemain, mendeteksi kondisi akhir lelang (pass berturut-turut sejumlah n-1 pemain), dan memindahkan kepemilikan properti ke pemenang. Minimal satu pemain harus bid sebelum lelang berakhir.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
TransactionLogger&
logger
Referensi ke logger untuk mencatat setiap bid dan hasil lelang
Menentukan index awal bidding (pemain setelah trigger player)
-
bool
isAuctionOver(int consecutivePasses, int nPlayers)
Cek kondisi akhir: pass berturut >= n-1 dan minimal ada satu bid
-
void
transferProperty(Property& prop, Player* winner, int finalBid)
Memindahkan kepemilikan ke pemenang dan memotong saldo sesuai bid akhir
Relasi dengan Kelas Lain
usesPlayer untuk operasi bid dan transfer kepemilikan
usesProperty untuk memindahkan status dan kepemilikan
usesTransactionLogger untuk mencatat setiap bid dan hasil akhir lelang
digunakan olehPropertyManager dan BankruptcyManager
2.41. Kelas BankruptcyManager
BankruptcyManager menangani seluruh proses kebangkrutan. handleDebt() pertama menghitung estimasi dana maksimum dari likuidasi total aset. Jika dapat menutup kewajiban, pemain diarahkan ke panel likuidasi interaktif. Jika tidak, declareBankrupt() dieksekusi. Jika kreditor pemain lain, semua aset diserahkan ke kreditor; jika Bank, uang hilang, properti kembali ke status BANK dan dilelang satu per satu.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
Bank&
bank
Referensi ke Bank untuk transaksi saat likuidasi ke bank
-
AuctionManager&
auctionManager
Referensi untuk menjalankan lelang properti saat bangkrut ke bank
-
TransactionLogger&
logger
Referensi ke logger untuk mencatat semua aksi kebangkrutan
Method
Visibilitas
Tipe
Nama
Keterangan
+
bool
canCoverDebt(const Player& p, int debt) const
True jika uang tunai + estimasi likuidasi >= debt
+
int
estimateLiquidationValue(const Player& p) const
Menghitung maksimum dana yang bisa diperoleh dari jual/gadai semua aset
+
void
handleDebt(Player& p, int amount, Creditor creditor, GameEngine& game)
Entry point: cek likuidasi possible, arahkan ke panel likuidasi atau langsung declare bankrupt
+
void
liquidateAssets(Player& p, int targetAmount, GameEngine& game)
Menampilkan panel likuidasi interaktif: pemain memilih jual/gadai hingga kewajiban terpenuhi
Mengembalikan properti ke status BANK dan menjalankan lelang satu per satu
Relasi dengan Kelas Lain
usesBank untuk transaksi saat bangkrut ke bank
usesAuctionManager untuk lelang properti pasca-bankruptcy ke bank
usesPlayer sebagai subjek dan kreditor
usesTransactionLogger untuk mencatat seluruh proses kebangkrutan
digunakan olehGameEngine: dipanggil dari berbagai titik saat pemain gagal bayar
2.42. Kelas CardManager
CardManager memegang semua deck kartu (chanceDeck, communityDeck, skillDeck) dan menyediakan operasi pengambilan serta penerapan kartu. drawChanceCard() dan drawCommunityCard() menarik kartu dari deck yang sesuai dan langsung mengeksekusi apply(). drawSkillCard() dipanggil di awal setiap giliran untuk semua pemain; jika pemain sudah memiliki 3 kartu dan mendapat kartu ke-4, handleExcessSkillCards() memicu prompt drop secara otomatis. Penggunaan Deck<ActionCard> dan Deck<SkillCard> mendemonstrasikan generic class template dalam satu kelas.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
Deck<ActionCard>
chanceDeck
Tumpukan kartu Kesempatan (3 jenis kartu)
-
Deck<ActionCard>
communityDeck
Tumpukan kartu Dana Umum (3 jenis kartu)
-
Deck<SkillCard>
skillDeck
Tumpukan kartu Kemampuan Spesial (15 kartu total)
-
TransactionLogger&
logger
Referensi ke logger untuk mencatat pengambilan dan penggunaan kartu
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
drawChanceCard(Player& p, GameEngine& game)
Tarik dari chanceDeck, tampilkan deskripsi, panggil apply(), buang ke discard
+
void
drawCommunityCard(Player& p, GameEngine& game)
Tarik dari communityDeck, tampilkan deskripsi, panggil apply(), buang ke discard
+
void
drawSkillCard(Player& p)
Tarik dari skillDeck, tambahkan ke tangan pemain; jika >3, panggil handleExcess
+
void
handleExcessSkillCards(Player& p)
Tampilkan daftar 4 kartu di tangan, minta pemain membuang 1, eksekusi drop
+
void
useSkillCard(Player& p, int idx, GameEngine& game)
Gunakan kartu pada index idx: panggil apply(), hapus dari tangan, buang ke discard
+
void
initializeDecks()
Membuat dan mengisi semua deck dengan kartu yang sesuai saat inisialisasi game
+
std::vector<std::string>
getSkillDeckStateForSave() const
Mengembalikan state deck untuk kebutuhan save/load
usesTransactionLogger: mencatat semua aktivitas kartu
digunakan olehGameEngine dan CardTile
2.43. Kelas EffectManager
EffectManager mengelola seluruh efek sementara yang berlaku lintas giliran agar logika durasi tidak tersebar di berbagai tempat. Bertanggung jawab atas penguatan/pengurangan festivalMultiplier dan festivalDuration pada Property, reset flag per giliran (hasUsedSkillThisTurn, shieldActive, consecutiveDoubles), dan penerapan/penghapusan discountPercent dari DiscountCard. onTurnStart() dipanggil di awal giliran setiap pemain, onTurnEnd() dipanggil di akhir.
Method
Visibilitas
Tipe
Nama
Keterangan
+
void
onTurnStart(Player& p, GameEngine& game)
Reset flag per giliran pemain aktif: hasUsedSkill, consecutiveDoubles
+
void
onTurnEnd(Player& p, GameEngine& game)
Dekremen durasi efek aktif (festival, discount), reset efek yang habis
+
void
decrementTemporaryEffects(Player& p)
Mengurangi festivalDuration semua properti milik pemain; reset multiplier jika 0
+
void
applyFestival(Player& p, Property& prop)
Menerapkan atau memperkuat efek festival pada properti yang dipilih pemain
+
void
resetShield(Player& p)
Mereset shieldActive ke false di akhir giliran
+
void
applyDiscount(Player& p)
Mengaktifkan discountPercent dari DiscountCard dan mengatur durasinya
+
void
decrementDiscount(Player& p)
Mengurangi durasi discount; reset ke 0 jika habis
Relasi dengan Kelas Lain
usesPlayer : untuk membaca/mengubah flag dan daftar properti
usesProperty : untuk mengelola festival multiplier dan durasi
digunakan olehGameEngine : dipanggil onTurnStart dan onTurnEnd setiap giliran
digunakan olehFestivalTile : untuk applyFestival()
2.44. Kelas TransactionLogger
TransactionLogger mencatat setiap kejadian signifikan permainan secara otomatis ke dalam vector<LogEntry>. Logger bekerja di semua GameEngine, Manager, dan Tile yang relevan memanggil log() setiap kali terjadi transaksi uang, pergerakan, penggunaan kartu, lelang, festival, bankruptcy, dan save/load. printAll() digunakan untuk CETAK_LOG tanpa argumen, printLastN(n) untuk CETAK_LOG N. Saat game di-save, getEntries() digunakan oleh GameStateSerializer.
Atribut
Visibilitas
Tipe
Nama
Keterangan
-
std::vector<LogEntry>
entries
Daftar semua entri log selama sesi permainan berlangsung
Menampilkan seluruh entries ke layar dengan format standar
+
void
printLastN(int n) const
Menampilkan n entri terakhir dari entries
+
const std::vector<LogEntry>&
getEntries() const
Getter referensi ke seluruh entries untuk keperluan save/load
+
void
loadEntries(const std::vector<LogEntry>& saved)
Memuat entries dari file save saat load game
+
void
clear()
Menghapus semua entries (saat memulai game baru)
Relasi dengan Kelas Lain
storesLogEntry : satu entri per kejadian
dipanggil oleh semua Manager dan GameEngine : untuk pencatatan aksi
diakses olehGameStateSerializer untuk menyertakan log dalam file save
2.45. Kelas ConfigLoader
ConfigLoader bertugas membaca dan memparsing semua file konfigurasi (.txt) saat program pertama kali dijalankan. Setiap method load bertanggung jawab atas satu file konfigurasi dan mengembalikan struct data yang kemudian digunakan GameEngine untuk membangun Board dan menginisialisasi semua objek. ConfigLoader tidak menyentuh logika game, hanya mengubah teks menjadi struktur C++ terstruktur.
Method
Visibilitas
Tipe
Nama
Keterangan
+
std::vector<PropertyDef>
loadProperties(const std::string& path)
Membaca property.txt: ID, kode, nama, jenis, warna, harga, nilai gadai, harga bangunan, tabel sewa
+
std::map<int,int>
loadRailroadConfig(const std::string& path)
Membaca railroad.txt: pemetaan jumlah railroad → biaya sewa
+
std::map<int,int>
loadUtilityConfig(const std::string& path)
Membaca utility.txt: pemetaan jumlah utility → faktor pengali
Memvalidasi konsistensi data konfigurasi sebelum digunakan
Relasi dengan Kelas Lain
digunakan olehGameEngine saat startNewGame() untuk menginisialisasi semua komponen
Tidak bergantung pada kelas lain, murni membaca file dan mengembalikan struct data
2.46. Kelas SaveLoadManager
SaveLoadManager mengatur operasi simpan dan muat state permainan ke/dari file .txt. save() meminta GameStateSerializer untuk mengubah seluruh state menjadi format teks, lalu menulisnya ke file, tetapi hanya boleh dipanggil di awal giliran sebelum aksi apapun. load() membaca file dan menyerahkan kontennya ke GameStateSerializer::deserialize() untuk merestorasi state GameEngine. SaveLoadManager juga menangani kasus edge, seperti file sudah ada, file tidak ditemukan, dan file rusak.
Menulis string data ke file; melempar exception jika gagal
Relasi dengan Kelas Lain
has-aGameStateSerializer untuk mendelegasikan format teks ke serializer
menggunakanGameEngine untuk membaca state saat save, merestorasi state saat load
digunakan olehGameEngine, dipanggil dari processCommand() untuk SIMPAN dan MUAT
2.47. Kelas GameStateSerializer
GameStateSerializer memisahkan logika format teks dari SaveLoadManager. serialize() mengiterasi semua komponen state GameEngine (turn, pemain, properti, deck, log) dan menghasilkan string dengan format persis sesuai spesifikasi Save/Load. deserialize() melakukan kebalikannya: memparsing string tersebut baris per baris dan merestorasi semua objek ke state tersimpan. Pemisahan ini memudahkan perubahan format save di masa depan tanpa mengubah SaveLoadManager.
Method
Visibilitas
Tipe
Nama
Keterangan
+
std::string
serialize(const GameEngine& game)
Mengubah seluruh state GameEngine menjadi string teks terstruktur sesuai format spesifikasi
Memparsing blok log dan merestorasi entries ke TransactionLogger
Relasi dengan Kelas Lain
digunakan olehSaveLoadManager
menggunakanGameEngine, Board, Player, CardManager, TransactionLogger sebagai sumber data serialize dan target deserialize
2.48. Kelas Command
Command merepresentasikan satu perintah dari pemain setelah diparse oleh CommandParser. Ia menyimpan CommandType (enum untuk setiap jenis perintah) dan vector<string> argumen tambahan. GameEngine menerima Command dan mendispatch ke handler yang sesuai berdasarkan type.
Atribut
Visibilitas
Tipe
Nama
Keterangan
+
CommandType
type
Jenis perintah (enum: PRINT_BOARD, ROLL_DICE, BUILD, SAVE, dst.)
+
std::vector<std::string>
args
Argumen tambahan (misal: kode properti, nama file, nilai dadu)
Method
Visibilitas
Tipe
Nama
Keterangan
+
Command(CommandType t, std::vector<std::string> a)
Konstruktor utama dengan tipe dan argumen
+
bool
hasArgs() const
True jika vector args tidak kosong
Relasi dengan Kelas Lain
diproduksi olehCommandParser
digunakan olehGameEngine untuk dispatch ke handler
2.49. Kelas LogEntry
LogEntry menyimpan satu entri log permainan: nomor turn, username pemain yang melakukan aksi, jenis aksi (sebagai string), dan detail aksi lengkap termasuk nilai uang jika ada. Digunakan secara internal oleh TransactionLogger dan oleh GameStateSerializer saat menyimpan log ke file.
Atribut
Visibilitas
Tipe
Nama
Keterangan
+
int
turn
Nomor turn saat entri ini dicatat
+
std::string
username
Username pemain yang melakukan aksi
+
std::string
action
Jenis aksi (misal: "DADU", "BELI", "SEWA", "KARTU")
+
std::string
detail
Detail aksi lengkap (misal: "Lempar: 3+4=7, mendarat di BDG")
Method
Visibilitas
Tipe
Nama
Keterangan
+
std::string
toString() const
Menghasilkan string format tampilan: `"[Turn N] User
Relasi dengan Kelas Lain
disimpan dalamTransactionLogger
digunakan olehGameStateSerializer untuk serialisasi log
3. Justifikasi
3.1. Alasan Pemilihan Desain
Desain kelas dibangun atas tiga prinsip utama yaitu Layered Architecture, Single Responsibility Principle, dan Composition over Inheritance. Prinsip ini dipilih sebagai fondasi karena spesifikasi permainan memiliki banyak mekanisme yang kompleks dan saling berinteraksi, sehingga pemisahan yang jelas antar tanggung jawab menjadi kunci utama agar kode tetap dapat dipahami, dikembangkan, dan diuji secara independen.
Layered Architecture (UI → Core → Data Access) dipilih karena memisahkan input/output dari logika permainan. Tanpa pemisahan ini, setiap perubahan tampilan (misalnya menambahkan pewarnaan baru di papan) akan berisiko merusak logika game. Sebaliknya, dengan lapisan yang bersih, lapisan UI dapat diganti dengan GUI sepenuhnya tanpa menyentuh Core Layer sama sekali.
Pemilihan inheritance pada hierarki Tile, Property, dan Card didasari oleh kebutuhan polimorfisme. GameEngine tidak perlu tahu tipe konkret tile saat memproses landing, PropertyManager tidak perlu tahu apakah properti adalah Street/Railroad/Utility saat menghitung sewa, dan CardManager tidak perlu tahu efek spesifik setiap kartu.
3.2. Kelebihan Desain Kelas
Modularitas tinggi: Setiap kelas memiliki satu tanggung jawab yang jelas. Penambahan jenis tile baru (misalnya PajakBonusTile) cukup membuat subclass Tile baru dengan onLand() yang sesuai, tanpa mengubah GameEngine, Board, atau tile lain. Hal yang sama berlaku untuk kartu baru atau jenis properti baru.
Polimorfisme yang bermakna: Ketiga hierarki utama (Tile, Property, Card) menggunakan virtual function secara logis sesuai use case, bukan sekadar formalitas. onLand() di Tile, calculateRent() di Property, dan apply() di Card masing-masing adalah titik ekstensi yang nyata.
Reusability via Generic Class:Deck<T> menghindari duplikasi kode untuk chanceDeck, communityDeck, dan skillDeck. Tanpa template, harus ada tiga kelas deck yang hampir identik dengan hanya perbedaan tipe elemen.
Testability: Karena setiap Manager berdiri sendiri dan menerima dependensi lewat referensi (bukan membuat sendiri), setiap Manager dapat diuji secara unit dengan mock/stub untuk dependensinya.
Pemisahan Data dari Posisi (Property vs Tile): Memisahkan PropertyTile (posisi di papan) dari Property (data aset) adalah keputusan desain yang penting. Data kepemilikan, bangunan, dan efek festival pada Property harus tetap ada dan konsisten terlepas dari posisi pemain; pemisahan ini memungkinkan hal tersebut.
Operator Overloading yang semantis: Penggunaan operator+= dan operator-= pada Player untuk operasi uang membuat kode seperti player += salary dan player -= rent lebih ekspresif dan lebih mudah dibaca dibandingkan player.addMoney(salary) yang panjang, sambil tetap menjaga enkapsulasi.
3.3. Kekurangan Desain Kelas
Ketergantungan silang antar Manager:PropertyManager perlu referensi ke AuctionManager dan BankruptcyManager; BankruptcyManager perlu referensi ke AuctionManager. Ketergantungan ini wajar secara domain bisnis (proses beli properti memang bisa berujung lelang yang bisa berujung bankruptcy), namun meningkatkan coupling antar Manager. Solusi ideal adalah menggunakan Observer Pattern atau Event System, namun hal tersebut meningkatkan kompleksitas yang mungkin tidak sebanding untuk skala proyek ini.
GameEngine masih menjadi pusat hubung: Ia tetap menjadi titik temu yang mengetahui semua Manager sekaligus. Untuk skala proyek yang lebih besar, bisa dipertimbangkan pola Mediator yang lebih formal, namun untuk proyek ini dinilai sudah cukup bersih.
Property::calculateRent() membutuhkan GameContext yang cukup besar:GameContext menyertakan referensi ke Board dan seluruh vector<Player> agar subclass dapat menghitung kepemilikan. Ini berarti setiap panggilan calculateRent() membawa overhead berupa referensi ke struktur besar. Alternatifnya adalah meneruskan nilai spesifik (jumlah railroad, total dadu) sebagai parameter terpisah, namun pendekatan itu akan memecah polimorfisme karena setiap subclass butuh parameter yang berbeda.
Kompleksitas BankruptcyManager: Mekanisme likuidasi interaktif (panel jual/gadai) menjadikan BankruptcyManager sebagai kelas yang paling kompleks dalam desain. Alternatif yang lebih bersih adalah memisahkan LiquidationPanel sebagai kelas UI tersendiri, namun hal ini menambah jumlah kelas yang perlu dikelola.
3.4. Kendala Dalam Pemilihan Desain
Dilema UI Otomatis vs Interaktif: Beberapa aksi dalam spesifikasi bersifat otomatis namun tetap memerlukan interaksi pengguna. Cara yang diambil adalah Core Logic menentukan apa yang harus terjadi (logika bisnis), sementara UI Layer menampilkan prompt dan mengambil input, lalu hasilnya diteruskan kembali ke Core. Hal ini memerlukan sedikit coupling terkontrol antara Manager dan GameUI.
Penempatan Logika Penjara: Mekanisme penjara melibatkan tiga kelas (JailTile, GoToJailTile, GoToJailCard) dan juga logika giliran. Logika giliran tetap di GameEngine::handleJailTurn() karena terkait erat dengan TurnManager, sementara JailTile hanya menyimpan state dan menyediakan sendToJail().
Shared_ptr vs Raw Pointer untuk Property:Property dipegang oleh PropertyTile (shared_ptr) sekaligus direferensikan oleh Player (raw pointer). Ini menyebabkan mixed ownership. Keputusan diambil karena PropertyTile adalah pemilik Property, sementara Player hanya perlu referensi; raw pointer lebih ringan dan tepat untuk referensi non-owning. Konsekuensinya, tim harus berhati-hati agar tidak ada dangling pointer saat pemain bangkrut.