From 16a4b2dbe74b295c5bb6a93db8348dc744f1f96d Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:25:51 +0000 Subject: [PATCH 001/115] Setting up GitHub Classroom Feedback From f8c5b46063da274a1c088a06f98ca237d6d154e3 Mon Sep 17 00:00:00 2001 From: Cirrofy Date: Wed, 1 May 2024 18:36:46 +0700 Subject: [PATCH 002/115] feat: Shop and Currency (Base Code) --- shop_currency.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 shop_currency.py diff --git a/shop_currency.py b/shop_currency.py new file mode 100644 index 0000000..f61210c --- /dev/null +++ b/shop_currency.py @@ -0,0 +1,51 @@ +def shopOpen(role): + if role == "agent": + print("Selamat datang di Shop!") + keluar = False + while keluar != True: + pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + print("monster") + lihatSelesai == True + # monster_list() + elif lihat_pilih == "potion": + print("potion") + lihatSelesai == True + # potion_list() + elif pilihMenu == "beli": + print("Jumlah O.W.C.A Coin-mu sekarang [jumlah].") + print() + beliType = input(">>> Mau beli apa? (monster/potion): ") + beliSelesai = False + while beliType != "monster" and beliType != "potion" and beliSelesai != True: + beliType = input(">>> Pilih antara monster/potion: ") + if beliType == "monster": + idMonsterBeli = input(">>> Masukkan id monster: ") + # if monster in inventory: + # print("[nama monster] sudah ada dalam inventory-mu! Pembelian dibatalkan.") + # if OWCA >= harga monster: + print("Berhasil membeli item: [nama monster]. Item sudah masuk ke inventory-mu!") + print() + beliSelesai == True + # Di sini ntar masukkin monster ke inventory, sama stok di toko ngurang 1 (harus ada database dulu), sama OWCA ngurang + # else: + # print("OC-mu tidak cukup.") + elif beliType == "potion": + idpotionBeli = input(">>> Masukkan id potion: ") + jumlahPotionBeli = input(">>> Masukkan jumlah: ") + # if OWCA >= jumlah x potion: + print("Berhasil membeli item: [jumlah potion] [nama potion]. Item sudah masuk ke inventory-mu!") + print() + beliSelesai == True + else: # pilihMenu == "keluar" + keluar == True + print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") + break + +role = "agent" +shopOpen("agent") \ No newline at end of file From da3103c7e4917258bac0deeac52d85a5505751dc Mon Sep 17 00:00:00 2001 From: 19623238-Favian <148781301+19623238-Favian@users.noreply.github.com> Date: Wed, 1 May 2024 18:38:24 +0700 Subject: [PATCH 003/115] Delete shop_currency.py --- shop_currency.py | 51 ------------------------------------------------ 1 file changed, 51 deletions(-) delete mode 100644 shop_currency.py diff --git a/shop_currency.py b/shop_currency.py deleted file mode 100644 index f61210c..0000000 --- a/shop_currency.py +++ /dev/null @@ -1,51 +0,0 @@ -def shopOpen(role): - if role == "agent": - print("Selamat datang di Shop!") - keluar = False - while keluar != True: - pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": - print("monster") - lihatSelesai == True - # monster_list() - elif lihat_pilih == "potion": - print("potion") - lihatSelesai == True - # potion_list() - elif pilihMenu == "beli": - print("Jumlah O.W.C.A Coin-mu sekarang [jumlah].") - print() - beliType = input(">>> Mau beli apa? (monster/potion): ") - beliSelesai = False - while beliType != "monster" and beliType != "potion" and beliSelesai != True: - beliType = input(">>> Pilih antara monster/potion: ") - if beliType == "monster": - idMonsterBeli = input(">>> Masukkan id monster: ") - # if monster in inventory: - # print("[nama monster] sudah ada dalam inventory-mu! Pembelian dibatalkan.") - # if OWCA >= harga monster: - print("Berhasil membeli item: [nama monster]. Item sudah masuk ke inventory-mu!") - print() - beliSelesai == True - # Di sini ntar masukkin monster ke inventory, sama stok di toko ngurang 1 (harus ada database dulu), sama OWCA ngurang - # else: - # print("OC-mu tidak cukup.") - elif beliType == "potion": - idpotionBeli = input(">>> Masukkan id potion: ") - jumlahPotionBeli = input(">>> Masukkan jumlah: ") - # if OWCA >= jumlah x potion: - print("Berhasil membeli item: [jumlah potion] [nama potion]. Item sudah masuk ke inventory-mu!") - print() - beliSelesai == True - else: # pilihMenu == "keluar" - keluar == True - print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break - -role = "agent" -shopOpen("agent") \ No newline at end of file From 9cd1271587e4b15afdce0b16a616b8d42258855c Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Wed, 1 May 2024 18:45:45 +0700 Subject: [PATCH 004/115] feat: Shop and Currency Function (V0.1) --- shop_currency.py | 1 - 1 file changed, 1 deletion(-) diff --git a/shop_currency.py b/shop_currency.py index f61210c..23b65b9 100644 --- a/shop_currency.py +++ b/shop_currency.py @@ -47,5 +47,4 @@ def shopOpen(role): print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") break -role = "agent" shopOpen("agent") \ No newline at end of file From 01a65bd3719e5e21b602c74aff7b4a9d55750fe7 Mon Sep 17 00:00:00 2001 From: 19623238-Favian <148781301+19623238-Favian@users.noreply.github.com> Date: Wed, 1 May 2024 18:57:59 +0700 Subject: [PATCH 005/115] refactor: Memindahkan file ke folder src --- shop_currency.py => src/shop_currency.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename shop_currency.py => src/shop_currency.py (99%) diff --git a/shop_currency.py b/src/shop_currency.py similarity index 99% rename from shop_currency.py rename to src/shop_currency.py index 23b65b9..d4a7d26 100644 --- a/shop_currency.py +++ b/src/shop_currency.py @@ -47,4 +47,4 @@ def shopOpen(role): print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") break -shopOpen("agent") \ No newline at end of file +shopOpen("agent") From 02dca4cec0c061ee4e4c72c3892870a84c13da4e Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Fri, 3 May 2024 15:28:30 +0700 Subject: [PATCH 006/115] feat: .csv parser Function --- data/item_shop.csv | 4 ++++ src/csvParser.py | 25 +++++++++++++++++++++++++ src/shop_currency.py | 4 ++-- 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 data/item_shop.csv create mode 100644 src/csvParser.py diff --git a/data/item_shop.csv b/data/item_shop.csv new file mode 100644 index 0000000..69ccb85 --- /dev/null +++ b/data/item_shop.csv @@ -0,0 +1,4 @@ +type;stock;price +strength;5;40 +resilience;5;35 +healing;5;25 \ No newline at end of file diff --git a/src/csvParser.py b/src/csvParser.py new file mode 100644 index 0000000..250d54e --- /dev/null +++ b/src/csvParser.py @@ -0,0 +1,25 @@ +def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja + separated = [] + word = '' + + for char in (text): + if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) + break + elif char != ';': + word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata + else: # char == ";" + separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array + word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) + + separated.append(word) # Untuk kata setelah semicolon terakhir + + return separated + +def csvRead(path): # Fungsi membaca file .csv baris per baris + csvOpen = open(path,'r') # Membuka file .csv + + for row in csvOpen: # Membaca setiap baris + cleanData = splitSemicolon(row) # Memisahkan kalimat dari semicolon + + csvOpen.close() # Menutup file + return cleanData \ No newline at end of file diff --git a/src/shop_currency.py b/src/shop_currency.py index d4a7d26..479f285 100644 --- a/src/shop_currency.py +++ b/src/shop_currency.py @@ -45,6 +45,6 @@ def shopOpen(role): else: # pilihMenu == "keluar" keluar == True print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break + break -shopOpen("agent") +shopOpen("agent") \ No newline at end of file From 88cbaf8bd82b03c73e276f293e9876df627129fb Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Fri, 3 May 2024 15:50:17 +0700 Subject: [PATCH 007/115] fix: Memperbaiki csvParser.py --- src/csvParser.py | 10 ++++++++-- src/shop_currency.py | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/csvParser.py b/src/csvParser.py index 250d54e..0d3caef 100644 --- a/src/csvParser.py +++ b/src/csvParser.py @@ -1,3 +1,6 @@ +import sys +sys.path.append("C:\if1210-2024-tubes-k08-b\data") + def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja separated = [] word = '' @@ -17,9 +20,12 @@ def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemi def csvRead(path): # Fungsi membaca file .csv baris per baris csvOpen = open(path,'r') # Membuka file .csv + cleanData = [] for row in csvOpen: # Membaca setiap baris - cleanData = splitSemicolon(row) # Memisahkan kalimat dari semicolon + cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon csvOpen.close() # Menutup file - return cleanData \ No newline at end of file + return cleanData + +print(csvRead("C:\if1210-2024-tubes-k08-b\data\item_shop.csv")) \ No newline at end of file diff --git a/src/shop_currency.py b/src/shop_currency.py index 479f285..f208357 100644 --- a/src/shop_currency.py +++ b/src/shop_currency.py @@ -1,3 +1,5 @@ +from csvParser import splitSemicolon, csvRead + def shopOpen(role): if role == "agent": print("Selamat datang di Shop!") @@ -45,6 +47,4 @@ def shopOpen(role): else: # pilihMenu == "keluar" keluar == True print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break - -shopOpen("agent") \ No newline at end of file + break \ No newline at end of file From 4f881f44b542a25329aa697cb602e82d4636af8f Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Fri, 3 May 2024 21:36:37 +0700 Subject: [PATCH 008/115] feat: Menambah fungsi csv Parser lengkap dan F10&F12 (V0.5) --- data/item_shop.csv | 6 +- src/csvParser.py | 55 +++++++++++--- src/shop_currency.py | 156 ++++++++++++++++++++++++++++++++++++-- src/tempCodeRunnerFile.py | 1 + 4 files changed, 198 insertions(+), 20 deletions(-) create mode 100644 src/tempCodeRunnerFile.py diff --git a/data/item_shop.csv b/data/item_shop.csv index 69ccb85..726b13b 100644 --- a/data/item_shop.csv +++ b/data/item_shop.csv @@ -1,4 +1,4 @@ type;stock;price -strength;5;40 -resilience;5;35 -healing;5;25 \ No newline at end of file +Strength Potion;5;40 +Resilience Potion;5;35 +Healing Potion;5;25 \ No newline at end of file diff --git a/src/csvParser.py b/src/csvParser.py index 0d3caef..669394e 100644 --- a/src/csvParser.py +++ b/src/csvParser.py @@ -1,31 +1,62 @@ import sys sys.path.append("C:\if1210-2024-tubes-k08-b\data") -def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja +def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja separated = [] word = '' for char in (text): - if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) + if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) break elif char != ';': - word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata + word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata else: # char == ";" - separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array - word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) + separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array + word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) - separated.append(word) # Untuk kata setelah semicolon terakhir + separated.append(word) # Untuk kata setelah semicolon terakhir return separated -def csvRead(path): # Fungsi membaca file .csv baris per baris - csvOpen = open(path,'r') # Membuka file .csv +def csvRead(path): # Fungsi membaca file .csv baris per baris + csvOpen = open(path,'r') # Membuka file .csv cleanData = [] - for row in csvOpen: # Membaca setiap baris - cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon + for row in csvOpen: # Membaca setiap baris + cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon - csvOpen.close() # Menutup file + csvOpen.close() # Menutup file return cleanData -print(csvRead("C:\if1210-2024-tubes-k08-b\data\item_shop.csv")) \ No newline at end of file +def csvWrite(path, input): # Fungsi memasukkan data dengan line baru pada csv + with open(path,'a', newline="") as csvOpen: # Membuka csv (dengan with, file tidak perlu diclose) + csvOpen.write('\n') + csvOpen.write(''.join(input)) # Mengisi baris baru dengan input + return + +def csvOverwrite(path, row, input): # Fungsi memperbaharui data yang sudah ada dengan data baru + csvOpen = open(path,'r') # Membuka csv + tempData = [] # Data sementara + for i in csvOpen: + tempData.append(i) # Mengisi list dengan data pada csv tanpa menghilangkan semicolon (";") + tempData[row] = input # Mengubah data csv pada baris yang ditentukan dengan input yang baru + + with open(path,'w') as csvWrite: # Mengembalikan bentuk list menjadi bentuk csv semula + for rows in tempData: + tempData = csvWrite.write(''.join(rows)) + return + +def csvDelete(path, row): # Fungsi menghapus data pada baris yang ditentukan + csvOpen = open(path,'r') # Membuka csv + tempData = [] # Data sementara + count = 0 + for i in csvOpen: + tempData.append(i) # Mengisi list dengan data tanpa menghilangkan semicolon (";") + if count == row: # Pada baris yang ditentukan, data di-pop (dihapus) + tempData.pop(row) + count += 1 + + with open(path,'w') as csvWrite: # Mengembalikan bentuk list menjadi bentuk csv semula + for rows in tempData: + tempData = csvWrite.write(''.join(rows)) + return \ No newline at end of file diff --git a/src/shop_currency.py b/src/shop_currency.py index f208357..5cfafc5 100644 --- a/src/shop_currency.py +++ b/src/shop_currency.py @@ -1,8 +1,12 @@ -from csvParser import splitSemicolon, csvRead +from csvParser import splitSemicolon, csvRead, csvWrite, csvOverwrite, csvDelete +pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" +potionList = csvRead(pathItemShop) +potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"] def shopOpen(role): if role == "agent": print("Selamat datang di Shop!") + print() keluar = False while keluar != True: pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") @@ -16,9 +20,10 @@ def shopOpen(role): lihatSelesai == True # monster_list() elif lihat_pilih == "potion": - print("potion") + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") lihatSelesai == True - # potion_list() elif pilihMenu == "beli": print("Jumlah O.W.C.A Coin-mu sekarang [jumlah].") print() @@ -38,7 +43,7 @@ def shopOpen(role): # else: # print("OC-mu tidak cukup.") elif beliType == "potion": - idpotionBeli = input(">>> Masukkan id potion: ") + idPotionBeli = input(">>> Masukkan id potion: ") jumlahPotionBeli = input(">>> Masukkan jumlah: ") # if OWCA >= jumlah x potion: print("Berhasil membeli item: [jumlah potion] [nama potion]. Item sudah masuk ke inventory-mu!") @@ -47,4 +52,145 @@ def shopOpen(role): else: # pilihMenu == "keluar" keluar == True print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break \ No newline at end of file + break + elif role == "admin": + print("Selamat datang kembali, Admin!") + print() + keluar = False + while keluar != True: + pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + print("monster") + lihatSelesai == True + # monster_list() + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") + lihatSelesai == True + elif pilihMenu == "tambah": + tambah_pilih = input("Mau tambah apa? (monster/potion): ") + tambahSelesai = False + while tambah_pilih != "monster" and tambah_pilih != "potion" and tambahSelesai != True: + tambah_pilih = (input(">>> Pilih antara monster/potion: ")) + if tambah_pilih == "monster": + print("monster") # Nanti di sini list semua monster dari database yang belom ada di Shop + print() + idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi + stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) + hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + # monster_list.append() + print("[nama monster] telah berhasil ditambahkan ke dalam Shop!") + elif tambah_pilih == "potion": + potionFound = False + countFalse = 0 + print("ID | Type") + for i in range(1,4): + for j in range(1,len(potionList)): + if potionID[i] in potionList[j][0]: + potionFound = True + break + else: + potionFound = False + continue + if potionFound == False: + print(f"{i} | {potionID[i]}") + countFalse += 1 + if countFalse == 0: + print("Semua Potion sudah tersedia pada Shop!") + print() + else: + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + while (idPotionTambah < 1 or idPotionTambah > 3): + print("id tidak valid!") + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + stokPotionTambah = int(input("Masukkan stok awal: ")) + hargaPotionTambah = int(input("Masukkan harga: ")) + csvWrite(pathItemShop, f"{potionID[idPotionTambah]};{stokPotionTambah};{hargaPotionTambah}") + print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") + print() + elif pilihMenu == "ubah": + ubah_pilih = input("Mau ubah apa? (monster/potion): ") + ubahSelesai = False + while ubah_pilih != "monster" and ubah_pilih != "potion" and ubahSelesai != True: + ubah_pilih = (input(">>> Pilih antara monster/potion: ")) + if ubah_pilih == "monster": + idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi + stokMonsterBaru = (input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"[nama monster] telah berhasil diubah " + # komponenubah = f"{monsterList[int(idMonsterUbah)]};" + if (stokMonsterBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + # komponenUbah += f"{stokMonsterBaru};" + # else: + # komponenUbah += f"{monsterList[int(idMonsterUbah)][1];}" + if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): + pesanUbah += " dan " + if (hargaMonsterBaru != ""): + pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + # komponenUbah += f"{hargaMonsterBaru}" + # else: + # komponenUbah += f"{monsterList[int(idMonsterUbah)][2]}" + pesanUbah += "!" + csvOverwrite(pathItemShop, int(idMonsterUbah)) # , komponenUbah (Nanti) + print(pesanUbah) + elif ubah_pilih == "potion": + idPotionUbah = (input(">>> Masukkan id potion: ")) + stokPotionBaru = (input(">>> Masukkan stok baru: ")) + hargaPotionBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " + komponenUbah = f"{potionID[int(idPotionUbah)]};" + if (stokPotionBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" + komponenUbah += f"{stokPotionBaru};" + else: + komponenUbah += f"{potionList[int(idPotionUbah)][1]};" + if (stokPotionBaru != "") and (hargaPotionBaru != ""): + pesanUbah += " dan " + if (hargaPotionBaru != ""): + pesanUbah += f"dengan harga baru {hargaPotionBaru}" + komponenUbah += f"{hargaPotionBaru}" + else: + komponenUbah += f"{potionList[int(idPotionUbah)][2]}" + pesanUbah += "!" + csvDelete(pathItemShop, int(idPotionUbah), komponenUbah) + print(pesanUbah) + print() + elif pilihMenu == "hapus": + hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") + hapusSelesai = False + while hapusPilih != "monster" and hapusPilih != "potion" and hapusSelesai != True: + hapusPilih = (input(">>> Pilih antara monster/potion: ")) + if hapusPilih == "monster": + idMonsterHapus = input(">>> Masukkan id monster: ") + # yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterList[int(idPokemonHapus)]} dari Shop (y/n)? ) + # if yakinHapus == "y": + # csvDelete(pathItemShop, int(idMonsterHapus)) + # print(f"{monsterList[int(idPokemonHapus)]} telah berhasil dihapus dari Shop!") + # else: + # continue + elif hapusPilih == "potion": + idPotionHapus = input(">>> Masukkan id potion: ") + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[int(idPotionHapus)]} dari Shop (y/n)? ") + if yakinHapus == "y": + csvDelete(pathItemShop, int(idPotionHapus)) + print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") + print() + else: + print("Penghapusan dibatalkan!") + print() + continue + else: # pilihMenu == "keluar" + keluar == True + print("Sampai bertemu lagi Admin!") + break + return + +# shopOpen("agent") +# shopOpen("admin") \ No newline at end of file diff --git a/src/tempCodeRunnerFile.py b/src/tempCodeRunnerFile.py new file mode 100644 index 0000000..9ad1705 --- /dev/null +++ b/src/tempCodeRunnerFile.py @@ -0,0 +1 @@ +csvOpen \ No newline at end of file From 0d82bb8ea5059c53e8eeb32436b290676287caeb Mon Sep 17 00:00:00 2001 From: echaa0018 <19623278@std.stei.itb.ac.id> Date: Fri, 10 May 2024 09:05:41 +0700 Subject: [PATCH 009/115] feat: Random Number Generator --- src/RandomNumberGenerator.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/RandomNumberGenerator.py diff --git a/src/RandomNumberGenerator.py b/src/RandomNumberGenerator.py new file mode 100644 index 0000000..e69de29 From 8687de2accf0286b517680b65d0a87e3e1550851 Mon Sep 17 00:00:00 2001 From: echaa0018 <19623278@std.stei.itb.ac.id> Date: Fri, 10 May 2024 09:06:43 +0700 Subject: [PATCH 010/115] feat: Random Number Generator --- src/RandomNumberGenerator.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/RandomNumberGenerator.py b/src/RandomNumberGenerator.py index e69de29..60a3b44 100644 --- a/src/RandomNumberGenerator.py +++ b/src/RandomNumberGenerator.py @@ -0,0 +1,27 @@ +import os +import time + +# Fungsi untuk membuat sebuah nomor acak +def LCG(a, c, m): + seed = int(os.getpid()*123 + time.time()*45) + x2 = (a * seed + c) % m # Rumus Dasar LCG + return x2 +# Seed ditentukan menggunakan process id dan time agar selalu bervariasi +# *123, *45 hanya untuk menambah kerandoman + +# Fungsi untuk memastikan bahwa nomor acak yang didapat berada pada range yang ditentukan +def GenerateNumber(x2,num_range): + a = 48271 + c = 0 + m = 2**31 - 1 + # Nilai-nilai diatas diapakai dalam C++11 dalam fungsi minstd_rand + x2 = (a * x2 + c) % m + return int((x2 / (m - 1)) * (num_range[1] - num_range[0]) + num_range[0]) +# Dapet formula dari yt :) + +# Fungsi yang digunakan untuk mensimplifikasi sehingga hanya perlu menyertakan batas-batasnnya +def RNG(x,y): + a = 48271 + c = 0 + m = 2**31 - 1 + return GenerateNumber(LCG(a,c,m),[x,y]) \ No newline at end of file From cc6ddd235d5a601c02359ef80504dd940eeb72a1 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sat, 11 May 2024 23:40:25 +0700 Subject: [PATCH 011/115] docs: file monster_shop.csv --- data/monster_shop.csv | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/monster_shop.csv diff --git a/data/monster_shop.csv b/data/monster_shop.csv new file mode 100644 index 0000000..41ee368 --- /dev/null +++ b/data/monster_shop.csv @@ -0,0 +1,4 @@ +monster_id;stock;price +1;6;800 +2;13;300 +3;2;750 \ No newline at end of file From e0a3d5eec327551b8a1e67cdb4bdccc9c4d3a770 Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Wed, 15 May 2024 11:51:50 +0700 Subject: [PATCH 012/115] refactor: Updating and Changing Variables of ShopCurrency and csvParser --- data/item_shop.csv | 6 +- src/csvParser.py | 10 +- src/{shop_currency.py => shopCurrency.py} | 156 ++++++++++------------ 3 files changed, 85 insertions(+), 87 deletions(-) rename src/{shop_currency.py => shopCurrency.py} (60%) diff --git a/data/item_shop.csv b/data/item_shop.csv index 726b13b..970a469 100644 --- a/data/item_shop.csv +++ b/data/item_shop.csv @@ -1,4 +1,4 @@ type;stock;price -Strength Potion;5;40 -Resilience Potion;5;35 -Healing Potion;5;25 \ No newline at end of file +Strength Potion;5;35 +Resilience Potion;5;25 +Healing Potion;5;40 \ No newline at end of file diff --git a/src/csvParser.py b/src/csvParser.py index 669394e..1cdc08c 100644 --- a/src/csvParser.py +++ b/src/csvParser.py @@ -51,12 +51,18 @@ def csvDelete(path, row): # Fun tempData = [] # Data sementara count = 0 for i in csvOpen: + if count == row: # Pada baris yang ditentukan, data dilewat + continue tempData.append(i) # Mengisi list dengan data tanpa menghilangkan semicolon (";") - if count == row: # Pada baris yang ditentukan, data di-pop (dihapus) - tempData.pop(row) count += 1 with open(path,'w') as csvWrite: # Mengembalikan bentuk list menjadi bentuk csv semula for rows in tempData: tempData = csvWrite.write(''.join(rows)) + return + +def csvWriteAll(path,newList): # Fungsi mengupdate csv lama dengan data-data list terbaru + with open(path,'w') as csvWrite: + for rows in newList: + csvWrite.write(''.join(rows)) return \ No newline at end of file diff --git a/src/shop_currency.py b/src/shopCurrency.py similarity index 60% rename from src/shop_currency.py rename to src/shopCurrency.py index 5cfafc5..daa7198 100644 --- a/src/shop_currency.py +++ b/src/shopCurrency.py @@ -1,82 +1,75 @@ -from csvParser import splitSemicolon, csvRead, csvWrite, csvOverwrite, csvDelete +from csvParser import csvRead, csvWrite, csvOverwrite, csvDelete, csvWriteAll pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" potionList = csvRead(pathItemShop) potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"] +def shopInterface(): + print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") + print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") + print(" |___|__∆|___|_|∆|_| ███▀▀▀███ __||_ ") + print(" |∆__|___|∆__|∆|_|_| ███████ /_____\ ") + print(" |___|_∆_|___|_|∆|_| ██████████████ KASIR ██") + print(" =================== ███████████████████████") + return + +def sortPotion(potionList): + if potionList[1][0] == "Resilience Potion": + potionList[1][0],potionList[2][0] = potionList[2][0],potionList[1][0] + if potionList[3][0] == "Resilience Potion": + potionList[3][0],potionList[2][0] = potionList[2][0],potionList[3][0] + if potionList[1][0] == "Healing Potion": + potionList[1][0],potionList[3][0] = potionList[3][0],potionList[1][0] + return potionList + +def listTocsv(list): + new_csv = [] + csvCell = "" + for i in range(len(list)): + for j in range(len(list[1])): + csvCell += f"{list[i][j]}" + if j != len(list[1])-1: + csvCell += f";" + if i != len(list)-1 and j == len(list[1])-1: + csvCell += "\n" + new_csv.append(csvCell) + csvCell = "" + return new_csv + def shopOpen(role): + global potionList if role == "agent": - print("Selamat datang di Shop!") + print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") + print() + shopInterface() print() - keluar = False - while keluar != True: - pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": - print("monster") - lihatSelesai == True - # monster_list() - elif lihat_pilih == "potion": - print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") - lihatSelesai == True - elif pilihMenu == "beli": - print("Jumlah O.W.C.A Coin-mu sekarang [jumlah].") - print() - beliType = input(">>> Mau beli apa? (monster/potion): ") - beliSelesai = False - while beliType != "monster" and beliType != "potion" and beliSelesai != True: - beliType = input(">>> Pilih antara monster/potion: ") - if beliType == "monster": - idMonsterBeli = input(">>> Masukkan id monster: ") - # if monster in inventory: - # print("[nama monster] sudah ada dalam inventory-mu! Pembelian dibatalkan.") - # if OWCA >= harga monster: - print("Berhasil membeli item: [nama monster]. Item sudah masuk ke inventory-mu!") - print() - beliSelesai == True - # Di sini ntar masukkin monster ke inventory, sama stok di toko ngurang 1 (harus ada database dulu), sama OWCA ngurang - # else: - # print("OC-mu tidak cukup.") - elif beliType == "potion": - idPotionBeli = input(">>> Masukkan id potion: ") - jumlahPotionBeli = input(">>> Masukkan jumlah: ") - # if OWCA >= jumlah x potion: - print("Berhasil membeli item: [jumlah potion] [nama potion]. Item sudah masuk ke inventory-mu!") - print() - beliSelesai == True - else: # pilihMenu == "keluar" - keluar == True - print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break elif role == "admin": - print("Selamat datang kembali, Admin!") + print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") print() - keluar = False - while keluar != True: + shopInterface() + print() + while True: pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") if pilihMenu == "lihat": lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + while lihat_pilih != "monster" and lihat_pilih != "potion": lihat_pilih = input(">>> Pilih antara monster/potion: ") if lihat_pilih == "monster": print("monster") - lihatSelesai == True # monster_list() elif lihat_pilih == "potion": print("ID | Type\t\t| Stok\t| Harga") for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") - lihatSelesai == True + if potionList[i][0] == "Strength Potion": + idPotion = 1 + elif potionList[i][0] == "Resilience Potion": + idPotion = 2 + elif potionList[i][0] == "Healing Potion": + idPotion = 3 + print(f"{idPotion} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") + elif pilihMenu == "tambah": tambah_pilih = input("Mau tambah apa? (monster/potion): ") - tambahSelesai = False - while tambah_pilih != "monster" and tambah_pilih != "potion" and tambahSelesai != True: + while tambah_pilih != "monster" and tambah_pilih != "potion": tambah_pilih = (input(">>> Pilih antara monster/potion: ")) if tambah_pilih == "monster": print("monster") # Nanti di sini list semua monster dari database yang belom ada di Shop @@ -111,13 +104,15 @@ def shopOpen(role): idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) stokPotionTambah = int(input("Masukkan stok awal: ")) hargaPotionTambah = int(input("Masukkan harga: ")) - csvWrite(pathItemShop, f"{potionID[idPotionTambah]};{stokPotionTambah};{hargaPotionTambah}") + newPotion = [potionID[idPotionTambah],stokPotionTambah,hargaPotionTambah] + potionList.append(newPotion) + sortPotion(potionList) print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") print() + elif pilihMenu == "ubah": ubah_pilih = input("Mau ubah apa? (monster/potion): ") - ubahSelesai = False - while ubah_pilih != "monster" and ubah_pilih != "potion" and ubahSelesai != True: + while ubah_pilih != "monster" and ubah_pilih != "potion": ubah_pilih = (input(">>> Pilih antara monster/potion: ")) if ubah_pilih == "monster": idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi @@ -141,31 +136,24 @@ def shopOpen(role): csvOverwrite(pathItemShop, int(idMonsterUbah)) # , komponenUbah (Nanti) print(pesanUbah) elif ubah_pilih == "potion": - idPotionUbah = (input(">>> Masukkan id potion: ")) - stokPotionBaru = (input(">>> Masukkan stok baru: ")) - hargaPotionBaru = (input(">>> Masukkan harga baru: ")) + idPotionUbah = int((input(">>> Masukkan id potion: "))) + stokPotionBaru = int((input(">>> Masukkan stok baru: "))) + hargaPotionBaru = int((input(">>> Masukkan harga baru: "))) pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " - komponenUbah = f"{potionID[int(idPotionUbah)]};" if (stokPotionBaru != ""): pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" - komponenUbah += f"{stokPotionBaru};" - else: - komponenUbah += f"{potionList[int(idPotionUbah)][1]};" if (stokPotionBaru != "") and (hargaPotionBaru != ""): pesanUbah += " dan " if (hargaPotionBaru != ""): pesanUbah += f"dengan harga baru {hargaPotionBaru}" - komponenUbah += f"{hargaPotionBaru}" - else: - komponenUbah += f"{potionList[int(idPotionUbah)][2]}" pesanUbah += "!" - csvDelete(pathItemShop, int(idPotionUbah), komponenUbah) + potionList[idPotionUbah] = [potionID[idPotionUbah],stokPotionBaru,hargaPotionBaru] print(pesanUbah) print() + elif pilihMenu == "hapus": hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") - hapusSelesai = False - while hapusPilih != "monster" and hapusPilih != "potion" and hapusSelesai != True: + while hapusPilih != "monster" and hapusPilih != "potion": hapusPilih = (input(">>> Pilih antara monster/potion: ")) if hapusPilih == "monster": idMonsterHapus = input(">>> Masukkan id monster: ") @@ -176,21 +164,25 @@ def shopOpen(role): # else: # continue elif hapusPilih == "potion": - idPotionHapus = input(">>> Masukkan id potion: ") - yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[int(idPotionHapus)]} dari Shop (y/n)? ") + idPotionHapus = int(input(">>> Masukkan id potion: ")) + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[idPotionHapus]} dari Shop (y/n)? ") if yakinHapus == "y": - csvDelete(pathItemShop, int(idPotionHapus)) + newPotionList = [] + for i in range(len(potionList)): + if i == idPotionHapus: + continue + else: + newPotionList.append(potionList[i]) + potionList = newPotionList print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") print() else: print("Penghapusan dibatalkan!") print() continue + else: # pilihMenu == "keluar" - keluar == True print("Sampai bertemu lagi Admin!") + csvWriteAll(pathItemShop,listTocsv(potionList)) break - return - -# shopOpen("agent") -# shopOpen("admin") \ No newline at end of file +shopOpen("admin") \ No newline at end of file From 7a5f4a56c379306d5299aaa9019f3f665ccca058 Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Wed, 15 May 2024 11:57:08 +0700 Subject: [PATCH 013/115] feat: csvParser --- src/shop_currency.py | 208 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 src/shop_currency.py diff --git a/src/shop_currency.py b/src/shop_currency.py new file mode 100644 index 0000000..8d62a7b --- /dev/null +++ b/src/shop_currency.py @@ -0,0 +1,208 @@ +from csvParser import csvRead, csvWrite, csvOverwrite, csvDelete, csvWriteAll +pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" +potionList = csvRead(pathItemShop) +potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"] +def shopInterface(): + print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") + print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") + print(" |___|__∆|___|_|∆|_| ███▀▀▀███ __||_ ") + print(" |∆__|___|∆__|∆|_|_| ███████ /_____\ ") + print(" |___|_∆_|___|_|∆|_| ██████████████ KASIR ██") + print(" =================== ███████████████████████") + return + +def shopOpen(role): + if role == "agent": + print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") + print() + shopInterface() + print() + keluar = False + while keluar != True: + pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + print("monster") + lihatSelesai == True + # monster_list() + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") + lihatSelesai == True + elif pilihMenu == "beli": + print("Jumlah O.W.C.A Coin-mu sekarang [jumlah].") + print() + beliType = input(">>> Mau beli apa? (monster/potion): ") + beliSelesai = False + while beliType != "monster" and beliType != "potion" and beliSelesai != True: + beliType = input(">>> Pilih antara monster/potion: ") + if beliType == "monster": + idMonsterBeli = input(">>> Masukkan id monster: ") + # if monster in inventory: + # print("[nama monster] sudah ada dalam inventory-mu! Pembelian dibatalkan.") + # if OWCA >= harga monster: + print("Berhasil membeli item: [nama monster]. Item sudah masuk ke inventory-mu!") + print() + beliSelesai == True + # Di sini ntar masukkin monster ke inventory, sama stok di toko ngurang 1 (harus ada database dulu), sama OWCA ngurang + # else: + # print("OC-mu tidak cukup.") + elif beliType == "potion": + idPotionBeli = input(">>> Masukkan id potion: ") + jumlahPotionBeli = input(">>> Masukkan jumlah: ") + # if OWCA >= jumlah x potion: + print("Berhasil membeli item: [jumlah potion] [nama potion]. Item sudah masuk ke inventory-mu!") + print() + beliSelesai == True + else: # pilihMenu == "keluar" + keluar == True + print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") + break + elif role == "admin": + print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") + print() + shopInterface() + print() + keluar = False + while keluar != True: + pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + print("monster") + lihatSelesai == True + # monster_list() + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") + lihatSelesai == True + elif pilihMenu == "tambah": + tambah_pilih = input("Mau tambah apa? (monster/potion): ") + tambahSelesai = False + while tambah_pilih != "monster" and tambah_pilih != "potion" and tambahSelesai != True: + tambah_pilih = (input(">>> Pilih antara monster/potion: ")) + if tambah_pilih == "monster": + print("monster") # Nanti di sini list semua monster dari database yang belom ada di Shop + print() + idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi + stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) + hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + # monster_list.append() + print("[nama monster] telah berhasil ditambahkan ke dalam Shop!") + elif tambah_pilih == "potion": + potionFound = False + countFalse = 0 + print("ID | Type") + for i in range(1,4): + for j in range(1,len(potionList)): + if potionID[i] in potionList[j][0]: + potionFound = True + break + else: + potionFound = False + continue + if potionFound == False: + print(f"{i} | {potionID[i]}") + countFalse += 1 + if countFalse == 0: + print("Semua Potion sudah tersedia pada Shop!") + print() + else: + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + while (idPotionTambah < 1 or idPotionTambah > 3): + print("id tidak valid!") + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + stokPotionTambah = int(input("Masukkan stok awal: ")) + hargaPotionTambah = int(input("Masukkan harga: ")) + csvWrite(pathItemShop, f"{potionID[idPotionTambah]};{stokPotionTambah};{hargaPotionTambah}") + print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") + print() + elif pilihMenu == "ubah": + ubah_pilih = input("Mau ubah apa? (monster/potion): ") + ubahSelesai = False + while ubah_pilih != "monster" and ubah_pilih != "potion" and ubahSelesai != True: + ubah_pilih = (input(">>> Pilih antara monster/potion: ")) + if ubah_pilih == "monster": + idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi + stokMonsterBaru = (input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"[nama monster] telah berhasil diubah " + # komponenubah = f"{monsterList[int(idMonsterUbah)]};" + if (stokMonsterBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + # komponenUbah += f"{stokMonsterBaru};" + # else: + # komponenUbah += f"{monsterList[int(idMonsterUbah)][1];}" + if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): + pesanUbah += " dan " + if (hargaMonsterBaru != ""): + pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + # komponenUbah += f"{hargaMonsterBaru}" + # else: + # komponenUbah += f"{monsterList[int(idMonsterUbah)][2]}" + pesanUbah += "!" + csvOverwrite(pathItemShop, int(idMonsterUbah)) # , komponenUbah (Nanti) + print(pesanUbah) + elif ubah_pilih == "potion": + idPotionUbah = (input(">>> Masukkan id potion: ")) + stokPotionBaru = (input(">>> Masukkan stok baru: ")) + hargaPotionBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " + komponenUbah = f"{potionID[int(idPotionUbah)]};" + if (stokPotionBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" + komponenUbah += f"{stokPotionBaru};" + else: + komponenUbah += f"{potionList[int(idPotionUbah)][1]};" + if (stokPotionBaru != "") and (hargaPotionBaru != ""): + pesanUbah += " dan " + if (hargaPotionBaru != ""): + pesanUbah += f"dengan harga baru {hargaPotionBaru}" + komponenUbah += f"{hargaPotionBaru}" + else: + komponenUbah += f"{potionList[int(idPotionUbah)][2]}" + pesanUbah += "!" + csvDelete(pathItemShop, int(idPotionUbah), komponenUbah) + print(pesanUbah) + print() + elif pilihMenu == "hapus": + hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") + hapusSelesai = False + while hapusPilih != "monster" and hapusPilih != "potion" and hapusSelesai != True: + hapusPilih = (input(">>> Pilih antara monster/potion: ")) + if hapusPilih == "monster": + idMonsterHapus = input(">>> Masukkan id monster: ") + # yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterList[int(idPokemonHapus)]} dari Shop (y/n)? ) + # if yakinHapus == "y": + # csvDelete(pathItemShop, int(idMonsterHapus)) + # print(f"{monsterList[int(idPokemonHapus)]} telah berhasil dihapus dari Shop!") + # else: + # continue + elif hapusPilih == "potion": + idPotionHapus = input(">>> Masukkan id potion: ") + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[int(idPotionHapus)]} dari Shop (y/n)? ") + if yakinHapus == "y": + csvDelete(pathItemShop, int(idPotionHapus)) + print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") + print() + else: + print("Penghapusan dibatalkan!") + print() + continue + else: # pilihMenu == "keluar" + keluar == True + print("Sampai bertemu lagi Admin!") + break + return + +# shopOpen("agent") +shopOpen("admin") \ No newline at end of file From 6cf64ac268be6d42e1054cbb44560d4ca53f388b Mon Sep 17 00:00:00 2001 From: 19623238-Favian <148781301+19623238-Favian@users.noreply.github.com> Date: Wed, 15 May 2024 15:13:05 +0700 Subject: [PATCH 014/115] fix: Delete old shop_currency.py file --- src/shop_currency.py | 208 ------------------------------------------- 1 file changed, 208 deletions(-) delete mode 100644 src/shop_currency.py diff --git a/src/shop_currency.py b/src/shop_currency.py deleted file mode 100644 index 8d62a7b..0000000 --- a/src/shop_currency.py +++ /dev/null @@ -1,208 +0,0 @@ -from csvParser import csvRead, csvWrite, csvOverwrite, csvDelete, csvWriteAll -pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" -potionList = csvRead(pathItemShop) -potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"] -def shopInterface(): - print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") - print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") - print(" |___|__∆|___|_|∆|_| ███▀▀▀███ __||_ ") - print(" |∆__|___|∆__|∆|_|_| ███████ /_____\ ") - print(" |___|_∆_|___|_|∆|_| ██████████████ KASIR ██") - print(" =================== ███████████████████████") - return - -def shopOpen(role): - if role == "agent": - print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") - print() - shopInterface() - print() - keluar = False - while keluar != True: - pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": - print("monster") - lihatSelesai == True - # monster_list() - elif lihat_pilih == "potion": - print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") - lihatSelesai == True - elif pilihMenu == "beli": - print("Jumlah O.W.C.A Coin-mu sekarang [jumlah].") - print() - beliType = input(">>> Mau beli apa? (monster/potion): ") - beliSelesai = False - while beliType != "monster" and beliType != "potion" and beliSelesai != True: - beliType = input(">>> Pilih antara monster/potion: ") - if beliType == "monster": - idMonsterBeli = input(">>> Masukkan id monster: ") - # if monster in inventory: - # print("[nama monster] sudah ada dalam inventory-mu! Pembelian dibatalkan.") - # if OWCA >= harga monster: - print("Berhasil membeli item: [nama monster]. Item sudah masuk ke inventory-mu!") - print() - beliSelesai == True - # Di sini ntar masukkin monster ke inventory, sama stok di toko ngurang 1 (harus ada database dulu), sama OWCA ngurang - # else: - # print("OC-mu tidak cukup.") - elif beliType == "potion": - idPotionBeli = input(">>> Masukkan id potion: ") - jumlahPotionBeli = input(">>> Masukkan jumlah: ") - # if OWCA >= jumlah x potion: - print("Berhasil membeli item: [jumlah potion] [nama potion]. Item sudah masuk ke inventory-mu!") - print() - beliSelesai == True - else: # pilihMenu == "keluar" - keluar == True - print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break - elif role == "admin": - print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") - print() - shopInterface() - print() - keluar = False - while keluar != True: - pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": - print("monster") - lihatSelesai == True - # monster_list() - elif lihat_pilih == "potion": - print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") - lihatSelesai == True - elif pilihMenu == "tambah": - tambah_pilih = input("Mau tambah apa? (monster/potion): ") - tambahSelesai = False - while tambah_pilih != "monster" and tambah_pilih != "potion" and tambahSelesai != True: - tambah_pilih = (input(">>> Pilih antara monster/potion: ")) - if tambah_pilih == "monster": - print("monster") # Nanti di sini list semua monster dari database yang belom ada di Shop - print() - idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi - stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) - hargaMonsterTambah = int(input(">>> Masukkan harga: ")) - # monster_list.append() - print("[nama monster] telah berhasil ditambahkan ke dalam Shop!") - elif tambah_pilih == "potion": - potionFound = False - countFalse = 0 - print("ID | Type") - for i in range(1,4): - for j in range(1,len(potionList)): - if potionID[i] in potionList[j][0]: - potionFound = True - break - else: - potionFound = False - continue - if potionFound == False: - print(f"{i} | {potionID[i]}") - countFalse += 1 - if countFalse == 0: - print("Semua Potion sudah tersedia pada Shop!") - print() - else: - idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) - while (idPotionTambah < 1 or idPotionTambah > 3): - print("id tidak valid!") - idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) - stokPotionTambah = int(input("Masukkan stok awal: ")) - hargaPotionTambah = int(input("Masukkan harga: ")) - csvWrite(pathItemShop, f"{potionID[idPotionTambah]};{stokPotionTambah};{hargaPotionTambah}") - print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") - print() - elif pilihMenu == "ubah": - ubah_pilih = input("Mau ubah apa? (monster/potion): ") - ubahSelesai = False - while ubah_pilih != "monster" and ubah_pilih != "potion" and ubahSelesai != True: - ubah_pilih = (input(">>> Pilih antara monster/potion: ")) - if ubah_pilih == "monster": - idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi - stokMonsterBaru = (input(">>> Masukkan stok baru: ")) - hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) - pesanUbah = f"[nama monster] telah berhasil diubah " - # komponenubah = f"{monsterList[int(idMonsterUbah)]};" - if (stokMonsterBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" - # komponenUbah += f"{stokMonsterBaru};" - # else: - # komponenUbah += f"{monsterList[int(idMonsterUbah)][1];}" - if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): - pesanUbah += " dan " - if (hargaMonsterBaru != ""): - pesanUbah += f"dengan harga baru {hargaMonsterBaru}" - # komponenUbah += f"{hargaMonsterBaru}" - # else: - # komponenUbah += f"{monsterList[int(idMonsterUbah)][2]}" - pesanUbah += "!" - csvOverwrite(pathItemShop, int(idMonsterUbah)) # , komponenUbah (Nanti) - print(pesanUbah) - elif ubah_pilih == "potion": - idPotionUbah = (input(">>> Masukkan id potion: ")) - stokPotionBaru = (input(">>> Masukkan stok baru: ")) - hargaPotionBaru = (input(">>> Masukkan harga baru: ")) - pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " - komponenUbah = f"{potionID[int(idPotionUbah)]};" - if (stokPotionBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" - komponenUbah += f"{stokPotionBaru};" - else: - komponenUbah += f"{potionList[int(idPotionUbah)][1]};" - if (stokPotionBaru != "") and (hargaPotionBaru != ""): - pesanUbah += " dan " - if (hargaPotionBaru != ""): - pesanUbah += f"dengan harga baru {hargaPotionBaru}" - komponenUbah += f"{hargaPotionBaru}" - else: - komponenUbah += f"{potionList[int(idPotionUbah)][2]}" - pesanUbah += "!" - csvDelete(pathItemShop, int(idPotionUbah), komponenUbah) - print(pesanUbah) - print() - elif pilihMenu == "hapus": - hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") - hapusSelesai = False - while hapusPilih != "monster" and hapusPilih != "potion" and hapusSelesai != True: - hapusPilih = (input(">>> Pilih antara monster/potion: ")) - if hapusPilih == "monster": - idMonsterHapus = input(">>> Masukkan id monster: ") - # yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterList[int(idPokemonHapus)]} dari Shop (y/n)? ) - # if yakinHapus == "y": - # csvDelete(pathItemShop, int(idMonsterHapus)) - # print(f"{monsterList[int(idPokemonHapus)]} telah berhasil dihapus dari Shop!") - # else: - # continue - elif hapusPilih == "potion": - idPotionHapus = input(">>> Masukkan id potion: ") - yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[int(idPotionHapus)]} dari Shop (y/n)? ") - if yakinHapus == "y": - csvDelete(pathItemShop, int(idPotionHapus)) - print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") - print() - else: - print("Penghapusan dibatalkan!") - print() - continue - else: # pilihMenu == "keluar" - keluar == True - print("Sampai bertemu lagi Admin!") - break - return - -# shopOpen("agent") -shopOpen("admin") \ No newline at end of file From 58d00bf4765da7a27862089a16d48515eb930213 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Wed, 15 May 2024 15:39:21 +0700 Subject: [PATCH 015/115] feat: combine everything --- data/data1/item_inventory.csv | 10 ++ data/data1/item_shop.csv | 4 + data/data1/monser_inventory.csv | 8 ++ data/data1/monster.csv | 6 + data/data1/monster_shop.csv | 4 + data/data1/user.csv | 8 ++ data/monster_shop.csv | 4 - main.py | 0 ok.py | 10 ++ src/arena.py | 38 +++++ src/battle.py | 148 ++++++++++++++++++++ src/csvParser.py | 62 +++++++++ src/help.py | 25 ++++ src/inventory.py | 188 +++++++++++++++++++++++++ src/laboratory.py | 88 ++++++++++++ src/load.py | 153 +++++++++++++++++++++ src/main.py | 86 ++++++++++++ src/monsterManagement.py | 192 ++++++++++++++++++++++++++ src/potion.py | 100 ++++++++++++++ src/readwritecsv.py | 27 ++++ src/shop_currency.py | 236 ++++++++++++++++++++++++++++++++ 21 files changed, 1393 insertions(+), 4 deletions(-) create mode 100644 data/data1/item_inventory.csv create mode 100644 data/data1/item_shop.csv create mode 100644 data/data1/monser_inventory.csv create mode 100644 data/data1/monster.csv create mode 100644 data/data1/monster_shop.csv create mode 100644 data/data1/user.csv delete mode 100644 data/monster_shop.csv delete mode 100644 main.py create mode 100644 ok.py create mode 100644 src/arena.py create mode 100644 src/battle.py create mode 100644 src/csvParser.py create mode 100644 src/help.py create mode 100644 src/inventory.py create mode 100644 src/laboratory.py create mode 100644 src/load.py create mode 100644 src/main.py create mode 100644 src/monsterManagement.py create mode 100644 src/potion.py create mode 100644 src/readwritecsv.py create mode 100644 src/shop_currency.py diff --git a/data/data1/item_inventory.csv b/data/data1/item_inventory.csv new file mode 100644 index 0000000..2ac051d --- /dev/null +++ b/data/data1/item_inventory.csv @@ -0,0 +1,10 @@ +userid,type,quantity +1,healingpotion,2 +1,respotion,3 +1,strenghpotion,2 +3,healingpotion,2 +3,respotion,3 +3,strenghpotion,2 +2,healingpotion,2 +2,respotion,2 +2,strenghpotion,9 \ No newline at end of file diff --git a/data/data1/item_shop.csv b/data/data1/item_shop.csv new file mode 100644 index 0000000..c515242 --- /dev/null +++ b/data/data1/item_shop.csv @@ -0,0 +1,4 @@ +type,stock,price +Healing Potion,5,25 +Resilience Potion,5,35 +Strength Potion,5,40 \ No newline at end of file diff --git a/data/data1/monser_inventory.csv b/data/data1/monser_inventory.csv new file mode 100644 index 0000000..e923adf --- /dev/null +++ b/data/data1/monser_inventory.csv @@ -0,0 +1,8 @@ +id,monster,level +1,Mimic,1 +1,Makima,2 +1,Jalangkung,3 +2,Makima,1 +2,Mimic,1 +3,Jalangkung,2 +3,Mimic,1 \ No newline at end of file diff --git a/data/data1/monster.csv b/data/data1/monster.csv new file mode 100644 index 0000000..b42d78c --- /dev/null +++ b/data/data1/monster.csv @@ -0,0 +1,6 @@ +id,type,atk_power,def_power,hp +1,Godzilla,170,40,600 +2,Mimic,35,5,150 +3,Makima,300,25,350 +4,Jalangkung,100,10,600 +5,gigidi gigididuu,100,10,100 \ No newline at end of file diff --git a/data/data1/monster_shop.csv b/data/data1/monster_shop.csv new file mode 100644 index 0000000..2ba38c2 --- /dev/null +++ b/data/data1/monster_shop.csv @@ -0,0 +1,4 @@ +monster_id,stock,price +1,6,800 +2,13,300 +3,2,750 \ No newline at end of file diff --git a/data/data1/user.csv b/data/data1/user.csv new file mode 100644 index 0000000..a6ceb17 --- /dev/null +++ b/data/data1/user.csv @@ -0,0 +1,8 @@ +id,username,password,role,coin +1,bagas,12345,agent,1000 +2,bagus,12345,agent,100 +3,bages,12345,agent,100 +4,bagos,12345,agent,100 +5,bagis,12345,agent,100 +6,june,12345,admin,100 +7,juni,12345,admin,100 \ No newline at end of file diff --git a/data/monster_shop.csv b/data/monster_shop.csv deleted file mode 100644 index 41ee368..0000000 --- a/data/monster_shop.csv +++ /dev/null @@ -1,4 +0,0 @@ -monster_id;stock;price -1;6;800 -2;13;300 -3;2;750 \ No newline at end of file diff --git a/main.py b/main.py deleted file mode 100644 index e69de29..0000000 diff --git a/ok.py b/ok.py new file mode 100644 index 0000000..09c2a9a --- /dev/null +++ b/ok.py @@ -0,0 +1,10 @@ +list=[1,2,3,4,5] +k=list[0] +m=list[1] +n=list[2] +list2=[k,m,n] +print(list) +print(list2) +list2[0]=list2[0]+1 +print(list) +print(list2) \ No newline at end of file diff --git a/src/arena.py b/src/arena.py new file mode 100644 index 0000000..5055271 --- /dev/null +++ b/src/arena.py @@ -0,0 +1,38 @@ +from battle import * +from RandomNumberGenerator import * + +def arena(monsterdata,yourmonsterdata,userinventory) : + + coins=0 + + print("DO YOU WANT TO ENTER THE ARENA? (Y/N)") + inp = input("--------->") + if inp=="N" : + print("SEE U ANOTHER DAY") + elif inp=="Y" : + print("=====WELCOME TO THE ARENA=====") + print("RULES :") + print("1. THERE WILL BE A TOTAL OF 5 STAGES IN THE ARENA, EACH STAGE") + print(" YOU HAVE TO FIGHT A MONSTER WITH EACH STAGE THE MONSTER WILL GET STRONGER") + print("2. DEFEATING A MONSTER IN EACH STAGE WILL REWARD YOU WITH COINS, THE HIGHER") + print(" THE STAGE THE BIGGER THE REWARD") + print("3. IF YOU LOSE ONCE, THE ARENA WILL BE OVER, IF YOU WIN ALL THE WAY") + print(" TO THE FIFTH STAGE YOU WILL GET MAXIMUM COINS") + + chosen = choose(yourmonsterdata) + + for i in range(5) : + random_number = RNG(1,5) + opening(monsterdata,random_number) + coin = battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) + coins += coin + if coin==0 : + print(f"YOU MADE IT TO STAGE NUMBER {i+1}, KEEP IMPROVING") + break + + else : + print("CONGRATULATION YOU MADE IT ALL THE WAY!!!!") + print("HERE A BONUS 50 COIN FOR YOU!!!") + coins += 50 + print(f"YOUR TOTAL COIN GAINED FROM THE ARENA : {coins}") + return coins diff --git a/src/battle.py b/src/battle.py new file mode 100644 index 0000000..56c8103 --- /dev/null +++ b/src/battle.py @@ -0,0 +1,148 @@ +import random + +from readwritecsv import * +from potion import * +from RandomNumberGenerator import * + +def choose(yourmonsterdata) : + while True : + print("=======PLEASE CHOOSE A MONSTER=======") + x=0 + for i in yourmonsterdata : + print(f"{x+1}. {i[1]}") + x+=1 + chosen = input("-------->") + k=0 + for i in range(1,len(yourmonsterdata)+1) : + if str(i)==chosen : + k=1 + break + if k==1 : break + else : + print(f'pilihan ke-{chosen} tidak tersedia') + return int(chosen) + + + +def opening(monsterdata,random_number) : + name = monsterdata[random_number][1] + print(f'{name} telah datang !!!!!!!!!!!') + +def battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) : + file1 = monsterdata + file2 = yourmonsterdata + + used_pot=[0,0,0] + level=yourmonsterdata[chosen-1][2] + name=yourmonsterdata[chosen-1][1] + #PROGRAM UTAMA ========================================================== + print("="*100) + print(f'{name} siap membantu') + + x=0 + for i in monsterdata : + if i[1]==name : + break + x+=1 + + yourattack = int(file1[x][2]) + (int(level)-1)*(5/100)*int(file1[x][2]) + yourdefense = int(file1[x][3]) + (int(level)-1)*(5/100)*int(file1[x][3]) + yourhealth = int(file1[x][4]) + (int(level)-1)*(5/100)*int(file1[x][4]) + + + enemyhealth = int(file1[random_number][4]) + enemyattack = int(file1[random_number][2]) + enemydefense = int(file1[random_number][3]) + '''yourhealth = int(file2[chosen][2])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][2]) + yourattack = int(file2[chosen][3])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][3]) + yourdefense = int(file2[chosen][4])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][4]) + yourlevel = int(file2[chosen][5])''' + n=1 + while True : + print(f"=====================TURN {n}======================") + print("="*100) + print(f"ENEMY : {file1[random_number][1]}") + print(f"HEALTH : {enemyhealth}") + print(f"ATTACK : {enemyattack}") + print(f"DEFENSE : {enemydefense}") + print("="*100) + print(f"YOUR MONSTER : {name}") + print(f"HEALTH : {yourhealth}") + print(f"ATTACK : {yourattack}") + print(f"DEFENSE : {yourdefense}") + print(f"LEVEL : {level}") + print(f"====================") + print("CHOOSE AN ACTION :") + print("1. ATTACK") + print("2. DRINK POTION") + print("3. QUIT") + print("=====================") + action = int(input("-------->")) + if action==1 : + enemyhealth -= (yourattack-(enemydefense/100)*yourattack) + print("YOU ATTACKED !!!!!!!!") + if enemyhealth >= 0 : + print(f"ENEMY MONSTER HEALTH IS DOWN TO {enemyhealth}") + elif action==2 : + while True : + print("=======CHOOSE A POTION !=======") + print(jumlahpot(userinventory)) + print("1. STRENGHT") + print(f" you have : {jumlahpot(userinventory)[0]}") + print("2. RESILIENSE") + print(f" you have : {jumlahpot(userinventory)[1]}") + print("3. HEAL") + print(f" you have : {jumlahpot(userinventory)[2]}") + print("4. CANCEL") + potionchoice = int(input("-------->")) + newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,100000,name,potionchoice) + if potionchoice ==1 : + if newstat==0 : + continue + else : + yourattack = newstat + break + elif potionchoice ==2 : + if newstat==0 : + continue + else : + yourdefense = newstat + break + elif potionchoice ==3 : + if newstat==0 : + continue + else : + yourhealth = newstat + break + elif potionchoice ==4 : + break + if potionchoice == 4 : + continue + + elif action==3 : + coin = 0 + return coin + break + + if enemyhealth <= 0 : + print("="*100) + print("YOU DEFEATED YOUR ENEMY") + print("WOHOOOOOO") + print("="*100) + coin = random.randint(50,100) + print(f"YEEEEEY YOU GOT {coin} coin") + return coin + break + + print(f"{file1[random_number][1]} ATTACK BACK !!!") + yourhealth -= (enemyattack - (yourdefense/100)*enemyattack) + print(f"{name} HEALTH IS DOWN TO {yourhealth}") + + if yourhealth <= 0 : + print("="*100) + print("YOU ARE DEAD") + print("DONT GIVE UP") + print("="*100) + return 0 + break + n+=1 \ No newline at end of file diff --git a/src/csvParser.py b/src/csvParser.py new file mode 100644 index 0000000..669394e --- /dev/null +++ b/src/csvParser.py @@ -0,0 +1,62 @@ +import sys +sys.path.append("C:\if1210-2024-tubes-k08-b\data") + +def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja + separated = [] + word = '' + + for char in (text): + if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) + break + elif char != ';': + word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata + else: # char == ";" + separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array + word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) + + separated.append(word) # Untuk kata setelah semicolon terakhir + + return separated + +def csvRead(path): # Fungsi membaca file .csv baris per baris + csvOpen = open(path,'r') # Membuka file .csv + cleanData = [] + + for row in csvOpen: # Membaca setiap baris + cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon + + csvOpen.close() # Menutup file + return cleanData + +def csvWrite(path, input): # Fungsi memasukkan data dengan line baru pada csv + with open(path,'a', newline="") as csvOpen: # Membuka csv (dengan with, file tidak perlu diclose) + csvOpen.write('\n') + csvOpen.write(''.join(input)) # Mengisi baris baru dengan input + return + +def csvOverwrite(path, row, input): # Fungsi memperbaharui data yang sudah ada dengan data baru + csvOpen = open(path,'r') # Membuka csv + tempData = [] # Data sementara + for i in csvOpen: + tempData.append(i) # Mengisi list dengan data pada csv tanpa menghilangkan semicolon (";") + tempData[row] = input # Mengubah data csv pada baris yang ditentukan dengan input yang baru + + with open(path,'w') as csvWrite: # Mengembalikan bentuk list menjadi bentuk csv semula + for rows in tempData: + tempData = csvWrite.write(''.join(rows)) + return + +def csvDelete(path, row): # Fungsi menghapus data pada baris yang ditentukan + csvOpen = open(path,'r') # Membuka csv + tempData = [] # Data sementara + count = 0 + for i in csvOpen: + tempData.append(i) # Mengisi list dengan data tanpa menghilangkan semicolon (";") + if count == row: # Pada baris yang ditentukan, data di-pop (dihapus) + tempData.pop(row) + count += 1 + + with open(path,'w') as csvWrite: # Mengembalikan bentuk list menjadi bentuk csv semula + for rows in tempData: + tempData = csvWrite.write(''.join(rows)) + return \ No newline at end of file diff --git a/src/help.py b/src/help.py new file mode 100644 index 0000000..243d7ef --- /dev/null +++ b/src/help.py @@ -0,0 +1,25 @@ +def help(status,role) : + if status == False : + print("List command yang dapat anda lakukan :") + print("1. Login") + print(" Login ke akun admin/agent") + print("2. Register") + print(" Membuat akun agent baru") + print("3. Save") + print(" Menyimpan semua perubahan dalam sebuah folder") + print("4. Exit") + print(" Keluar dari program") + else : + if role == 'agent' : + print("List command yang dapat anda lakukan :") + print("1. Battle") + print(" 1v1 dengan monster random") + print("2. Arena") + print(" Tempat pelatihan monster anda") + print("3. Shop") + print(" Tempat jual beli potion dan monster") + print("4. Inventory") + print(" Cek semua item dan monster anda") + print("5. Logout") + print(" Keluar dari akun anda") + \ No newline at end of file diff --git a/src/inventory.py b/src/inventory.py new file mode 100644 index 0000000..1ba0ebe --- /dev/null +++ b/src/inventory.py @@ -0,0 +1,188 @@ +import sys +sys.path.append("C:\if1210-2024-tubes-k08-b\data") + +def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja + separated = [] + word = '' + + for char in (text): + if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) + break + elif char != ';': + word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata + else: # char == ";" + separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array + word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) + + separated.append(word) # Untuk kata setelah semicolon terakhir + + return separated + +def csvRead(path): # Fungsi membaca file .csv baris per baris + csvOpen = open(path,'r') # Membuka file .csv + cleanData = [] + + for row in csvOpen: # Membaca setiap baris + cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon + + csvOpen.close() # Menutup file + return cleanData + + +'''user_Data = csvRead("data/data1/user.csv") +pot_Inv_Data = csvRead(r"E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\data\item_inventory.csv") +monster_Data = csvRead(r"E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\data\monster.csv") +mons_Inv_Data = csvRead(r"E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\data\monster_inventory.csv")''' + +def check_Admin (id, userData): + for i in range (1, len(userData)): + if id == int(userData[i][0]) : + if userData[i][3] == 'admin' : + return False + else : + return True + +def owca_Coin (id, userData): + for i in range (1, len(userData)): + if id == int(userData[i][0]) : + return int(userData[i][4]) + +'''def pot_Inventory (userinventory): + for i in userinventory: + if i[1]=='strenghpotion': + jumlahstr=i[2] + break + else : jumlahstr = 0 + for i in userinventory: + if i[1]=='respotion' : + jumlahres=i[2] + break + else : jumlahres = 0 + for i in userinventory: + if i[1]=='healingpotion' : + jumlahheal=i[2] + break + else : jumlahheal = 0 + return [jumlahstr,jumlahres,jumlahheal] + +def pot_List (qty): + pot_Type = ['ATK', 'DEF', 'HEAL'] + pot_Type_2 = [] + pot_Qty =[] + for i in range (3): + if qty[i] != 0 : + pot_Type_2.append(pot_Type[i]) + pot_Qty.append(qty[i]) + return (pot_Type_2, pot_Qty) + +def monster_Id (yourmonsterdata): + mons_Id_Array = [] + for i in yourmonsterdata : + mons_Id_Array.append(i[1]) + return mons_Id_Array + +def monster_Lv (yourmonsterdata): + mons_Lv_Array = [] + for i in yourmonsterdata : + mons_Lv_Array.append(i[2]) + return mons_Lv_Array''' + +def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : + if role=='admin': + print("Maaf! Anda tidak memiliki akses sebagai admin") + else : + print(f'jumlah OWCA coin anda saat ini : {coin}') + while True : + check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Potion/Back): ') + if check.lower() == 'potion' : + x=1 + types=[] + for i in userinventory: + if i[1] == 'strenghpotion' : + type = 'ATK' + if i[1] == 'respotion' : + type = 'DEF' + if i[1] == 'healingpotion' : + type = 'HEAL' + types.append(type) + print(f'{x}. Type: {type}') + x+=1 + while True : + pot_Number = input('Masukkan nomor potion untuk menampilkan detail item (1/2/3/Back): ') + if pot_Number.lower() != 'back': + pot_Number = int(pot_Number) + print('POTION') + print(f'Type: {types[pot_Number-1]}') + print(f'Quantity: {userinventory[pot_Number-1][2]}') + else : + break + elif check.lower() == 'monster' : + y = 0 + for i in yourmonsterdata : + print(f"{y+1}. {i[1]}") + y+=1 + while True : + mons_Number = input('Masukkan nomor monster untuk menampilkan detail monster (1/2/dst/Back): ') + if mons_Number.lower() != 'back' : + mons_Number = int(mons_Number) + monsterlvl = int(yourmonsterdata[mons_Number-1][2]) + for i in monsterdata : + if i[1]==yourmonsterdata[mons_Number-1][1] : + print(f'Nama : {i[1]}') + print(f'ATK Power : {int(i[2])+(monsterlvl-1)*(5/100)*(int(i[2]))}') + print(f'DEF Power : {int(i[3])+(monsterlvl-1)*(5/100)*(int(i[3]))}') + print(f'HP : {int(i[4])+(monsterlvl-1)*(5/100)*(int(i[4]))}') + print(f'Level : {monsterlvl}') + else : + break + elif check.lower() == 'back' : + break + +'''def inventory (monsId, monsData, potData, monsLevel, access, oc): + if access == False : + print('Maaf! Anda tidak memiliki akses sebagai admin') + elif access == True : + print(f'Jumlah O.W.C.A. Coin Anda saat ini : {oc}') + while True : + check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Potion/Back): ') + if check.lower() == 'potion' : + for i in range(len(potData[0])): + print(f'{i+1}. Type: {potData[0][i]}') + + while True : + pot_Number = input('Masukkan nomor potion untuk menampilkan detail item (1/2/3/Back): ') + if pot_Number.lower() != 'back': + pot_Number = int(pot_Number) + print('POTION') + print(f'Type: {potData[0][pot_Number-1]}') + print(f'Quantity: {potData[1][pot_Number-1]}') + else : + break + + elif check.lower() == 'monster' : + number = 0 + for i in range (1, len(monsData)): + for j in range (len(monsId)): + if monsId[j] == int(monsData[i][0]) : + number += 1 + print(f'{number}. {monsData[i][1]}') + + while True : + mons_Number = input('Masukkan nomor monster untuk menampilkan detail monster (1/2/dst/Back): ') + if mons_Number.lower() != 'back' : + mons_Number = int(mons_Number) + print('MONSTER') + for i in range (1, len(monsData)): + if int(monsData[i][0]) == monsId[mons_Number-1] : + print(f'Nama : {monsData[i][1]}') + print(f'ATK Power : {int(monsData[i][2]) + (int(monsData[i][2])*(monsLevel[mons_Number-1]-1)*0.1)}') + print(f'DEF Power : {int(monsData[i][3]) + (int(monsData[i][3])*(monsLevel[mons_Number-1]-1)*0.1)}') + print(f'HP : {int(monsData[i][4]) + (int(monsData[i][4])*(monsLevel[mons_Number-1]-1)*0.1)}') + print(f'Level : {monsLevel[mons_Number-1]}') + else : + break + elif check.lower() == 'back' : + break ''' + +# contoh penggunaan function : +#inventory(monster_Id(3, mons_Inv_Data), monster_Data, pot_List(pot_Inventory(3, pot_Inv_Data)),monster_Lv(3, mons_Inv_Data), check_Admin(3, user_Data), owca_Coin(3, user_Data)) \ No newline at end of file diff --git a/src/laboratory.py b/src/laboratory.py new file mode 100644 index 0000000..7d65798 --- /dev/null +++ b/src/laboratory.py @@ -0,0 +1,88 @@ + +'''from csvParser import splitSemicolon, csvRead, csvWrite, csvOverwrite, csvDelete''' + + + +'''def check_Admin (id, userData): + for i in range (1, len(userData)): + if id == int(userData[i][0]) : + if userData[i][3] == 'admin' : + return False + else : + return True + +def owca_Coin (id, userData): + for i in range (1, len(userData)): + if id == int(userData[i][0]) : + return int(userData[i][4]) + +def monster_Id (id, monsInvData): + mons_Id_Array = [] + for i in range (1, len(monsInvData)): + if int(monsInvData[i][0]) == id : + mons_Id_Array.append(int(monsInvData[i][1])) + return mons_Id_Array + +def monster_Lv (id, monsInvData): + mons_Lv_Array = [] + for i in range (1, len(monsInvData)): + if int(monsInvData[i][0]) == id : + mons_Lv_Array.append(int(monsInvData[i][2])) + return mons_Lv_Array''' + +def laboratory(yourmonsterdata,coin,role): + if role == 'admin' : + print('Maaf! Anda tidak memiliki akses sebagai admin') + elif role == 'agent' : + print(f'Jumlah O.W.C.A. Coin Anda saat ini : {coin}') + print('============ MONSTER LIST ============') + number = 0 + for i in yourmonsterdata : + print(f"{number+1}. {i[1]}, LEVEL :{i[2]}") + array_Harga = [100, 200, 400, 700] + print('============ UPGRADE PRICE ============') + for i in range (1,5): + print(f'{i}. Level {i} -> Level {i+1}: {array_Harga[i-1]}') + + while True: + idpilihan = input('Pilih monster yang ingin di-upgrade (1/2/dst/Back): ') + if idpilihan.lower() != 'back': + idpilihan = int(idpilihan) + while True: + if yourmonsterdata[idpilihan-1][2] != 5: + up_level = input('Silakan pilih ke level berapa kah Anda ingin meng-upgrade monster Anda (1/2/dst/Back): ') + if up_level.lower() != 'back': + if up_level == yourmonsterdata[idpilihan-1][2] : + print("masa mau upgrade kelevel yg sama si") + break + else : + up_level = int(up_level) + harga = 0 + for i in range (int(yourmonsterdata[idpilihan-1][2]), up_level): + harga += array_Harga[i-1] + print(f'{yourmonsterdata[idpilihan-1][1]} akan di-upgrade ke level {up_level}') + print(f'Harga untuk meng-upgrade {yourmonsterdata[idpilihan-1][1]} adalah {harga}') + lanjut = input('Lanjutkan upgrade (Y/N): ') + if lanjut.lower() != 'n': + if coin >= harga : + yourmonsterdata[idpilihan-1][2]=str(up_level) + coin -= harga + print(f'Selamat! {yourmonsterdata[idpilihan-1][1]} berhasil di-upgrade ke level {up_level}!') + print(f'Coin Anda tersisa {coin}') + break + else : + print('Maaf! Anda tidak memiliki Coin yang cukup') + break + else : + break + else : + break + else : + print('Maaf! Monster yang Anda pilih sudah memiliki level maksimum. Silakan pilih monster lain') + break + else: + break + return coin + +# contoh penggunaan function : +#inventory(3, user_Data, mons_Inv_Data, monster_Id(3, mons_Inv_Data), monster_Data, monster_Lv(3, mons_Inv_Data), check_Admin(3, user_Data), owca_Coin(3, user_Data)) \ No newline at end of file diff --git a/src/load.py b/src/load.py new file mode 100644 index 0000000..7d7f906 --- /dev/null +++ b/src/load.py @@ -0,0 +1,153 @@ +from readwritecsv import * +import os +import argparse +def load() : + parser = argparse.ArgumentParser(add_help=False,usage='%(prog)s ') + parser.add_argument("nama_folder",nargs="?",type=str,default="") + args = parser.parse_args() + path = "data/"+args.nama_folder # Perlu ditambah "save/" karena parent foldernya "save" + if(path == "data/"): # jika args.nama_folder kosong + print("Tidak ada nama folder yang diberikan!\n") + parser.print_usage() + return [] + elif(os.path.exists(path)): # jika folder ditemukan + print("Loading...") + print("Selamat datang") + user = read_csv("data/data1/user.csv") + inventory = read_csv("data/data1/item_inventory.csv") + monster = read_csv("data/data1/monster.csv") + monsterinventory = read_csv("data/data1/monser_inventory.csv") + itemshop=read_csv("data/data1/item_shop.csv") + monstershop=read_csv("data/data1/monster_shop.csv") + return [user,inventory,monster,monsterinventory,itemshop,monstershop] + else: # folder tidak ditemukan + print(f"Folder \"{path}\" tidak ditemukan.") + return [] + +def login(user,inventory,monsterinventory) : + username = input("username :") + password = input("password :") + for i in user : + if i[1] == username : + if i[2] == password : + player_inventory = [] + monster_inventory =[] + print("login berhasil") + for j in inventory : + if j[0]==i[0] : + player_inventory.append(j) + for j in monsterinventory : + if j[0]==i[0] : + monster_inventory.append(j) + return player_inventory,monster_inventory,i[3],int(i[4]) + break + else : + print("password salah") + return 0,0,0,0 + break + else : + print("username tidak ditemukan") + return 0,0,0,0 + +def register(user,inventory,monsterinventory,monster) : + while True : + usernamebaru = input("Masukkan Username :") + for i in user : + if i[1]== usernamebaru : + print("Username sudah terpakai") + break + else : + break + passwordbaru = input("Masukkan password :") + print('PILIH MONSTER PERTAMA ANDA :') + for i in range(3) : + print(f"{i+1}. {monster[i+1][1]}") + idpilihan = input("--->") + idbaru = len(user) + monsterinventory.append([str(idbaru),monster[int(idpilihan)][1],'1']) + user.append([str(idbaru),usernamebaru,passwordbaru,'agent','0']) + inventory.append([str(idbaru),'healingpotion','0']) + inventory.append([str(idbaru),'respotion','0']) + inventory.append([str(idbaru),'strenghpotion','0']) + + player_inventory = [] + monster_inventory =[] + print("SELAMAT DATANG AGENT BARU") + for j in inventory : + if j[0]==str(idbaru) : + player_inventory.append(j) + for j in monsterinventory : + if j[0]==str(idbaru) : + monster_inventory.append(j) + return player_inventory,monster_inventory,'agent',0 + + +def buang(data,inventory) : + print("mau buang item apa ?") + inp = input("(1(str)/2(res)/3(heal))? ------->") + if inp == '1' : + for i in data : + if i[1]=='strenghpotion' : + if int(i[2]) >0 : + i[2]=str(int(i[2])-1) + print("strenght potion dibuang satu") + break + else : + print("anda tidak memiliki str potion") + break + else : + print("anda tidak memiliki strenght potion") + elif inp == '2' : + for i in data : + if i[1]=='respotion' : + if int(i[2])>0 : + i[2]=str(int(i[2])-1) + print("resistance potion dibuang satu") + break + else : + print("anda tidak memiliki res potion") + break + else : + print("anda tidak memiliki resistance potion") + elif inp == '3' : + for i in data : + if i[1]=='healingpotion' : + if int(i[2]) > 0 : + i[2]=str(int(i[2])-1) + print("heal potion dibuang satu") + break + else : + print("anda tidak memiliki heal potion") + break + else : + print("anda tidak memiliki heal potion") + x=0 + idx=[] + for i in inventory : + print(f"{i[0]} DAN {data[0][0]}") + if i[0]==data[0][0] : + idx.append(x) + x+=1 + for i in range(len(idx)-1,-1,-1) : + inventory.pop(idx[i]) + for i in data : + inventory.append(i) + + +def write(path,data) : + # Writing data to the CSV file + with open(path, 'w') as file: + for row in data: + file.write(','.join(map(str, row)) + '\n') + + print(f"CSV file '{path}' has been created successfully.") + +def save(inventory,monster,user) : + # ALGORITMA + path = "data/" + input("Masukkan nama folder: ") + print("Saving...") + if (os.path.exists(path)) : + write(path+"/inventory.csv",inventory) + write(path+"user.csv",user) + write(path+"/monster.csv",monster) + \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..c59465b --- /dev/null +++ b/src/main.py @@ -0,0 +1,86 @@ +from load import * +from battle import * +from arena import* +from RandomNumberGenerator import * +from inventory import * +from shop_currency import * +from help import * +from laboratory import * + +data=load() +if data != [] : + user = data[0] + inventory = data[1] + monster = data[2] + monsterinventory = data[3] + itemshop=data[4] + monstershop=data[5] + loginstatus = False + while True : + command = input("--->") + if command =="login" : + while True : + userinventory,yourmonsterinventory,role,coins = login(user,inventory,monsterinventory) + if userinventory != 0 and role != 0 and coins !=0 and yourmonsterinventory !=0 : + loginstatus = True + break + elif command =='register' : + userinventory,yourmonsterinventory,role,coins = register(user,inventory,monsterinventory,monster) + loginstatus = True + elif command =="help" : + help(loginstatus,"belumlogin") + else : + print(f"command '{command}' tidak ada.") + if loginstatus==True : + if role=='agent': + while True : + id = int(userinventory[0][0]) + command = input("--->") + if command == 'battle' : + random_number = RNG(1,5) + opening(monster,random_number) + chosen=choose(yourmonsterinventory) + coin = battle(monster,yourmonsterinventory,userinventory,chosen,random_number) + coins+=coin + user[id][4]=str(coins) + print(userinventory) + elif command == 'arena' : + coin = arena(monster,yourmonsterinventory,userinventory) + coins+=coin + user[id][4]=str(coins) + elif command == 'inventory' : + inventoryy(userinventory,yourmonsterinventory,monster,role,coins) + elif command == 'logout' : + t=0 + while True : + confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + if confirm == "Y" : + print("Logout berhasil") + t=1 + break + elif confirm =='N' : + t=1 + break + else : print("mangsud?") + if t==1 : + loginstatus=False + break + + elif command == 'Shop' : + coins=shopOpen(role,itemshop,coins,userinventory,monster,monstershop,yourmonsterinventory,monsterinventory) + user[id][4]=str(coins) + elif command == 'help' : + help(loginstatus,role) + elif command == 'laboratory' : + coins = laboratory(yourmonsterinventory,coins,role) + user[id][4]=str(coins) + else : + print(f"command '{command}' tidak ada.") + print(userinventory) + print(inventory) + print(user) + print(monsterinventory) + print(yourmonsterinventory) + print(itemshop) + print(monstershop) + \ No newline at end of file diff --git a/src/monsterManagement.py b/src/monsterManagement.py new file mode 100644 index 0000000..10ad774 --- /dev/null +++ b/src/monsterManagement.py @@ -0,0 +1,192 @@ +from csvParser import splitSemicolonInt, csvReadInt, csvWrite +pathFileMonster = r"C:\Files\if1210-2024-tubes-k08-b\data\monster.csv" +listMonster = csvReadInt(pathFileMonster) + +# FUNGSI UNTUK PENAMBAHAN MONSTER +# Fungsi - fungsi proses untuk mengecek validasi input data monster +def checkType(type): + while True: + monsterExist = False # asumsi awal, nama yang diinput tidak sama dengan nama pada database. + for i in range(1, len(listMonster)): # 1 sebagai parameter karena listMonster[0] merupakan judul, len(listMonster) sebagai parameter akhir karena database monster bisa berubah seiring game berjalan. + if listMonster[i][1] == type: # apabila nama monster yang diinput ada yang sama dengan nama monster yang ada di database + print("Nama sudah terdaftar. Coba lagi!") + type = str(input("Masukkan Type Monster : ")) + monsterExist = True # bila nama monster yang diinput ada yang sama dengan nama monster yang ada di database, maka menjadi True. + if monsterExist == False : # Terjadi apabila nama monster yang diinput berhasil pengecekan + break + return type + +def checkAttack(attack): + while True: + if attack.isdigit(): # bila keseluruhan attack berupa angka + attack = int(attack) # ubah menjadi integer agar dapat dioperasikan + break + else : # terdapat character yang bukan angka + print("Masukkan bukan bertipe integer, coba lagi!") + attack = str(input("Masukkan attack power : ")) # input berupa string karena untuk pengecekan isdigit() + return attack + +def checkDefense(defense): + while True: + if defense.isdigit(): # defense berupa angka secara keseluruhan + defense = int(defense) # diubah menjadi integer agar dapat dioperasikan + if 0 <= defense <= 50 : # nilai sudah sesuai ketentuan + break + else : # defense > 0 dan defense > 50, belum sesuai + print("Masukkan harus bernilai 0-50") + defense = str(input("Masukkan DEF power (0-50) : ")) + else : # defense tidak merupakan angka secara keseluruhan + print("Masukkan bukan bertipe integer, coba lagi!") + defense = str(input("Masukkan DEF power (0-50) : ")) + return defense + +def checkHp(hp): + while True: + if hp.isdigit(): # keseluruhan hp berupa angka + hp = int(hp) # ubah menjadi integer agar dapat dioperasikan + break + else : # terdapat character yang bukan angka pada hp + print("Masukkan bukan bertipe integer, coba lagi!") + hp = str(input("Masukkan hp : ")) # input berupa string karena untuk pengecekan isdigit() perlu tipe data string + return hp + +# FUNGSI SIMPLIFIKASI +# Fungsi-fungsi dibawah berisi input awal data monster baru dari user +def newType(): + type = str(input("Masukkan Type Monster : ")) + return checkType(type) + +def newAttack(): + attack = str(input("Masukkan attack power : ")) + return checkAttack(attack) + +def newDefense(): + defense = str(input("Masukkan DEF power (0-50) : ")) + return checkDefense(defense) + +def newHp(): + hp = str(input("Masukkan hp : ")) + return checkHp(hp) + +# FUNGSI CHECK Y/N +def checkUserInput(userInput, nType, nAttack , nDefense, nHp): + while True: + if userInput == "Y" : + # disini masukkan file ke csv dulu karena bila append terlebih dahulu len(listMonster) id akan tidak sesuai pada file monster.csv + csvWrite(pathFileMonster, f"{len(listMonster)};{nType};{nAttack};{nDefense};{nHp}") + listMonster.append([len(listMonster), nType, nAttack, nDefense, nHp]) + print("Monster berhasil ditambahkan") + break + elif userInput == "N" : + print("Monster gagal ditambahkan") + break + else : # Input bukan Y/N + print("input tidak valid, hanya menerima input Y/N") + userInput = str(input("(Y/N): ")) +def validUserInput(userInput, nType, nAttack, nDefense, nHp): + userInput = str(input("(Y/N): ")) + return checkUserInput(userInput, nType, nAttack, nDefense, nHp) + +# FUNGSI PENAMBAHAN MONSTER BARU SECARA KESELURUHAN +def newMonster(): + nType = newType() + nAttack = newAttack() + nDefense = newDefense() + nHp = newHp() + userInput = "" + validUserInput(userInput, nType, nAttack, nDefense, nHp) + return + +# FUNGSI PENCETAKAN TABEL RAPIH +# Fungsi mengubah elemen integer pada list dari data csv menjadi string karena nanti akan digunakan fungsi len() +def changeInt(listMonster): + for i in range(1,len(listMonster)): + for j in range(5): + if j != 1 : # karena j == 1 berupa type monster yang berupa string + listMonster[i][j] = str(listMonster[i][j]) + return listMonster + +# Fungsi mencari elemen terbesar dalam 1 kolom +# elemen terbesar tiap kolom akan disimpan pada array largestElement, posisi bersamaan dengan kolom +def findLargestElement(largestElement): + for i in range(len(largestElement)): + for j in range(len(listMonster)): + if largestElement[i] < len(listMonster[j][i]): + largestElement[i] = len(listMonster[j][i]) + return largestElement + +# Fungsi mengganti header dari file csv yang kurang rapih +def changeHeader(newHeader, listMonster): + for i in range(5): + listMonster[0][i] = newHeader[i] + return + +# Fungsi print tabel database monster +def printTabel (listMonster, largestElement): + for i in range(len(listMonster)): + # Print judul terlebih dahulu + print(listMonster[i][0], end="") + for j in range(abs(largestElement[0]-(len(listMonster[i][0])))): + print(" ", end="") + print(" |", end="") + + # Print type monster + print(" ", listMonster[i][1], end="") + for j in range(abs(largestElement[1]-(len(listMonster[i][1])))): + print(" ", end="") + print(" |", end="") + + # Print ATK Power + print(" ", listMonster[i][2], end="") + for j in range(abs(largestElement[2]-(len(listMonster[i][2])))): + print(" ", end="") + print(" |", end="") + + # Print DEF Power + print(" ", listMonster[i][3], end="") + for j in range(abs(largestElement[3]-(len(listMonster[i][3])))): + print(" ", end="") + print(" |", end="") + + # Print HP + print(" ", listMonster[i][4], end="") + for j in range(abs(largestElement[4]-(len(listMonster[i][4])))): + print(" ", end="") + print(" |", end="") + + # Enter agar program lanjut print baris ke-2 dan seterusnya + print("") + return + +# Fungsi akhir pencetakan tabel +def tabelMonster(): + largestElement = [-1, -1, -1, -1, -1] + newHeader = ["ID", "Type", "ATK Power", "DEF Power", "HP"] + changeInt(listMonster) + findLargestElement(largestElement) + changeHeader(newHeader, listMonster) + printTabel(listMonster, largestElement) + return + +# FUNGSI AKHIR MONSTER MANAGEMENT +def monsterManagement(): + while True : + print(""" +SELAMAT DATANG DI DATABASE PARA MONSTER !!! +1. Tampilkan Semua Monster +2. Tambah Monster Baru +( Ketik nomor untuk aksi yang diinginkan, ketik 0 untuk keluar ) + """) + aksiUser = str(input("Pilih Aksi: ")) + if aksiUser == "1" : + tabelMonster() + str(input("Ketik apapun untuk balik ke menu: ")) + elif aksiUser == "2" : + newMonster() + elif aksiUser == "0" : + print("Teirma kasih telah mengunjungi database monster") + break + else : + print("Input tidak valid, input yang diterima hanya 0/1/2") + +# PENERAPAN FUNGSI \ No newline at end of file diff --git a/src/potion.py b/src/potion.py new file mode 100644 index 0000000..745eff5 --- /dev/null +++ b/src/potion.py @@ -0,0 +1,100 @@ +from readwritecsv import * + +def jumlahpot(userinventory) : + for i in userinventory : + if i[1]=='strenghpotion' : + jumlahstr = i[2] + break + else : jumlahstr = 0 + for i in userinventory : + if i[1]=='respotion' : + jumlahres = i[2] + break + else : jumlahres = 0 + for i in userinventory : + if i[1]=='healingpotion' : + jumlahheal = i[2] + break + else : jumlahheal = 0 + return [int(jumlahstr),int(jumlahres),int(jumlahheal)] + +def lokasipot(userinventory) : + x=0 + for i in userinventory : + if i[1]=='strenghpotion' : + break + x+=1 + else : x=999 + y=0 + for i in userinventory : + if i[1]=='respotion' : + break + y+=1 + else : y=999 + z=0 + for i in userinventory : + if i[1]=='healingpotion' : + break + z+=1 + else : x=999 + return [x,y,z] + + # used_Pot_Array adalah array untuk menunjukkan apakah sebuah potion telah digunakan sekali dalam battle dengan used_Pot_Array [jumlah strength potion digunakan, jumlah resilience potion digunakan, jumlah heal potion digunakan] +def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, HP, max_HP, mons_Name, pilihan): + if pilihan==1 : + if int(jumlahpot[0])> 0 : + if used_Pot_Array[0] == 0 : + used_Pot_Array[0] += 1 + attack *= 105/100 + print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih kuat!!") + jumlahpot[0] -= 1 + userinventory[lokasipot[0]][2]=str(int(userinventory[lokasipot[0]][2])-1) + return attack + else : + print(f"Potion hanya bisa digunakan sekali") + return 0 + else : + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + return 0 + + elif pilihan==2 : + if int(jumlahpot[1]) > 0 : + if used_Pot_Array[1] == 0 : + used_Pot_Array[1] += 1 + defense *= 105/100 + print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih sulit dilukai!!") + jumlahpot[1] -=1 + userinventory[lokasipot[1]][2]=str(int(userinventory[lokasipot[1]][2])-1) + return defense + else : + print(f"Potion hanya bisa digunakan sekali") + return 0 + else : + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + return 0 + elif pilihan==3 : + if int(jumlahpot[2]) > 0 : + if used_Pot_Array[2] == 0 : + used_Pot_Array[2] += 1 + if HP * 125/100 <= max_HP : + HP *= 125/100 + print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") + jumlahpot[2] -=1 + userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) + return HP + else : + HP = max_HP + print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") + jumlahpot[2] -=1 + userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) + return HP + else : + print(f"Potion hanya bisa digunakan sekali") + return 0 + else : + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + return 0 + + + +# contoh penggunaan function : potion(pot_Inventory (2, csvRead("E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\item_inventory.csv")), used_Pot_Array, 10, 20, 30, 100, "Zuko") \ No newline at end of file diff --git a/src/readwritecsv.py b/src/readwritecsv.py new file mode 100644 index 0000000..f02f407 --- /dev/null +++ b/src/readwritecsv.py @@ -0,0 +1,27 @@ +def read_csv(path) : + field = '' + row = [] + data =[] + with open(path) as file : + for char in file.read(): + if char == ',': + row.append(field) + field='' + elif char=="\n" : + row.append(field) + data.append(row) + field='' + row=[] + else : + field += char + row.append(field) + data.append(row) + return data + +'''def write_csv(filename, data): + with open(filename, 'w') as file: + for i in range(len(data)): + file.write(','.join(data[i])) + if i < len(data) - 1: # Add newline if it's not the last row + file.write('\n')''' + diff --git a/src/shop_currency.py b/src/shop_currency.py new file mode 100644 index 0000000..5bffb86 --- /dev/null +++ b/src/shop_currency.py @@ -0,0 +1,236 @@ +'''from csvParser import splitSemicolon, csvRead, csvWrite, csvOverwrite, csvDelete''' +'''pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" +potionList = csvRead(pathItemShop) +potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"]''' + +def shopOpen(role,potionshop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): + yourcoin=coin + if role == "agent": + print("Selamat datang di Shop!") + print() + keluar = False + while keluar != True: + pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") + for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop + x=int(monstershop[i][0]) + print(f"{i} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + lihatSelesai == True + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionshop)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionshop[i][0]}\t| {potionshop[i][1]}\t| {potionshop[i][2]}") + lihatSelesai == True + elif pilihMenu == "beli": + print(f"Jumlah O.W.C.A Coin-mu sekarang {yourcoin}.") + print() + beliType = input(">>> Mau beli apa? (monster/potion): ") + beliSelesai = False + while beliType != "monster" and beliType != "potion" and beliSelesai != True: + beliType = input(">>> Pilih antara monster/potion: ") + if beliType == "monster": + while True : + r=0 + idMonsterBeli = int(input(">>> Masukkan id monster: ")) + for i in yourmonsterdata : + if monsterdata[idMonsterBeli][1]==i[1] : + print("Monster sudah dimiliki") + break + else : + for i in monstershop : + if i[0]==str(idMonsterBeli) : + if yourcoin >= int(i[2]) : + print("monster berhasil ditambahkan") + yourcoin-= int(i[2]) + yourmonsterdata.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) + monsterinventory.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) + x=0 + for i in monstershop : + if i[0]==str(idMonsterBeli) : + monstershop[x][1]=str(int(monstershop[x][1])-1) + break + x+=1 + r=1 + break + else : + print("maaf coin mu kurang") + break + if r==1 : break + # if OWCA >= harga monster: + print() + beliSelesai == True + elif beliType == "potion": + idPotion = int(input(">>> Masukkan id potion: ")) + while True : + jumlahPotionBeli = int(input(">>> Masukkan jumlah: ")) + if int(potionshop[idPotion][1]) >0 : + if jumlahPotionBeli>int(potionshop[idPotion][1]): + print("Stock tidak cukup") + else : + if yourcoin >= (jumlahPotionBeli * int(potionshop[idPotion][2])): + print(f"Berhasil membeli item: {jumlahPotionBeli} {potionshop[idPotion][0]}. Item sudah masuk ke inventory-mu!") + print() + userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) + print(userinventory) + yourcoin-=(jumlahPotionBeli * int(potionshop[idPotion][2])) + potionshop[idPotion][1]=str(int(potionshop[idPotion][1])-jumlahPotionBeli) + break + else : + print("maaf coin mu kurang") + else : + print("Stock habis!") + break + + beliSelesai == True + else: # pilihMenu == "keluar" + keluar == True + print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") + break + return yourcoin + '''elif role == "admin": + print("Selamat datang kembali, Admin!") + print() + keluar = False + while keluar != True: + pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + print("monster") + lihatSelesai == True + # monster_list() + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") + lihatSelesai == True + elif pilihMenu == "tambah": + tambah_pilih = input("Mau tambah apa? (monster/potion): ") + tambahSelesai = False + while tambah_pilih != "monster" and tambah_pilih != "potion" and tambahSelesai != True: + tambah_pilih = (input(">>> Pilih antara monster/potion: ")) + if tambah_pilih == "monster": + print("monster") # Nanti di sini list semua monster dari database yang belom ada di Shop + print() + idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi + stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) + hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + # monster_list.append() + print("[nama monster] telah berhasil ditambahkan ke dalam Shop!") + elif tambah_pilih == "potion": + potionFound = False + countFalse = 0 + print("ID | Type") + for i in range(1,4): + for j in range(1,len(potionList)): + if potionID[i] in potionList[j][0]: + potionFound = True + break + else: + potionFound = False + continue + if potionFound == False: + print(f"{i} | {potionID[i]}") + countFalse += 1 + if countFalse == 0: + print("Semua Potion sudah tersedia pada Shop!") + print() + else: + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + while (idPotionTambah < 1 or idPotionTambah > 3): + print("id tidak valid!") + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + stokPotionTambah = int(input("Masukkan stok awal: ")) + hargaPotionTambah = int(input("Masukkan harga: ")) + csvWrite(pathItemShop, f"{potionID[idPotionTambah]};{stokPotionTambah};{hargaPotionTambah}") + print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") + print() + elif pilihMenu == "ubah": + ubah_pilih = input("Mau ubah apa? (monster/potion): ") + ubahSelesai = False + while ubah_pilih != "monster" and ubah_pilih != "potion" and ubahSelesai != True: + ubah_pilih = (input(">>> Pilih antara monster/potion: ")) + if ubah_pilih == "monster": + idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi + stokMonsterBaru = (input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"[nama monster] telah berhasil diubah " + # komponenubah = f"{monsterList[int(idMonsterUbah)]};" + if (stokMonsterBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + # komponenUbah += f"{stokMonsterBaru};" + # else: + # komponenUbah += f"{monsterList[int(idMonsterUbah)][1];}" + if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): + pesanUbah += " dan " + if (hargaMonsterBaru != ""): + pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + # komponenUbah += f"{hargaMonsterBaru}" + # else: + # komponenUbah += f"{monsterList[int(idMonsterUbah)][2]}" + pesanUbah += "!" + csvOverwrite(pathItemShop, int(idMonsterUbah)) # , komponenUbah (Nanti) + print(pesanUbah) + elif ubah_pilih == "potion": + idPotionUbah = (input(">>> Masukkan id potion: ")) + stokPotionBaru = (input(">>> Masukkan stok baru: ")) + hargaPotionBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " + komponenUbah = f"{potionID[int(idPotionUbah)]};" + if (stokPotionBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" + komponenUbah += f"{stokPotionBaru};" + else: + komponenUbah += f"{potionList[int(idPotionUbah)][1]};" + if (stokPotionBaru != "") and (hargaPotionBaru != ""): + pesanUbah += " dan " + if (hargaPotionBaru != ""): + pesanUbah += f"dengan harga baru {hargaPotionBaru}" + komponenUbah += f"{hargaPotionBaru}" + else: + komponenUbah += f"{potionList[int(idPotionUbah)][2]}" + pesanUbah += "!" + csvDelete(pathItemShop, int(idPotionUbah), komponenUbah) + print(pesanUbah) + print() + elif pilihMenu == "hapus": + hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") + hapusSelesai = False + while hapusPilih != "monster" and hapusPilih != "potion" and hapusSelesai != True: + hapusPilih = (input(">>> Pilih antara monster/potion: ")) + if hapusPilih == "monster": + idMonsterHapus = input(">>> Masukkan id monster: ") + # yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterList[int(idPokemonHapus)]} dari Shop (y/n)? ) + # if yakinHapus == "y": + # csvDelete(pathItemShop, int(idMonsterHapus)) + # print(f"{monsterList[int(idPokemonHapus)]} telah berhasil dihapus dari Shop!") + # else: + # continue + elif hapusPilih == "potion": + idPotionHapus = input(">>> Masukkan id potion: ") + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[int(idPotionHapus)]} dari Shop (y/n)? ") + if yakinHapus == "y": + csvDelete(pathItemShop, int(idPotionHapus)) + print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") + print() + else: + print("Penghapusan dibatalkan!") + print() + continue + else: # pilihMenu == "keluar" + keluar == True + print("Sampai bertemu lagi Admin!") + break''' + return + +# shopOpen("agent") +# shopOpen("admin") \ No newline at end of file From 82b5e2778f4e5e1cd31223ba47a03aee5c052f85 Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Wed, 15 May 2024 15:48:37 +0700 Subject: [PATCH 016/115] feat: Exit (F16) --- src/exit.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/exit.py diff --git a/src/exit.py b/src/exit.py new file mode 100644 index 0000000..25f25f0 --- /dev/null +++ b/src/exit.py @@ -0,0 +1,9 @@ +def exit(): + confirmExit = input(print("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) + while confirmExit != "y" or confirmExit != "n": + confirmExit = input(print("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) + if confirmExit == "y": + # jalankan fungsi SAVE + print("Program berhasil ditutup!") + else: # confirmExit =="n + print("Program berhasil ditutup!") \ No newline at end of file From 3271b6a4cfbaa70a6fc8d029629e7020811c4fa7 Mon Sep 17 00:00:00 2001 From: echaa0018 <167690463+echaa0018@users.noreply.github.com> Date: Wed, 15 May 2024 16:01:55 +0700 Subject: [PATCH 017/115] refactor: edit input dan file path --- src/monsterManagement.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 10ad774..4786fb8 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -1,4 +1,4 @@ -from csvParser import splitSemicolonInt, csvReadInt, csvWrite +from csvParser import * pathFileMonster = r"C:\Files\if1210-2024-tubes-k08-b\data\monster.csv" listMonster = csvReadInt(pathFileMonster) @@ -73,7 +73,6 @@ def checkUserInput(userInput, nType, nAttack , nDefense, nHp): while True: if userInput == "Y" : # disini masukkan file ke csv dulu karena bila append terlebih dahulu len(listMonster) id akan tidak sesuai pada file monster.csv - csvWrite(pathFileMonster, f"{len(listMonster)};{nType};{nAttack};{nDefense};{nHp}") listMonster.append([len(listMonster), nType, nAttack, nDefense, nHp]) print("Monster berhasil ditambahkan") break @@ -84,7 +83,7 @@ def checkUserInput(userInput, nType, nAttack , nDefense, nHp): print("input tidak valid, hanya menerima input Y/N") userInput = str(input("(Y/N): ")) def validUserInput(userInput, nType, nAttack, nDefense, nHp): - userInput = str(input("(Y/N): ")) + userInput = str(input("Apakah mau tambahkan monster? (Y/N): ") return checkUserInput(userInput, nType, nAttack, nDefense, nHp) # FUNGSI PENAMBAHAN MONSTER BARU SECARA KESELURUHAN @@ -189,4 +188,4 @@ def monsterManagement(): else : print("Input tidak valid, input yang diterima hanya 0/1/2") -# PENERAPAN FUNGSI \ No newline at end of file +# PENERAPAN FUNGSI From 365c59f1db5cec64387226fa535d2fb9fe865ee7 Mon Sep 17 00:00:00 2001 From: echaa0018 <167690463+echaa0018@users.noreply.github.com> Date: Wed, 15 May 2024 16:24:19 +0700 Subject: [PATCH 018/115] refactor: tambah monster --- data/data1/monster.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/data1/monster.csv b/data/data1/monster.csv index b42d78c..24990d0 100644 --- a/data/data1/monster.csv +++ b/data/data1/monster.csv @@ -1,6 +1,6 @@ id,type,atk_power,def_power,hp 1,Godzilla,170,40,600 -2,Mimic,35,5,150 +2,Mimic,100,5,150 3,Makima,300,25,350 4,Jalangkung,100,10,600 -5,gigidi gigididuu,100,10,100 \ No newline at end of file +5,gigidi gigididuu,100,10,100 From 2f0e521e6e59633ea4a75bce1a07e9e73b225976 Mon Sep 17 00:00:00 2001 From: echaa0018 <167690463+echaa0018@users.noreply.github.com> Date: Wed, 15 May 2024 16:29:51 +0700 Subject: [PATCH 019/115] refactor: tambah monster --- data/data1/monster.csv | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data/data1/monster.csv b/data/data1/monster.csv index 24990d0..d0a5967 100644 --- a/data/data1/monster.csv +++ b/data/data1/monster.csv @@ -1,6 +1,7 @@ id,type,atk_power,def_power,hp -1,Godzilla,170,40,600 -2,Mimic,100,5,150 -3,Makima,300,25,350 -4,Jalangkung,100,10,600 -5,gigidi gigididuu,100,10,100 +1,Godzilla,60,35,540 +2,Mimic,45,25,600 +3,Makima,135,15,250 +4,Jalangkung,50,20,580 +5,gigidi gigididuu,25,10,800 +6,Gorlock the Destroyer,150,40,1700 From eeb3dd09d5d8a65e1ba444a4528d513df43e1225 Mon Sep 17 00:00:00 2001 From: echaa0018 <167690463+echaa0018@users.noreply.github.com> Date: Wed, 15 May 2024 16:30:31 +0700 Subject: [PATCH 020/115] Update monster.csv From 81c2cb464a5ea90801949b3e328b09e53d36b1b2 Mon Sep 17 00:00:00 2001 From: echaa0018 <167690463+echaa0018@users.noreply.github.com> Date: Wed, 15 May 2024 16:50:00 +0700 Subject: [PATCH 021/115] refactor: tambah monster --- data/data1/monster.csv | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/data/data1/monster.csv b/data/data1/monster.csv index d0a5967..bddbaee 100644 --- a/data/data1/monster.csv +++ b/data/data1/monster.csv @@ -1,7 +1,16 @@ id,type,atk_power,def_power,hp -1,Godzilla,60,35,540 -2,Mimic,45,25,600 -3,Makima,135,15,250 -4,Jalangkung,50,20,580 -5,gigidi gigididuu,25,10,800 -6,Gorlock the Destroyer,150,40,1700 +1,Godzilla,70,32,540 +2,Mimic,45,28,600 +3,Makima,135,5,250 +4,Jalangkung,37,12,650 +5,gigidi gigididuu,54,19,420 +6,Gorlock the Destroyer,22,20,700 +7,Colossal Bunny,65,24,550 +8,Roga,88,8,222 +9,Molded,66,24,440 +10,Mohg,50,20,600 +11,Malenia,55,30,500 +12,Kraken,20,35,570 +13,Mothra,57,21,520 +14,Parkinson,44,31,470 +15,Ifrit,90,5,330 From 3f1eb9b1666669af0856e7cca9054df8103ee539 Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Thu, 16 May 2024 16:51:00 +0700 Subject: [PATCH 022/115] feat: Update shopCurrency Function --- src/csvParser.py | 61 +++++++++ src/shopCurrency.py | 309 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 src/csvParser.py create mode 100644 src/shopCurrency.py diff --git a/src/csvParser.py b/src/csvParser.py new file mode 100644 index 0000000..6682c0a --- /dev/null +++ b/src/csvParser.py @@ -0,0 +1,61 @@ +import sys +sys.path.append("C:\if1210-2024-tubes-k08-b\data") + +def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja + separated = [] + word = '' + + for char in (text): + if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) + break + elif char != ';': + word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata + else: # char == ";" + separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array + word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) + + separated.append(word) # Untuk kata setelah semicolon terakhir + + return separated + +def csvRead(path): # Fungsi membaca file .csv baris per baris + csvOpen = open(path,'r') # Membuka file .csv + cleanData = [] + + for row in csvOpen: # Membaca setiap baris + cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon + + csvOpen.close() # Menutup file + return cleanData + +def splitSemicolonInt(text): + separated = [] + word = '' + for char in (text): + if char == '\n' : + break + elif char != ';': + word += char + else: + if word.isdigit(): + word = int(word) + separated.append(word) + word = '' + if word.isdigit(): + word = int(word) + separated.append(word) + return separated + +def csvReadInt(path): + csvOpen = open(path,'r') + cleanData = [] + for row in csvOpen: + cleanData.append(splitSemicolonInt(row)) + csvOpen.close() + return cleanData + +def csvWriteAll(path,newList): # Fungsi mengupdate csv lama dengan data-data list terbaru + with open(path,'w') as csvWrite: + for rows in newList: + csvWrite.write(''.join(rows)) + return \ No newline at end of file diff --git a/src/shopCurrency.py b/src/shopCurrency.py new file mode 100644 index 0000000..d0da61c --- /dev/null +++ b/src/shopCurrency.py @@ -0,0 +1,309 @@ +'''from csvParser import csvRead, csvWriteAll +pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" +potionShop = csvRead(pathItemShop)''' +potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"] + + +def shopInterface(): + print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") + print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") + print(" |___|__∆|___|_|∆|_| ███▀▀▀███ __||_ ") + print(" |∆__|___|∆__|∆|_|_| ███████ /_____\ ") + print(" |___|_∆_|___|_|∆|_| ██████████████ KASIR ██") + print(" =================== ███████████████████████") + return + +def sortPotion(potionShop): + if potionShop[1][0] == "Resilience Potion": + potionShop[1][0],potionShop[2][0] = potionShop[2][0],potionShop[1][0] + if potionShop[3][0] == "Resilience Potion": + potionShop[3][0],potionShop[2][0] = potionShop[2][0],potionShop[3][0] + if potionShop[1][0] == "Strength Potion": + potionShop[1][0],potionShop[3][0] = potionShop[3][0],potionShop[1][0] + return potionShop + +def listTocsv(list): + new_csv = [] + csvCell = "" + for i in range(len(list)): + for j in range(len(list[1])): + csvCell += f"{list[i][j]}" + if j != len(list[1])-1: + csvCell += f";" + if i != len(list)-1 and j == len(list[1])-1: + csvCell += "\n" + new_csv.append(csvCell) + csvCell = "" + return new_csv + +def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): + yourcoin = coin + if role == "agent": + print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") + print() + shopInterface() + print() + while True: + pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "potion": + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + idMonsterShop = [] + for i in range(1,len(monstershop)): + idMonsterShop.append(monstershop[i][0]) + idMonsterData = [] + for i in range(1,len(monsterdata)): + idMonsterData.append(monsterdata[i][0]) + print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") + for i in range(1,len(monstershop)): # Menampilkan setiap monster yang tersedia di Shop + idMonsterLihat=int(monstershop[i][0]) + print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop + if potionShop[i][0] == "Healing Potion": + idPotion = 1 + elif potionShop[i][0] == "Resilience Potion": + idPotion = 2 + elif potionShop[i][0] == "Strength Potion": + idPotion = 3 + print(f"{i} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") + lihatSelesai == True + elif pilihMenu == "beli": + print(f"Jumlah O.W.C.A Coin-mu sekarang {yourcoin}.") + print() + beliType = input(">>> Mau beli apa? (monster/potion): ") + while beliType != "monster" and beliType != "potion": + beliType = input(">>> Pilih antara monster/potion: ") + if beliType == "monster": + while True: + transactionStatus = 0 + idMonsterBeli = int(input(">>> Masukkan id monster: ")) + for i in yourmonsterdata : + if monsterdata[idMonsterBeli][1] == i[1] : + print("Monster sudah dimiliki") + break + else : + for i in monstershop : + if i[0]==str(idMonsterBeli) : + if yourcoin >= int(i[2]) : + print("monster berhasil ditambahkan") + yourcoin -= int(i[2]) + yourmonsterdata.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) + monsterinventory.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) + monsterShopLocation = 0 + for i in monstershop : + if i[0]==str(idMonsterBeli) : + monstershop[monsterShopLocation][1] = str(int(monstershop[monsterShopLocation][1])-1) + break + monsterShopLocation += 1 + transactionStatus = 1 + break + else : + print("Maaf O.W.C.A. Coin-mu kurang.") + break + if transactionStatus == 1 : + break + print() + elif beliType == "potion": + idPotion = int(input(">>> Masukkan id potion: ")) + while True : + jumlahPotionBeli = int(input(">>> Masukkan jumlah: ")) + if int(potionShop[idPotion][1]) >0 : + if jumlahPotionBeli>int(potionShop[idPotion][1]): + print("Stock tidak cukup") + else : + if yourcoin >= (jumlahPotionBeli * int(potionShop[idPotion][2])): + print(f"Berhasil membeli item: {jumlahPotionBeli} {potionShop[idPotion][0]}. Item sudah masuk ke inventory-mu!") + print() + userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) + print(userinventory) + yourcoin-=(jumlahPotionBeli * int(potionShop[idPotion][2])) + potionShop[idPotion][1]=str(int(potionShop[idPotion][1])-jumlahPotionBeli) + break + else : + print("Maaf O.W.C.A Coin-mu kurang.") + else : + print("Stock Potion habis!") + break + break + else: # pilihMenu == "keluar" + print(f"Sampai bertemu lagi, User!") + break + + elif role == "admin": + print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") + print() + shopInterface() + print() + while True: + pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") + if pilihMenu == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + while lihat_pilih != "monster" and lihat_pilih != "potion": + lihat_pilih = input(">>> Pilih antara monster/potion: ") + if lihat_pilih == "monster": + idMonsterShop = [] + for i in range(1,len(monstershop)): + idMonsterShop.append(monstershop[i][0]) + idMonsterData = [] + for i in range(1,len(monsterdata)): + idMonsterData.append(monsterdata[i][0]) + print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") + for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop + idMonsterLihat=int(monstershop[i][0]) + print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + elif lihat_pilih == "potion": + print("ID | Type\t\t| Stok\t| Harga") + for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop + if potionShop[i][0] == "Healing Potion": + idPotion = 1 + elif potionShop[i][0] == "Resilience Potion": + idPotion = 2 + elif potionShop[i][0] == "Strength Potion": + idPotion = 3 + print(f"{idPotion} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") + + elif pilihMenu == "tambah": + tambah_pilih = input("Mau tambah apa? (monster/potion): ") + while tambah_pilih != "monster" and tambah_pilih != "potion": + tambah_pilih = (input(">>> Pilih antara monster/potion: ")) + if tambah_pilih == "monster": + print("ID | Type\t\t\t| ATK Power\t| DEF Power\t| HP\t|") + for i in range(1,len(monsterdata)): # Menampilkan setiap monster yang tersedia di Shop + if monsterdata[i][0] in idMonsterShop: + continue + else: + idMonsterLihat=int(monsterdata[i][0]) + print(f"{i} | {monsterdata[idMonsterLihat][1]}\t\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t|") + print() + idMonsterTambah = input(">>> Masukkan id monster: ") + while idMonsterTambah in idMonsterShop or idMonsterTambah not in idMonsterData: + if idMonsterTambah not in idMonsterData: + print("ID tidak valid! Pilih ID yang terdapat pada tabel!") + idMonsterTambah = (input(">>> Masukkan id monster: ")) + elif idMonsterTambah in idMonsterShop: + print("Monster sudah ada di Shop!") + idMonsterTambah = (input(">>> Masukkan id monster: ")) + stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) + hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + addMonsterShop = [idMonsterTambah,str(stokMonsterTambah),str(hargaMonsterTambah)] + monstershop.append(addMonsterShop) + print(f"{monsterdata[int(idMonsterTambah)][1]} telah berhasil ditambahkan ke dalam Shop!") + elif tambah_pilih == "potion": + potionFound = False + countFalse = 0 + print("ID | Type") + for i in range(1,4): + for j in range(1,len(potionShop)): + if potionID[i] in potionShop[j][0]: + potionFound = True + break + else: + potionFound = False + continue + if potionFound == False: + print(f"{i} | {potionID[i]}") + countFalse += 1 + if countFalse == 0: + print("Semua Potion sudah tersedia pada Shop!") + print() + else: + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + while (idPotionTambah < 1 or idPotionTambah > 3): + print("id tidak valid!") + idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + stokPotionTambah = int(input("Masukkan stok awal: ")) + hargaPotionTambah = int(input("Masukkan harga: ")) + newPotion = [potionID[idPotionTambah],str(stokPotionTambah),str(hargaPotionTambah)] + potionShop.append(newPotion) + sortPotion(potionShop) + print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") + print() + + elif pilihMenu == "ubah": + ubah_pilih = input("Mau ubah apa? (monster/potion): ") + while ubah_pilih != "monster" and ubah_pilih != "potion": + ubah_pilih = (input(">>> Pilih antara monster/potion: ")) + if ubah_pilih == "monster": + idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi + stokMonsterBaru = int(input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = int(input(">>> Masukkan harga baru: ")) + pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " + if (stokMonsterBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): + pesanUbah += " dan " + if (hargaMonsterBaru != ""): + pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + pesanUbah += "!" + print(monstershop) + monstershop[int(idMonsterUbah)] = [monsterdata[int(idMonsterUbah)][0],str(stokMonsterBaru),str(hargaMonsterBaru)] + print(monstershop) + print(pesanUbah) + elif ubah_pilih == "potion": + idPotionUbah = int((input(">>> Masukkan id potion: "))) + while idPotionUbah < 1 or idPotionUbah > 3: + print("ID tidak valid!") + idPotionUbah = int((input(">>> Masukkan id potion: "))) + stokPotionBaru = int((input(">>> Masukkan stok baru: "))) + hargaPotionBaru = int((input(">>> Masukkan harga baru: "))) + pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " + if (stokPotionBaru != ""): + pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" + if (stokPotionBaru != "") and (hargaPotionBaru != ""): + pesanUbah += " dan " + if (hargaPotionBaru != ""): + pesanUbah += f"dengan harga baru {hargaPotionBaru}" + pesanUbah += "!" + potionShop[idPotionUbah] = [potionID[idPotionUbah],stokPotionBaru,hargaPotionBaru] + print(pesanUbah) + print() + + elif pilihMenu == "hapus": + hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") + while hapusPilih != "monster" and hapusPilih != "potion": + hapusPilih = (input(">>> Pilih antara monster/potion: ")) + if hapusPilih == "monster": + idMonsterHapus = int(input(">>> Masukkan id monster: ")) + while idMonsterHapus not in idMonsterShop: + print("Monster dengan ID tersebut tidak ada pada Shop!") + idMonsterHapus = int(input(">>> Masukkan id monster: ")) + yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[idMonsterHapus][1]} dari Shop (y/n)? ") + if yakinHapus == "y": + newMonsterList = [] + for i in range(len(monstershop)): + if i == idMonsterHapus: + continue + else: + newMonsterList.append(monstershop[i]) + monstershop = newMonsterList + print(f"{monsterdata[idMonsterHapus][1]} telah berhasil dihapus dari Shop!") + else: + print("Penghapusan dibatalkan!") + print() + continue + elif hapusPilih == "potion": + idPotionHapus = int(input(">>> Masukkan id potion: ")) + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[idPotionHapus]} dari Shop (y/n)? ") + if yakinHapus == "y": + newPotionList = [] + for i in range(len(potionShop)): + if i == idPotionHapus: + continue + else: + newPotionList.append(potionShop[i]) + potionShop = newPotionList + print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") + print() + else: + print("Penghapusan dibatalkan!") + print() + continue + + else: # pilihMenu == "keluar" + print("Sampai bertemu lagi Admin!") + break \ No newline at end of file From aaff96eb0701dc1a67c81830612cebeb61cafc2c Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Thu, 16 May 2024 17:02:02 +0700 Subject: [PATCH 023/115] refactor: Changing ',' to ';' on csv files --- data/data1/item_inventory.csv | 20 ++++++++++---------- data/data1/item_shop.csv | 8 ++++---- data/data1/monser_inventory.csv | 16 ++++++++-------- data/data1/monster.csv | 32 ++++++++++++++++---------------- data/data1/monster_shop.csv | 8 ++++---- data/data1/user.csv | 16 ++++++++-------- src/monsterManagement.py | 2 +- src/tempCodeRunnerFile.py | 1 + 8 files changed, 52 insertions(+), 51 deletions(-) create mode 100644 src/tempCodeRunnerFile.py diff --git a/data/data1/item_inventory.csv b/data/data1/item_inventory.csv index 2ac051d..11fd4a0 100644 --- a/data/data1/item_inventory.csv +++ b/data/data1/item_inventory.csv @@ -1,10 +1,10 @@ -userid,type,quantity -1,healingpotion,2 -1,respotion,3 -1,strenghpotion,2 -3,healingpotion,2 -3,respotion,3 -3,strenghpotion,2 -2,healingpotion,2 -2,respotion,2 -2,strenghpotion,9 \ No newline at end of file +userid;type;quantity +1;healingpotion;2 +1;respotion;3 +1;strenghpotion;2 +3;healingpotion;2 +3;respotion;3 +3;strenghpotion;2 +2;healingpotion;2 +2;respotion;2 +2;strenghpotion;9 \ No newline at end of file diff --git a/data/data1/item_shop.csv b/data/data1/item_shop.csv index c515242..91693bb 100644 --- a/data/data1/item_shop.csv +++ b/data/data1/item_shop.csv @@ -1,4 +1,4 @@ -type,stock,price -Healing Potion,5,25 -Resilience Potion,5,35 -Strength Potion,5,40 \ No newline at end of file +type;stock;price +Healing Potion;5;25 +Resilience Potion;5;35 +Strength Potion;5;40 \ No newline at end of file diff --git a/data/data1/monser_inventory.csv b/data/data1/monser_inventory.csv index e923adf..fa699c0 100644 --- a/data/data1/monser_inventory.csv +++ b/data/data1/monser_inventory.csv @@ -1,8 +1,8 @@ -id,monster,level -1,Mimic,1 -1,Makima,2 -1,Jalangkung,3 -2,Makima,1 -2,Mimic,1 -3,Jalangkung,2 -3,Mimic,1 \ No newline at end of file +id;monster;level +1;Mimic;1 +1;Makima;2 +1;Jalangkung;3 +2;Makima;1 +2;Mimic;1 +3;Jalangkung;2 +3;Mimic;1 \ No newline at end of file diff --git a/data/data1/monster.csv b/data/data1/monster.csv index bddbaee..79af8d1 100644 --- a/data/data1/monster.csv +++ b/data/data1/monster.csv @@ -1,16 +1,16 @@ -id,type,atk_power,def_power,hp -1,Godzilla,70,32,540 -2,Mimic,45,28,600 -3,Makima,135,5,250 -4,Jalangkung,37,12,650 -5,gigidi gigididuu,54,19,420 -6,Gorlock the Destroyer,22,20,700 -7,Colossal Bunny,65,24,550 -8,Roga,88,8,222 -9,Molded,66,24,440 -10,Mohg,50,20,600 -11,Malenia,55,30,500 -12,Kraken,20,35,570 -13,Mothra,57,21,520 -14,Parkinson,44,31,470 -15,Ifrit,90,5,330 +id;type;atk_power;def_power;hp +1;Godzilla;70;32;540 +2;Mimic;45;28;600 +3;Makima;135;5;250 +4;Jalangkung;37;12;650 +5;gigidi gigididuu;54;19;420 +6;Gorlock the Destroyer;22;20;700 +7;Colossal Bunny;65;24;550 +8;Roga;88;8;222 +9;Molded;66;24;440 +10;Mohg;50;20;600 +11;Malenia;55;30;500 +12;Kraken;20;35;570 +13;Mothra;57;21;520 +14;Parkinson;44;31;470 +15;Ifrit;90;5;330 \ No newline at end of file diff --git a/data/data1/monster_shop.csv b/data/data1/monster_shop.csv index 2ba38c2..41ee368 100644 --- a/data/data1/monster_shop.csv +++ b/data/data1/monster_shop.csv @@ -1,4 +1,4 @@ -monster_id,stock,price -1,6,800 -2,13,300 -3,2,750 \ No newline at end of file +monster_id;stock;price +1;6;800 +2;13;300 +3;2;750 \ No newline at end of file diff --git a/data/data1/user.csv b/data/data1/user.csv index a6ceb17..6b2ac13 100644 --- a/data/data1/user.csv +++ b/data/data1/user.csv @@ -1,8 +1,8 @@ -id,username,password,role,coin -1,bagas,12345,agent,1000 -2,bagus,12345,agent,100 -3,bages,12345,agent,100 -4,bagos,12345,agent,100 -5,bagis,12345,agent,100 -6,june,12345,admin,100 -7,juni,12345,admin,100 \ No newline at end of file +id;username;password;role;coin +1;bagas;12345;agent;1000 +2;bagus;12345;agent;100 +3;bages;12345;agent;100 +4;bagos;12345;agent;100 +5;bagis;12345;agent;100 +6;june;12345;admin;9999 +7;juni;12345;admin;9999 \ No newline at end of file diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 4786fb8..340344a 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -83,7 +83,7 @@ def checkUserInput(userInput, nType, nAttack , nDefense, nHp): print("input tidak valid, hanya menerima input Y/N") userInput = str(input("(Y/N): ")) def validUserInput(userInput, nType, nAttack, nDefense, nHp): - userInput = str(input("Apakah mau tambahkan monster? (Y/N): ") + userInput = str(input("Apakah mau tambahkan monster? (Y/N): ")) return checkUserInput(userInput, nType, nAttack, nDefense, nHp) # FUNGSI PENAMBAHAN MONSTER BARU SECARA KESELURUHAN diff --git a/src/tempCodeRunnerFile.py b/src/tempCodeRunnerFile.py new file mode 100644 index 0000000..9ad1705 --- /dev/null +++ b/src/tempCodeRunnerFile.py @@ -0,0 +1 @@ +csvOpen \ No newline at end of file From 232771b516c2e56d506c43ce08ab20f36263d8bc Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Thu, 16 May 2024 19:12:54 +0700 Subject: [PATCH 024/115] feat :recombine evenrything --- data/data1/item_inventory.csv | 21 ++- data/data1/item_shop.csv | 4 +- data/data1/monster.csv | 6 +- src/arena.py | 6 +- src/battle.py | 40 ++-- src/help.py | 12 +- src/inventory.py | 17 +- src/jackpot.py | 50 +++++ src/load.py | 91 +++------ src/main.py | 33 +++- src/monsterball.py | 54 ++++++ src/potion.py | 14 +- src/readwritecsv.py | 2 +- src/shopCurrency.py | 345 +++++++++++++++------------------- src/shop_currency.py | 236 ----------------------- 15 files changed, 381 insertions(+), 550 deletions(-) create mode 100644 src/jackpot.py create mode 100644 src/monsterball.py delete mode 100644 src/shop_currency.py diff --git a/data/data1/item_inventory.csv b/data/data1/item_inventory.csv index 11fd4a0..82b2573 100644 --- a/data/data1/item_inventory.csv +++ b/data/data1/item_inventory.csv @@ -1,10 +1,13 @@ userid;type;quantity -1;healingpotion;2 -1;respotion;3 -1;strenghpotion;2 -3;healingpotion;2 -3;respotion;3 -3;strenghpotion;2 -2;healingpotion;2 -2;respotion;2 -2;strenghpotion;9 \ No newline at end of file +1;Healing Potion;2 +1;Resilience Potion;3 +1;Strength Potion;2 +1;Monster Ball;2 +3;Healing Potion;2 +3;Resilience Potion;1 +3;Strength Potion;4 +3;Monster Ball;1 +2;Healing Potion;2 +2;Resilience Potion;2 +2;Strength Potion;9 +2;Monster Ball;5 \ No newline at end of file diff --git a/data/data1/item_shop.csv b/data/data1/item_shop.csv index 91693bb..4bc3289 100644 --- a/data/data1/item_shop.csv +++ b/data/data1/item_shop.csv @@ -1,4 +1,4 @@ type;stock;price Healing Potion;5;25 -Resilience Potion;5;35 -Strength Potion;5;40 \ No newline at end of file +Strength Potion;5;40 +Monster Ball;5;100 \ No newline at end of file diff --git a/data/data1/monster.csv b/data/data1/monster.csv index 79af8d1..70ccb85 100644 --- a/data/data1/monster.csv +++ b/data/data1/monster.csv @@ -3,9 +3,9 @@ id;type;atk_power;def_power;hp 2;Mimic;45;28;600 3;Makima;135;5;250 4;Jalangkung;37;12;650 -5;gigidi gigididuu;54;19;420 -6;Gorlock the Destroyer;22;20;700 -7;Colossal Bunny;65;24;550 +5;gigidi;54;19;420 +6;Gorlock;22;20;700 +7;Bunny;65;24;550 8;Roga;88;8;222 9;Molded;66;24;440 10;Mohg;50;20;600 diff --git a/src/arena.py b/src/arena.py index 5055271..131f2d5 100644 --- a/src/arena.py +++ b/src/arena.py @@ -1,7 +1,7 @@ from battle import * from RandomNumberGenerator import * -def arena(monsterdata,yourmonsterdata,userinventory) : +def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : coins=0 @@ -23,8 +23,9 @@ def arena(monsterdata,yourmonsterdata,userinventory) : for i in range(5) : random_number = RNG(1,5) + random_level = RNG(1,5) opening(monsterdata,random_number) - coin = battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) + coin = battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,random_level,'arena') coins += coin if coin==0 : print(f"YOU MADE IT TO STAGE NUMBER {i+1}, KEEP IMPROVING") @@ -36,3 +37,4 @@ def arena(monsterdata,yourmonsterdata,userinventory) : coins += 50 print(f"YOUR TOTAL COIN GAINED FROM THE ARENA : {coins}") return coins + diff --git a/src/battle.py b/src/battle.py index 5fb6142..a44a488 100644 --- a/src/battle.py +++ b/src/battle.py @@ -1,8 +1,6 @@ -import random - -from readwritecsv import * from potion import * from RandomNumberGenerator import * +from monsterball import * def choose(yourmonsterdata) : while True : @@ -28,7 +26,7 @@ def opening(monsterdata,random_number) : name = monsterdata[random_number][1] print(f'{name} telah datang !!!!!!!!!!!') -def battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) : +def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,random_level,type) : file1 = monsterdata file2 = yourmonsterdata @@ -50,9 +48,9 @@ def battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) : yourhealth = int(file1[x][4]) + (int(level)-1)*(10/100)*int(file1[x][4]) - enemyhealth = int(file1[random_number][4]) - enemyattack = int(file1[random_number][2]) - enemydefense = int(file1[random_number][3]) + enemyhealth = int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4]) + enemyattack = int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2]) + enemydefense = int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3]) '''yourhealth = int(file2[chosen][2])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][2]) yourattack = int(file2[chosen][3])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][3]) yourdefense = int(file2[chosen][4])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][4]) @@ -75,7 +73,11 @@ def battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) : print("CHOOSE AN ACTION :") print("1. ATTACK") print("2. DRINK POTION") - print("3. QUIT") + if type=='battle' : + print("3. MONSTER BALL ") + print("4. QUIT") + elif type=='arena' : + print("3. QUIT") print("=====================") action = int(input("-------->")) if action==1 : @@ -120,16 +122,30 @@ def battle(monsterdata,yourmonsterdata,userinventory,chosen,random_number) : continue elif action==3 : - coin = 0 - return coin - break + if type =='battle' : + success = monsterball(random_number,random_level,userinventory,monsterdata,monsterinventory,yourmonsterdata) + if success==1 : + return 0 + elif success ==2 : + continue + elif type =='arena': + coin = 0 + return coin + break + elif action==4 : + if type=='arena' : + print("opsi 4 tidak ada") + elif type=='battle' : + coin = 0 + return coin + break if enemyhealth <= 0 : print("="*100) print("YOU DEFEATED YOUR ENEMY") print("WOHOOOOOO") print("="*100) - coin = random.randint(50,100) + coin = RNG(50,100) print(f"YEEEEEY YOU GOT {coin} coin") return coin break diff --git a/src/help.py b/src/help.py index 243d7ef..9b80676 100644 --- a/src/help.py +++ b/src/help.py @@ -20,6 +20,16 @@ def help(status,role) : print(" Tempat jual beli potion dan monster") print("4. Inventory") print(" Cek semua item dan monster anda") - print("5. Logout") + print("5. Laboratory") + print(" Tempat untuk meng-upgrade monster anda") + print("6. Logout") + print(" Keluar dari akun anda") + if role == 'admin' : + print("List command yang dapat anda lakukan :") + print("1. Shop") + print(" Manage shop") + print("2. Monster") + print(" Manage monster") + print("3. Logout") print(" Keluar dari akun anda") \ No newline at end of file diff --git a/src/inventory.py b/src/inventory.py index 1ba0ebe..2db5e6b 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -93,17 +93,19 @@ def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : else : print(f'jumlah OWCA coin anda saat ini : {coin}') while True : - check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Potion/Back): ') - if check.lower() == 'potion' : + check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Item/Back): ') + if check.lower() == 'item' : x=1 types=[] for i in userinventory: if i[1] == 'strenghpotion' : - type = 'ATK' - if i[1] == 'respotion' : - type = 'DEF' - if i[1] == 'healingpotion' : - type = 'HEAL' + type = 'ATK potion' + elif i[1] == 'respotion' : + type = 'DEF potion' + elif i[1] == 'healingpotion' : + type = 'HEAL potion' + elif i[1] == 'monsterball' : + type = 'MONSTER BALL' types.append(type) print(f'{x}. Type: {type}') x+=1 @@ -111,7 +113,6 @@ def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : pot_Number = input('Masukkan nomor potion untuk menampilkan detail item (1/2/3/Back): ') if pot_Number.lower() != 'back': pot_Number = int(pot_Number) - print('POTION') print(f'Type: {types[pot_Number-1]}') print(f'Quantity: {userinventory[pot_Number-1][2]}') else : diff --git a/src/jackpot.py b/src/jackpot.py new file mode 100644 index 0000000..4eb2d64 --- /dev/null +++ b/src/jackpot.py @@ -0,0 +1,50 @@ +from RandomNumberGenerator import * +import time +def cekrng(RNG) : + if RNG>=1 and RNG<=40 : + item = 0 + elif RNG>=41 and RNG<=65 : + item = 1 + elif RNG>=66 and RNG<=80 : + item = 2 + elif RNG>=81 and RNG<=95 : + item = 3 + elif RNG>=96 and RNG<=100 : + item = 4 + return item + +def gacha() : + icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM' ] + value = [50,100,150,200,250,400] + RNG1 = RNG(1,100) + time.sleep(2/10) + RNG2 = RNG(1,100) + time.sleep(1/10) + RNG3 = RNG(1,100) + item1 = cekrng(RNG1) + item2 = cekrng(RNG2) + item3 = cekrng(RNG3) + totalcoin = value[item1]+value[item2]+value[item3] + print(f"{icon[item1]} | {icon[item2]} | {icon[item3]}") + if item1==item2 and item2==item3 : + print('s') + else : + print(f"ANDA TIDAK DAPAT GORLOCK, TAPI ANDA DAPAT {totalcoin} COINS !!!") + +def jackpot(yourcoin) : + coin=yourcoin + print("SELAMAT DATANG DIJACKPOT 888!!!") + print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") + print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 400 COIN") + while True : + inp = input("(Y/N)----->") + if inp == 'Y' : + confirm = input("APAKAH ANDA YAKIN? (Y/N) :") + if confirm == 'Y' : + if coin>=400 : + gacha() + coin-=400 + else : + print("COIN TIDAK CUKUP") + else : + print("OK") \ No newline at end of file diff --git a/src/load.py b/src/load.py index 7d7f906..46d79a3 100644 --- a/src/load.py +++ b/src/load.py @@ -13,12 +13,12 @@ def load() : elif(os.path.exists(path)): # jika folder ditemukan print("Loading...") print("Selamat datang") - user = read_csv("data/data1/user.csv") - inventory = read_csv("data/data1/item_inventory.csv") - monster = read_csv("data/data1/monster.csv") - monsterinventory = read_csv("data/data1/monser_inventory.csv") - itemshop=read_csv("data/data1/item_shop.csv") - monstershop=read_csv("data/data1/monster_shop.csv") + user = read_csv(path+"/user.csv") + inventory = read_csv(path+"/item_inventory.csv") + monster = read_csv(path+"/monster.csv") + monsterinventory = read_csv(path+"/monser_inventory.csv") + itemshop=read_csv(path+"/item_shop.csv") + monstershop=read_csv(path+"/monster_shop.csv") return [user,inventory,monster,monsterinventory,itemshop,monstershop] else: # folder tidak ditemukan print(f"Folder \"{path}\" tidak ditemukan.") @@ -30,17 +30,20 @@ def login(user,inventory,monsterinventory) : for i in user : if i[1] == username : if i[2] == password : - player_inventory = [] - monster_inventory =[] - print("login berhasil") - for j in inventory : - if j[0]==i[0] : - player_inventory.append(j) - for j in monsterinventory : - if j[0]==i[0] : - monster_inventory.append(j) - return player_inventory,monster_inventory,i[3],int(i[4]) - break + if i[3] =='agent' : + player_inventory = [] + monster_inventory =[] + print("login berhasil") + for j in inventory : + if j[0]==i[0] : + player_inventory.append(j) + for j in monsterinventory : + if j[0]==i[0] : + monster_inventory.append(j) + return player_inventory,monster_inventory,i[3],int(i[4]) + break + elif i[3] =='admin' : + return 1,1,i[3],1 else : print("password salah") return 0,0,0,0 @@ -82,57 +85,6 @@ def register(user,inventory,monsterinventory,monster) : return player_inventory,monster_inventory,'agent',0 -def buang(data,inventory) : - print("mau buang item apa ?") - inp = input("(1(str)/2(res)/3(heal))? ------->") - if inp == '1' : - for i in data : - if i[1]=='strenghpotion' : - if int(i[2]) >0 : - i[2]=str(int(i[2])-1) - print("strenght potion dibuang satu") - break - else : - print("anda tidak memiliki str potion") - break - else : - print("anda tidak memiliki strenght potion") - elif inp == '2' : - for i in data : - if i[1]=='respotion' : - if int(i[2])>0 : - i[2]=str(int(i[2])-1) - print("resistance potion dibuang satu") - break - else : - print("anda tidak memiliki res potion") - break - else : - print("anda tidak memiliki resistance potion") - elif inp == '3' : - for i in data : - if i[1]=='healingpotion' : - if int(i[2]) > 0 : - i[2]=str(int(i[2])-1) - print("heal potion dibuang satu") - break - else : - print("anda tidak memiliki heal potion") - break - else : - print("anda tidak memiliki heal potion") - x=0 - idx=[] - for i in inventory : - print(f"{i[0]} DAN {data[0][0]}") - if i[0]==data[0][0] : - idx.append(x) - x+=1 - for i in range(len(idx)-1,-1,-1) : - inventory.pop(idx[i]) - for i in data : - inventory.append(i) - def write(path,data) : # Writing data to the CSV file @@ -149,5 +101,4 @@ def save(inventory,monster,user) : if (os.path.exists(path)) : write(path+"/inventory.csv",inventory) write(path+"user.csv",user) - write(path+"/monster.csv",monster) - \ No newline at end of file + write(path+"/monster.csv",monster) \ No newline at end of file diff --git a/src/main.py b/src/main.py index c59465b..64520b8 100644 --- a/src/main.py +++ b/src/main.py @@ -3,9 +3,10 @@ from arena import* from RandomNumberGenerator import * from inventory import * -from shop_currency import * +from shopCurrency import * from help import * from laboratory import * +import time data=load() if data != [] : @@ -38,14 +39,16 @@ command = input("--->") if command == 'battle' : random_number = RNG(1,5) + time.sleep(2/10) + random_level = RNG(1,5) opening(monster,random_number) chosen=choose(yourmonsterinventory) - coin = battle(monster,yourmonsterinventory,userinventory,chosen,random_number) + coin = battle(monster,monsterinventory,yourmonsterinventory,userinventory,chosen,random_number,random_level,'battle') coins+=coin user[id][4]=str(coins) print(userinventory) elif command == 'arena' : - coin = arena(monster,yourmonsterinventory,userinventory) + coin = arena(monster,monsterinventory,yourmonsterinventory,userinventory) coins+=coin user[id][4]=str(coins) elif command == 'inventory' : @@ -65,7 +68,6 @@ if t==1 : loginstatus=False break - elif command == 'Shop' : coins=shopOpen(role,itemshop,coins,userinventory,monster,monstershop,yourmonsterinventory,monsterinventory) user[id][4]=str(coins) @@ -83,4 +85,25 @@ print(yourmonsterinventory) print(itemshop) print(monstershop) - \ No newline at end of file + elif role=='admin' : + while True : + command = input("--->") + if command=='help': + help(loginstatus,role) + elif command=='shop': + shopmanagement(itemshop,monstershop,monster) + elif command == 'logout' : + t=0 + while True : + confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + if confirm == "Y" : + print("Logout berhasil") + t=1 + break + elif confirm =='N' : + t=1 + break + else : print("mangsud?") + if t==1 : + loginstatus=False + break \ No newline at end of file diff --git a/src/monsterball.py b/src/monsterball.py new file mode 100644 index 0000000..781cd92 --- /dev/null +++ b/src/monsterball.py @@ -0,0 +1,54 @@ +from RandomNumberGenerator import * + +def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventory,yourmonsterdata): + jumlahball = int(userinventory[3][2]) + chance = RNG(1,100) + print(chance) + success = 0 + if jumlahball >= 1 : + for i in yourmonsterdata : + if i[1]==monsterdata[monsterid][1] : + print("Anda sudah memiliki monster tersebut!") + success= 2 + return success + else : + print('WHOOSSHHH anda melempar monster ball') + jumlahball -=1 + userinventory[3][2]=str(jumlahball) + if monsterlevel==1 : + if chance>=1 and chance<=75 : + print('ANDA DAPAT!!') + success = 1 + else : + print('yaah ga dapet') + elif monsterlevel==2 : + if chance>=1 and chance<=50 : + print('ANDA DAPAT!!') + success = 1 + else : + print('yaah ga dapet') + elif monsterlevel==3 : + if chance>=1 and chance<=25 : + print('ANDA DAPAT!!') + success = 1 + else : + print('yaah ga dapet') + elif monsterlevel==4 : + if chance>=1 and chance<=10 : + print('ANDA DAPAT!!') + success = 1 + else : + print('yaah ga dapet') + elif monsterlevel==5 : + if chance>=1 and chance<=5 : + print('ANDA DAPAT!!') + success = 1 + else : + print('yaah ga dapet') + else : + print('Anda tidak memiliki monster ball') + success = 2 + if success==1 : + yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) + monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) + return success \ No newline at end of file diff --git a/src/potion.py b/src/potion.py index 745eff5..15e0e25 100644 --- a/src/potion.py +++ b/src/potion.py @@ -1,18 +1,16 @@ -from readwritecsv import * - def jumlahpot(userinventory) : for i in userinventory : - if i[1]=='strenghpotion' : + if i[1]=='Strength Potion' : jumlahstr = i[2] break else : jumlahstr = 0 for i in userinventory : - if i[1]=='respotion' : + if i[1]=='Resilience Potion' : jumlahres = i[2] break else : jumlahres = 0 for i in userinventory : - if i[1]=='healingpotion' : + if i[1]=='Healing Potion' : jumlahheal = i[2] break else : jumlahheal = 0 @@ -21,19 +19,19 @@ def jumlahpot(userinventory) : def lokasipot(userinventory) : x=0 for i in userinventory : - if i[1]=='strenghpotion' : + if i[1]=='Strength Potion' : break x+=1 else : x=999 y=0 for i in userinventory : - if i[1]=='respotion' : + if i[1]=='Resilience Potion' : break y+=1 else : y=999 z=0 for i in userinventory : - if i[1]=='healingpotion' : + if i[1]=='Healing Potion' : break z+=1 else : x=999 diff --git a/src/readwritecsv.py b/src/readwritecsv.py index f02f407..0396193 100644 --- a/src/readwritecsv.py +++ b/src/readwritecsv.py @@ -4,7 +4,7 @@ def read_csv(path) : data =[] with open(path) as file : for char in file.read(): - if char == ',': + if char == ';': row.append(field) field='' elif char=="\n" : diff --git a/src/shopCurrency.py b/src/shopCurrency.py index d0da61c..320518b 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -1,9 +1,3 @@ -'''from csvParser import csvRead, csvWriteAll -pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" -potionShop = csvRead(pathItemShop)''' -potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"] - - def shopInterface(): print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") @@ -13,77 +7,44 @@ def shopInterface(): print(" =================== ███████████████████████") return -def sortPotion(potionShop): - if potionShop[1][0] == "Resilience Potion": - potionShop[1][0],potionShop[2][0] = potionShop[2][0],potionShop[1][0] - if potionShop[3][0] == "Resilience Potion": - potionShop[3][0],potionShop[2][0] = potionShop[2][0],potionShop[3][0] - if potionShop[1][0] == "Strength Potion": - potionShop[1][0],potionShop[3][0] = potionShop[3][0],potionShop[1][0] - return potionShop - -def listTocsv(list): - new_csv = [] - csvCell = "" - for i in range(len(list)): - for j in range(len(list[1])): - csvCell += f"{list[i][j]}" - if j != len(list[1])-1: - csvCell += f";" - if i != len(list)-1 and j == len(list[1])-1: - csvCell += "\n" - new_csv.append(csvCell) - csvCell = "" - return new_csv - -def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): - yourcoin = coin +def shopOpen(role,potionshop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): + yourcoin=coin if role == "agent": - print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") + print("Selamat datang di Shop!") print() shopInterface() - print() - while True: + keluar = False + while keluar != True: pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + lihat_pilih = input(">>> Mau lihat apa? (monster/item): ") lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion": + while lihat_pilih != "monster" and lihat_pilih != "item" and lihatSelesai != True: lihat_pilih = input(">>> Pilih antara monster/potion: ") if lihat_pilih == "monster": - idMonsterShop = [] - for i in range(1,len(monstershop)): - idMonsterShop.append(monstershop[i][0]) - idMonsterData = [] - for i in range(1,len(monsterdata)): - idMonsterData.append(monsterdata[i][0]) print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") - for i in range(1,len(monstershop)): # Menampilkan setiap monster yang tersedia di Shop - idMonsterLihat=int(monstershop[i][0]) - print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - elif lihat_pilih == "potion": + for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop + x=int(monstershop[i][0]) + print(f"{x} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + lihatSelesai == True + elif lihat_pilih == "item": print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop - if potionShop[i][0] == "Healing Potion": - idPotion = 1 - elif potionShop[i][0] == "Resilience Potion": - idPotion = 2 - elif potionShop[i][0] == "Strength Potion": - idPotion = 3 - print(f"{i} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") + for i in range(1,len(potionshop)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionshop[i][0]}\t| {potionshop[i][1]}\t| {potionshop[i][2]}") lihatSelesai == True elif pilihMenu == "beli": print(f"Jumlah O.W.C.A Coin-mu sekarang {yourcoin}.") print() - beliType = input(">>> Mau beli apa? (monster/potion): ") - while beliType != "monster" and beliType != "potion": + beliType = input(">>> Mau beli apa? (monster/item): ") + beliSelesai = False + while beliType != "monster" and beliType != "item" and beliSelesai != True: beliType = input(">>> Pilih antara monster/potion: ") if beliType == "monster": - while True: - transactionStatus = 0 + while True : + r=0 idMonsterBeli = int(input(">>> Masukkan id monster: ")) for i in yourmonsterdata : - if monsterdata[idMonsterBeli][1] == i[1] : + if monsterdata[idMonsterBeli][1]==i[1] : print("Monster sudah dimiliki") break else : @@ -91,219 +52,217 @@ def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmons if i[0]==str(idMonsterBeli) : if yourcoin >= int(i[2]) : print("monster berhasil ditambahkan") - yourcoin -= int(i[2]) + yourcoin-= int(i[2]) yourmonsterdata.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) monsterinventory.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) - monsterShopLocation = 0 + x=0 for i in monstershop : if i[0]==str(idMonsterBeli) : - monstershop[monsterShopLocation][1] = str(int(monstershop[monsterShopLocation][1])-1) + monstershop[x][1]=str(int(monstershop[x][1])-1) break - monsterShopLocation += 1 - transactionStatus = 1 + x+=1 + r=1 break else : - print("Maaf O.W.C.A. Coin-mu kurang.") + print("maaf coin mu kurang") break - if transactionStatus == 1 : - break + if r==1 : break + print() - elif beliType == "potion": + beliSelesai == True + elif beliType == "item": idPotion = int(input(">>> Masukkan id potion: ")) while True : jumlahPotionBeli = int(input(">>> Masukkan jumlah: ")) - if int(potionShop[idPotion][1]) >0 : - if jumlahPotionBeli>int(potionShop[idPotion][1]): + if int(potionshop[idPotion][1]) >0 : + if jumlahPotionBeli>int(potionshop[idPotion][1]): print("Stock tidak cukup") else : - if yourcoin >= (jumlahPotionBeli * int(potionShop[idPotion][2])): - print(f"Berhasil membeli item: {jumlahPotionBeli} {potionShop[idPotion][0]}. Item sudah masuk ke inventory-mu!") + if yourcoin >= (jumlahPotionBeli * int(potionshop[idPotion][2])): + print(f"Berhasil membeli item: {jumlahPotionBeli} {potionshop[idPotion][0]}. Item sudah masuk ke inventory-mu!") print() - userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) + index=0 + for i in userinventory : + if i[1]==potionshop[idPotion][0]: + break + else : + index+=1 + userinventory[index][2]=str(int(userinventory[index][2])+jumlahPotionBeli) print(userinventory) - yourcoin-=(jumlahPotionBeli * int(potionShop[idPotion][2])) - potionShop[idPotion][1]=str(int(potionShop[idPotion][1])-jumlahPotionBeli) + yourcoin-=(jumlahPotionBeli * int(potionshop[idPotion][2])) + potionshop[idPotion][1]=str(int(potionshop[idPotion][1])-jumlahPotionBeli) break else : - print("Maaf O.W.C.A Coin-mu kurang.") + print("maaf coin mu kurang") else : - print("Stock Potion habis!") + print("Stock habis!") break - break + + beliSelesai == True else: # pilihMenu == "keluar" - print(f"Sampai bertemu lagi, User!") + keluar == True + print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") break - - elif role == "admin": - print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") - print() - shopInterface() + return yourcoin +def shopmanagement(potionshop,monstershop,monsterdata) : + print("Selamat datang kembali, Admin!") print() - while True: + keluar = False + while keluar != True: pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - while lihat_pilih != "monster" and lihat_pilih != "potion": - lihat_pilih = input(">>> Pilih antara monster/potion: ") + lihat_pilih = input(">>> Mau lihat apa? (monster/item): ") + lihatSelesai = False + while lihat_pilih != "monster" and lihat_pilih != "item" and lihatSelesai != True: + lihat_pilih = input(">>> Pilih antara monster/item: ") if lihat_pilih == "monster": - idMonsterShop = [] - for i in range(1,len(monstershop)): - idMonsterShop.append(monstershop[i][0]) - idMonsterData = [] - for i in range(1,len(monsterdata)): - idMonsterData.append(monsterdata[i][0]) print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop - idMonsterLihat=int(monstershop[i][0]) - print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - elif lihat_pilih == "potion": + x=int(monstershop[i][0]) + print(f"{x} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + lihatSelesai == True + elif lihat_pilih == "item": print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop - if potionShop[i][0] == "Healing Potion": - idPotion = 1 - elif potionShop[i][0] == "Resilience Potion": - idPotion = 2 - elif potionShop[i][0] == "Strength Potion": - idPotion = 3 - print(f"{idPotion} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") - + for i in range(1,len(potionshop)): # Menampilkan setiap potion yang tersedia di Shop + print(f"{i} | {potionshop[i][0]}\t| {potionshop[i][1]}\t| {potionshop[i][2]}") + lihatSelesai == True elif pilihMenu == "tambah": - tambah_pilih = input("Mau tambah apa? (monster/potion): ") - while tambah_pilih != "monster" and tambah_pilih != "potion": - tambah_pilih = (input(">>> Pilih antara monster/potion: ")) + tambah_pilih = input("Mau tambah apa? (monster/item): ") + tambahSelesai = False + while tambah_pilih != "monster" and tambah_pilih != "item" and tambahSelesai != True: + tambah_pilih = (input(">>> Pilih antara monster/item: ")) if tambah_pilih == "monster": - print("ID | Type\t\t\t| ATK Power\t| DEF Power\t| HP\t|") - for i in range(1,len(monsterdata)): # Menampilkan setiap monster yang tersedia di Shop - if monsterdata[i][0] in idMonsterShop: - continue - else: - idMonsterLihat=int(monsterdata[i][0]) - print(f"{i} | {monsterdata[idMonsterLihat][1]}\t\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t|") - print() - idMonsterTambah = input(">>> Masukkan id monster: ") - while idMonsterTambah in idMonsterShop or idMonsterTambah not in idMonsterData: - if idMonsterTambah not in idMonsterData: - print("ID tidak valid! Pilih ID yang terdapat pada tabel!") - idMonsterTambah = (input(">>> Masukkan id monster: ")) - elif idMonsterTambah in idMonsterShop: - print("Monster sudah ada di Shop!") - idMonsterTambah = (input(">>> Masukkan id monster: ")) - stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) - hargaMonsterTambah = int(input(">>> Masukkan harga: ")) - addMonsterShop = [idMonsterTambah,str(stokMonsterTambah),str(hargaMonsterTambah)] - monstershop.append(addMonsterShop) - print(f"{monsterdata[int(idMonsterTambah)][1]} telah berhasil ditambahkan ke dalam Shop!") - elif tambah_pilih == "potion": + countabsencemonster = 0 + absencemonsterid=[] + for i in monsterdata : + for j in monstershop : + if i[0]==j[0] : + break + else : + if i[0] != 'id' : + countabsencemonster+=1 + absencemonsterid.append(i[0]) + if countabsencemonster==0 : + print("semua monster sudah ada dishop") + else : + print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t") + for i in absencemonsterid : + x=int(i) + print(f"{x} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t") + print() + idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi + stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) + hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + monstershop.append([str(idMonsterTambah),str(stokMonsterTambah),str(hargaMonsterTambah)]) + print(f"{monsterdata[idMonsterTambah][1]} telah berhasil ditambahkan ke dalam Shop!") + elif tambah_pilih == "item": potionFound = False countFalse = 0 + notinshoplist=[] print("ID | Type") - for i in range(1,4): - for j in range(1,len(potionShop)): - if potionID[i] in potionShop[j][0]: + for i in ['Healing Potion','Strength Potion','Resilience Potion','Monster Ball']: + for j in potionshop: + if i == j[0]: potionFound = True break - else: - potionFound = False - continue - if potionFound == False: - print(f"{i} | {potionID[i]}") + else: + potionFound = False countFalse += 1 + notinshoplist.append(i) + if potionFound == False: + print(f"{countFalse} | {i}") if countFalse == 0: print("Semua Potion sudah tersedia pada Shop!") print() else: - idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) - while (idPotionTambah < 1 or idPotionTambah > 3): - print("id tidak valid!") - idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) + idPotionTambah = int(input(">>> Masukkan id potion : ")) stokPotionTambah = int(input("Masukkan stok awal: ")) hargaPotionTambah = int(input("Masukkan harga: ")) - newPotion = [potionID[idPotionTambah],str(stokPotionTambah),str(hargaPotionTambah)] - potionShop.append(newPotion) - sortPotion(potionShop) - print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") + potionshop.append([notinshoplist[idPotionTambah-1],str(stokPotionTambah),str(hargaPotionTambah)]) + print(f"{notinshoplist[idPotionTambah-1]} telah berhasil ditambahkan ke dalam Shop!") print() - + elif pilihMenu=='keluar' : + keluar=True elif pilihMenu == "ubah": ubah_pilih = input("Mau ubah apa? (monster/potion): ") - while ubah_pilih != "monster" and ubah_pilih != "potion": - ubah_pilih = (input(">>> Pilih antara monster/potion: ")) + ubahSelesai = False + while ubah_pilih != "monster" and ubah_pilih != "item" and ubahSelesai != True: + ubah_pilih = (input(">>> Pilih antara monster/item: ")) if ubah_pilih == "monster": idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi - stokMonsterBaru = int(input(">>> Masukkan stok baru: ")) - hargaMonsterBaru = int(input(">>> Masukkan harga baru: ")) + stokMonsterBaru = (input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) + index=0 + for i in monstershop : + if i[0]==(idMonsterUbah) : + break + index+=1 + print(index) pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " if (stokMonsterBaru != ""): pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + monstershop[index][1]=stokMonsterBaru if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): pesanUbah += " dan " if (hargaMonsterBaru != ""): pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + monstershop[index][2]=hargaMonsterBaru pesanUbah += "!" - print(monstershop) - monstershop[int(idMonsterUbah)] = [monsterdata[int(idMonsterUbah)][0],str(stokMonsterBaru),str(hargaMonsterBaru)] - print(monstershop) print(pesanUbah) - elif ubah_pilih == "potion": - idPotionUbah = int((input(">>> Masukkan id potion: "))) - while idPotionUbah < 1 or idPotionUbah > 3: - print("ID tidak valid!") - idPotionUbah = int((input(">>> Masukkan id potion: "))) - stokPotionBaru = int((input(">>> Masukkan stok baru: "))) - hargaPotionBaru = int((input(">>> Masukkan harga baru: "))) - pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " + elif ubah_pilih == "item": + idPotionUbah = (input(">>> Masukkan id item: ")) + stokPotionBaru = (input(">>> Masukkan stok baru: ")) + hargaPotionBaru = (input(">>> Masukkan harga baru: ")) + pesanUbah = f"{potionshop[int(idPotionUbah)][0]} telah berhasil diubah " if (stokPotionBaru != ""): pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" + potionshop[int(idPotionUbah)][1]=stokPotionBaru if (stokPotionBaru != "") and (hargaPotionBaru != ""): pesanUbah += " dan " if (hargaPotionBaru != ""): pesanUbah += f"dengan harga baru {hargaPotionBaru}" + potionshop[int(idPotionUbah)][2]=hargaPotionBaru pesanUbah += "!" - potionShop[idPotionUbah] = [potionID[idPotionUbah],stokPotionBaru,hargaPotionBaru] print(pesanUbah) print() - + elif pilihMenu == "hapus": - hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") - while hapusPilih != "monster" and hapusPilih != "potion": + hapusPilih = input(">>> Mau hapus apa? (monster/item): ") + hapusSelesai = False + while hapusPilih != "monster" and hapusPilih != "item" and hapusSelesai != True: hapusPilih = (input(">>> Pilih antara monster/potion: ")) if hapusPilih == "monster": - idMonsterHapus = int(input(">>> Masukkan id monster: ")) - while idMonsterHapus not in idMonsterShop: - print("Monster dengan ID tersebut tidak ada pada Shop!") - idMonsterHapus = int(input(">>> Masukkan id monster: ")) - yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[idMonsterHapus][1]} dari Shop (y/n)? ") + idMonsterHapus = input(">>> Masukkan id monster: ") + index=0 + for i in monstershop : + if i[0]==(idMonsterHapus) : + break + index+=1 + yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[int(idMonsterHapus)][1]}dari Shop (y/n)?" ) if yakinHapus == "y": - newMonsterList = [] - for i in range(len(monstershop)): - if i == idMonsterHapus: - continue - else: - newMonsterList.append(monstershop[i]) - monstershop = newMonsterList - print(f"{monsterdata[idMonsterHapus][1]} telah berhasil dihapus dari Shop!") + monstershop.pop(index) + print(f"{monsterdata[int(idMonsterHapus)][1]} telah berhasil dihapus dari Shop!") + print() else: print("Penghapusan dibatalkan!") print() continue - elif hapusPilih == "potion": - idPotionHapus = int(input(">>> Masukkan id potion: ")) - yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[idPotionHapus]} dari Shop (y/n)? ") + if hapusPilih == "item": + idPotionHapus = input(">>> Masukkan id item: ") + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionshop[int(idPotionHapus)][0]} dari Shop (y/n)? ") if yakinHapus == "y": - newPotionList = [] - for i in range(len(potionShop)): - if i == idPotionHapus: - continue - else: - newPotionList.append(potionShop[i]) - potionShop = newPotionList - print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") + potionshop.pop(int(idPotionHapus)) + print(f"{potionshop[int(idPotionHapus)][0]} telah berhasil dihapus dari Shop!") print() else: print("Penghapusan dibatalkan!") print() continue - else: # pilihMenu == "keluar" + keluar == True print("Sampai bertemu lagi Admin!") - break \ No newline at end of file + break + + +# shopOpen("agent") +# shopOpen("admin") \ No newline at end of file diff --git a/src/shop_currency.py b/src/shop_currency.py deleted file mode 100644 index 5bffb86..0000000 --- a/src/shop_currency.py +++ /dev/null @@ -1,236 +0,0 @@ -'''from csvParser import splitSemicolon, csvRead, csvWrite, csvOverwrite, csvDelete''' -'''pathItemShop = "C:\if1210-2024-tubes-k08-b\data\item_shop.csv" -potionList = csvRead(pathItemShop) -potionID = ["Type", "Strength Potion", "Resilience Potion", "Healing Potion"]''' - -def shopOpen(role,potionshop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): - yourcoin=coin - if role == "agent": - print("Selamat datang di Shop!") - print() - keluar = False - while keluar != True: - pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": - print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") - for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop - x=int(monstershop[i][0]) - print(f"{i} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - lihatSelesai == True - elif lihat_pilih == "potion": - print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionshop)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionshop[i][0]}\t| {potionshop[i][1]}\t| {potionshop[i][2]}") - lihatSelesai == True - elif pilihMenu == "beli": - print(f"Jumlah O.W.C.A Coin-mu sekarang {yourcoin}.") - print() - beliType = input(">>> Mau beli apa? (monster/potion): ") - beliSelesai = False - while beliType != "monster" and beliType != "potion" and beliSelesai != True: - beliType = input(">>> Pilih antara monster/potion: ") - if beliType == "monster": - while True : - r=0 - idMonsterBeli = int(input(">>> Masukkan id monster: ")) - for i in yourmonsterdata : - if monsterdata[idMonsterBeli][1]==i[1] : - print("Monster sudah dimiliki") - break - else : - for i in monstershop : - if i[0]==str(idMonsterBeli) : - if yourcoin >= int(i[2]) : - print("monster berhasil ditambahkan") - yourcoin-= int(i[2]) - yourmonsterdata.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) - monsterinventory.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) - x=0 - for i in monstershop : - if i[0]==str(idMonsterBeli) : - monstershop[x][1]=str(int(monstershop[x][1])-1) - break - x+=1 - r=1 - break - else : - print("maaf coin mu kurang") - break - if r==1 : break - # if OWCA >= harga monster: - print() - beliSelesai == True - elif beliType == "potion": - idPotion = int(input(">>> Masukkan id potion: ")) - while True : - jumlahPotionBeli = int(input(">>> Masukkan jumlah: ")) - if int(potionshop[idPotion][1]) >0 : - if jumlahPotionBeli>int(potionshop[idPotion][1]): - print("Stock tidak cukup") - else : - if yourcoin >= (jumlahPotionBeli * int(potionshop[idPotion][2])): - print(f"Berhasil membeli item: {jumlahPotionBeli} {potionshop[idPotion][0]}. Item sudah masuk ke inventory-mu!") - print() - userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) - print(userinventory) - yourcoin-=(jumlahPotionBeli * int(potionshop[idPotion][2])) - potionshop[idPotion][1]=str(int(potionshop[idPotion][1])-jumlahPotionBeli) - break - else : - print("maaf coin mu kurang") - else : - print("Stock habis!") - break - - beliSelesai == True - else: # pilihMenu == "keluar" - keluar == True - print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") - break - return yourcoin - '''elif role == "admin": - print("Selamat datang kembali, Admin!") - print() - keluar = False - while keluar != True: - pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": - print("monster") - lihatSelesai == True - # monster_list() - elif lihat_pilih == "potion": - print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionList)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionList[i][0]}\t| {potionList[i][1]}\t| {potionList[i][2]}") - lihatSelesai == True - elif pilihMenu == "tambah": - tambah_pilih = input("Mau tambah apa? (monster/potion): ") - tambahSelesai = False - while tambah_pilih != "monster" and tambah_pilih != "potion" and tambahSelesai != True: - tambah_pilih = (input(">>> Pilih antara monster/potion: ")) - if tambah_pilih == "monster": - print("monster") # Nanti di sini list semua monster dari database yang belom ada di Shop - print() - idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi - stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) - hargaMonsterTambah = int(input(">>> Masukkan harga: ")) - # monster_list.append() - print("[nama monster] telah berhasil ditambahkan ke dalam Shop!") - elif tambah_pilih == "potion": - potionFound = False - countFalse = 0 - print("ID | Type") - for i in range(1,4): - for j in range(1,len(potionList)): - if potionID[i] in potionList[j][0]: - potionFound = True - break - else: - potionFound = False - continue - if potionFound == False: - print(f"{i} | {potionID[i]}") - countFalse += 1 - if countFalse == 0: - print("Semua Potion sudah tersedia pada Shop!") - print() - else: - idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) - while (idPotionTambah < 1 or idPotionTambah > 3): - print("id tidak valid!") - idPotionTambah = int(input(">>> Masukkan id potion (1-3): ")) - stokPotionTambah = int(input("Masukkan stok awal: ")) - hargaPotionTambah = int(input("Masukkan harga: ")) - csvWrite(pathItemShop, f"{potionID[idPotionTambah]};{stokPotionTambah};{hargaPotionTambah}") - print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") - print() - elif pilihMenu == "ubah": - ubah_pilih = input("Mau ubah apa? (monster/potion): ") - ubahSelesai = False - while ubah_pilih != "monster" and ubah_pilih != "potion" and ubahSelesai != True: - ubah_pilih = (input(">>> Pilih antara monster/potion: ")) - if ubah_pilih == "monster": - idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi - stokMonsterBaru = (input(">>> Masukkan stok baru: ")) - hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) - pesanUbah = f"[nama monster] telah berhasil diubah " - # komponenubah = f"{monsterList[int(idMonsterUbah)]};" - if (stokMonsterBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" - # komponenUbah += f"{stokMonsterBaru};" - # else: - # komponenUbah += f"{monsterList[int(idMonsterUbah)][1];}" - if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): - pesanUbah += " dan " - if (hargaMonsterBaru != ""): - pesanUbah += f"dengan harga baru {hargaMonsterBaru}" - # komponenUbah += f"{hargaMonsterBaru}" - # else: - # komponenUbah += f"{monsterList[int(idMonsterUbah)][2]}" - pesanUbah += "!" - csvOverwrite(pathItemShop, int(idMonsterUbah)) # , komponenUbah (Nanti) - print(pesanUbah) - elif ubah_pilih == "potion": - idPotionUbah = (input(">>> Masukkan id potion: ")) - stokPotionBaru = (input(">>> Masukkan stok baru: ")) - hargaPotionBaru = (input(">>> Masukkan harga baru: ")) - pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " - komponenUbah = f"{potionID[int(idPotionUbah)]};" - if (stokPotionBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" - komponenUbah += f"{stokPotionBaru};" - else: - komponenUbah += f"{potionList[int(idPotionUbah)][1]};" - if (stokPotionBaru != "") and (hargaPotionBaru != ""): - pesanUbah += " dan " - if (hargaPotionBaru != ""): - pesanUbah += f"dengan harga baru {hargaPotionBaru}" - komponenUbah += f"{hargaPotionBaru}" - else: - komponenUbah += f"{potionList[int(idPotionUbah)][2]}" - pesanUbah += "!" - csvDelete(pathItemShop, int(idPotionUbah), komponenUbah) - print(pesanUbah) - print() - elif pilihMenu == "hapus": - hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") - hapusSelesai = False - while hapusPilih != "monster" and hapusPilih != "potion" and hapusSelesai != True: - hapusPilih = (input(">>> Pilih antara monster/potion: ")) - if hapusPilih == "monster": - idMonsterHapus = input(">>> Masukkan id monster: ") - # yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterList[int(idPokemonHapus)]} dari Shop (y/n)? ) - # if yakinHapus == "y": - # csvDelete(pathItemShop, int(idMonsterHapus)) - # print(f"{monsterList[int(idPokemonHapus)]} telah berhasil dihapus dari Shop!") - # else: - # continue - elif hapusPilih == "potion": - idPotionHapus = input(">>> Masukkan id potion: ") - yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[int(idPotionHapus)]} dari Shop (y/n)? ") - if yakinHapus == "y": - csvDelete(pathItemShop, int(idPotionHapus)) - print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") - print() - else: - print("Penghapusan dibatalkan!") - print() - continue - else: # pilihMenu == "keluar" - keluar == True - print("Sampai bertemu lagi Admin!") - break''' - return - -# shopOpen("agent") -# shopOpen("admin") \ No newline at end of file From 89df1237f01ba73624a0bc19a1b585f1120b3e58 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Fri, 17 May 2024 13:59:56 +0700 Subject: [PATCH 025/115] fix: update coin --- src/jackpot.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index 4eb2d64..1e2c401 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -13,7 +13,8 @@ def cekrng(RNG) : item = 4 return item -def gacha() : +def gacha(yourcoin) : + yourcoin = int(yourcoin) icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM' ] value = [50,100,150,200,250,400] RNG1 = RNG(1,100) @@ -26,23 +27,34 @@ def gacha() : item3 = cekrng(RNG3) totalcoin = value[item1]+value[item2]+value[item3] print(f"{icon[item1]} | {icon[item2]} | {icon[item3]}") - if item1==item2 and item2==item3 : - print('s') - else : - print(f"ANDA TIDAK DAPAT GORLOCK, TAPI ANDA DAPAT {totalcoin} COINS !!!") + prize = False + if prize == False : + if item1==item2 and item2==item3 : + print('SELAMATT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') + prize == True + else : + print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COINS !!!") + yourcoin += totalcoin + elif prize == True : + if item1==item2 and item2==item3 : + print('SELAMATT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 1000 Coin') + yourcoin += 1000 + else : + print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COINS !!!") + yourcoin += totalcoin def jackpot(yourcoin) : coin=yourcoin - print("SELAMAT DATANG DIJACKPOT 888!!!") - print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") + print("SELAMAT DATANG DI JACKPOT 888!!!") print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 400 COIN") + print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") while True : inp = input("(Y/N)----->") if inp == 'Y' : confirm = input("APAKAH ANDA YAKIN? (Y/N) :") if confirm == 'Y' : - if coin>=400 : - gacha() + if coin >= 400 : + gacha(yourcoin) coin-=400 else : print("COIN TIDAK CUKUP") From 44b78a4ea1fc785b7b42060fc67481932529b2e5 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Fri, 17 May 2024 14:12:59 +0700 Subject: [PATCH 026/115] fix: allow lowercase input --- src/jackpot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index 1e2c401..e3db64c 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -50,12 +50,13 @@ def jackpot(yourcoin) : print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") while True : inp = input("(Y/N)----->") - if inp == 'Y' : + if inp.lower() == 'y' : confirm = input("APAKAH ANDA YAKIN? (Y/N) :") - if confirm == 'Y' : + if confirm.lower() == 'y' : if coin >= 400 : gacha(yourcoin) coin-=400 + print("APAKAH ANDA INGIN MELANJUTKAN??",end=" ") else : print("COIN TIDAK CUKUP") else : From 834353284d911ec2d48a1d97d5005963fabd90f2 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Fri, 17 May 2024 14:14:37 +0700 Subject: [PATCH 027/115] fix: allow lowercased input --- src/main.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/main.py b/src/main.py index 64520b8..008ed1c 100644 --- a/src/main.py +++ b/src/main.py @@ -6,6 +6,7 @@ from shopCurrency import * from help import * from laboratory import * +from jackpot import * import time data=load() @@ -19,25 +20,25 @@ loginstatus = False while True : command = input("--->") - if command =="login" : + if command.lower() == "login" : while True : userinventory,yourmonsterinventory,role,coins = login(user,inventory,monsterinventory) if userinventory != 0 and role != 0 and coins !=0 and yourmonsterinventory !=0 : loginstatus = True break - elif command =='register' : + elif command.lower() == 'register' : userinventory,yourmonsterinventory,role,coins = register(user,inventory,monsterinventory,monster) loginstatus = True - elif command =="help" : + elif command.lower() == "help" : help(loginstatus,"belumlogin") else : print(f"command '{command}' tidak ada.") if loginstatus==True : - if role=='agent': + if role.lower() == 'agent': while True : id = int(userinventory[0][0]) command = input("--->") - if command == 'battle' : + if command.lower() == 'battle' : random_number = RNG(1,5) time.sleep(2/10) random_level = RNG(1,5) @@ -47,35 +48,37 @@ coins+=coin user[id][4]=str(coins) print(userinventory) - elif command == 'arena' : + elif command.lower() == 'arena' : coin = arena(monster,monsterinventory,yourmonsterinventory,userinventory) coins+=coin user[id][4]=str(coins) - elif command == 'inventory' : + elif command.lower() == 'inventory' : inventoryy(userinventory,yourmonsterinventory,monster,role,coins) - elif command == 'logout' : + elif command.lower() == 'logout' : t=0 while True : confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") - if confirm == "Y" : + if confirm.lower() == "y" : print("Logout berhasil") t=1 break - elif confirm =='N' : + elif confirm.lower() =='n' : t=1 break else : print("mangsud?") if t==1 : loginstatus=False break - elif command == 'Shop' : + elif command.lower() == 'shop' : coins=shopOpen(role,itemshop,coins,userinventory,monster,monstershop,yourmonsterinventory,monsterinventory) user[id][4]=str(coins) - elif command == 'help' : + elif command.lower() == 'help' : help(loginstatus,role) - elif command == 'laboratory' : + elif command.lower() == 'laboratory' : coins = laboratory(yourmonsterinventory,coins,role) user[id][4]=str(coins) + elif command.lower() == 'jackpot' : + jackpot(coins) else : print(f"command '{command}' tidak ada.") print(userinventory) @@ -88,19 +91,19 @@ elif role=='admin' : while True : command = input("--->") - if command=='help': + if command.lower() =='help': help(loginstatus,role) - elif command=='shop': + elif command.lower() =='shop': shopmanagement(itemshop,monstershop,monster) - elif command == 'logout' : + elif command.lower() == 'logout' : t=0 while True : confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") - if confirm == "Y" : + if confirm.lower() == "y" : print("Logout berhasil") t=1 break - elif confirm =='N' : + elif confirm.lower() =='n' : t=1 break else : print("mangsud?") From 489cb785b0b04e6f2886332f1071bde544319034 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Fri, 17 May 2024 15:52:10 +0700 Subject: [PATCH 028/115] feat: Jackpot feature --- src/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index 008ed1c..7480734 100644 --- a/src/main.py +++ b/src/main.py @@ -78,7 +78,7 @@ coins = laboratory(yourmonsterinventory,coins,role) user[id][4]=str(coins) elif command.lower() == 'jackpot' : - jackpot(coins) + jackpot(id, coins, monsterinventory) else : print(f"command '{command}' tidak ada.") print(userinventory) @@ -103,7 +103,7 @@ print("Logout berhasil") t=1 break - elif confirm.lower() =='n' : + elif confirm.lower() =='n ' : t=1 break else : print("mangsud?") From 032febc6a468509bdb86625459cb1912a5a5b344 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Fri, 17 May 2024 15:53:52 +0700 Subject: [PATCH 029/115] fix: break & update jackpot prize --- src/jackpot.py | 118 +++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index e3db64c..6eb8931 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -1,63 +1,73 @@ -from RandomNumberGenerator import * import time -def cekrng(RNG) : - if RNG>=1 and RNG<=40 : - item = 0 - elif RNG>=41 and RNG<=65 : - item = 1 - elif RNG>=66 and RNG<=80 : - item = 2 - elif RNG>=81 and RNG<=95 : - item = 3 - elif RNG>=96 and RNG<=100 : - item = 4 - return item - -def gacha(yourcoin) : - yourcoin = int(yourcoin) - icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM' ] - value = [50,100,150,200,250,400] - RNG1 = RNG(1,100) - time.sleep(2/10) - RNG2 = RNG(1,100) - time.sleep(1/10) - RNG3 = RNG(1,100) +from RandomNumberGenerator import RNG + +def cekrng(RNG): + if 1 <= RNG <= 40: + return 0 + elif 41 <= RNG <= 65: + return 1 + elif 66 <= RNG <= 80: + return 2 + elif 81 <= RNG <= 95: + return 3 + elif 96 <= RNG <= 100: + return 4 + +def gacha(id, yourcoin, monsInv): + icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM'] + value = [50, 100, 150, 200, 250, 400] + RNG1 = RNG(1, 100) + time.sleep(0.2) + RNG2 = RNG(1, 100) + time.sleep(0.1) + RNG3 = RNG(1, 100) + item1 = cekrng(RNG1) item2 = cekrng(RNG2) item3 = cekrng(RNG3) - totalcoin = value[item1]+value[item2]+value[item3] + totalcoin = value[item1] + value[item2] + value[item3] + print(f"{icon[item1]} | {icon[item2]} | {icon[item3]}") - prize = False - if prize == False : - if item1==item2 and item2==item3 : - print('SELAMATT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') - prize == True - else : - print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COINS !!!") - yourcoin += totalcoin - elif prize == True : - if item1==item2 and item2==item3 : - print('SELAMATT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 1000 Coin') + + if item1 == item2 and item2 == item3: + print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') + if any(item[1] == "Gorlock" for item in monsInv): + print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 1000 Coin') yourcoin += 1000 - else : - print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COINS !!!") - yourcoin += totalcoin + else: + monsInv.append([id, "Gorlock", 1]) + else: + print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COIN !!!") + yourcoin += totalcoin + + return yourcoin -def jackpot(yourcoin) : - coin=yourcoin +def jackpot(id, yourcoin, monsInv): + yourcoin = int(yourcoin) print("SELAMAT DATANG DI JACKPOT 888!!!") - print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 400 COIN") + print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 500 COIN") + print(f"COIN ANDA SAAT INI SEJUMLAH {yourcoin}") print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") - while True : - inp = input("(Y/N)----->") - if inp.lower() == 'y' : - confirm = input("APAKAH ANDA YAKIN? (Y/N) :") - if confirm.lower() == 'y' : - if coin >= 400 : - gacha(yourcoin) - coin-=400 - print("APAKAH ANDA INGIN MELANJUTKAN??",end=" ") - else : - print("COIN TIDAK CUKUP") - else : - print("OK") \ No newline at end of file + + while True: + inp = input("(Y/N)----->").lower() + if inp == 'y': + confirm = input("APAKAH ANDA YAKIN? (Y/N) :").lower() + if confirm == 'y': + if yourcoin >= 500: + yourcoin = gacha(id, yourcoin, monsInv) + yourcoin -= 500 + print(f'COIN ANDA TERSISA {yourcoin}') + print("APAKAH ANDA INGIN MELANJUTKAN??", end=" ") + else: + print("YAH COIN ANDA TIDAK CUKUP") + print("SILAKAN COBA JACKPOT DI WAKTU LAIN") + break + elif confirm == 'n': + break + else: + print("Masukkan input yang benar") + elif inp == 'n': + break + else: + print("Masukkan input yang benar") From 1485386f7ff21683ffd4a7e09134dbfafc8b0a86 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Fri, 17 May 2024 16:06:43 +0700 Subject: [PATCH 030/115] fix: fix some bug --- src/arena.py | 2 +- src/csvParser.py | 2 ++ src/inventory.py | 8 ++++---- src/laboratory.py | 11 ++++++++--- src/main.py | 4 ++-- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/arena.py b/src/arena.py index 131f2d5..5ef51f5 100644 --- a/src/arena.py +++ b/src/arena.py @@ -22,7 +22,7 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : chosen = choose(yourmonsterdata) for i in range(5) : - random_number = RNG(1,5) + random_number = RNG(1,len(monsterdata)) random_level = RNG(1,5) opening(monsterdata,random_number) coin = battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,random_level,'arena') diff --git a/src/csvParser.py b/src/csvParser.py index 6682c0a..593351a 100644 --- a/src/csvParser.py +++ b/src/csvParser.py @@ -28,6 +28,8 @@ def csvRead(path): # Fun csvOpen.close() # Menutup file return cleanData + + def splitSemicolonInt(text): separated = [] word = '' diff --git a/src/inventory.py b/src/inventory.py index 2db5e6b..17ad6ce 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -98,13 +98,13 @@ def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : x=1 types=[] for i in userinventory: - if i[1] == 'strenghpotion' : + if i[1] == 'Strength Potion' : type = 'ATK potion' - elif i[1] == 'respotion' : + elif i[1] == 'Resilience Potion' : type = 'DEF potion' - elif i[1] == 'healingpotion' : + elif i[1] == 'Healing Potion' : type = 'HEAL potion' - elif i[1] == 'monsterball' : + elif i[1] == 'Monster Ball' : type = 'MONSTER BALL' types.append(type) print(f'{x}. Type: {type}') diff --git a/src/laboratory.py b/src/laboratory.py index 7d65798..b695608 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -30,15 +30,20 @@ def monster_Lv (id, monsInvData): mons_Lv_Array.append(int(monsInvData[i][2])) return mons_Lv_Array''' -def laboratory(yourmonsterdata,coin,role): +def laboratory(yourmonsterdata,monsterdata,coin,role): if role == 'admin' : print('Maaf! Anda tidak memiliki akses sebagai admin') elif role == 'agent' : print(f'Jumlah O.W.C.A. Coin Anda saat ini : {coin}') print('============ MONSTER LIST ============') - number = 0 for i in yourmonsterdata : - print(f"{number+1}. {i[1]}, LEVEL :{i[2]}") + index=0 + for j in monsterdata : + if j[1]==i[1] : + break + else : + index+=1 + print(f"{index}. {i[1]}, LEVEL :{i[2]}") array_Harga = [100, 200, 400, 700] print('============ UPGRADE PRICE ============') for i in range (1,5): diff --git a/src/main.py b/src/main.py index 008ed1c..268186d 100644 --- a/src/main.py +++ b/src/main.py @@ -39,7 +39,7 @@ id = int(userinventory[0][0]) command = input("--->") if command.lower() == 'battle' : - random_number = RNG(1,5) + random_number = RNG(1,len(monster)) time.sleep(2/10) random_level = RNG(1,5) opening(monster,random_number) @@ -75,7 +75,7 @@ elif command.lower() == 'help' : help(loginstatus,role) elif command.lower() == 'laboratory' : - coins = laboratory(yourmonsterinventory,coins,role) + coins = laboratory(yourmonsterinventory,monster,coins,role) user[id][4]=str(coins) elif command.lower() == 'jackpot' : jackpot(coins) From edee809a52297f17f951dc48be48b41655da1d60 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Fri, 17 May 2024 16:30:59 +0700 Subject: [PATCH 031/115] fix:some bug --- data/data1/user.csv | 2 +- src/jackpot.py | 17 +++++++++-------- src/main.py | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/data/data1/user.csv b/data/data1/user.csv index 6b2ac13..6f16e9b 100644 --- a/data/data1/user.csv +++ b/data/data1/user.csv @@ -1,5 +1,5 @@ id;username;password;role;coin -1;bagas;12345;agent;1000 +1;bagas;12345;agent;100000000000 2;bagus;12345;agent;100 3;bages;12345;agent;100 4;bagos;12345;agent;100 diff --git a/src/jackpot.py b/src/jackpot.py index 6eb8931..654b038 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -13,18 +13,18 @@ def cekrng(RNG): elif 96 <= RNG <= 100: return 4 -def gacha(id, yourcoin, monsInv): +def gacha(id, yourcoin,monsInv,yourmonsterinventory): icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM'] - value = [50, 100, 150, 200, 250, 400] + value = [30, 60, 80, 120, 170, 300] RNG1 = RNG(1, 100) time.sleep(0.2) RNG2 = RNG(1, 100) time.sleep(0.1) RNG3 = RNG(1, 100) - item1 = cekrng(RNG1) - item2 = cekrng(RNG2) - item3 = cekrng(RNG3) + item1 = 1 + item2 = 1 + item3 = 1 totalcoin = value[item1] + value[item2] + value[item3] print(f"{icon[item1]} | {icon[item2]} | {icon[item3]}") @@ -35,14 +35,15 @@ def gacha(id, yourcoin, monsInv): print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 1000 Coin') yourcoin += 1000 else: - monsInv.append([id, "Gorlock", 1]) + monsInv.append([str(id),"Gorlock",'1']) + yourmonsterinventory.append([str(id),"Gorlock",'1']) else: print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COIN !!!") yourcoin += totalcoin return yourcoin -def jackpot(id, yourcoin, monsInv): +def jackpot(id, yourcoin, monsInv,yourmonsterinventory): yourcoin = int(yourcoin) print("SELAMAT DATANG DI JACKPOT 888!!!") print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 500 COIN") @@ -55,7 +56,7 @@ def jackpot(id, yourcoin, monsInv): confirm = input("APAKAH ANDA YAKIN? (Y/N) :").lower() if confirm == 'y': if yourcoin >= 500: - yourcoin = gacha(id, yourcoin, monsInv) + yourcoin = gacha(id, yourcoin, monsInv,yourmonsterinventory) yourcoin -= 500 print(f'COIN ANDA TERSISA {yourcoin}') print("APAKAH ANDA INGIN MELANJUTKAN??", end=" ") diff --git a/src/main.py b/src/main.py index 7499d1d..d8addb7 100644 --- a/src/main.py +++ b/src/main.py @@ -78,7 +78,7 @@ coins = laboratory(yourmonsterinventory,monster,coins,role) user[id][4]=str(coins) elif command.lower() == 'jackpot' : - jackpot(id, coins, monsterinventory) + jackpot(id,coins, monsterinventory,yourmonsterinventory) else : print(f"command '{command}' tidak ada.") print(userinventory) From b9deb44751c5f06825875f76b39a89190977edff Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Fri, 17 May 2024 16:35:44 +0700 Subject: [PATCH 032/115] fix: some bug again --- src/jackpot.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index 654b038..d9725b4 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -21,10 +21,10 @@ def gacha(id, yourcoin,monsInv,yourmonsterinventory): RNG2 = RNG(1, 100) time.sleep(0.1) RNG3 = RNG(1, 100) - - item1 = 1 - item2 = 1 - item3 = 1 + + item1 = cekrng(RNG1) + item2 = cekrng(RNG2) + item3 = cekrng(RNG3) totalcoin = value[item1] + value[item2] + value[item3] print(f"{icon[item1]} | {icon[item2]} | {icon[item3]}") From 1fc857caf03859a5f1b87413bddb194f95b4db69 Mon Sep 17 00:00:00 2001 From: Cirrofy <19623238@std.stei.itb.ac.id> Date: Fri, 17 May 2024 16:43:01 +0700 Subject: [PATCH 033/115] fix: Memperbaiki shop menegamenet --- data/data1/item_shop.csv | 1 + src/shopCurrency.py | 355 ++++++++++++++++++++++---------------- src/tempCodeRunnerFile.py | 1 - 3 files changed, 206 insertions(+), 151 deletions(-) delete mode 100644 src/tempCodeRunnerFile.py diff --git a/data/data1/item_shop.csv b/data/data1/item_shop.csv index 4bc3289..7e08cd5 100644 --- a/data/data1/item_shop.csv +++ b/data/data1/item_shop.csv @@ -1,4 +1,5 @@ type;stock;price Healing Potion;5;25 +Resilience Potion;5;30 Strength Potion;5;40 Monster Ball;5;100 \ No newline at end of file diff --git a/src/shopCurrency.py b/src/shopCurrency.py index 320518b..cf48604 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -1,3 +1,31 @@ +from csvParser import csvRead, csvWriteAll +potionID = ["Type", "Healing Potion", "Resilience Potion", "Strength Potion", "Monster Ball"] +pathMonsterShop = "data\data1\monster_shop.csv" +monstershop = csvRead(pathMonsterShop) +pathMonsterDatabase = "data\data1\monster.csv" +monsterdata = csvRead(pathMonsterDatabase) +idMonsterShop = [] +for i in range(1,len(monstershop)): + idMonsterShop.append(monstershop[i][0]) +idMonsterData = [] +for i in range(1,len(monsterdata)): + idMonsterData.append(monsterdata[i][0]) + +def sortPotion(potionShop): + if potionShop[1][0] == "Resilience Potion": + potionShop[1][0],potionShop[2][0] = potionShop[2][0],potionShop[1][0] + if potionShop[3][0] == "Resilience Potion": + potionShop[3][0],potionShop[2][0] = potionShop[2][0],potionShop[3][0] + if potionShop[4][0] == "Resilience Potion": + potionShop[4][0],potionShop[2][0] = potionShop[2][0],potionShop[4][0] + if potionShop[1][0] == "Strength Potion": + potionShop[1][0],potionShop[3][0] = potionShop[3][0],potionShop[1][0] + if potionShop[4][0] == "Strength Potion": + potionShop[4][0],potionShop[3][0] = potionShop[3][0],potionShop[4][0] + if potionShop[1][0] == "Monster Ball": + potionShop[1][0],potionShop[4][0] = potionShop[4][0],potionShop[1][0] + return potionShop + def shopInterface(): print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") @@ -7,44 +35,51 @@ def shopInterface(): print(" =================== ███████████████████████") return -def shopOpen(role,potionshop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): - yourcoin=coin +def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): + yourcoin = coin if role == "agent": - print("Selamat datang di Shop!") + + print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") print() shopInterface() - keluar = False - while keluar != True: + print() + while True: pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/item): ") + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "item" and lihatSelesai != True: + while lihat_pilih != "monster" and lihat_pilih != "potion": lihat_pilih = input(">>> Pilih antara monster/potion: ") if lihat_pilih == "monster": print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") - for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop - x=int(monstershop[i][0]) - print(f"{x} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - lihatSelesai == True - elif lihat_pilih == "item": + for i in range(1,len(monstershop)): # Menampilkan setiap monster yang tersedia di Shop + idMonsterLihat=int(monstershop[i][0]) + print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + elif lihat_pilih == "potion": print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionshop)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionshop[i][0]}\t| {potionshop[i][1]}\t| {potionshop[i][2]}") + for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop + if potionShop[i][0] == "Healing Potion": + idPotion = 1 + elif potionShop[i][0] == "Resilience Potion": + idPotion = 2 + elif potionShop[i][0] == "Strength Potion": + idPotion = 3 + elif potionShop[i][0] == "Monster Ball": + idPotion = 4 + print(f"{idPotion} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") lihatSelesai == True elif pilihMenu == "beli": print(f"Jumlah O.W.C.A Coin-mu sekarang {yourcoin}.") print() - beliType = input(">>> Mau beli apa? (monster/item): ") - beliSelesai = False - while beliType != "monster" and beliType != "item" and beliSelesai != True: + beliType = input(">>> Mau beli apa? (monster/potion): ") + while beliType != "monster" and beliType != "potion": beliType = input(">>> Pilih antara monster/potion: ") if beliType == "monster": - while True : - r=0 + while True: + transactionStatus = 0 idMonsterBeli = int(input(">>> Masukkan id monster: ")) for i in yourmonsterdata : - if monsterdata[idMonsterBeli][1]==i[1] : + if monsterdata[idMonsterBeli][1] == i[1] : print("Monster sudah dimiliki") break else : @@ -52,217 +87,237 @@ def shopOpen(role,potionshop,coin,userinventory,monsterdata,monstershop,yourmons if i[0]==str(idMonsterBeli) : if yourcoin >= int(i[2]) : print("monster berhasil ditambahkan") - yourcoin-= int(i[2]) + yourcoin -= int(i[2]) yourmonsterdata.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) monsterinventory.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) - x=0 + monsterShopLocation = 0 for i in monstershop : if i[0]==str(idMonsterBeli) : - monstershop[x][1]=str(int(monstershop[x][1])-1) + monstershop[monsterShopLocation][1] = str(int(monstershop[monsterShopLocation][1])-1) break - x+=1 - r=1 + monsterShopLocation += 1 + transactionStatus = 1 break else : - print("maaf coin mu kurang") + print("Maaf O.W.C.A. Coin-mu kurang.") break - if r==1 : break - + if transactionStatus == 1 : + break print() - beliSelesai == True - elif beliType == "item": + elif beliType == "potion": idPotion = int(input(">>> Masukkan id potion: ")) while True : jumlahPotionBeli = int(input(">>> Masukkan jumlah: ")) - if int(potionshop[idPotion][1]) >0 : - if jumlahPotionBeli>int(potionshop[idPotion][1]): + if int(potionShop[idPotion][1]) >0 : + if jumlahPotionBeli>int(potionShop[idPotion][1]): print("Stock tidak cukup") else : - if yourcoin >= (jumlahPotionBeli * int(potionshop[idPotion][2])): - print(f"Berhasil membeli item: {jumlahPotionBeli} {potionshop[idPotion][0]}. Item sudah masuk ke inventory-mu!") + if yourcoin >= (jumlahPotionBeli * int(potionShop[idPotion][2])): + print(f"Berhasil membeli item: {jumlahPotionBeli} {potionShop[idPotion][0]}. Item sudah masuk ke inventory-mu!") print() - index=0 - for i in userinventory : - if i[1]==potionshop[idPotion][0]: - break - else : - index+=1 - userinventory[index][2]=str(int(userinventory[index][2])+jumlahPotionBeli) + userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) print(userinventory) - yourcoin-=(jumlahPotionBeli * int(potionshop[idPotion][2])) - potionshop[idPotion][1]=str(int(potionshop[idPotion][1])-jumlahPotionBeli) + yourcoin-=(jumlahPotionBeli * int(potionShop[idPotion][2])) + potionShop[idPotion][1]=str(int(potionShop[idPotion][1])-jumlahPotionBeli) break else : - print("maaf coin mu kurang") + print("Maaf O.W.C.A Coin-mu kurang.") else : - print("Stock habis!") + print("Stock Potion habis!") break - - beliSelesai == True + break else: # pilihMenu == "keluar" - keluar == True - print("Terima kasih sudah berkunjung. Sampai bertemu lagi!") + print(f"Sampai bertemu lagi, User!") break - return yourcoin -def shopmanagement(potionshop,monstershop,monsterdata) : - print("Selamat datang kembali, Admin!") +def shopmanagement(potionShop,monstershop,monsterdata) : + print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") + print() + shopInterface() print() - keluar = False - while keluar != True: + while True: pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/item): ") - lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "item" and lihatSelesai != True: - lihat_pilih = input(">>> Pilih antara monster/item: ") + lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + while lihat_pilih != "monster" and lihat_pilih != "potion": + lihat_pilih = input(">>> Pilih antara monster/potion: ") if lihat_pilih == "monster": print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") - for i in range(1,len(monstershop)): # Menampilkan setiap potion yang tersedia di Shop - x=int(monstershop[i][0]) - print(f"{x} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - lihatSelesai == True - elif lihat_pilih == "item": + for i in range(1,len(monstershop)): # Menampilkan setiap monster yang tersedia di Shop + idMonsterLihat=int(monstershop[i][0]) + print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") + elif lihat_pilih == "potion": print("ID | Type\t\t| Stok\t| Harga") - for i in range(1,len(potionshop)): # Menampilkan setiap potion yang tersedia di Shop - print(f"{i} | {potionshop[i][0]}\t| {potionshop[i][1]}\t| {potionshop[i][2]}") - lihatSelesai == True + for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop + if potionShop[i][0] == "Healing Potion": + idPotion = 1 + elif potionShop[i][0] == "Resilience Potion": + idPotion = 2 + elif potionShop[i][0] == "Strength Potion": + idPotion = 3 + elif potionShop[i][0] == "Monster Ball": + idPotion = 4 + print(f"{idPotion} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") + elif pilihMenu == "tambah": - tambah_pilih = input("Mau tambah apa? (monster/item): ") - tambahSelesai = False - while tambah_pilih != "monster" and tambah_pilih != "item" and tambahSelesai != True: - tambah_pilih = (input(">>> Pilih antara monster/item: ")) + idMonsterShop = [] + for i in range(1,len(monstershop)): + idMonsterShop.append(monstershop[i][0]) + idMonsterData = [] + for i in range(1,len(monsterdata)): + idMonsterData.append(monsterdata[i][0]) + tambah_pilih = input("Mau tambah apa? (monster/potion): ") + while tambah_pilih != "monster" and tambah_pilih != "potion": + tambah_pilih = (input(">>> Pilih antara monster/potion: ")) if tambah_pilih == "monster": - countabsencemonster = 0 - absencemonsterid=[] - for i in monsterdata : - for j in monstershop : - if i[0]==j[0] : - break - else : - if i[0] != 'id' : - countabsencemonster+=1 - absencemonsterid.append(i[0]) - if countabsencemonster==0 : - print("semua monster sudah ada dishop") - else : - print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t") - for i in absencemonsterid : - x=int(i) - print(f"{x} | {monsterdata[x][1]}\t| {monsterdata[x][2]}\t\t| {monsterdata[x][3]}\t\t| {monsterdata[x][4]}\t") - print() - idMonsterTambah = int(input(">>> Masukkan id monster: ")) # Nanti tambah validasi - stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) - hargaMonsterTambah = int(input(">>> Masukkan harga: ")) - monstershop.append([str(idMonsterTambah),str(stokMonsterTambah),str(hargaMonsterTambah)]) - print(f"{monsterdata[idMonsterTambah][1]} telah berhasil ditambahkan ke dalam Shop!") - elif tambah_pilih == "item": + print("ID | Type\t\t\t| ATK Power\t| DEF Power\t| HP\t|") + for i in range(1,len(monsterdata)): # Menampilkan setiap monster yang tersedia di Shop + if monsterdata[i][0] in idMonsterShop: + continue + else: + idMonsterLihat=int(monsterdata[i][0]) + print(f"{i} | {monsterdata[idMonsterLihat][1]}\t\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t|") + print() + idMonsterTambah = input(">>> Masukkan id monster: ") + while idMonsterTambah in idMonsterShop or idMonsterTambah not in idMonsterData: + if idMonsterTambah not in idMonsterData: + print("ID tidak valid! Pilih ID yang terdapat pada tabel!") + idMonsterTambah = (input(">>> Masukkan id monster: ")) + elif idMonsterTambah in idMonsterShop: + print("Monster sudah ada di Shop!") + idMonsterTambah = (input(">>> Masukkan id monster: ")) + stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) + hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + addMonsterShop = [idMonsterTambah,str(stokMonsterTambah),str(hargaMonsterTambah)] + monstershop.append(addMonsterShop) + print(f"{monsterdata[int(idMonsterTambah)][1]} telah berhasil ditambahkan ke dalam Shop!") + elif tambah_pilih == "potion": potionFound = False countFalse = 0 - notinshoplist=[] print("ID | Type") - for i in ['Healing Potion','Strength Potion','Resilience Potion','Monster Ball']: - for j in potionshop: - if i == j[0]: + for i in range(1,4): + for j in range(1,len(potionShop)): + if potionID[i] in potionShop[j][0]: potionFound = True break - else: - potionFound = False - countFalse += 1 - notinshoplist.append(i) + else: + potionFound = False + continue if potionFound == False: - print(f"{countFalse} | {i}") + print(f"{i} | {potionID[i]}") + countFalse += 1 if countFalse == 0: print("Semua Potion sudah tersedia pada Shop!") print() else: - idPotionTambah = int(input(">>> Masukkan id potion : ")) + idPotionTambah = int(input(">>> Masukkan id potion (1-4): ")) + while (idPotionTambah < 1 or idPotionTambah > 4): + print("id tidak valid!") + idPotionTambah = int(input(">>> Masukkan id potion (1-4): ")) stokPotionTambah = int(input("Masukkan stok awal: ")) hargaPotionTambah = int(input("Masukkan harga: ")) - potionshop.append([notinshoplist[idPotionTambah-1],str(stokPotionTambah),str(hargaPotionTambah)]) - print(f"{notinshoplist[idPotionTambah-1]} telah berhasil ditambahkan ke dalam Shop!") + newPotion = [potionID[idPotionTambah],str(stokPotionTambah),str(hargaPotionTambah)] + potionShop.append(newPotion) + sortPotion(potionShop) + print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") print() - elif pilihMenu=='keluar' : - keluar=True + elif pilihMenu == "ubah": ubah_pilih = input("Mau ubah apa? (monster/potion): ") - ubahSelesai = False - while ubah_pilih != "monster" and ubah_pilih != "item" and ubahSelesai != True: - ubah_pilih = (input(">>> Pilih antara monster/item: ")) + while ubah_pilih != "monster" and ubah_pilih != "potion": + ubah_pilih = (input(">>> Pilih antara monster/potion: ")) if ubah_pilih == "monster": idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi - stokMonsterBaru = (input(">>> Masukkan stok baru: ")) - hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) - index=0 - for i in monstershop : - if i[0]==(idMonsterUbah) : - break - index+=1 - print(index) + stokMonsterBaru = int(input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = int(input(">>> Masukkan harga baru: ")) pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " if (stokMonsterBaru != ""): pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" - monstershop[index][1]=stokMonsterBaru if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): pesanUbah += " dan " if (hargaMonsterBaru != ""): pesanUbah += f"dengan harga baru {hargaMonsterBaru}" - monstershop[index][2]=hargaMonsterBaru pesanUbah += "!" + for i in range(1,len(monstershop)): + if monstershop[i][0] == int(idMonsterUbah): + monstershop[int(idMonsterUbah)] = [monsterdata[int(idMonsterUbah)][0],str(stokMonsterBaru),str(hargaMonsterBaru)] print(pesanUbah) - elif ubah_pilih == "item": - idPotionUbah = (input(">>> Masukkan id item: ")) - stokPotionBaru = (input(">>> Masukkan stok baru: ")) - hargaPotionBaru = (input(">>> Masukkan harga baru: ")) - pesanUbah = f"{potionshop[int(idPotionUbah)][0]} telah berhasil diubah " + elif ubah_pilih == "potion": + idPotionUbah = int((input(">>> Masukkan id potion: "))) + while idPotionUbah < 1 or idPotionUbah > 4: + print("ID tidak valid!") + idPotionUbah = int((input(">>> Masukkan id potion: "))) + stokPotionBaru = int((input(">>> Masukkan stok baru: "))) + hargaPotionBaru = int((input(">>> Masukkan harga baru: "))) + pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " if (stokPotionBaru != ""): pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" - potionshop[int(idPotionUbah)][1]=stokPotionBaru if (stokPotionBaru != "") and (hargaPotionBaru != ""): pesanUbah += " dan " if (hargaPotionBaru != ""): pesanUbah += f"dengan harga baru {hargaPotionBaru}" - potionshop[int(idPotionUbah)][2]=hargaPotionBaru pesanUbah += "!" + for i in range(1,len(potionShop)): + if potionShop[i][0] == potionID[idPotionUbah]: + potionShop[i] = [potionID[idPotionUbah],stokPotionBaru,hargaPotionBaru] + else: + continue print(pesanUbah) print() - + elif pilihMenu == "hapus": - hapusPilih = input(">>> Mau hapus apa? (monster/item): ") - hapusSelesai = False - while hapusPilih != "monster" and hapusPilih != "item" and hapusSelesai != True: + hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") + while hapusPilih != "monster" and hapusPilih != "potion": hapusPilih = (input(">>> Pilih antara monster/potion: ")) if hapusPilih == "monster": - idMonsterHapus = input(">>> Masukkan id monster: ") - index=0 - for i in monstershop : - if i[0]==(idMonsterHapus) : - break - index+=1 - yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[int(idMonsterHapus)][1]}dari Shop (y/n)?" ) + idMonsterHapus = int(input(">>> Masukkan id monster: ")) + idMonsterShop = [] + for i in range(1,len(monstershop)): + idMonsterShop.append(monstershop[i][0]) + idMonsterData = [] + for i in range(1,len(monsterdata)): + idMonsterData.append(monsterdata[i][0]) + if str(idMonsterHapus) not in idMonsterShop: + print("Monster dengan ID tersebut tidak ada pada Shop!") + idMonsterHapus = int(input(">>> Masukkan id monster: ")) + + yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[idMonsterHapus][1]} dari Shop (y/n)? ") if yakinHapus == "y": - monstershop.pop(index) - print(f"{monsterdata[int(idMonsterHapus)][1]} telah berhasil dihapus dari Shop!") - print() + newMonsterList = [['monster_id','stock','price']] + for i in range(1,len(monstershop)): + if monstershop[i][0] == str(idMonsterHapus): + continue + else: + newMonsterList.append(monstershop[i]) + monstershop = newMonsterList + print(f"{monsterdata[idMonsterHapus][1]} telah berhasil dihapus dari Shop!") else: print("Penghapusan dibatalkan!") print() continue - if hapusPilih == "item": - idPotionHapus = input(">>> Masukkan id item: ") - yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionshop[int(idPotionHapus)][0]} dari Shop (y/n)? ") + elif hapusPilih == "potion": + idPotionHapus = int(input(">>> Masukkan id potion: ")) + yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[idPotionHapus]} dari Shop (y/n)? ") if yakinHapus == "y": - potionshop.pop(int(idPotionHapus)) - print(f"{potionshop[int(idPotionHapus)][0]} telah berhasil dihapus dari Shop!") + print(potionShop) + newPotionList = [] + for i in range(len(potionShop)): + if potionShop[i][0] == potionID[idPotionHapus]: + continue + else: + newPotionList.append(potionShop[i]) + print(newPotionList) + potionShop = newPotionList + print(potionShop) + print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") print() else: print("Penghapusan dibatalkan!") print() continue + else: # pilihMenu == "keluar" - keluar == True print("Sampai bertemu lagi Admin!") - break - + break # shopOpen("agent") # shopOpen("admin") \ No newline at end of file diff --git a/src/tempCodeRunnerFile.py b/src/tempCodeRunnerFile.py deleted file mode 100644 index 9ad1705..0000000 --- a/src/tempCodeRunnerFile.py +++ /dev/null @@ -1 +0,0 @@ -csvOpen \ No newline at end of file From 46b620085fc175e4ff9122d6532f4496433590d4 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Fri, 17 May 2024 18:28:19 +0700 Subject: [PATCH 034/115] feat : save function --- data/data2/item_inventory.csv | 13 +++++++++++++ data/data2/item_shop.csv | 5 +++++ data/data2/monser_inventory.csv | 8 ++++++++ data/data2/monster.csv | 16 ++++++++++++++++ data/data2/monster_shop.csv | 4 ++++ data/data2/user.csv | 8 ++++++++ src/load.py | 22 ++++++++++++++++++---- src/main.py | 2 ++ src/monsterball.py | 4 ++-- src/readwritecsv.py | 14 ++++++++------ 10 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 data/data2/item_inventory.csv create mode 100644 data/data2/item_shop.csv create mode 100644 data/data2/monser_inventory.csv create mode 100644 data/data2/monster.csv create mode 100644 data/data2/monster_shop.csv create mode 100644 data/data2/user.csv diff --git a/data/data2/item_inventory.csv b/data/data2/item_inventory.csv new file mode 100644 index 0000000..b395040 --- /dev/null +++ b/data/data2/item_inventory.csv @@ -0,0 +1,13 @@ +userid;type;quantity +1;Healing Potion;2 +1;Resilience Potion;3 +1;Strength Potion;2 +1;Monster Ball;1 +3;Healing Potion;2 +3;Resilience Potion;1 +3;Strength Potion;4 +3;Monster Ball;1 +2;Healing Potion;2 +2;Resilience Potion;2 +2;Strength Potion;9 +2;Monster Ball;5 \ No newline at end of file diff --git a/data/data2/item_shop.csv b/data/data2/item_shop.csv new file mode 100644 index 0000000..7e08cd5 --- /dev/null +++ b/data/data2/item_shop.csv @@ -0,0 +1,5 @@ +type;stock;price +Healing Potion;5;25 +Resilience Potion;5;30 +Strength Potion;5;40 +Monster Ball;5;100 \ No newline at end of file diff --git a/data/data2/monser_inventory.csv b/data/data2/monser_inventory.csv new file mode 100644 index 0000000..fa699c0 --- /dev/null +++ b/data/data2/monser_inventory.csv @@ -0,0 +1,8 @@ +id;monster;level +1;Mimic;1 +1;Makima;2 +1;Jalangkung;3 +2;Makima;1 +2;Mimic;1 +3;Jalangkung;2 +3;Mimic;1 \ No newline at end of file diff --git a/data/data2/monster.csv b/data/data2/monster.csv new file mode 100644 index 0000000..70ccb85 --- /dev/null +++ b/data/data2/monster.csv @@ -0,0 +1,16 @@ +id;type;atk_power;def_power;hp +1;Godzilla;70;32;540 +2;Mimic;45;28;600 +3;Makima;135;5;250 +4;Jalangkung;37;12;650 +5;gigidi;54;19;420 +6;Gorlock;22;20;700 +7;Bunny;65;24;550 +8;Roga;88;8;222 +9;Molded;66;24;440 +10;Mohg;50;20;600 +11;Malenia;55;30;500 +12;Kraken;20;35;570 +13;Mothra;57;21;520 +14;Parkinson;44;31;470 +15;Ifrit;90;5;330 \ No newline at end of file diff --git a/data/data2/monster_shop.csv b/data/data2/monster_shop.csv new file mode 100644 index 0000000..41ee368 --- /dev/null +++ b/data/data2/monster_shop.csv @@ -0,0 +1,4 @@ +monster_id;stock;price +1;6;800 +2;13;300 +3;2;750 \ No newline at end of file diff --git a/data/data2/user.csv b/data/data2/user.csv new file mode 100644 index 0000000..6f16e9b --- /dev/null +++ b/data/data2/user.csv @@ -0,0 +1,8 @@ +id;username;password;role;coin +1;bagas;12345;agent;100000000000 +2;bagus;12345;agent;100 +3;bages;12345;agent;100 +4;bagos;12345;agent;100 +5;bagis;12345;agent;100 +6;june;12345;admin;9999 +7;juni;12345;admin;9999 \ No newline at end of file diff --git a/src/load.py b/src/load.py index 46d79a3..f9da44c 100644 --- a/src/load.py +++ b/src/load.py @@ -1,4 +1,5 @@ from readwritecsv import * +from csvParser import * import os import argparse def load() : @@ -94,11 +95,24 @@ def write(path,data) : print(f"CSV file '{path}' has been created successfully.") -def save(inventory,monster,user) : +def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : # ALGORITMA path = "data/" + input("Masukkan nama folder: ") print("Saving...") if (os.path.exists(path)) : - write(path+"/inventory.csv",inventory) - write(path+"user.csv",user) - write(path+"/monster.csv",monster) \ No newline at end of file + write_csv(path+"/inventory.csv",inventory) + write_csv(path+"/user.csv",user) + write_csv(path+"/monster.csv",monster) + write_csv(path+"/monster_shop.csv",monstershop) + write_csv(path+"/item_shop.csv",itemshop) + write_csv(path+"/monser_inventory",monsterinventory) + else : + os.mkdir(path) + write_csv(path+"/item_inventory.csv",inventory) + write_csv(path+"/user.csv",user) + write_csv(path+"/monster.csv",monster) + write_csv(path+"/monster_shop.csv",monstershop) + write_csv(path+"/item_shop.csv",itemshop) + write_csv(path+"/monser_inventory.csv",monsterinventory) + + diff --git a/src/main.py b/src/main.py index d8addb7..5ab9a3c 100644 --- a/src/main.py +++ b/src/main.py @@ -31,6 +31,8 @@ loginstatus = True elif command.lower() == "help" : help(loginstatus,"belumlogin") + elif command.lower() == 'save' : + save(inventory,monster,user,monstershop,itemshop,monsterinventory) else : print(f"command '{command}' tidak ada.") if loginstatus==True : diff --git a/src/monsterball.py b/src/monsterball.py index 781cd92..d0f2360 100644 --- a/src/monsterball.py +++ b/src/monsterball.py @@ -49,6 +49,6 @@ def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventor print('Anda tidak memiliki monster ball') success = 2 if success==1 : - yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) - monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) + yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) + monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) return success \ No newline at end of file diff --git a/src/readwritecsv.py b/src/readwritecsv.py index 0396193..70dd428 100644 --- a/src/readwritecsv.py +++ b/src/readwritecsv.py @@ -18,10 +18,12 @@ def read_csv(path) : data.append(row) return data -'''def write_csv(filename, data): +def write_csv(filename, data): with open(filename, 'w') as file: - for i in range(len(data)): - file.write(','.join(data[i])) - if i < len(data) - 1: # Add newline if it's not the last row - file.write('\n')''' - + for row_index, row in enumerate(data): + for item_index, item in enumerate(row): + file.write(item) + if item_index < len(row) - 1: + file.write(';') + if row_index < len(data) - 1: + file.write('\n') \ No newline at end of file From a54fc1139fbef1eba5c06452fcd88b8976fd908b Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Fri, 17 May 2024 20:45:21 +0700 Subject: [PATCH 035/115] feat : add exit functioon --- src/exit.py | 11 ++++++----- src/main.py | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/exit.py b/src/exit.py index 25f25f0..049d7ad 100644 --- a/src/exit.py +++ b/src/exit.py @@ -1,9 +1,10 @@ -def exit(): - confirmExit = input(print("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) - while confirmExit != "y" or confirmExit != "n": +from load import save +def exit(user,monsterinventory,itemshop,monster,monstershop,iteminventory): + confirmExit = input(("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) + while confirmExit != "y" and confirmExit != "n": confirmExit = input(print("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) if confirmExit == "y": - # jalankan fungsi SAVE - print("Program berhasil ditutup!") + save(iteminventory,monster,user,monstershop,itemshop,monsterinventory) + print("Program berhasil disave dan ditutup!") else: # confirmExit =="n print("Program berhasil ditutup!") \ No newline at end of file diff --git a/src/main.py b/src/main.py index 5ab9a3c..20fe6b1 100644 --- a/src/main.py +++ b/src/main.py @@ -8,6 +8,7 @@ from laboratory import * from jackpot import * import time +from exit import * data=load() if data != [] : @@ -33,6 +34,9 @@ help(loginstatus,"belumlogin") elif command.lower() == 'save' : save(inventory,monster,user,monstershop,itemshop,monsterinventory) + elif command.lower()=='exit' : + exit(user,monsterinventory,itemshop,monster,monstershop,inventory) + break else : print(f"command '{command}' tidak ada.") if loginstatus==True : From 16d82a0db21ccab37049e91ab4bae49f847ba5c2 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Fri, 17 May 2024 21:43:36 +0700 Subject: [PATCH 036/115] fix: fix some bug in ubah&hapus monster --- src/main.py | 6 ++++-- src/shopCurrency.py | 15 +++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main.py b/src/main.py index 20fe6b1..d95e9f8 100644 --- a/src/main.py +++ b/src/main.py @@ -100,7 +100,7 @@ if command.lower() =='help': help(loginstatus,role) elif command.lower() =='shop': - shopmanagement(itemshop,monstershop,monster) + monstershop,itemshop=shopmanagement(itemshop,monstershop,monster) elif command.lower() == 'logout' : t=0 while True : @@ -115,4 +115,6 @@ else : print("mangsud?") if t==1 : loginstatus=False - break \ No newline at end of file + break + else : + print("apansih") \ No newline at end of file diff --git a/src/shopCurrency.py b/src/shopCurrency.py index cf48604..a1ee7d8 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -1,6 +1,6 @@ from csvParser import csvRead, csvWriteAll potionID = ["Type", "Healing Potion", "Resilience Potion", "Strength Potion", "Monster Ball"] -pathMonsterShop = "data\data1\monster_shop.csv" +'''pathMonsterShop = "data\data1\monster_shop.csv" monstershop = csvRead(pathMonsterShop) pathMonsterDatabase = "data\data1\monster.csv" monsterdata = csvRead(pathMonsterDatabase) @@ -9,7 +9,7 @@ idMonsterShop.append(monstershop[i][0]) idMonsterData = [] for i in range(1,len(monsterdata)): - idMonsterData.append(monsterdata[i][0]) + idMonsterData.append(monsterdata[i][0])''' def sortPotion(potionShop): if potionShop[1][0] == "Resilience Potion": @@ -232,14 +232,17 @@ def shopmanagement(potionShop,monstershop,monsterdata) : pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " if (stokMonsterBaru != ""): pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + for i in range(len(monstershop)) : + if monstershop[i][0]==(idMonsterUbah) : + monstershop[i][1]=str(stokMonsterBaru) if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): pesanUbah += " dan " if (hargaMonsterBaru != ""): pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + for i in range(len(monstershop)) : + if monstershop[i][0]==(idMonsterUbah) : + monstershop[i][2]=str(hargaMonsterBaru) pesanUbah += "!" - for i in range(1,len(monstershop)): - if monstershop[i][0] == int(idMonsterUbah): - monstershop[int(idMonsterUbah)] = [monsterdata[int(idMonsterUbah)][0],str(stokMonsterBaru),str(hargaMonsterBaru)] print(pesanUbah) elif ubah_pilih == "potion": idPotionUbah = int((input(">>> Masukkan id potion: "))) @@ -317,7 +320,7 @@ def shopmanagement(potionShop,monstershop,monsterdata) : else: # pilihMenu == "keluar" print("Sampai bertemu lagi Admin!") - break + return monstershop,potionShop # shopOpen("agent") # shopOpen("admin") \ No newline at end of file From 9722d7c14342384463f8e304cb8033a407f87922 Mon Sep 17 00:00:00 2001 From: echaa0018 <19623278@std.stei.itb.ac.id> Date: Fri, 17 May 2024 21:57:26 +0700 Subject: [PATCH 037/115] refacture: menambah komentar pada kode --- src/monsterball.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/monsterball.py b/src/monsterball.py index 781cd92..8947b5a 100644 --- a/src/monsterball.py +++ b/src/monsterball.py @@ -1,54 +1,55 @@ from RandomNumberGenerator import * +# Fungsi untuk fitur bonus Monster Ball def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventory,yourmonsterdata): jumlahball = int(userinventory[3][2]) chance = RNG(1,100) print(chance) success = 0 - if jumlahball >= 1 : - for i in yourmonsterdata : - if i[1]==monsterdata[monsterid][1] : + if jumlahball >= 1 : # Cek apakah player memiliki monster bal; + for i in yourmonsterdata : # Looping untuk cek apakah monster yang ingin ditangkap sudah ada di inventory + if i[1]==monsterdata[monsterid][1] : # bila monster sudah dimiliki player print("Anda sudah memiliki monster tersebut!") success= 2 return success - else : + else : # bila monster tidak dimiliki player print('WHOOSSHHH anda melempar monster ball') - jumlahball -=1 + jumlahball -=1 # 1 bola sudah digunakan userinventory[3][2]=str(jumlahball) - if monsterlevel==1 : + if monsterlevel==1 : # bila monster yang dilawan level 1, maka chance player mendapatkan monster tersebut 75% if chance>=1 and chance<=75 : print('ANDA DAPAT!!') success = 1 - else : + else : print('yaah ga dapet') - elif monsterlevel==2 : + elif monsterlevel==2 : # monster level 2, chance 50% if chance>=1 and chance<=50 : print('ANDA DAPAT!!') success = 1 else : print('yaah ga dapet') - elif monsterlevel==3 : + elif monsterlevel==3 : # monster level 3, chance 25% if chance>=1 and chance<=25 : print('ANDA DAPAT!!') success = 1 else : print('yaah ga dapet') - elif monsterlevel==4 : + elif monsterlevel==4 : # monster level 4, chance 10% if chance>=1 and chance<=10 : print('ANDA DAPAT!!') success = 1 else : print('yaah ga dapet') - elif monsterlevel==5 : + elif monsterlevel==5 : # monster level 5, chance 5% if chance>=1 and chance<=5 : print('ANDA DAPAT!!') success = 1 else : print('yaah ga dapet') - else : + else : # Player tidak memiliki monster ball print('Anda tidak memiliki monster ball') success = 2 - if success==1 : + if success==1 : # success = 1 berarti monster success ditangkap dan monster ditambah ke inventory player yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) return success \ No newline at end of file From c4e740c1667e4d91d88401f7b27142abd6f72c91 Mon Sep 17 00:00:00 2001 From: echaa0018 <167690463+echaa0018@users.noreply.github.com> Date: Fri, 17 May 2024 22:07:48 +0700 Subject: [PATCH 038/115] refactor: fix comment --- src/monsterball.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/monsterball.py b/src/monsterball.py index b86638e..4eee6f2 100644 --- a/src/monsterball.py +++ b/src/monsterball.py @@ -49,13 +49,7 @@ def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventor else : # Player tidak memiliki monster ball print('Anda tidak memiliki monster ball') success = 2 -<<<<<<< HEAD if success==1 : # success = 1 berarti monster success ditangkap dan monster ditambah ke inventory player - yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) - monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) -======= - if success==1 : yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) ->>>>>>> 16d82a0db21ccab37049e91ab4bae49f847ba5c2 - return success \ No newline at end of file + return success From 99e68de7ec5583dd88706166fc9f024f9c9092b7 Mon Sep 17 00:00:00 2001 From: echaa0018 <19623278@std.stei.itb.ac.id> Date: Fri, 17 May 2024 22:12:58 +0700 Subject: [PATCH 039/115] refactor: fix file path --- src/monsterManagement.py | 2 +- src/monsterball.py | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 340344a..99fdc0b 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -1,5 +1,5 @@ from csvParser import * -pathFileMonster = r"C:\Files\if1210-2024-tubes-k08-b\data\monster.csv" +pathFileMonster = r"data\data1\monster.csv" listMonster = csvReadInt(pathFileMonster) # FUNGSI UNTUK PENAMBAHAN MONSTER diff --git a/src/monsterball.py b/src/monsterball.py index b86638e..0b1ef82 100644 --- a/src/monsterball.py +++ b/src/monsterball.py @@ -49,13 +49,7 @@ def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventor else : # Player tidak memiliki monster ball print('Anda tidak memiliki monster ball') success = 2 -<<<<<<< HEAD if success==1 : # success = 1 berarti monster success ditangkap dan monster ditambah ke inventory player - yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) - monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],monsterlevel]) -======= - if success==1 : yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) monsterinventory.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) ->>>>>>> 16d82a0db21ccab37049e91ab4bae49f847ba5c2 return success \ No newline at end of file From 6be899751421d43b0cd6fd15924a71825cbccfc7 Mon Sep 17 00:00:00 2001 From: echaa0018 <19623278@std.stei.itb.ac.id> Date: Fri, 17 May 2024 22:37:09 +0700 Subject: [PATCH 040/115] fix: file path lagi --- src/monsterManagement.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 99fdc0b..abc8d2a 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -189,3 +189,4 @@ def monsterManagement(): print("Input tidak valid, input yang diterima hanya 0/1/2") # PENERAPAN FUNGSI +# monsterManagement() \ No newline at end of file From 093414caad3fc3efa573b4f225897efdf7350908 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 00:57:20 +0700 Subject: [PATCH 041/115] fix: fix a bug in save --- src/load.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/load.py b/src/load.py index f9da44c..aa61c4c 100644 --- a/src/load.py +++ b/src/load.py @@ -100,12 +100,12 @@ def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : path = "data/" + input("Masukkan nama folder: ") print("Saving...") if (os.path.exists(path)) : - write_csv(path+"/inventory.csv",inventory) + write_csv(path+"/item_inventory.csv",inventory) write_csv(path+"/user.csv",user) write_csv(path+"/monster.csv",monster) write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) - write_csv(path+"/monser_inventory",monsterinventory) + write_csv(path+"/monser_inventory.csv",monsterinventory) else : os.mkdir(path) write_csv(path+"/item_inventory.csv",inventory) From cc6017bb417e6a71dc9badd149b18626cc693a35 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 00:58:47 +0700 Subject: [PATCH 042/115] fix:fix an error in ubah monster --- src/shopCurrency.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/shopCurrency.py b/src/shopCurrency.py index a1ee7d8..4c9bee3 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -169,7 +169,7 @@ def shopmanagement(potionShop,monstershop,monsterdata) : while tambah_pilih != "monster" and tambah_pilih != "potion": tambah_pilih = (input(">>> Pilih antara monster/potion: ")) if tambah_pilih == "monster": - print("ID | Type\t\t\t| ATK Power\t| DEF Power\t| HP\t|") + print("ID | Type\t\t| ATK Power\t| DEF Power\t| HP\t|") for i in range(1,len(monsterdata)): # Menampilkan setiap monster yang tersedia di Shop if monsterdata[i][0] in idMonsterShop: continue @@ -227,18 +227,18 @@ def shopmanagement(potionShop,monstershop,monsterdata) : ubah_pilih = (input(">>> Pilih antara monster/potion: ")) if ubah_pilih == "monster": idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi - stokMonsterBaru = int(input(">>> Masukkan stok baru: ")) - hargaMonsterBaru = int(input(">>> Masukkan harga baru: ")) + stokMonsterBaru = (input(">>> Masukkan stok baru: ")) + hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " if (stokMonsterBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {stokMonsterBaru}" + pesanUbah += f"dengan stok baru sejumlah {int(stokMonsterBaru)}" for i in range(len(monstershop)) : if monstershop[i][0]==(idMonsterUbah) : monstershop[i][1]=str(stokMonsterBaru) if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): pesanUbah += " dan " if (hargaMonsterBaru != ""): - pesanUbah += f"dengan harga baru {hargaMonsterBaru}" + pesanUbah += f"dengan harga baru {int(hargaMonsterBaru)}" for i in range(len(monstershop)) : if monstershop[i][0]==(idMonsterUbah) : monstershop[i][2]=str(hargaMonsterBaru) From de8c7dd96f571be954105f26eceeaeb1dc7ce73b Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 01:00:39 +0700 Subject: [PATCH 043/115] feat: add and connect monstermanagement function --- src/main.py | 3 +++ src/monsterManagement.py | 58 ++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/main.py b/src/main.py index d95e9f8..0ea6929 100644 --- a/src/main.py +++ b/src/main.py @@ -9,6 +9,7 @@ from jackpot import * import time from exit import * +from monsterManagement import * data=load() if data != [] : @@ -116,5 +117,7 @@ if t==1 : loginstatus=False break + elif command.lower() =='monster' : + monsterManagement(monster) else : print("apansih") \ No newline at end of file diff --git a/src/monsterManagement.py b/src/monsterManagement.py index abc8d2a..33e68e9 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -1,10 +1,27 @@ -from csvParser import * +'''from csvParser import * pathFileMonster = r"data\data1\monster.csv" -listMonster = csvReadInt(pathFileMonster) +listMonster = csvReadInt(pathFileMonster)''' # FUNGSI UNTUK PENAMBAHAN MONSTER # Fungsi - fungsi proses untuk mengecek validasi input data monster -def checkType(type): +def cekint(input): + # Check if the input is empty, it's not an integer + if input == '': + return False + # Convert input to string if it is not already + input = str(input) + # Check for a negative sign at the beginning + if input[0] == '-': + if len(input) == 1: + return False # Only a '-' is not an integer + input = input[1:] # Remove the negative sign for further check + # Check if all characters are digits + for char in input: + if ord(char) < ord('0') or ord(char) > ord('9'): + return False + return True + +def checkType(type,listMonster): while True: monsterExist = False # asumsi awal, nama yang diinput tidak sama dengan nama pada database. for i in range(1, len(listMonster)): # 1 sebagai parameter karena listMonster[0] merupakan judul, len(listMonster) sebagai parameter akhir karena database monster bisa berubah seiring game berjalan. @@ -18,7 +35,7 @@ def checkType(type): def checkAttack(attack): while True: - if attack.isdigit(): # bila keseluruhan attack berupa angka + if cekint(attack): # bila keseluruhan attack berupa angka attack = int(attack) # ubah menjadi integer agar dapat dioperasikan break else : # terdapat character yang bukan angka @@ -28,7 +45,7 @@ def checkAttack(attack): def checkDefense(defense): while True: - if defense.isdigit(): # defense berupa angka secara keseluruhan + if cekint(defense): # defense berupa angka secara keseluruhan defense = int(defense) # diubah menjadi integer agar dapat dioperasikan if 0 <= defense <= 50 : # nilai sudah sesuai ketentuan break @@ -42,7 +59,7 @@ def checkDefense(defense): def checkHp(hp): while True: - if hp.isdigit(): # keseluruhan hp berupa angka + if cekint(hp): # keseluruhan hp berupa angka hp = int(hp) # ubah menjadi integer agar dapat dioperasikan break else : # terdapat character yang bukan angka pada hp @@ -52,9 +69,9 @@ def checkHp(hp): # FUNGSI SIMPLIFIKASI # Fungsi-fungsi dibawah berisi input awal data monster baru dari user -def newType(): +def newType(listMonster): type = str(input("Masukkan Type Monster : ")) - return checkType(type) + return checkType(type,listMonster) def newAttack(): attack = str(input("Masukkan attack power : ")) @@ -69,7 +86,7 @@ def newHp(): return checkHp(hp) # FUNGSI CHECK Y/N -def checkUserInput(userInput, nType, nAttack , nDefense, nHp): +def checkUserInput(listMonster,userInput, nType, nAttack , nDefense, nHp): while True: if userInput == "Y" : # disini masukkan file ke csv dulu karena bila append terlebih dahulu len(listMonster) id akan tidak sesuai pada file monster.csv @@ -82,18 +99,19 @@ def checkUserInput(userInput, nType, nAttack , nDefense, nHp): else : # Input bukan Y/N print("input tidak valid, hanya menerima input Y/N") userInput = str(input("(Y/N): ")) -def validUserInput(userInput, nType, nAttack, nDefense, nHp): + +def validUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp): userInput = str(input("Apakah mau tambahkan monster? (Y/N): ")) - return checkUserInput(userInput, nType, nAttack, nDefense, nHp) + return checkUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp) # FUNGSI PENAMBAHAN MONSTER BARU SECARA KESELURUHAN -def newMonster(): - nType = newType() +def newMonster(listMonster): + nType = newType(listMonster) nAttack = newAttack() nDefense = newDefense() nHp = newHp() userInput = "" - validUserInput(userInput, nType, nAttack, nDefense, nHp) + validUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp) return # FUNGSI PENCETAKAN TABEL RAPIH @@ -107,7 +125,7 @@ def changeInt(listMonster): # Fungsi mencari elemen terbesar dalam 1 kolom # elemen terbesar tiap kolom akan disimpan pada array largestElement, posisi bersamaan dengan kolom -def findLargestElement(largestElement): +def findLargestElement(largestElement,listMonster): for i in range(len(largestElement)): for j in range(len(listMonster)): if largestElement[i] < len(listMonster[j][i]): @@ -158,17 +176,17 @@ def printTabel (listMonster, largestElement): return # Fungsi akhir pencetakan tabel -def tabelMonster(): +def tabelMonster(listMonster): largestElement = [-1, -1, -1, -1, -1] newHeader = ["ID", "Type", "ATK Power", "DEF Power", "HP"] changeInt(listMonster) - findLargestElement(largestElement) + findLargestElement(largestElement,listMonster) changeHeader(newHeader, listMonster) printTabel(listMonster, largestElement) return # FUNGSI AKHIR MONSTER MANAGEMENT -def monsterManagement(): +def monsterManagement(listMonster): while True : print(""" SELAMAT DATANG DI DATABASE PARA MONSTER !!! @@ -178,10 +196,10 @@ def monsterManagement(): """) aksiUser = str(input("Pilih Aksi: ")) if aksiUser == "1" : - tabelMonster() + tabelMonster(listMonster) str(input("Ketik apapun untuk balik ke menu: ")) elif aksiUser == "2" : - newMonster() + newMonster(listMonster) elif aksiUser == "0" : print("Teirma kasih telah mengunjungi database monster") break From 3f917d13e4ee41e9f137d40c7951313a1a5abe6f Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 01:34:26 +0700 Subject: [PATCH 044/115] fix: fix an error at monster shop --- src/shopCurrency.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shopCurrency.py b/src/shopCurrency.py index 4c9bee3..7d1b164 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -125,10 +125,9 @@ def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmons else : print("Stock Potion habis!") break - break else: # pilihMenu == "keluar" print(f"Sampai bertemu lagi, User!") - break + return yourcoin def shopmanagement(potionShop,monstershop,monsterdata) : print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") print() From b0c1019b0ea4234167abb4d4591f2895b757cd6d Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 01:35:11 +0700 Subject: [PATCH 045/115] fix: fix an error when adding monster --- src/monsterManagement.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 33e68e9..36468e7 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -90,7 +90,7 @@ def checkUserInput(listMonster,userInput, nType, nAttack , nDefense, nHp): while True: if userInput == "Y" : # disini masukkan file ke csv dulu karena bila append terlebih dahulu len(listMonster) id akan tidak sesuai pada file monster.csv - listMonster.append([len(listMonster), nType, nAttack, nDefense, nHp]) + listMonster.append([str(len(listMonster)), nType, str(nAttack), str(nDefense), str(nHp)]) print("Monster berhasil ditambahkan") break elif userInput == "N" : @@ -102,7 +102,7 @@ def checkUserInput(listMonster,userInput, nType, nAttack , nDefense, nHp): def validUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp): userInput = str(input("Apakah mau tambahkan monster? (Y/N): ")) - return checkUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp) + checkUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp) # FUNGSI PENAMBAHAN MONSTER BARU SECARA KESELURUHAN def newMonster(listMonster): @@ -112,7 +112,6 @@ def newMonster(listMonster): nHp = newHp() userInput = "" validUserInput(listMonster,userInput, nType, nAttack, nDefense, nHp) - return # FUNGSI PENCETAKAN TABEL RAPIH # Fungsi mengubah elemen integer pada list dari data csv menjadi string karena nanti akan digunakan fungsi len() From f29e05d37d188107bea05934140f7ad16be12e04 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 14:08:11 +0700 Subject: [PATCH 046/115] fix&style:membentulkan beberapa eror dan mempercantik tampilan --- src/battle.py | 155 ++++++++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 67 deletions(-) diff --git a/src/battle.py b/src/battle.py index a44a488..312bdd1 100644 --- a/src/battle.py +++ b/src/battle.py @@ -1,91 +1,100 @@ +#import module yang dibutuhkan from potion import * from RandomNumberGenerator import * from monsterball import * +#fungsi untuk memilih monster yg ingin dipakai untuk battle def choose(yourmonsterdata) : while True : print("=======PLEASE CHOOSE A MONSTER=======") x=0 - for i in yourmonsterdata : + for i in yourmonsterdata : #menampilkan seluruh monster yg player punya print(f"{x+1}. {i[1]}") x+=1 - chosen = input("-------->") + chosen = input("(1/2/3/dst)--->") #input monster yg ingin dipilih k=0 - for i in range(1,len(yourmonsterdata)+1) : + for i in range(1,len(yourmonsterdata)+1) : if str(i)==chosen : k=1 - break + break #jika monster yg dipilih ada dalam pilihan if k==1 : break else : - print(f'pilihan ke-{chosen} tidak tersedia') + print(f'pilihan ke-{chosen} tidak tersedia') #jika tidak ada dalam pilihan return int(chosen) - +#fungsi untuk menampilkan monster yg akan dilawan def opening(monsterdata,random_number) : name = monsterdata[random_number][1] - print(f'{name} telah datang !!!!!!!!!!!') + print(f''' ============================================= + >>>>>>>>>{name} telah datang !!!<<<<<<<<< + =============================================''' + ) def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,random_level,type) : file1 = monsterdata - file2 = yourmonsterdata - used_pot=[0,0,0] - level=yourmonsterdata[chosen-1][2] - name=yourmonsterdata[chosen-1][1] + used_pot=[0,0,0] #potion hanya bisa digunakan sekali + + level=yourmonsterdata[chosen-1][2] #level monster anda + name=yourmonsterdata[chosen-1][1] #nama monster anda + #PROGRAM UTAMA ========================================================== print("="*100) print(f'{name} siap membantu') - x=0 - for i in monsterdata : + indeks=0 + for i in file1 : #mencari indeks monster kita di file monster.csv if i[1]==name : break - x+=1 - - yourattack = int(file1[x][2]) + (int(level)-1)*(10/100)*int(file1[x][2]) - yourdefense = int(file1[x][3]) + (int(level)-1)*(10/100)*int(file1[x][3]) - yourhealth = int(file1[x][4]) + (int(level)-1)*(10/100)*int(file1[x][4]) - - + indeks+=1 + + #deklarasi stat variabel + yourattack = int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2]) + yourdefense = int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3]) + yourhealth = int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4]) enemyhealth = int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4]) enemyattack = int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2]) enemydefense = int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3]) - '''yourhealth = int(file2[chosen][2])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][2]) - yourattack = int(file2[chosen][3])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][3]) - yourdefense = int(file2[chosen][4])+(5/100)*(int(file2[chosen][5])-1)*int(file2[chosen][4]) - yourlevel = int(file2[chosen][5])''' - n=1 + + turn=1 while True : - print(f"=====================TURN {n}======================") - print("="*100) + #menampilkan stat kedua monster saat battle + print(f">>>>>>>>>>>>>>>>>TURN {turn}<<<<<<<<<<<<<<<<<<<<") + print("=============================================") print(f"ENEMY : {file1[random_number][1]}") print(f"HEALTH : {enemyhealth}") print(f"ATTACK : {enemyattack}") print(f"DEFENSE : {enemydefense}") - print("="*100) + print(f"LEVEL : {random_level}") + print("=============================================") print(f"YOUR MONSTER : {name}") print(f"HEALTH : {yourhealth}") print(f"ATTACK : {yourattack}") print(f"DEFENSE : {yourdefense}") print(f"LEVEL : {level}") - print(f"====================") + print("=============================================") + #menampilkan action yg bisa dilakukan print("CHOOSE AN ACTION :") print("1. ATTACK") print("2. DRINK POTION") - if type=='battle' : + if type=='battle' : #jika mode battle terdapat option tambahan yaitu monsterball print("3. MONSTER BALL ") print("4. QUIT") elif type=='arena' : - print("3. QUIT") + print("3. QUIT") #jika mode arena tidak ada option monsterball print("=====================") - action = int(input("-------->")) - if action==1 : - enemyhealth -= (yourattack-(enemydefense/100)*yourattack) - print("YOU ATTACKED !!!!!!!!") - if enemyhealth >= 0 : + action = (input("choose an action(1/2/3/4)--->")) + if action=='1' : + #ACTION ATTACK + damage = RNG(yourattack*(70/100),yourattack*(130/100)) + enemyhealth -= (damage-(enemydefense/100)*damage) + print("=============================================") + print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") + if enemyhealth > 0 : #JIKA MONSTER BELOM MATI print(f"ENEMY MONSTER HEALTH IS DOWN TO {enemyhealth}") - elif action==2 : + elif action=='2' : + #ACTION POTION while True : print("=======CHOOSE A POTION !=======") print(jumlahpot(userinventory)) @@ -96,69 +105,81 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print("3. HEAL") print(f" you have : {jumlahpot(userinventory)[2]}") print("4. CANCEL") - potionchoice = int(input("-------->")) - newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,100000,name,potionchoice) - if potionchoice ==1 : - if newstat==0 : + potionchoice = (input("(1/2/3/4)--->")) + #jika input tidak benar + if potionchoice!='1' and potionchoice!='2' and potionchoice!='3' and potionchoice!='4' : + print(f"Opsi {potionchoice} tidak ada") + continue + #newstat adalah stat baru baik untuk atk/def/hp setelah memakai potion + newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,100000,name,int(potionchoice)) + if potionchoice =='1' : #ATK potion + if newstat==0 : #jika potion tidak bisa digunakan continue else : yourattack = newstat break - elif potionchoice ==2 : + elif potionchoice =='2' : #DEF potion if newstat==0 : continue else : yourdefense = newstat break - elif potionchoice ==3 : + elif potionchoice =='3' : #Heal potion if newstat==0 : continue else : yourhealth = newstat break - elif potionchoice ==4 : + elif potionchoice =='4' : #Cancel break - if potionchoice == 4 : + if potionchoice == '4' : continue - - elif action==3 : - if type =='battle' : + elif action=='3' : + if type =='battle' : #Jika mode battle action 3 adalah monster ball success = monsterball(random_number,random_level,userinventory,monsterdata,monsterinventory,yourmonsterdata) if success==1 : return 0 - elif success ==2 : + elif success ==2 : #Jika gagal continue - elif type =='arena': + elif type =='arena': #Jika mode arena action 3 adalah quit + print('=============================================') + print('ANDA MENINGGALKAN PERTANDINGAN') + print('=============================================') coin = 0 return coin - break - elif action==4 : + elif action=='4' : if type=='arena' : print("opsi 4 tidak ada") elif type=='battle' : + print('ANDA MENINGGALKAN PERTANDINGAN') coin = 0 - return coin - break - + return coin + else : + print(f"opsi {action} tidak ada") + continue + + #Jika musuh darahnya sudah habis if enemyhealth <= 0 : - print("="*100) + print("=============================================") print("YOU DEFEATED YOUR ENEMY") print("WOHOOOOOO") print("="*100) - coin = RNG(50,100) + coin = RNG(1,50) print(f"YEEEEEY YOU GOT {coin} coin") + print("=============================================") return coin - break - - print(f"{file1[random_number][1]} ATTACK BACK !!!") - yourhealth -= (enemyattack - (yourdefense/100)*enemyattack) - print(f"{name} HEALTH IS DOWN TO {yourhealth}") - + #Jika musuh masih hidup, musuh menyerang balik + damagemusuh=RNG(enemyattack*(70/100),enemyattack*(130/100)) + print(f">>>>>>>>>>>>>{file1[random_number][1]} ATTACK BACK !!!<<<<<<<<<<<<") + yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) + if yourhealth >0 : #jika monster kita masih hidup + print(f"{name} HEALTH IS DOWN TO {yourhealth}") + print("=============================================") + #jika darah monster kita habis if yourhealth <= 0 : - print("="*100) + print("=============================================") print("YOU ARE DEAD") print("DONT GIVE UP") - print("="*100) + print("=============================================") return 0 - break - n+=1 \ No newline at end of file + turn+=1 \ No newline at end of file From 25f739b4a8d14564d697c3b9ce40533d395a8452 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sat, 18 May 2024 15:20:45 +0700 Subject: [PATCH 047/115] refactor: Change variables name --- src/jackpot.py | 59 +++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index d9725b4..fdc4d2f 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -1,7 +1,8 @@ import time from RandomNumberGenerator import RNG -def cekrng(RNG): +# fungsi prob untuk menghasilkan kemungkinan muncul masing-masing item +def prob(RNG): if 1 <= RNG <= 40: return 0 elif 41 <= RNG <= 65: @@ -13,41 +14,41 @@ def cekrng(RNG): elif 96 <= RNG <= 100: return 4 -def gacha(id, yourcoin,monsInv,yourmonsterinventory): - icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM'] - value = [30, 60, 80, 120, 170, 300] - RNG1 = RNG(1, 100) - time.sleep(0.2) +# fungsi gacha untuk mengimplementasi probabilitas acak untuk mendapat reward +def gacha(id, coin, monsInv, yourMonsInv): + icon = ['TOPI', 'PEDANG', 'BAJU', 'CELANA', 'JAM'] + iconValue = [60, 80, 120, 170, 300] # menunjukkan value masing-masing icon sesuai dengan index array icon secara berurut + RNG1 = RNG(1, 100) # memberi range RNG masing-masing item + time.sleep(0.2) # men-delay waktu karena RNG yang digunakan berdasar time RNG2 = RNG(1, 100) - time.sleep(0.1) + time.sleep(0.1) RNG3 = RNG(1, 100) - item1 = cekrng(RNG1) - item2 = cekrng(RNG2) - item3 = cekrng(RNG3) - totalcoin = value[item1] + value[item2] + value[item3] + indexItem1 = prob(RNG1) + indexItem2 = prob(RNG2) + indexItem3 = prob(RNG3) + totalcoin = iconValue[indexItem1] + iconValue[indexItem2] + iconValue[indexItem3] - print(f"{icon[item1]} | {icon[item2]} | {icon[item3]}") + print(f"{icon[indexItem1]} | {icon[indexItem2]} | {icon[indexItem3]}") - if item1 == item2 and item2 == item3: + if indexItem1 == indexItem2 and indexItem2 == indexItem3: print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') if any(item[1] == "Gorlock" for item in monsInv): - print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 1000 Coin') - yourcoin += 1000 + print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') + coin += 2000 else: - monsInv.append([str(id),"Gorlock",'1']) - yourmonsterinventory.append([str(id),"Gorlock",'1']) + monsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list monsterInventory + yourMonsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list yourMonsterInventory else: print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COIN !!!") - yourcoin += totalcoin - - return yourcoin - -def jackpot(id, yourcoin, monsInv,yourmonsterinventory): - yourcoin = int(yourcoin) + coin += totalcoin + return coin + +def jackpot(id, coin, monsInv , yourMonsInv): + coin = int(coin) print("SELAMAT DATANG DI JACKPOT 888!!!") print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 500 COIN") - print(f"COIN ANDA SAAT INI SEJUMLAH {yourcoin}") + print(f"COIN ANDA SAAT INI SEJUMLAH {coin} ") print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") while True: @@ -55,10 +56,10 @@ def jackpot(id, yourcoin, monsInv,yourmonsterinventory): if inp == 'y': confirm = input("APAKAH ANDA YAKIN? (Y/N) :").lower() if confirm == 'y': - if yourcoin >= 500: - yourcoin = gacha(id, yourcoin, monsInv,yourmonsterinventory) - yourcoin -= 500 - print(f'COIN ANDA TERSISA {yourcoin}') + if coin >= 500: + coin = gacha(id, coin, monsInv, yourMonsInv) + coin -= 500 + print(f'COIN ANDA TERSISA {coin} ') print("APAKAH ANDA INGIN MELANJUTKAN??", end=" ") else: print("YAH COIN ANDA TIDAK CUKUP") @@ -71,4 +72,4 @@ def jackpot(id, yourcoin, monsInv,yourmonsterinventory): elif inp == 'n': break else: - print("Masukkan input yang benar") + print("Masukkan input yang benar") \ No newline at end of file From 9b701dbcb777af29a5f73ad689db46ac1d339a60 Mon Sep 17 00:00:00 2001 From: usernamedarren <165989042+usernamedarren@users.noreply.github.com> Date: Sat, 18 May 2024 15:26:27 +0700 Subject: [PATCH 048/115] Update jackpot.py --- src/jackpot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index fdc4d2f..7d887c4 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -43,7 +43,8 @@ def gacha(id, coin, monsInv, yourMonsInv): print(f"ANDA TIDAK DAPAT JACKPOT, TAPI ANDA DAPAT {totalcoin} COIN !!!") coin += totalcoin return coin - + +# fungsi jackpot untuk menjalankan program jackpot def jackpot(id, coin, monsInv , yourMonsInv): coin = int(coin) print("SELAMAT DATANG DI JACKPOT 888!!!") @@ -72,4 +73,4 @@ def jackpot(id, coin, monsInv , yourMonsInv): elif inp == 'n': break else: - print("Masukkan input yang benar") \ No newline at end of file + print("Masukkan input yang benar") From cadbecf9dad0b56d4e9dab1b764319369480f8ee Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sat, 18 May 2024 15:55:09 +0700 Subject: [PATCH 049/115] rename file --- data/data1/monster_inventory.csv | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 data/data1/monster_inventory.csv diff --git a/data/data1/monster_inventory.csv b/data/data1/monster_inventory.csv new file mode 100644 index 0000000..fa699c0 --- /dev/null +++ b/data/data1/monster_inventory.csv @@ -0,0 +1,8 @@ +id;monster;level +1;Mimic;1 +1;Makima;2 +1;Jalangkung;3 +2;Makima;1 +2;Mimic;1 +3;Jalangkung;2 +3;Mimic;1 \ No newline at end of file From 7280114d0a4456c34de5c3014537562e154a175b Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 16:11:30 +0700 Subject: [PATCH 050/115] fix: rename monster_inventory.csv --- data/data1/monster.csv | 2 +- data/data2/item_inventory.csv | 2 +- data/data2/monser_inventory.csv | 8 -------- data/data2/monster.csv | 3 ++- .../monser_inventory.csv => data2/monster_inventory.csv} | 4 +++- data/data2/monster_shop.csv | 5 +++-- data/data2/user.csv | 2 +- src/load.py | 4 ++-- 8 files changed, 13 insertions(+), 17 deletions(-) delete mode 100644 data/data2/monser_inventory.csv rename data/{data1/monser_inventory.csv => data2/monster_inventory.csv} (72%) diff --git a/data/data1/monster.csv b/data/data1/monster.csv index 70ccb85..86babdf 100644 --- a/data/data1/monster.csv +++ b/data/data1/monster.csv @@ -2,7 +2,7 @@ id;type;atk_power;def_power;hp 1;Godzilla;70;32;540 2;Mimic;45;28;600 3;Makima;135;5;250 -4;Jalangkung;37;12;650 +4;Jalangkung;3700;12;650 5;gigidi;54;19;420 6;Gorlock;22;20;700 7;Bunny;65;24;550 diff --git a/data/data2/item_inventory.csv b/data/data2/item_inventory.csv index b395040..82b2573 100644 --- a/data/data2/item_inventory.csv +++ b/data/data2/item_inventory.csv @@ -2,7 +2,7 @@ userid;type;quantity 1;Healing Potion;2 1;Resilience Potion;3 1;Strength Potion;2 -1;Monster Ball;1 +1;Monster Ball;2 3;Healing Potion;2 3;Resilience Potion;1 3;Strength Potion;4 diff --git a/data/data2/monser_inventory.csv b/data/data2/monser_inventory.csv deleted file mode 100644 index fa699c0..0000000 --- a/data/data2/monser_inventory.csv +++ /dev/null @@ -1,8 +0,0 @@ -id;monster;level -1;Mimic;1 -1;Makima;2 -1;Jalangkung;3 -2;Makima;1 -2;Mimic;1 -3;Jalangkung;2 -3;Mimic;1 \ No newline at end of file diff --git a/data/data2/monster.csv b/data/data2/monster.csv index 70ccb85..2afb49b 100644 --- a/data/data2/monster.csv +++ b/data/data2/monster.csv @@ -13,4 +13,5 @@ id;type;atk_power;def_power;hp 12;Kraken;20;35;570 13;Mothra;57;21;520 14;Parkinson;44;31;470 -15;Ifrit;90;5;330 \ No newline at end of file +15;Ifrit;90;5;330 +16;kanaguri;1000;50;1000 \ No newline at end of file diff --git a/data/data1/monser_inventory.csv b/data/data2/monster_inventory.csv similarity index 72% rename from data/data1/monser_inventory.csv rename to data/data2/monster_inventory.csv index fa699c0..a96177d 100644 --- a/data/data1/monser_inventory.csv +++ b/data/data2/monster_inventory.csv @@ -5,4 +5,6 @@ id;monster;level 2;Makima;1 2;Mimic;1 3;Jalangkung;2 -3;Mimic;1 \ No newline at end of file +3;Mimic;1 +1;kanaguri;1 +1;Godzilla;1 \ No newline at end of file diff --git a/data/data2/monster_shop.csv b/data/data2/monster_shop.csv index 41ee368..bc44c3e 100644 --- a/data/data2/monster_shop.csv +++ b/data/data2/monster_shop.csv @@ -1,4 +1,5 @@ monster_id;stock;price -1;6;800 +1;5;800 2;13;300 -3;2;750 \ No newline at end of file +3;2;750 +16;110;111 \ No newline at end of file diff --git a/data/data2/user.csv b/data/data2/user.csv index 6f16e9b..8f3e7b3 100644 --- a/data/data2/user.csv +++ b/data/data2/user.csv @@ -1,5 +1,5 @@ id;username;password;role;coin -1;bagas;12345;agent;100000000000 +1;bagas;12345;agent;99999999089 2;bagus;12345;agent;100 3;bages;12345;agent;100 4;bagos;12345;agent;100 diff --git a/src/load.py b/src/load.py index aa61c4c..40f142e 100644 --- a/src/load.py +++ b/src/load.py @@ -105,7 +105,7 @@ def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : write_csv(path+"/monster.csv",monster) write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) - write_csv(path+"/monser_inventory.csv",monsterinventory) + write_csv(path+"/monster_inventory.csv",monsterinventory) else : os.mkdir(path) write_csv(path+"/item_inventory.csv",inventory) @@ -113,6 +113,6 @@ def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : write_csv(path+"/monster.csv",monster) write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) - write_csv(path+"/monser_inventory.csv",monsterinventory) + write_csv(path+"/monster_inventory.csv",monsterinventory) From 343d95f26180e74c98f7d18ef4398d2e39dbe01f Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 16:17:49 +0700 Subject: [PATCH 051/115] fix: fix an error in load --- src/load.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/load.py b/src/load.py index 40f142e..823a1bd 100644 --- a/src/load.py +++ b/src/load.py @@ -17,7 +17,7 @@ def load() : user = read_csv(path+"/user.csv") inventory = read_csv(path+"/item_inventory.csv") monster = read_csv(path+"/monster.csv") - monsterinventory = read_csv(path+"/monser_inventory.csv") + monsterinventory = read_csv(path+"/monster_inventory.csv") itemshop=read_csv(path+"/item_shop.csv") monstershop=read_csv(path+"/monster_shop.csv") return [user,inventory,monster,monsterinventory,itemshop,monstershop] From 4919c1acacb22e663cfadd6f53c5021be6e2f7b7 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 16:29:30 +0700 Subject: [PATCH 052/115] fix: put return coin in jackpot --- src/jackpot.py | 4 ++-- src/main.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index 7d887c4..21fa9d9 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -67,10 +67,10 @@ def jackpot(id, coin, monsInv , yourMonsInv): print("SILAKAN COBA JACKPOT DI WAKTU LAIN") break elif confirm == 'n': - break + return coin else: print("Masukkan input yang benar") elif inp == 'n': - break + return coin else: print("Masukkan input yang benar") diff --git a/src/main.py b/src/main.py index 0ea6929..484ee30 100644 --- a/src/main.py +++ b/src/main.py @@ -85,7 +85,8 @@ coins = laboratory(yourmonsterinventory,monster,coins,role) user[id][4]=str(coins) elif command.lower() == 'jackpot' : - jackpot(id,coins, monsterinventory,yourmonsterinventory) + coins = jackpot(id,coins, monsterinventory,yourmonsterinventory) + user[id][4]=str(coins) else : print(f"command '{command}' tidak ada.") print(userinventory) From b010a03b041613862c1061efb4b153ac7c2dbf99 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sat, 18 May 2024 16:30:45 +0700 Subject: [PATCH 053/115] refactor: change variables name --- src/main.py | 118 ++++++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/main.py b/src/main.py index 0ea6929..c3336fb 100644 --- a/src/main.py +++ b/src/main.py @@ -13,95 +13,96 @@ data=load() if data != [] : - user = data[0] - inventory = data[1] - monster = data[2] - monsterinventory = data[3] - itemshop=data[4] - monstershop=data[5] - loginstatus = False + userData = data[0] + inventoryData = data[1] + monsterData = data[2] + monsInvData = data[3] + itemShopData = data[4] + monsShopData = data[5] + loginStatus = False while True : - command = input("--->") + command = input("--->") if command.lower() == "login" : while True : - userinventory,yourmonsterinventory,role,coins = login(user,inventory,monsterinventory) - if userinventory != 0 and role != 0 and coins !=0 and yourmonsterinventory !=0 : - loginstatus = True + userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) + if userInv != 0 and role != 0 and coin !=0 and yourMonsInv !=0 : + loginStatus = True break elif command.lower() == 'register' : - userinventory,yourmonsterinventory,role,coins = register(user,inventory,monsterinventory,monster) - loginstatus = True + userInv, yourMonsInv, role, coin = register(userData, inventoryData, monsInvData, monsterData) + loginStatus = True elif command.lower() == "help" : - help(loginstatus,"belumlogin") + help(loginStatus, "belumlogin") elif command.lower() == 'save' : - save(inventory,monster,user,monstershop,itemshop,monsterinventory) + save(inventoryData, monsterData, userData, monsterShop, itemShop, monsInvData) elif command.lower()=='exit' : - exit(user,monsterinventory,itemshop,monster,monstershop,inventory) + exit(userData, monsInvData, itemShop, monsterData, monsterShop, inventoryData) break else : print(f"command '{command}' tidak ada.") - if loginstatus==True : + if loginStatus == True : if role.lower() == 'agent': while True : - id = int(userinventory[0][0]) + id = int(userInv[0][0]) command = input("--->") if command.lower() == 'battle' : - random_number = RNG(1,len(monster)) + randomNumber = RNG(1, len(monsterData)) time.sleep(2/10) - random_level = RNG(1,5) - opening(monster,random_number) - chosen=choose(yourmonsterinventory) - coin = battle(monster,monsterinventory,yourmonsterinventory,userinventory,chosen,random_number,random_level,'battle') - coins+=coin - user[id][4]=str(coins) - print(userinventory) + randomLevel = RNG(1,5) + opening(monsterData, randomNumber) + chosen = choose(yourMonsInv) + battleCoin = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') + coin += battleCoin + userData[id][4] = str(coin) + print(userInv) elif command.lower() == 'arena' : - coin = arena(monster,monsterinventory,yourmonsterinventory,userinventory) - coins+=coin - user[id][4]=str(coins) + arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) + coin += arenaCoin + userData[id][4] = str(coin) elif command.lower() == 'inventory' : - inventoryy(userinventory,yourmonsterinventory,monster,role,coins) + inventoryy(userInv, yourMonsInv, monsterData, role, coin) elif command.lower() == 'logout' : t=0 while True : confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") if confirm.lower() == "y" : print("Logout berhasil") - t=1 + t = 1 break - elif confirm.lower() =='n' : - t=1 + elif confirm.lower() == 'n' : + t = 1 break - else : print("mangsud?") + else : + print("mangsud?") if t==1 : - loginstatus=False + loginStatus=False break elif command.lower() == 'shop' : - coins=shopOpen(role,itemshop,coins,userinventory,monster,monstershop,yourmonsterinventory,monsterinventory) - user[id][4]=str(coins) + shopCoin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) + userData[id][4] = str(shopCoin) elif command.lower() == 'help' : - help(loginstatus,role) + help(loginStatus, role) elif command.lower() == 'laboratory' : - coins = laboratory(yourmonsterinventory,monster,coins,role) - user[id][4]=str(coins) + labCoin = laboratory(yourMonsInv, monsterData, coin, role) + userData[id][4] = str(labCoin) elif command.lower() == 'jackpot' : - jackpot(id,coins, monsterinventory,yourmonsterinventory) + jackpot(id, coin, monsInvData, yourMonsInv) else : print(f"command '{command}' tidak ada.") - print(userinventory) - print(inventory) - print(user) - print(monsterinventory) - print(yourmonsterinventory) - print(itemshop) - print(monstershop) - elif role=='admin' : + print(userInv) + print(inventoryData) + print(userData) + print(monsInvData) + print(yourMonsInv) + print(itemShopData) + print(monsShopData) + elif role == 'admin' : while True : command = input("--->") - if command.lower() =='help': - help(loginstatus,role) - elif command.lower() =='shop': - monstershop,itemshop=shopmanagement(itemshop,monstershop,monster) + if command.lower() == 'help': + help(loginStatus, role) + elif command.lower() == 'shop': + monsterShop, itemShop = shopmanagement(itemShopData, monsShopData, monsterData) elif command.lower() == 'logout' : t=0 while True : @@ -110,14 +111,15 @@ print("Logout berhasil") t=1 break - elif confirm.lower() =='n ' : + elif confirm.lower() =='n' : t=1 break - else : print("mangsud?") + else : + print("mangsud?") if t==1 : - loginstatus=False + loginStatus = False break - elif command.lower() =='monster' : - monsterManagement(monster) + elif command.lower() == 'monster' : + monsterManagement(monsterData) else : print("apansih") \ No newline at end of file From 3dd605c485b751409a66a2549afebbf47cde57a2 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 16:50:54 +0700 Subject: [PATCH 054/115] Rename variabel --- src/main.py | 119 ++++++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/src/main.py b/src/main.py index 484ee30..f1da6bc 100644 --- a/src/main.py +++ b/src/main.py @@ -13,96 +13,96 @@ data=load() if data != [] : - user = data[0] - inventory = data[1] - monster = data[2] - monsterinventory = data[3] - itemshop=data[4] - monstershop=data[5] - loginstatus = False + userData = data[0] + inventoryData = data[1] + monsterData = data[2] + monsInvData = data[3] + itemShopData = data[4] + monsShopData = data[5] + loginStatus = False while True : - command = input("--->") + command = input("--->") if command.lower() == "login" : while True : - userinventory,yourmonsterinventory,role,coins = login(user,inventory,monsterinventory) - if userinventory != 0 and role != 0 and coins !=0 and yourmonsterinventory !=0 : - loginstatus = True + userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) + if userInv != 0 and role != 0 and coin !=0 and yourMonsInv !=0 : + loginStatus = True break elif command.lower() == 'register' : - userinventory,yourmonsterinventory,role,coins = register(user,inventory,monsterinventory,monster) - loginstatus = True + userInv, yourMonsInv, role, coin = register(userData, inventoryData, monsInvData, monsterData) + loginStatus = True elif command.lower() == "help" : - help(loginstatus,"belumlogin") + help(loginStatus, "belumlogin") elif command.lower() == 'save' : - save(inventory,monster,user,monstershop,itemshop,monsterinventory) + save(inventoryData, monsterData, userData, monsterShop, itemShop, monsInvData) elif command.lower()=='exit' : - exit(user,monsterinventory,itemshop,monster,monstershop,inventory) + exit(userData, monsInvData, itemShop, monsterData, monsterShop, inventoryData) break else : print(f"command '{command}' tidak ada.") - if loginstatus==True : + if loginStatus == True : if role.lower() == 'agent': while True : - id = int(userinventory[0][0]) + id = int(userInv[0][0]) command = input("--->") if command.lower() == 'battle' : - random_number = RNG(1,len(monster)) + randomNumber = RNG(1, len(monsterData)) time.sleep(2/10) - random_level = RNG(1,5) - opening(monster,random_number) - chosen=choose(yourmonsterinventory) - coin = battle(monster,monsterinventory,yourmonsterinventory,userinventory,chosen,random_number,random_level,'battle') - coins+=coin - user[id][4]=str(coins) - print(userinventory) + randomLevel = RNG(1,5) + opening(monsterData, randomNumber) + chosen = choose(yourMonsInv) + battleCoin = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') + coin += battleCoin + userData[id][4] = str(coin) + print(userInv) elif command.lower() == 'arena' : - coin = arena(monster,monsterinventory,yourmonsterinventory,userinventory) - coins+=coin - user[id][4]=str(coins) + arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) + coin += arenaCoin + userData[id][4] = str(coin) elif command.lower() == 'inventory' : - inventoryy(userinventory,yourmonsterinventory,monster,role,coins) + inventoryy(userInv, yourMonsInv, monsterData, role, coin) elif command.lower() == 'logout' : t=0 while True : confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") if confirm.lower() == "y" : print("Logout berhasil") - t=1 + t = 1 break - elif confirm.lower() =='n' : - t=1 + elif confirm.lower() == 'n' : break - else : print("mangsud?") + else : + print("mangsud?") if t==1 : - loginstatus=False + loginStatus=False break elif command.lower() == 'shop' : - coins=shopOpen(role,itemshop,coins,userinventory,monster,monstershop,yourmonsterinventory,monsterinventory) - user[id][4]=str(coins) + shopCoin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) + userData[id][4] = str(shopCoin) elif command.lower() == 'help' : - help(loginstatus,role) + help(loginStatus, role) elif command.lower() == 'laboratory' : - coins = laboratory(yourmonsterinventory,monster,coins,role) - user[id][4]=str(coins) + labCoin = laboratory(yourMonsInv, monsterData, coin, role) + userData[id][4] = str(labCoin) elif command.lower() == 'jackpot' : - coins = jackpot(id,coins, monsterinventory,yourmonsterinventory) - user[id][4]=str(coins) + jackpotCoin = jackpot(id, coin, monsInvData, yourMonsInv) + userData[id][4] = str(jackpotCoin) else : print(f"command '{command}' tidak ada.") - print(userinventory) - print(inventory) - print(user) - print(monsterinventory) - print(yourmonsterinventory) - print(itemshop) - print(monstershop) - elif role=='admin' : + print(userInv) + print(inventoryData) + print(userData) + print(monsInvData) + print(yourMonsInv) + print(itemShopData) + print(monsShopData) + elif role == 'admin' : while True : command = input("--->") - if command.lower() =='help': - help(loginstatus,role) - elif command.lower() =='shop': - monstershop,itemshop=shopmanagement(itemshop,monstershop,monster) + if command.lower() == 'help': + help(loginStatus, role) + elif command.lower() == 'shop': + monsterShop, itemShop = shopmanagement(itemShopData, monsShopData, monsterData) elif command.lower() == 'logout' : t=0 while True : @@ -111,14 +111,15 @@ print("Logout berhasil") t=1 break - elif confirm.lower() =='n ' : + elif confirm.lower() =='n' : t=1 break - else : print("mangsud?") + else : + print("mangsud?") if t==1 : - loginstatus=False + loginStatus = False break - elif command.lower() =='monster' : - monsterManagement(monster) + elif command.lower() == 'monster' : + monsterManagement(monsterData) else : print("apansih") \ No newline at end of file From 9cac799fa42c6c7568fd3358121eed16fc0388e1 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sat, 18 May 2024 16:55:15 +0700 Subject: [PATCH 055/115] resolve conflict --- blank.py | 0 data/item_inventory.csv | 6 ++++++ data/item_shop.csv | 4 ++++ data/monster.csv | 6 ++++++ data/monster_inventory.csv | 6 ++++++ data/user.csv | 6 ++++++ src/main.py | 6 ++---- 7 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 blank.py create mode 100644 data/item_inventory.csv create mode 100644 data/item_shop.csv create mode 100644 data/monster.csv create mode 100644 data/monster_inventory.csv create mode 100644 data/user.csv diff --git a/blank.py b/blank.py new file mode 100644 index 0000000..e69de29 diff --git a/data/item_inventory.csv b/data/item_inventory.csv new file mode 100644 index 0000000..eb522ba --- /dev/null +++ b/data/item_inventory.csv @@ -0,0 +1,6 @@ +user_id;type;quantity +2;strength;5 +2;resilience;3 +3;resilience;7 +4;healing;3 +5;strength;20 \ No newline at end of file diff --git a/data/item_shop.csv b/data/item_shop.csv new file mode 100644 index 0000000..b692f7e --- /dev/null +++ b/data/item_shop.csv @@ -0,0 +1,4 @@ +type;stock;price +strength;10;50 +resilience;5;30 +healing;3;20 diff --git a/data/monster.csv b/data/monster.csv new file mode 100644 index 0000000..b95ea6f --- /dev/null +++ b/data/monster.csv @@ -0,0 +1,6 @@ +id;type;atk_power;def_power;hp +1;Pikachow;125;10;600 +2;Bulbu;50;50;1200 +3;Zeze;300;10;100 +4;Zuko;100;25;800 +5;Chacha;80;30;700 diff --git a/data/monster_inventory.csv b/data/monster_inventory.csv new file mode 100644 index 0000000..4c4a704 --- /dev/null +++ b/data/monster_inventory.csv @@ -0,0 +1,6 @@ +user_id;monster_id;level +2;1;1 +3;2;2 +3;3;1 +4;4;1 +5;5;5 diff --git a/data/user.csv b/data/user.csv new file mode 100644 index 0000000..b0acd80 --- /dev/null +++ b/data/user.csv @@ -0,0 +1,6 @@ +id;username;password;role;oc +1;Mr_Monogram;monogrammer77;admin;0 +2;Asep_Spakbor;asepwow123;agent;9999 +3;Agen_P;platypus123;agent;9999 +4;B4ngk1dd0ssss;bangkitganteng;agent;1337 +5;Kenny_agen_rahasia;kribogeming55;agent;6699 diff --git a/src/main.py b/src/main.py index 20fb8f9..f1da6bc 100644 --- a/src/main.py +++ b/src/main.py @@ -5,7 +5,7 @@ from inventory import * from shopCurrency import * from help import * -from laboratory import * +from laboratory import * from jackpot import * import time from exit import * @@ -35,7 +35,7 @@ help(loginStatus, "belumlogin") elif command.lower() == 'save' : save(inventoryData, monsterData, userData, monsterShop, itemShop, monsInvData) - elif command.lower()== 'exit' : + elif command.lower()=='exit' : exit(userData, monsInvData, itemShop, monsterData, monsterShop, inventoryData) break else : @@ -70,7 +70,6 @@ t = 1 break elif confirm.lower() == 'n' : - t = 1 break else : print("mangsud?") @@ -86,7 +85,6 @@ labCoin = laboratory(yourMonsInv, monsterData, coin, role) userData[id][4] = str(labCoin) elif command.lower() == 'jackpot' : - jackpot(id, coin, monsInvData, yourMonsInv) jackpotCoin = jackpot(id, coin, monsInvData, yourMonsInv) userData[id][4] = str(jackpotCoin) else : From 084a8a35f0c75db21629eb4d169e62cddec350e4 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 17:04:41 +0700 Subject: [PATCH 056/115] fix:fix some little errors --- src/main.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main.py b/src/main.py index f1da6bc..4c1f75f 100644 --- a/src/main.py +++ b/src/main.py @@ -34,9 +34,9 @@ elif command.lower() == "help" : help(loginStatus, "belumlogin") elif command.lower() == 'save' : - save(inventoryData, monsterData, userData, monsterShop, itemShop, monsInvData) + save(inventoryData, monsterData, userData, monsShopData, itemShopData, monsInvData) elif command.lower()=='exit' : - exit(userData, monsInvData, itemShop, monsterData, monsterShop, inventoryData) + exit(userData, monsInvData, itemShopData, monsterData, monsShopData, inventoryData) break else : print(f"command '{command}' tidak ada.") @@ -102,7 +102,7 @@ if command.lower() == 'help': help(loginStatus, role) elif command.lower() == 'shop': - monsterShop, itemShop = shopmanagement(itemShopData, monsShopData, monsterData) + monsShopData, itemShopData = shopmanagement(itemShopData, monsShopData, monsterData) elif command.lower() == 'logout' : t=0 while True : @@ -112,7 +112,6 @@ t=1 break elif confirm.lower() =='n' : - t=1 break else : print("mangsud?") From 6ae48b8dc7693701e21ff9800bfa309a594ad114 Mon Sep 17 00:00:00 2001 From: echaa0018 <19623278@std.stei.itb.ac.id> Date: Sat, 18 May 2024 17:51:23 +0700 Subject: [PATCH 057/115] refactor: menambahkan .lower() untuk validasi input --- src/monsterManagement.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 36468e7..560bc8d 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -88,12 +88,12 @@ def newHp(): # FUNGSI CHECK Y/N def checkUserInput(listMonster,userInput, nType, nAttack , nDefense, nHp): while True: - if userInput == "Y" : + if userInput.lower() == "y" : # disini masukkan file ke csv dulu karena bila append terlebih dahulu len(listMonster) id akan tidak sesuai pada file monster.csv listMonster.append([str(len(listMonster)), nType, str(nAttack), str(nDefense), str(nHp)]) print("Monster berhasil ditambahkan") break - elif userInput == "N" : + elif userInput.lower() == "n" : print("Monster gagal ditambahkan") break else : # Input bukan Y/N From c3c45e07de79f535921a50d45adf40f523877abb Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 21:04:25 +0700 Subject: [PATCH 058/115] feat: add damagetaken and damagedealt variable --- src/arena.py | 51 ++++++++++++++++++++++++++++++++++----------------- src/battle.py | 29 +++++++++++++++++++++-------- src/main.py | 2 +- 3 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/arena.py b/src/arena.py index 5ef51f5..f389f3e 100644 --- a/src/arena.py +++ b/src/arena.py @@ -2,15 +2,17 @@ from RandomNumberGenerator import * def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : - + #deklarasi variabel coins=0 + totaldamageTaken = 0 + totaldamageDealt = 0 - print("DO YOU WANT TO ENTER THE ARENA? (Y/N)") - inp = input("--------->") - if inp=="N" : + print("DO YOU WANT TO ENTER THE ARENA? (Y/N)") #double cek dari user + inp = input("--->") + if inp.lower()=="n" : #jika tidak jadi print("SEE U ANOTHER DAY") - elif inp=="Y" : - print("=====WELCOME TO THE ARENA=====") + elif inp.lower()=="y" : + print("==========WELCOME TO THE ARENA==========") print("RULES :") print("1. THERE WILL BE A TOTAL OF 5 STAGES IN THE ARENA, EACH STAGE") print(" YOU HAVE TO FIGHT A MONSTER WITH EACH STAGE THE MONSTER WILL GET STRONGER") @@ -19,22 +21,37 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : print("3. IF YOU LOSE ONCE, THE ARENA WILL BE OVER, IF YOU WIN ALL THE WAY") print(" TO THE FIFTH STAGE YOU WILL GET MAXIMUM COINS") - chosen = choose(yourmonsterdata) - - for i in range(5) : + chosen = choose(yourmonsterdata) #fungsi untuk memilih monster dari pilihan monsterinventory + stage = 1 + for i in range(5) : #pemanggilan fungsi battle sebanyak maksimum 5 kali random_number = RNG(1,len(monsterdata)) - random_level = RNG(1,5) + enemylevel = i+1 #level monster musuh sesuai nomor stage + print(f"--------->>>STAGE {i+1}<<<---------") opening(monsterdata,random_number) - coin = battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,random_level,'arena') + coin,damageTaken,damageDealt = battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,enemylevel,'arena') coins += coin - if coin==0 : - print(f"YOU MADE IT TO STAGE NUMBER {i+1}, KEEP IMPROVING") + totaldamageTaken += damageTaken + totaldamageDealt += damageDealt + + if coin==0 : #coin==0 di arena hanya terjadi saat monster kita kalah + print("ARENA IS OVER, TRY AGAIN") break + else : #monster kita menang + stage += 1 - else : + if stage==5 : #jika berhasil sampai ke stage terakhir dan menang akan mendapatkan bonus 50 coin print("CONGRATULATION YOU MADE IT ALL THE WAY!!!!") - print("HERE A BONUS 50 COIN FOR YOU!!!") + print("HERE A BONUS 50 COINs FOR YOU!!!") coins += 50 - print(f"YOUR TOTAL COIN GAINED FROM THE ARENA : {coins}") - return coins + #STATISTIK ARENA + print("==========================================") + print("STATISTICS FROM THE ARENA :") + print(f"NUMBER OF STAGE : {stage-1}") + print(f"TOTAL COIN GAINED FROM THE ARENA : {coins}") + print(f"TOTAL DAMAGE TAKEN : {totaldamageTaken}") + print(f"TOTAL DAMAGE DEALT : {totaldamageDealt}") + print("==========================================") + else : + print("Masukkan input yg benar(Y/N)--->") + return coins \ No newline at end of file diff --git a/src/battle.py b/src/battle.py index 312bdd1..6415f6c 100644 --- a/src/battle.py +++ b/src/battle.py @@ -26,9 +26,9 @@ def choose(yourmonsterdata) : #fungsi untuk menampilkan monster yg akan dilawan def opening(monsterdata,random_number) : name = monsterdata[random_number][1] - print(f''' ============================================= - >>>>>>>>>{name} telah datang !!!<<<<<<<<< - =============================================''' + print(f'''============================================= +>>>>>>>>>{name} telah datang !!!<<<<<<<<< +=============================================''' ) def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,random_level,type) : @@ -57,6 +57,8 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran enemyattack = int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2]) enemydefense = int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3]) + damagetaken=0 + damagedealt=0 turn=1 while True : #menampilkan stat kedua monster saat battle @@ -88,6 +90,10 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran if action=='1' : #ACTION ATTACK damage = RNG(yourattack*(70/100),yourattack*(130/100)) + if enemyhealth >= (damage-(enemydefense/100)*damage) : #menghitung damagedealt jika enemy belom mati + damagedealt += (damage-(enemydefense/100)*damage) + else : #jika enemy mati maka damagedealt hanya ditambah sebesar sisa darah enemy sebelum mati + damagedealt += enemyhealth enemyhealth -= (damage-(enemydefense/100)*damage) print("=============================================") print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") @@ -138,7 +144,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran if type =='battle' : #Jika mode battle action 3 adalah monster ball success = monsterball(random_number,random_level,userinventory,monsterdata,monsterinventory,yourmonsterdata) if success==1 : - return 0 + return 0,damagetaken,damagedealt elif success ==2 : #Jika gagal continue elif type =='arena': #Jika mode arena action 3 adalah quit @@ -146,14 +152,15 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print('ANDA MENINGGALKAN PERTANDINGAN') print('=============================================') coin = 0 - return coin + return coin,damagetaken,damagedealt elif action=='4' : if type=='arena' : print("opsi 4 tidak ada") + continue elif type=='battle' : print('ANDA MENINGGALKAN PERTANDINGAN') coin = 0 - return coin + return coin,damagetaken,damagedealt else : print(f"opsi {action} tidak ada") continue @@ -167,19 +174,25 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran coin = RNG(1,50) print(f"YEEEEEY YOU GOT {coin} coin") print("=============================================") - return coin + return coin,damagetaken,damagedealt + #Jika musuh masih hidup, musuh menyerang balik damagemusuh=RNG(enemyattack*(70/100),enemyattack*(130/100)) print(f">>>>>>>>>>>>>{file1[random_number][1]} ATTACK BACK !!!<<<<<<<<<<<<") + if yourhealth >= (damagemusuh - (yourdefense/100)*damagemusuh) : + damagetaken += (damagemusuh - (yourdefense/100)*damagemusuh) #Jika monster kita masih hidup setelah serangan + else : + damagetaken += yourhealth #jika monster kita mati setelah serangan yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) if yourhealth >0 : #jika monster kita masih hidup print(f"{name} HEALTH IS DOWN TO {yourhealth}") print("=============================================") + #jika darah monster kita habis if yourhealth <= 0 : print("=============================================") print("YOU ARE DEAD") print("DONT GIVE UP") print("=============================================") - return 0 + return 0,damagetaken,damagedealt turn+=1 \ No newline at end of file diff --git a/src/main.py b/src/main.py index 4c1f75f..278db94 100644 --- a/src/main.py +++ b/src/main.py @@ -51,7 +51,7 @@ randomLevel = RNG(1,5) opening(monsterData, randomNumber) chosen = choose(yourMonsInv) - battleCoin = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') + battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') coin += battleCoin userData[id][4] = str(coin) print(userInv) From c52eb6682f5065abdfe114d06b35dbf9c3b8469f Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 21:07:25 +0700 Subject: [PATCH 059/115] feat: add jackpot in help --- src/help.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/help.py b/src/help.py index 9b80676..bbc1a54 100644 --- a/src/help.py +++ b/src/help.py @@ -22,7 +22,9 @@ def help(status,role) : print(" Cek semua item dan monster anda") print("5. Laboratory") print(" Tempat untuk meng-upgrade monster anda") - print("6. Logout") + print("6. Jackpot") + print(" Tempat untuk menguji keberuntungan anda") + print("7. Logout") print(" Keluar dari akun anda") if role == 'admin' : print("List command yang dapat anda lakukan :") From b6b3ec355f29752dff0037315fcb27d85e1cd070 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 23:25:58 +0700 Subject: [PATCH 060/115] fix: fix an error with the coin variable --- src/main.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main.py b/src/main.py index 278db94..0f441da 100644 --- a/src/main.py +++ b/src/main.py @@ -77,16 +77,16 @@ loginStatus=False break elif command.lower() == 'shop' : - shopCoin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) - userData[id][4] = str(shopCoin) + coin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) + userData[id][4] = str(coin) elif command.lower() == 'help' : help(loginStatus, role) elif command.lower() == 'laboratory' : - labCoin = laboratory(yourMonsInv, monsterData, coin, role) - userData[id][4] = str(labCoin) + coin = laboratory(yourMonsInv, monsterData, coin, role) + userData[id][4] = str(coin) elif command.lower() == 'jackpot' : - jackpotCoin = jackpot(id, coin, monsInvData, yourMonsInv) - userData[id][4] = str(jackpotCoin) + coin = jackpot(id, coin, monsInvData, yourMonsInv) + userData[id][4] = str(coin) else : print(f"command '{command}' tidak ada.") print(userInv) From 37e7dc51b10ae4e86e76e4bad5e66414abd17a52 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 23:33:01 +0700 Subject: [PATCH 061/115] fix&feat: fix eror saat input tidak benar dan add comment --- src/inventory.py | 177 ++++++++--------------------------------------- 1 file changed, 29 insertions(+), 148 deletions(-) diff --git a/src/inventory.py b/src/inventory.py index 17ad6ce..8217e2a 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -1,102 +1,13 @@ -import sys -sys.path.append("C:\if1210-2024-tubes-k08-b\data") - -def splitSemicolon(text): # Fungsi mirip .split() namun untuk string dengan pemisah semicolon saja - separated = [] - word = '' - - for char in (text): - if char == '\n' : # jika "\n" (newline), pengecekan berhenti (agar newline tidak masuk ke array) - break - elif char != ';': - word += char # jika bukan ";", huruf akan digabung satu persatu menjadi sebuah kata - else: # char == ";" - separated.append(word) # jika ";", maka kata yang telah terbentuk akan dimasukkan dalam array - word = '' # kemudian kata akan dikosongkan kembali (semicolon dilewat) - - separated.append(word) # Untuk kata setelah semicolon terakhir - - return separated - -def csvRead(path): # Fungsi membaca file .csv baris per baris - csvOpen = open(path,'r') # Membuka file .csv - cleanData = [] - - for row in csvOpen: # Membaca setiap baris - cleanData.append(splitSemicolon(row)) # Memisahkan kalimat dari semicolon - - csvOpen.close() # Menutup file - return cleanData - - -'''user_Data = csvRead("data/data1/user.csv") -pot_Inv_Data = csvRead(r"E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\data\item_inventory.csv") -monster_Data = csvRead(r"E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\data\monster.csv") -mons_Inv_Data = csvRead(r"E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\data\monster_inventory.csv")''' - -def check_Admin (id, userData): - for i in range (1, len(userData)): - if id == int(userData[i][0]) : - if userData[i][3] == 'admin' : - return False - else : - return True - -def owca_Coin (id, userData): - for i in range (1, len(userData)): - if id == int(userData[i][0]) : - return int(userData[i][4]) - -'''def pot_Inventory (userinventory): - for i in userinventory: - if i[1]=='strenghpotion': - jumlahstr=i[2] - break - else : jumlahstr = 0 - for i in userinventory: - if i[1]=='respotion' : - jumlahres=i[2] - break - else : jumlahres = 0 - for i in userinventory: - if i[1]=='healingpotion' : - jumlahheal=i[2] - break - else : jumlahheal = 0 - return [jumlahstr,jumlahres,jumlahheal] - -def pot_List (qty): - pot_Type = ['ATK', 'DEF', 'HEAL'] - pot_Type_2 = [] - pot_Qty =[] - for i in range (3): - if qty[i] != 0 : - pot_Type_2.append(pot_Type[i]) - pot_Qty.append(qty[i]) - return (pot_Type_2, pot_Qty) - -def monster_Id (yourmonsterdata): - mons_Id_Array = [] - for i in yourmonsterdata : - mons_Id_Array.append(i[1]) - return mons_Id_Array - -def monster_Lv (yourmonsterdata): - mons_Lv_Array = [] - for i in yourmonsterdata : - mons_Lv_Array.append(i[2]) - return mons_Lv_Array''' - def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : - if role=='admin': + if role=='admin': #jika role player adalah admin print("Maaf! Anda tidak memiliki akses sebagai admin") else : print(f'jumlah OWCA coin anda saat ini : {coin}') while True : check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Item/Back): ') if check.lower() == 'item' : - x=1 - types=[] + number=1 + types=[] #list untuk type dari item yang tersedia for i in userinventory: if i[1] == 'Strength Potion' : type = 'ATK potion' @@ -107,26 +18,43 @@ def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : elif i[1] == 'Monster Ball' : type = 'MONSTER BALL' types.append(type) - print(f'{x}. Type: {type}') - x+=1 - while True : - pot_Number = input('Masukkan nomor potion untuk menampilkan detail item (1/2/3/Back): ') + print(f'{number}. Type: {type}') + number+=1 + while True : + pot_Number = input('Masukkan nomor item untuk menampilkan detail item (1/2/3/Back): ') + #cek apakah input sudah benar (yaitu 1/2/3/4) if pot_Number.lower() != 'back': + for i in range(4) : + if pot_Number == str(i+1) : + break #jika output benar + else : #jika output salah + print('Nomor item tersebut tidak tersedia') + continue pot_Number = int(pot_Number) + #menampilkan type dan jumlah item print(f'Type: {types[pot_Number-1]}') print(f'Quantity: {userinventory[pot_Number-1][2]}') - else : + else : #jika input = back break elif check.lower() == 'monster' : y = 0 + #menampilkan seluruh monster yang kita punya for i in yourmonsterdata : print(f"{y+1}. {i[1]}") y+=1 while True : mons_Number = input('Masukkan nomor monster untuk menampilkan detail monster (1/2/dst/Back): ') if mons_Number.lower() != 'back' : - mons_Number = int(mons_Number) + #validasi apakah input sudah benar (1,2,3,..len(monsterkita)) + for i in range(len(yourmonsterdata)) : + if mons_Number == str(i+1) : + break #jika input sudah benar + else : #jika input salah + print("Nomor monster tersebut tidak tersedia") + continue + mons_Number=int(mons_Number) monsterlvl = int(yourmonsterdata[mons_Number-1][2]) + #menampilkan stats dari monster yg dipilih for i in monsterdata : if i[1]==yourmonsterdata[mons_Number-1][1] : print(f'Nama : {i[1]}') @@ -134,56 +62,9 @@ def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : print(f'DEF Power : {int(i[3])+(monsterlvl-1)*(5/100)*(int(i[3]))}') print(f'HP : {int(i[4])+(monsterlvl-1)*(5/100)*(int(i[4]))}') print(f'Level : {monsterlvl}') - else : + else : #jika input == break break elif check.lower() == 'back' : break - -'''def inventory (monsId, monsData, potData, monsLevel, access, oc): - if access == False : - print('Maaf! Anda tidak memiliki akses sebagai admin') - elif access == True : - print(f'Jumlah O.W.C.A. Coin Anda saat ini : {oc}') - while True : - check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Potion/Back): ') - if check.lower() == 'potion' : - for i in range(len(potData[0])): - print(f'{i+1}. Type: {potData[0][i]}') - - while True : - pot_Number = input('Masukkan nomor potion untuk menampilkan detail item (1/2/3/Back): ') - if pot_Number.lower() != 'back': - pot_Number = int(pot_Number) - print('POTION') - print(f'Type: {potData[0][pot_Number-1]}') - print(f'Quantity: {potData[1][pot_Number-1]}') - else : - break - - elif check.lower() == 'monster' : - number = 0 - for i in range (1, len(monsData)): - for j in range (len(monsId)): - if monsId[j] == int(monsData[i][0]) : - number += 1 - print(f'{number}. {monsData[i][1]}') - - while True : - mons_Number = input('Masukkan nomor monster untuk menampilkan detail monster (1/2/dst/Back): ') - if mons_Number.lower() != 'back' : - mons_Number = int(mons_Number) - print('MONSTER') - for i in range (1, len(monsData)): - if int(monsData[i][0]) == monsId[mons_Number-1] : - print(f'Nama : {monsData[i][1]}') - print(f'ATK Power : {int(monsData[i][2]) + (int(monsData[i][2])*(monsLevel[mons_Number-1]-1)*0.1)}') - print(f'DEF Power : {int(monsData[i][3]) + (int(monsData[i][3])*(monsLevel[mons_Number-1]-1)*0.1)}') - print(f'HP : {int(monsData[i][4]) + (int(monsData[i][4])*(monsLevel[mons_Number-1]-1)*0.1)}') - print(f'Level : {monsLevel[mons_Number-1]}') - else : - break - elif check.lower() == 'back' : - break ''' - -# contoh penggunaan function : -#inventory(monster_Id(3, mons_Inv_Data), monster_Data, pot_List(pot_Inventory(3, pot_Inv_Data)),monster_Lv(3, mons_Inv_Data), check_Admin(3, user_Data), owca_Coin(3, user_Data)) \ No newline at end of file + else : #jika input salah + print("Jenis item tersebut tidak ada") \ No newline at end of file From f6561c52256a8e7800765cd989b1df0302b6d43f Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sat, 18 May 2024 23:50:21 +0700 Subject: [PATCH 062/115] rename potionnumber variavle to itemnumber --- src/inventory.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/inventory.py b/src/inventory.py index 8217e2a..d6f5bad 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -21,19 +21,19 @@ def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : print(f'{number}. Type: {type}') number+=1 while True : - pot_Number = input('Masukkan nomor item untuk menampilkan detail item (1/2/3/Back): ') + item_Number = input('Masukkan nomor item untuk menampilkan detail item (1/2/3/Back): ') #cek apakah input sudah benar (yaitu 1/2/3/4) - if pot_Number.lower() != 'back': + if item_Number.lower() != 'back': for i in range(4) : - if pot_Number == str(i+1) : + if item_Number == str(i+1) : break #jika output benar else : #jika output salah print('Nomor item tersebut tidak tersedia') continue - pot_Number = int(pot_Number) + item_Number = int(item_Number) #menampilkan type dan jumlah item - print(f'Type: {types[pot_Number-1]}') - print(f'Quantity: {userinventory[pot_Number-1][2]}') + print(f'Type: {types[item_Number-1]}') + print(f'Quantity: {userinventory[item_Number-1][2]}') else : #jika input = back break elif check.lower() == 'monster' : From a45bfe06eab31585d1a2fe22c5a37c6b3195da99 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 00:34:20 +0700 Subject: [PATCH 063/115] fix&feat: fix a validation error and add comment --- src/laboratory.py | 127 +++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 70 deletions(-) diff --git a/src/laboratory.py b/src/laboratory.py index b695608..73d0e86 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -1,93 +1,80 @@ - -'''from csvParser import splitSemicolon, csvRead, csvWrite, csvOverwrite, csvDelete''' - - - -'''def check_Admin (id, userData): - for i in range (1, len(userData)): - if id == int(userData[i][0]) : - if userData[i][3] == 'admin' : - return False - else : - return True - -def owca_Coin (id, userData): - for i in range (1, len(userData)): - if id == int(userData[i][0]) : - return int(userData[i][4]) - -def monster_Id (id, monsInvData): - mons_Id_Array = [] - for i in range (1, len(monsInvData)): - if int(monsInvData[i][0]) == id : - mons_Id_Array.append(int(monsInvData[i][1])) - return mons_Id_Array - -def monster_Lv (id, monsInvData): - mons_Lv_Array = [] - for i in range (1, len(monsInvData)): - if int(monsInvData[i][0]) == id : - mons_Lv_Array.append(int(monsInvData[i][2])) - return mons_Lv_Array''' - def laboratory(yourmonsterdata,monsterdata,coin,role): - if role == 'admin' : + if role == 'admin' : #jika role adalah admin print('Maaf! Anda tidak memiliki akses sebagai admin') - elif role == 'agent' : - print(f'Jumlah O.W.C.A. Coin Anda saat ini : {coin}') - print('============ MONSTER LIST ============') - for i in yourmonsterdata : - index=0 - for j in monsterdata : - if j[1]==i[1] : - break - else : - index+=1 - print(f"{index}. {i[1]}, LEVEL :{i[2]}") - array_Harga = [100, 200, 400, 700] - print('============ UPGRADE PRICE ============') - for i in range (1,5): - print(f'{i}. Level {i} -> Level {i+1}: {array_Harga[i-1]}') + else : #role == 'agent' + array_Harga = [100, 200, 400, 700] #list harga untuk mengupgrade level monster while True: + print(f"JUMLAH COIN ANDA : {coin}") + #menampilkan seluruh monster yg kita miliki + print('============ MONSTER LIST ============') + number=1 + for i in yourmonsterdata : + print(f"{number}. {i[1]}, LEVEL :{i[2]}") + number+=1 + #menampilkan harga untuk mengupgrade ke masing2 level + print('============ UPGRADE PRICE ============') + for i in range (1,5): + print(f'{i}. Level {i} -> Level {i+1}: {array_Harga[i-1]}') idpilihan = input('Pilih monster yang ingin di-upgrade (1/2/dst/Back): ') + #validasi input + for i in range(len(yourmonsterdata)) : + if idpilihan== str(i+1) or idpilihan.lower()=='back' : + break #jika input benar + else : #jika input salah + print("Monster tersebut tidak tersedia") + continue + if idpilihan.lower() != 'back': idpilihan = int(idpilihan) while True: - if yourmonsterdata[idpilihan-1][2] != 5: + if yourmonsterdata[idpilihan-1][2] != '5': #jika monster tidak maks level up_level = input('Silakan pilih ke level berapa kah Anda ingin meng-upgrade monster Anda (1/2/dst/Back): ') + #periksa apakah input berupa int dari 1-5 atau back + for i in range(5) : + if up_level == str(i+1) or up_level.lower()=='back' : + break + else : + print("Masukkan level yg dituju dengan benar") + continue + if up_level.lower() != 'back': - if up_level == yourmonsterdata[idpilihan-1][2] : - print("masa mau upgrade kelevel yg sama si") - break - else : + if up_level <= yourmonsterdata[idpilihan-1][2] : #jika level yg dituju sudah tercapai + print("masa mau upgrade kelevel yg sama/lebihrendah si") + continue + else : #jika input benar dan sesuai up_level = int(up_level) harga = 0 + #menghitung harga yg dibutuhkan for i in range (int(yourmonsterdata[idpilihan-1][2]), up_level): harga += array_Harga[i-1] print(f'{yourmonsterdata[idpilihan-1][1]} akan di-upgrade ke level {up_level}') print(f'Harga untuk meng-upgrade {yourmonsterdata[idpilihan-1][1]} adalah {harga}') - lanjut = input('Lanjutkan upgrade (Y/N): ') - if lanjut.lower() != 'n': - if coin >= harga : - yourmonsterdata[idpilihan-1][2]=str(up_level) - coin -= harga - print(f'Selamat! {yourmonsterdata[idpilihan-1][1]} berhasil di-upgrade ke level {up_level}!') - print(f'Coin Anda tersisa {coin}') - break - else : - print('Maaf! Anda tidak memiliki Coin yang cukup') - break - else : - break - else : + while True : #double cek apakah benar mau di upgarde + lanjut = input('Lanjutkan upgrade (Y/N): ') + if lanjut.lower() == 'y': + if coin >= harga : #jika coin cukup + yourmonsterdata[idpilihan-1][2]=str(up_level) + coin -= harga + print(f'Selamat! {yourmonsterdata[idpilihan-1][1]} berhasil di-upgrade ke level {up_level}!') + print(f'Coin Anda tersisa {coin}') + break + else : #jika tidak cukup + print('Maaf! Anda tidak memiliki Coin yang cukup') + break + elif lanjut.lower() == 'n' : #jika tidak jadi upgrade + break + else : #jika input bukan y atau n + print("Mohon masukkan input yang benar") + continue + break + + else : #jika input == break break - else : + else : #jika sudah maks level print('Maaf! Monster yang Anda pilih sudah memiliki level maksimum. Silakan pilih monster lain') break else: break return coin -# contoh penggunaan function : -#inventory(3, user_Data, mons_Inv_Data, monster_Id(3, mons_Inv_Data), monster_Data, monster_Lv(3, mons_Inv_Data), check_Admin(3, user_Data), owca_Coin(3, user_Data)) \ No newline at end of file From 7685c79d5f4b31690b7e662648ccc53e48efe7cd Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 01:05:07 +0700 Subject: [PATCH 064/115] refactor: change inventoryy variable name --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index 0f441da..fbff800 100644 --- a/src/main.py +++ b/src/main.py @@ -60,7 +60,7 @@ coin += arenaCoin userData[id][4] = str(coin) elif command.lower() == 'inventory' : - inventoryy(userInv, yourMonsInv, monsterData, role, coin) + inventory(userInv, yourMonsInv, monsterData, role, coin) elif command.lower() == 'logout' : t=0 while True : From ae7c7e4e1258938f4b617e27254f1ac287b51ad0 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 01:05:28 +0700 Subject: [PATCH 065/115] refactor: change inventoryy variable name --- src/inventory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inventory.py b/src/inventory.py index d6f5bad..ffbd482 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -1,4 +1,4 @@ -def inventoryy(userinventory,yourmonsterdata,monsterdata,role,coin) : +def inventory(userinventory,yourmonsterdata,monsterdata,role,coin) : if role=='admin': #jika role player adalah admin print("Maaf! Anda tidak memiliki akses sebagai admin") else : From e54b05920a56992dae7a9055c947f975d3b0aa84 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 01:43:04 +0700 Subject: [PATCH 066/115] fix:turn every stat to integer(round number) --- src/battle.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/battle.py b/src/battle.py index 6415f6c..a0ed678 100644 --- a/src/battle.py +++ b/src/battle.py @@ -50,12 +50,13 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran indeks+=1 #deklarasi stat variabel - yourattack = int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2]) - yourdefense = int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3]) - yourhealth = int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4]) - enemyhealth = int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4]) - enemyattack = int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2]) - enemydefense = int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3]) + originalhealth = int(int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4])) + yourattack = int(int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2])) + yourdefense = int(int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3])) + yourhealth = int(int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4])) + enemyhealth = int(int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4])) + enemyattack = int(int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2])) + enemydefense = int(int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3])) damagetaken=0 damagedealt=0 @@ -95,6 +96,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran else : #jika enemy mati maka damagedealt hanya ditambah sebesar sisa darah enemy sebelum mati damagedealt += enemyhealth enemyhealth -= (damage-(enemydefense/100)*damage) + enemyhealth = int(enemyhealth) print("=============================================") print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") if enemyhealth > 0 : #JIKA MONSTER BELOM MATI @@ -103,7 +105,6 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran #ACTION POTION while True : print("=======CHOOSE A POTION !=======") - print(jumlahpot(userinventory)) print("1. STRENGHT") print(f" you have : {jumlahpot(userinventory)[0]}") print("2. RESILIENSE") @@ -117,24 +118,24 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print(f"Opsi {potionchoice} tidak ada") continue #newstat adalah stat baru baik untuk atk/def/hp setelah memakai potion - newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,100000,name,int(potionchoice)) + newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,originalhealth,name,int(potionchoice)) if potionchoice =='1' : #ATK potion if newstat==0 : #jika potion tidak bisa digunakan continue else : - yourattack = newstat + yourattack = int(newstat) break elif potionchoice =='2' : #DEF potion if newstat==0 : continue else : - yourdefense = newstat + yourdefense = int(newstat) break elif potionchoice =='3' : #Heal potion if newstat==0 : continue else : - yourhealth = newstat + yourhealth = int(newstat) break elif potionchoice =='4' : #Cancel break @@ -184,6 +185,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran else : damagetaken += yourhealth #jika monster kita mati setelah serangan yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) + yourhealth = int(yourhealth) if yourhealth >0 : #jika monster kita masih hidup print(f"{name} HEALTH IS DOWN TO {yourhealth}") print("=============================================") From e4f69d3bf8a6b8ea76171afb900fd3bfdc936de1 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 01:48:05 +0700 Subject: [PATCH 067/115] remove unnecessary files --- data/item_inventory.csv | 6 ------ data/item_shop.csv | 4 ---- data/monster.csv | 6 ------ data/monster_inventory.csv | 6 ------ data/user.csv | 6 ------ 5 files changed, 28 deletions(-) delete mode 100644 data/item_inventory.csv delete mode 100644 data/item_shop.csv delete mode 100644 data/monster.csv delete mode 100644 data/monster_inventory.csv delete mode 100644 data/user.csv diff --git a/data/item_inventory.csv b/data/item_inventory.csv deleted file mode 100644 index eb522ba..0000000 --- a/data/item_inventory.csv +++ /dev/null @@ -1,6 +0,0 @@ -user_id;type;quantity -2;strength;5 -2;resilience;3 -3;resilience;7 -4;healing;3 -5;strength;20 \ No newline at end of file diff --git a/data/item_shop.csv b/data/item_shop.csv deleted file mode 100644 index b692f7e..0000000 --- a/data/item_shop.csv +++ /dev/null @@ -1,4 +0,0 @@ -type;stock;price -strength;10;50 -resilience;5;30 -healing;3;20 diff --git a/data/monster.csv b/data/monster.csv deleted file mode 100644 index b95ea6f..0000000 --- a/data/monster.csv +++ /dev/null @@ -1,6 +0,0 @@ -id;type;atk_power;def_power;hp -1;Pikachow;125;10;600 -2;Bulbu;50;50;1200 -3;Zeze;300;10;100 -4;Zuko;100;25;800 -5;Chacha;80;30;700 diff --git a/data/monster_inventory.csv b/data/monster_inventory.csv deleted file mode 100644 index 4c4a704..0000000 --- a/data/monster_inventory.csv +++ /dev/null @@ -1,6 +0,0 @@ -user_id;monster_id;level -2;1;1 -3;2;2 -3;3;1 -4;4;1 -5;5;5 diff --git a/data/user.csv b/data/user.csv deleted file mode 100644 index b0acd80..0000000 --- a/data/user.csv +++ /dev/null @@ -1,6 +0,0 @@ -id;username;password;role;oc -1;Mr_Monogram;monogrammer77;admin;0 -2;Asep_Spakbor;asepwow123;agent;9999 -3;Agen_P;platypus123;agent;9999 -4;B4ngk1dd0ssss;bangkitganteng;agent;1337 -5;Kenny_agen_rahasia;kribogeming55;agent;6699 From b875803cc9bf240952e075cb7eb0417c47d386a3 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 01:53:46 +0700 Subject: [PATCH 068/115] feat: add comment in potion.py --- src/potion.py | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/potion.py b/src/potion.py index 15e0e25..5447c01 100644 --- a/src/potion.py +++ b/src/potion.py @@ -1,3 +1,4 @@ +#FUNGI UNTUK MENGHITUNG JUMLAH MASING MASING POTION def jumlahpot(userinventory) : for i in userinventory : if i[1]=='Strength Potion' : @@ -14,8 +15,9 @@ def jumlahpot(userinventory) : jumlahheal = i[2] break else : jumlahheal = 0 - return [int(jumlahstr),int(jumlahres),int(jumlahheal)] + return [int(jumlahstr),int(jumlahres),int(jumlahheal)] #RETURN LIST MASING MASING JUMLAH POTION +#FUNGSI MENCARI INDEKS LOKASI POTION DI INVENTORY def lokasipot(userinventory) : x=0 for i in userinventory : @@ -35,31 +37,30 @@ def lokasipot(userinventory) : break z+=1 else : x=999 - return [x,y,z] + return [x,y,z] #RETURN INDEKS POTION DI INVENTORY - # used_Pot_Array adalah array untuk menunjukkan apakah sebuah potion telah digunakan sekali dalam battle dengan used_Pot_Array [jumlah strength potion digunakan, jumlah resilience potion digunakan, jumlah heal potion digunakan] def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, HP, max_HP, mons_Name, pilihan): - if pilihan==1 : + if pilihan==1 : #PILIHAN 1 ADALAH STR POTION if int(jumlahpot[0])> 0 : if used_Pot_Array[0] == 0 : - used_Pot_Array[0] += 1 - attack *= 105/100 + used_Pot_Array[0] += 1 #MENANDAKAN POTION SUDAH DIPAKE DAN TIDAK BISA DIPAKE LAGI + attack *= 110/100 #ATTACK BERTAMBAH 10 PERSEN print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih kuat!!") - jumlahpot[0] -= 1 + jumlahpot[0] -= 1 #JUMLAH STR POTION BERKURANG SATU userinventory[lokasipot[0]][2]=str(int(userinventory[lokasipot[0]][2])-1) return attack else : - print(f"Potion hanya bisa digunakan sekali") + print(f"Potion hanya bisa digunakan sekali") #POTION SUDAH DIGUNAKAN return 0 - else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + else : #POTION TIDAK ADA + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") return 0 - elif pilihan==2 : + elif pilihan==2 : #PILIHAN 2 ADALAH RES POTION if int(jumlahpot[1]) > 0 : if used_Pot_Array[1] == 0 : used_Pot_Array[1] += 1 - defense *= 105/100 + defense *= 110/100 #DEFENSE BERTAMBAH 10 PERSEN print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih sulit dilukai!!") jumlahpot[1] -=1 userinventory[lokasipot[1]][2]=str(int(userinventory[lokasipot[1]][2])-1) @@ -70,17 +71,17 @@ def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, H else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") return 0 - elif pilihan==3 : + elif pilihan==3 : #PILIHAN 3 ADALAH HEAL POTION if int(jumlahpot[2]) > 0 : if used_Pot_Array[2] == 0 : used_Pot_Array[2] += 1 - if HP * 125/100 <= max_HP : + if HP * 125/100 <= max_HP : #JIKA HP + 25PERSEN TIDAK MELAMPAU MAKS HP(HP AWAL) HP *= 125/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") jumlahpot[2] -=1 userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) return HP - else : + else : #JIKA MELAMPAU MAKS HP MAKA HEAL HANYA AKAN SAMPAI MAKS HP HP = max_HP print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") jumlahpot[2] -=1 @@ -91,8 +92,4 @@ def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, H return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") - return 0 - - - -# contoh penggunaan function : potion(pot_Inventory (2, csvRead("E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\item_inventory.csv")), used_Pot_Array, 10, 20, 30, 100, "Zuko") \ No newline at end of file + return 0 \ No newline at end of file From bb0ae43d0e25fd25db3859a9b0af1df4590a63e8 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 02:17:52 +0700 Subject: [PATCH 069/115] refactor: change variables name --- src/potion.py | 129 ++++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 61 deletions(-) diff --git a/src/potion.py b/src/potion.py index 15e0e25..a49c28d 100644 --- a/src/potion.py +++ b/src/potion.py @@ -1,98 +1,105 @@ -def jumlahpot(userinventory) : - for i in userinventory : - if i[1]=='Strength Potion' : - jumlahstr = i[2] +# fungsi jumlahPot untuk mengambil data potion yang ada di userInventory +def jumlahPot(userInventory) : + for i in userInventory : + if i[1] == 'Strength Potion' : + jumlahStr = i[2] break - else : jumlahstr = 0 - for i in userinventory : - if i[1]=='Resilience Potion' : - jumlahres = i[2] + else : + jumlahStr = 0 + for i in userInventory : + if i[1] == 'Resilience Potion' : + jumlahRes = i[2] break - else : jumlahres = 0 - for i in userinventory : - if i[1]=='Healing Potion' : - jumlahheal = i[2] + else : + jumlahRes = 0 + for i in userInventory : + if i[1] == 'Healing Potion' : + jumlahHeal = i[2] break - else : jumlahheal = 0 - return [int(jumlahstr),int(jumlahres),int(jumlahheal)] + else : + jumlahHeal = 0 -def lokasipot(userinventory) : - x=0 - for i in userinventory : - if i[1]=='Strength Potion' : + return [int(jumlahStr), int(jumlahRes), int(jumlahHeal)] + +# fungsi indexPot untuk mengecek index masing-masing tipe potion di userInventory +def indexPot(userInventory) : + indexStr = 0 + indexRes = 0 + indexHeal = 0 + + for i in userInventory : + if i[1] != 'Strength Potion' : # untuk mencari indexStr dengan menambahkan indexStr secara berulang + indexStr += 1 + elif i[1] == 'Strength Potion' : # untuk mendapatkan indexStr dengan menghentikan penambahan indexStr break - x+=1 - else : x=999 - y=0 - for i in userinventory : - if i[1]=='Resilience Potion' : + + for i in userInventory : + if i[1] != 'Resilience Potion' : + indexRes += 1 + elif i[1] == 'Resilience Potion' : break - y+=1 - else : y=999 - z=0 - for i in userinventory : - if i[1]=='Healing Potion' : + + for i in userInventory : + if i[1] != 'Healing Potion' : + indexHeal += 1 + elif i[1] == 'Healing Potion' : break - z+=1 - else : x=999 - return [x,y,z] - # used_Pot_Array adalah array untuk menunjukkan apakah sebuah potion telah digunakan sekali dalam battle dengan used_Pot_Array [jumlah strength potion digunakan, jumlah resilience potion digunakan, jumlah heal potion digunakan] -def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, HP, max_HP, mons_Name, pilihan): - if pilihan==1 : - if int(jumlahpot[0])> 0 : - if used_Pot_Array[0] == 0 : + return [indexStr, indexRes, indexHeal] + +# fungsi potion untuk meng-return nilai 1 atau 0 untuk diproses di battle.py +def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, HP, max_HP, mons_Name, pilihan): + if pilihan == 1 : + if int(jumlahpot[0]) > 0 : # mengecek ada tidaknya potion strength + if used_Pot_Array[0] == 0 : # mengecek pernah tidaknya potion strength digunakan used_Pot_Array[0] += 1 attack *= 105/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih kuat!!") jumlahpot[0] -= 1 - userinventory[lokasipot[0]][2]=str(int(userinventory[lokasipot[0]][2])-1) - return attack + userInventory[indexPot[0]][2] = str(int(userInventory[indexPot[0]][2])-1) + return attack # return nilai attack monster setelah menggunakan potion strength else : - print(f"Potion hanya bisa digunakan sekali") - return 0 + print("Potion hanya bisa digunakan sekali") + return 0 # return 0 untuk mengindikasi potion tidak bisa digunakan else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain") return 0 - elif pilihan==2 : - if int(jumlahpot[1]) > 0 : - if used_Pot_Array[1] == 0 : + elif pilihan == 2 : + if int(jumlahpot[1]) > 0 : # mengecek ada tidaknya potion resilience + if used_Pot_Array[1] == 0 : # mengecek pernah tidaknya potion resilience digunakan used_Pot_Array[1] += 1 defense *= 105/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih sulit dilukai!!") jumlahpot[1] -=1 - userinventory[lokasipot[1]][2]=str(int(userinventory[lokasipot[1]][2])-1) - return defense + userInventory[indexPot[1]][2] = str(int(userInventory[indexPot[1]][2])-1) + return defense # return nilai defense monster setelah menggunakan potion resilience else : - print(f"Potion hanya bisa digunakan sekali") + print("Potion hanya bisa digunakan sekali") return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") return 0 + elif pilihan==3 : - if int(jumlahpot[2]) > 0 : - if used_Pot_Array[2] == 0 : + if int(jumlahpot[2]) > 0 : # mengecek ada tidaknya potion healing + if used_Pot_Array[2] == 0 : # mengecek pernah tidaknya potion healing digunakan used_Pot_Array[2] += 1 - if HP * 125/100 <= max_HP : + if HP * 125/100 <= max_HP : # mengecek penggunaan potion melebihi HP maksimum atau tidak HP *= 125/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") - jumlahpot[2] -=1 - userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) - return HP + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) + return HP # return nilai HP monster setelah menggunakan potion healing else : HP = max_HP print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") - jumlahpot[2] -=1 - userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP else : - print(f"Potion hanya bisa digunakan sekali") + print("Potion hanya bisa digunakan sekali") return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") - return 0 - - - -# contoh penggunaan function : potion(pot_Inventory (2, csvRead("E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\item_inventory.csv")), used_Pot_Array, 10, 20, 30, 100, "Zuko") \ No newline at end of file + return 0 \ No newline at end of file From bdc65eb4b41cdad8670926b89f4c928477e31acd Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 02:23:06 +0700 Subject: [PATCH 070/115] refactor: change variables name --- src/potion.py | 131 ++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/src/potion.py b/src/potion.py index 15e0e25..59c44ee 100644 --- a/src/potion.py +++ b/src/potion.py @@ -1,98 +1,105 @@ -def jumlahpot(userinventory) : - for i in userinventory : - if i[1]=='Strength Potion' : - jumlahstr = i[2] +# fungsi jumlahPot untuk mengambil data potion yang ada di userInventory +def jumlahPot(userInventory) : + for i in userInventory : + if i[1] == 'Strength Potion' : + jumlahStr = i[2] break - else : jumlahstr = 0 - for i in userinventory : - if i[1]=='Resilience Potion' : - jumlahres = i[2] + else : + jumlahStr = 0 + for i in userInventory : + if i[1] == 'Resilience Potion' : + jumlahRes = i[2] break - else : jumlahres = 0 - for i in userinventory : - if i[1]=='Healing Potion' : - jumlahheal = i[2] + else : + jumlahRes = 0 + for i in userInventory : + if i[1] == 'Healing Potion' : + jumlahHeal = i[2] break - else : jumlahheal = 0 - return [int(jumlahstr),int(jumlahres),int(jumlahheal)] + else : + jumlahHeal = 0 -def lokasipot(userinventory) : - x=0 - for i in userinventory : - if i[1]=='Strength Potion' : + return [int(jumlahStr), int(jumlahRes), int(jumlahHeal)] + +# fungsi indexPot untuk mengecek index masing-masing tipe potion di userInventory +def indexPot(userInventory) : + indexStr = 0 + indexRes = 0 + indexHeal = 0 + + for i in userInventory : + if i[1] != 'Strength Potion' : # untuk mencari indexStr dengan menambahkan indexStr secara berulang + indexStr += 1 + elif i[1] == 'Strength Potion' : # untuk mendapatkan indexStr dengan menghentikan penambahan indexStr break - x+=1 - else : x=999 - y=0 - for i in userinventory : - if i[1]=='Resilience Potion' : + + for i in userInventory : + if i[1] != 'Resilience Potion' : + indexRes += 1 + elif i[1] == 'Resilience Potion' : break - y+=1 - else : y=999 - z=0 - for i in userinventory : - if i[1]=='Healing Potion' : + + for i in userInventory : + if i[1] != 'Healing Potion' : + indexHeal += 1 + elif i[1] == 'Healing Potion' : break - z+=1 - else : x=999 - return [x,y,z] - # used_Pot_Array adalah array untuk menunjukkan apakah sebuah potion telah digunakan sekali dalam battle dengan used_Pot_Array [jumlah strength potion digunakan, jumlah resilience potion digunakan, jumlah heal potion digunakan] -def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, HP, max_HP, mons_Name, pilihan): - if pilihan==1 : - if int(jumlahpot[0])> 0 : - if used_Pot_Array[0] == 0 : + return [indexStr, indexRes, indexHeal] + +# fungsi potion untuk meng-return nilai hasil penggunaan potion atau 0 untuk diproses di battle.py +def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, HP, max_HP, mons_Name, pilihan): + if pilihan == 1 : + if int(jumlahpot[0]) > 0 : # mengecek ada tidaknya potion strength + if used_Pot_Array[0] == 0 : # mengecek pernah tidaknya potion strength digunakan used_Pot_Array[0] += 1 attack *= 105/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih kuat!!") jumlahpot[0] -= 1 - userinventory[lokasipot[0]][2]=str(int(userinventory[lokasipot[0]][2])-1) - return attack + userInventory[indexPot[0]][2] = str(int(userInventory[indexPot[0]][2])-1) + return attack # return nilai attack monster setelah menggunakan potion strength else : - print(f"Potion hanya bisa digunakan sekali") - return 0 + print("Potion hanya bisa digunakan sekali") + return 0 # return 0 untuk mengindikasi potion tidak bisa digunakan else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain") return 0 - elif pilihan==2 : - if int(jumlahpot[1]) > 0 : - if used_Pot_Array[1] == 0 : + elif pilihan == 2 : + if int(jumlahpot[1]) > 0 : # mengecek ada tidaknya potion resilience + if used_Pot_Array[1] == 0 : # mengecek pernah tidaknya potion resilience digunakan used_Pot_Array[1] += 1 - defense *= 105/100 + defense *= 110/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih sulit dilukai!!") jumlahpot[1] -=1 - userinventory[lokasipot[1]][2]=str(int(userinventory[lokasipot[1]][2])-1) - return defense + userInventory[indexPot[1]][2] = str(int(userInventory[indexPot[1]][2])-1) + return defense # return nilai defense monster setelah menggunakan potion resilience else : - print(f"Potion hanya bisa digunakan sekali") + print("Potion hanya bisa digunakan sekali") return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") return 0 + elif pilihan==3 : - if int(jumlahpot[2]) > 0 : - if used_Pot_Array[2] == 0 : + if int(jumlahpot[2]) > 0 : # mengecek ada tidaknya potion healing + if used_Pot_Array[2] == 0 : # mengecek pernah tidaknya potion healing digunakan used_Pot_Array[2] += 1 - if HP * 125/100 <= max_HP : + if HP * 125/100 <= max_HP : # mengecek penggunaan potion melebihi HP maksimum atau tidak HP *= 125/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") - jumlahpot[2] -=1 - userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) - return HP + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) + return HP # return nilai HP monster setelah menggunakan potion healing else : HP = max_HP print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") - jumlahpot[2] -=1 - userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP else : - print(f"Potion hanya bisa digunakan sekali") + print("Potion hanya bisa digunakan sekali") return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") - return 0 - - - -# contoh penggunaan function : potion(pot_Inventory (2, csvRead("E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\item_inventory.csv")), used_Pot_Array, 10, 20, 30, 100, "Zuko") \ No newline at end of file + return 0 \ No newline at end of file From b721804470b9963d111f7094892de9ccac6738e0 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 02:33:26 +0700 Subject: [PATCH 071/115] refactor: change variable names --- src/potion.py | 131 ++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/src/potion.py b/src/potion.py index 15e0e25..745d77c 100644 --- a/src/potion.py +++ b/src/potion.py @@ -1,98 +1,105 @@ -def jumlahpot(userinventory) : - for i in userinventory : - if i[1]=='Strength Potion' : - jumlahstr = i[2] +# fungsi jumlahPot untuk mengambil data potion yang ada di userInventory +def jumlahPot(userInventory) : + for i in userInventory : + if i[1] == 'Strength Potion' : + jumlahStr = i[2] break - else : jumlahstr = 0 - for i in userinventory : - if i[1]=='Resilience Potion' : - jumlahres = i[2] + else : + jumlahStr = 0 + for i in userInventory : + if i[1] == 'Resilience Potion' : + jumlahRes = i[2] break - else : jumlahres = 0 - for i in userinventory : - if i[1]=='Healing Potion' : - jumlahheal = i[2] + else : + jumlahRes = 0 + for i in userInventory : + if i[1] == 'Healing Potion' : + jumlahHeal = i[2] break - else : jumlahheal = 0 - return [int(jumlahstr),int(jumlahres),int(jumlahheal)] + else : + jumlahHeal = 0 -def lokasipot(userinventory) : - x=0 - for i in userinventory : - if i[1]=='Strength Potion' : + return [int(jumlahStr), int(jumlahRes), int(jumlahHeal)] + +# fungsi indexPot untuk mengecek index masing-masing tipe potion di userInventory +def indexPot(userInventory) : + indexStr = 0 + indexRes = 0 + indexHeal = 0 + + for i in userInventory : + if i[1] != 'Strength Potion' : # untuk mencari indexStr dengan menambahkan indexStr secara berulang + indexStr += 1 + elif i[1] == 'Strength Potion' : # untuk mendapatkan indexStr dengan menghentikan penambahan indexStr break - x+=1 - else : x=999 - y=0 - for i in userinventory : - if i[1]=='Resilience Potion' : + + for i in userInventory : + if i[1] != 'Resilience Potion' : + indexRes += 1 + elif i[1] == 'Resilience Potion' : break - y+=1 - else : y=999 - z=0 - for i in userinventory : - if i[1]=='Healing Potion' : + + for i in userInventory : + if i[1] != 'Healing Potion' : + indexHeal += 1 + elif i[1] == 'Healing Potion' : break - z+=1 - else : x=999 - return [x,y,z] - # used_Pot_Array adalah array untuk menunjukkan apakah sebuah potion telah digunakan sekali dalam battle dengan used_Pot_Array [jumlah strength potion digunakan, jumlah resilience potion digunakan, jumlah heal potion digunakan] -def potion(jumlahpot,lokasipot,used_Pot_Array, userinventory, attack, defense, HP, max_HP, mons_Name, pilihan): - if pilihan==1 : - if int(jumlahpot[0])> 0 : - if used_Pot_Array[0] == 0 : + return [indexStr, indexRes, indexHeal] + +# fungsi potion untuk meng-return nilai 1 atau 0 untuk diproses di battle.py +def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, HP, max_HP, mons_Name, pilihan): + if pilihan == 1 : + if int(jumlahpot[0]) > 0 : # mengecek ada tidaknya potion strength + if used_Pot_Array[0] == 0 : # mengecek pernah tidaknya potion strength digunakan used_Pot_Array[0] += 1 attack *= 105/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih kuat!!") jumlahpot[0] -= 1 - userinventory[lokasipot[0]][2]=str(int(userinventory[lokasipot[0]][2])-1) - return attack + userInventory[indexPot[0]][2] = str(int(userInventory[indexPot[0]][2])-1) + return attack # return nilai attack monster setelah menggunakan potion strength else : - print(f"Potion hanya bisa digunakan sekali") - return 0 + print("Potion hanya bisa digunakan sekali") + return 0 # return 0 untuk mengindikasi potion tidak bisa digunakan else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain") return 0 - elif pilihan==2 : - if int(jumlahpot[1]) > 0 : - if used_Pot_Array[1] == 0 : + elif pilihan == 2 : + if int(jumlahpot[1]) > 0 : # mengecek ada tidaknya potion resilience + if used_Pot_Array[1] == 0 : # mengecek pernah tidaknya potion resilience digunakan used_Pot_Array[1] += 1 - defense *= 105/100 + defense *= 110/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih sulit dilukai!!") jumlahpot[1] -=1 - userinventory[lokasipot[1]][2]=str(int(userinventory[lokasipot[1]][2])-1) - return defense + userInventory[indexPot[1]][2] = str(int(userInventory[indexPot[1]][2])-1) + return defense # return nilai defense monster setelah menggunakan potion resilience else : - print(f"Potion hanya bisa digunakan sekali") + print("Potion hanya bisa digunakan sekali") return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") return 0 + elif pilihan==3 : - if int(jumlahpot[2]) > 0 : - if used_Pot_Array[2] == 0 : + if int(jumlahpot[2]) > 0 : # mengecek ada tidaknya potion healing + if used_Pot_Array[2] == 0 : # mengecek pernah tidaknya potion healing digunakan used_Pot_Array[2] += 1 - if HP * 125/100 <= max_HP : + if HP * 125/100 <= max_HP : # mengecek penggunaan potion melebihi HP maksimum atau tidak HP *= 125/100 print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") - jumlahpot[2] -=1 - userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) - return HP + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) + return HP # return nilai HP monster setelah menggunakan potion healing else : HP = max_HP print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") - jumlahpot[2] -=1 - userinventory[lokasipot[2]][2]=str(int(userinventory[lokasipot[2]][2])-1) + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP else : - print(f"Potion hanya bisa digunakan sekali") + print("Potion hanya bisa digunakan sekali") return 0 else : print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") - return 0 - - - -# contoh penggunaan function : potion(pot_Inventory (2, csvRead("E:\Documents\Daspro\Tubes\if1210-2024-tubes-k08-b\item_inventory.csv")), used_Pot_Array, 10, 20, 30, 100, "Zuko") \ No newline at end of file + return 0 \ No newline at end of file From aaa0b934be83c6f2323a7b6e7800306853d5439a Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 02:36:01 +0700 Subject: [PATCH 072/115] refactor: change variables name --- src/battle.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/battle.py b/src/battle.py index a0ed678..314b2ef 100644 --- a/src/battle.py +++ b/src/battle.py @@ -50,13 +50,12 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran indeks+=1 #deklarasi stat variabel - originalhealth = int(int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4])) - yourattack = int(int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2])) - yourdefense = int(int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3])) - yourhealth = int(int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4])) - enemyhealth = int(int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4])) - enemyattack = int(int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2])) - enemydefense = int(int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3])) + yourattack = int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2]) + yourdefense = int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3]) + yourhealth = int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4]) + enemyhealth = int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4]) + enemyattack = int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2]) + enemydefense = int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3]) damagetaken=0 damagedealt=0 @@ -96,7 +95,6 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran else : #jika enemy mati maka damagedealt hanya ditambah sebesar sisa darah enemy sebelum mati damagedealt += enemyhealth enemyhealth -= (damage-(enemydefense/100)*damage) - enemyhealth = int(enemyhealth) print("=============================================") print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") if enemyhealth > 0 : #JIKA MONSTER BELOM MATI @@ -105,12 +103,13 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran #ACTION POTION while True : print("=======CHOOSE A POTION !=======") - print("1. STRENGHT") - print(f" you have : {jumlahpot(userinventory)[0]}") - print("2. RESILIENSE") - print(f" you have : {jumlahpot(userinventory)[1]}") + print(jumlahPot(userinventory)) + print("1. STRENGTH") + print(f" you have : {jumlahPot(userinventory)[0]}") + print("2. RESILIENCE") + print(f" you have : {jumlahPot(userinventory)[1]}") print("3. HEAL") - print(f" you have : {jumlahpot(userinventory)[2]}") + print(f" you have : {jumlahPot(userinventory)[2]}") print("4. CANCEL") potionchoice = (input("(1/2/3/4)--->")) #jika input tidak benar @@ -118,24 +117,24 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print(f"Opsi {potionchoice} tidak ada") continue #newstat adalah stat baru baik untuk atk/def/hp setelah memakai potion - newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,originalhealth,name,int(potionchoice)) + newstat = potion(jumlahPot(userinventory),indexPot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,100000,name,int(potionchoice)) if potionchoice =='1' : #ATK potion if newstat==0 : #jika potion tidak bisa digunakan continue else : - yourattack = int(newstat) + yourattack = newstat break elif potionchoice =='2' : #DEF potion if newstat==0 : continue else : - yourdefense = int(newstat) + yourdefense = newstat break elif potionchoice =='3' : #Heal potion if newstat==0 : continue else : - yourhealth = int(newstat) + yourhealth = newstat break elif potionchoice =='4' : #Cancel break @@ -185,7 +184,6 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran else : damagetaken += yourhealth #jika monster kita mati setelah serangan yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) - yourhealth = int(yourhealth) if yourhealth >0 : #jika monster kita masih hidup print(f"{name} HEALTH IS DOWN TO {yourhealth}") print("=============================================") From 3be1b3e811521081313db338116071a1daf283f0 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 03:42:30 +0700 Subject: [PATCH 073/115] feat: add input validation and comment in shop function --- src/shopCurrency.py | 122 +++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/src/shopCurrency.py b/src/shopCurrency.py index 7d1b164..1fd6e93 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -1,16 +1,7 @@ -from csvParser import csvRead, csvWriteAll +from monsterManagement import cekint potionID = ["Type", "Healing Potion", "Resilience Potion", "Strength Potion", "Monster Ball"] -'''pathMonsterShop = "data\data1\monster_shop.csv" -monstershop = csvRead(pathMonsterShop) -pathMonsterDatabase = "data\data1\monster.csv" -monsterdata = csvRead(pathMonsterDatabase) -idMonsterShop = [] -for i in range(1,len(monstershop)): - idMonsterShop.append(monstershop[i][0]) -idMonsterData = [] -for i in range(1,len(monsterdata)): - idMonsterData.append(monsterdata[i][0])''' +#FUNGSI UNTUK MENYUSUN LIST POTION SHOP def sortPotion(potionShop): if potionShop[1][0] == "Resilience Potion": potionShop[1][0],potionShop[2][0] = potionShop[2][0],potionShop[1][0] @@ -26,6 +17,7 @@ def sortPotion(potionShop): potionShop[1][0],potionShop[4][0] = potionShop[4][0],potionShop[1][0] return potionShop +#TAMPILAN KASIR def shopInterface(): print(" ▀▄▀▄▀▄ SHOP ▄▀▄▀▄▀ ▂███████▂ _____ ") print(" |__∆|___|_∆_|_|_|∆| ██ █ ██ |$___| ") @@ -37,25 +29,24 @@ def shopInterface(): def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmonsterdata,monsterinventory): yourcoin = coin - if role == "agent": - + if role == "agent": #jika role agent print(" ↤↤↤↤↤ SELAMAT DATANG DI SHOP!!! ↦↦↦↦↦") print() - shopInterface() + shopInterface() #tampilkan kasir print() while True: pilihMenu = input(">>> Pilih aksi (lihat/beli/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") + if pilihMenu.lower() == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/item): ") lihatSelesai = False - while lihat_pilih != "monster" and lihat_pilih != "potion": - lihat_pilih = input(">>> Pilih antara monster/potion: ") - if lihat_pilih == "monster": + while lihat_pilih != "monster" and lihat_pilih != "item": + lihat_pilih = input(">>> Pilih antara monster/item: ") #jika input bukan monster/item + if lihat_pilih.lower() == "monster" : print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") for i in range(1,len(monstershop)): # Menampilkan setiap monster yang tersedia di Shop idMonsterLihat=int(monstershop[i][0]) print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - elif lihat_pilih == "potion": + elif lihat_pilih.lower() == "item": print("ID | Type\t\t| Stok\t| Harga") for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop if potionShop[i][0] == "Healing Potion": @@ -68,66 +59,93 @@ def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmons idPotion = 4 print(f"{idPotion} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") lihatSelesai == True - elif pilihMenu == "beli": + elif pilihMenu.lower() == "beli": print(f"Jumlah O.W.C.A Coin-mu sekarang {yourcoin}.") print() - beliType = input(">>> Mau beli apa? (monster/potion): ") - while beliType != "monster" and beliType != "potion": - beliType = input(">>> Pilih antara monster/potion: ") - if beliType == "monster": + beliType = input(">>> Mau beli apa? (monster/item): ") + while beliType.lower() != "monster" and beliType.lower() != "item": + beliType = input(">>> Pilih antara monster/item: ") #jika input bukan monster/item + if beliType.lower() == "monster": while True: transactionStatus = 0 - idMonsterBeli = int(input(">>> Masukkan id monster: ")) - for i in yourmonsterdata : + idMonsterBeli = (input(">>> Masukkan id monster: ")) + #validasi input + for i in monstershop : + if idMonsterBeli== i[0] : #jika id monster terdapat dishop + break + else : + print("Id monster tersebut tidak tersedia") #jika id tidak ada dishop + continue + idMonsterBeli = int(idMonsterBeli) + for i in yourmonsterdata : #cek jika monster tersebut sudah dimiliki if monsterdata[idMonsterBeli][1] == i[1] : print("Monster sudah dimiliki") break - else : + else : #jika belum for i in monstershop : if i[0]==str(idMonsterBeli) : - if yourcoin >= int(i[2]) : + if yourcoin >= int(i[2]) : #jika coin cukup untuk membeli print("monster berhasil ditambahkan") yourcoin -= int(i[2]) yourmonsterdata.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) monsterinventory.append([userinventory[0][0],monsterdata[idMonsterBeli][1],'1']) monsterShopLocation = 0 - for i in monstershop : + for i in monstershop : #stok berkurang satu (dimasukkan ke list monstershop) if i[0]==str(idMonsterBeli) : monstershop[monsterShopLocation][1] = str(int(monstershop[monsterShopLocation][1])-1) break monsterShopLocation += 1 transactionStatus = 1 break - else : + else : #jika coin tidak cukup print("Maaf O.W.C.A. Coin-mu kurang.") break - if transactionStatus == 1 : + if transactionStatus == 1 : #jika transaski sukses break print() - elif beliType == "potion": - idPotion = int(input(">>> Masukkan id potion: ")) + elif beliType.lower() == "item": while True : - jumlahPotionBeli = int(input(">>> Masukkan jumlah: ")) - if int(potionShop[idPotion][1]) >0 : - if jumlahPotionBeli>int(potionShop[idPotion][1]): - print("Stock tidak cukup") - else : - if yourcoin >= (jumlahPotionBeli * int(potionShop[idPotion][2])): - print(f"Berhasil membeli item: {jumlahPotionBeli} {potionShop[idPotion][0]}. Item sudah masuk ke inventory-mu!") - print() - userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) - print(userinventory) - yourcoin-=(jumlahPotionBeli * int(potionShop[idPotion][2])) - potionShop[idPotion][1]=str(int(potionShop[idPotion][1])-jumlahPotionBeli) - break - else : - print("Maaf O.W.C.A Coin-mu kurang.") + idPotion = (input(">>> Masukkan id item: ")) + #validasi input id + for i in range(1,5) : + if idPotion == str(i) : #jika idinput == 1/2/3/4 + break else : - print("Stock Potion habis!") - break - else: # pilihMenu == "keluar" + print("Id tersebut tidak tersedia") #jika idinput selain 1/2/3/4 + continue + idPotion=int(idPotion) + while True : + jumlahPotionBeli = (input(">>> Masukkan jumlah: ")) + if cekint(jumlahPotionBeli) : #jika input adalah integer + if int(potionShop[idPotion][1]) >0 : #jika stok tersedia + jumlahPotionBeli=int(jumlahPotionBeli) + if jumlahPotionBeli>int(potionShop[idPotion][1]): + print("Stock tidak cukup") #jika jumlah yg dibeli melebihi stok + else : + if yourcoin >= (jumlahPotionBeli * int(potionShop[idPotion][2])): #jika coinmu cukup + print(f"Berhasil membeli item: {jumlahPotionBeli} {potionShop[idPotion][0]}. Item sudah masuk ke inventory-mu!") + print() + userinventory[idPotion-1][2]=str(int(userinventory[idPotion-1][2])+jumlahPotionBeli) + yourcoin-=(jumlahPotionBeli * int(potionShop[idPotion][2])) + #stok berkurang satu + potionShop[idPotion][1]=str(int(potionShop[idPotion][1])-jumlahPotionBeli) + break + else : #jika coinmu kurang + print("Maaf O.W.C.A Coin-mu kurang.") + break + else : #jika stok habis + print("Stock Potion habis!") + break + else : #jika input bukan integer + print("Tolong masukkan integer yang benar") + break + elif pilihMenu.lower()=="keluar": # pilihMenu == "keluar" print(f"Sampai bertemu lagi, User!") return yourcoin + else : + print("Aksi tidak diketahui") + else : + print("anda tidak memiliki akses") def shopmanagement(potionShop,monstershop,monsterdata) : print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") print() From 6922e0670a9ac56f3cadcf9befc0daef117fb276 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 03:52:03 +0700 Subject: [PATCH 074/115] testing --- src/battle.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/battle.py b/src/battle.py index a0ed678..c83f0e2 100644 --- a/src/battle.py +++ b/src/battle.py @@ -113,14 +113,17 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print(f" you have : {jumlahpot(userinventory)[2]}") print("4. CANCEL") potionchoice = (input("(1/2/3/4)--->")) - #jika input tidak benar - if potionchoice!='1' and potionchoice!='2' and potionchoice!='3' and potionchoice!='4' : - print(f"Opsi {potionchoice} tidak ada") + #validasi input + for i in range(1,5) : + if potionchoice==str(i) : #jika input==1/2/3/4 + break + else : + print(f"Opsi {potionchoice} tidak ada") #jika input lainnya continue #newstat adalah stat baru baik untuk atk/def/hp setelah memakai potion newstat = potion(jumlahpot(userinventory),lokasipot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,originalhealth,name,int(potionchoice)) if potionchoice =='1' : #ATK potion - if newstat==0 : #jika potion tidak bisa digunakan + if newstat==0 : #newstat ==0 hanya terjadi jika potion tidak bisa digunakan continue else : yourattack = int(newstat) From edf4898fadc5b57111c2f467ed329249b0dcbec4 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 04:04:25 +0700 Subject: [PATCH 075/115] fix: fix merging error with battle.py --- src/battle.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/battle.py b/src/battle.py index f8bc812..efab39d 100644 --- a/src/battle.py +++ b/src/battle.py @@ -50,12 +50,13 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran indeks+=1 #deklarasi stat variabel - yourattack = int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2]) - yourdefense = int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3]) - yourhealth = int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4]) - enemyhealth = int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4]) - enemyattack = int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2]) - enemydefense = int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3]) + originalhealth = int(int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4])) + yourattack = int(int(file1[indeks][2]) + (int(level)-1)*(10/100)*int(file1[indeks][2])) + yourdefense = int(int(file1[indeks][3]) + (int(level)-1)*(10/100)*int(file1[indeks][3])) + yourhealth = int(int(file1[indeks][4]) + (int(level)-1)*(10/100)*int(file1[indeks][4])) + enemyhealth = int(int(file1[random_number][4]) + (random_level-1)*(10/100)*int(file1[random_number][4])) + enemyattack = int(int(file1[random_number][2]) + (random_level-1)*(10/100)*int(file1[random_number][2])) + enemydefense = int(int(file1[random_number][3]) + (random_level-1)*(10/100)*int(file1[random_number][3])) damagetaken=0 damagedealt=0 @@ -95,6 +96,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran else : #jika enemy mati maka damagedealt hanya ditambah sebesar sisa darah enemy sebelum mati damagedealt += enemyhealth enemyhealth -= (damage-(enemydefense/100)*damage) + enemyhealth = int(enemyhealth) print("=============================================") print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") if enemyhealth > 0 : #JIKA MONSTER BELOM MATI @@ -103,10 +105,9 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran #ACTION POTION while True : print("=======CHOOSE A POTION !=======") - print(jumlahPot(userinventory)) - print("1. STRENGTH") + print("1. STRENGHT") print(f" you have : {jumlahPot(userinventory)[0]}") - print("2. RESILIENCE") + print("2. RESILIENSE") print(f" you have : {jumlahPot(userinventory)[1]}") print("3. HEAL") print(f" you have : {jumlahPot(userinventory)[2]}") @@ -120,24 +121,24 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print(f"Opsi {potionchoice} tidak ada") #jika input lainnya continue #newstat adalah stat baru baik untuk atk/def/hp setelah memakai potion - newstat = potion(jumlahPot(userinventory),indexPot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,100000,name,int(potionchoice)) + newstat = potion(jumlahPot(userinventory),indexPot(userinventory),used_pot,userinventory,yourattack,yourdefense,yourhealth,originalhealth,name,int(potionchoice)) if potionchoice =='1' : #ATK potion if newstat==0 : #newstat ==0 hanya terjadi jika potion tidak bisa digunakan continue else : - yourattack = newstat + yourattack = int(newstat) break elif potionchoice =='2' : #DEF potion if newstat==0 : continue else : - yourdefense = newstat + yourdefense = int(newstat) break elif potionchoice =='3' : #Heal potion if newstat==0 : continue else : - yourhealth = newstat + yourhealth = int(newstat) break elif potionchoice =='4' : #Cancel break @@ -187,6 +188,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran else : damagetaken += yourhealth #jika monster kita mati setelah serangan yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) + yourhealth = int(yourhealth) if yourhealth >0 : #jika monster kita masih hidup print(f"{name} HEALTH IS DOWN TO {yourhealth}") print("=============================================") From f69c167beb97823057b0f07a9d852aebb47299c3 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 04:18:14 +0700 Subject: [PATCH 076/115] feat: add fix reward perstage --- src/arena.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/arena.py b/src/arena.py index f389f3e..4afdda0 100644 --- a/src/arena.py +++ b/src/arena.py @@ -3,6 +3,7 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : #deklarasi variabel + reward = [20,35,50,75,90] #coins gain from defeating each stage coins=0 totaldamageTaken = 0 totaldamageDealt = 0 @@ -29,7 +30,6 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : print(f"--------->>>STAGE {i+1}<<<---------") opening(monsterdata,random_number) coin,damageTaken,damageDealt = battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,random_number,enemylevel,'arena') - coins += coin totaldamageTaken += damageTaken totaldamageDealt += damageDealt @@ -39,9 +39,12 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : else : #monster kita menang stage += 1 - if stage==5 : #jika berhasil sampai ke stage terakhir dan menang akan mendapatkan bonus 50 coin + for i in range(1,stage) : + coins += reward[i-1] + + if stage==6 : #jika berhasil sampai ke stage terakhir dan menang akan mendapatkan bonus 50 coin print("CONGRATULATION YOU MADE IT ALL THE WAY!!!!") - print("HERE A BONUS 50 COINs FOR YOU!!!") + print("HERE A BONUS 50 COINS FOR YOU!!!") coins += 50 #STATISTIK ARENA From ea9c0e021598e0b06d2092b74b9c57f6785c3a53 Mon Sep 17 00:00:00 2001 From: refinormdhn <19623028@std.stei.itb.ac.id> Date: Sun, 19 May 2024 11:52:12 +0700 Subject: [PATCH 077/115] fix : penambahan komen pada fungsi login dan register --- src/load.py | 54 ++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/load.py b/src/load.py index 823a1bd..4e21525 100644 --- a/src/load.py +++ b/src/load.py @@ -25,51 +25,55 @@ def load() : print(f"Folder \"{path}\" tidak ditemukan.") return [] -def login(user,inventory,monsterinventory) : - username = input("username :") - password = input("password :") +def login(user,inventory,monsterinventory) : #fungsi untuk login + username = input("username :") #input username + password = input("password :") #input password for i in user : - if i[1] == username : - if i[2] == password : - if i[3] =='agent' : - player_inventory = [] + if i[1] == username : #pemeriksaan apakah username sesuai + if i[2] == password : #pemeriksaan apakah password sesuai + if i[3] =='agent' : #jika pengguna adalah agent + player_inventory = [] monster_inventory =[] print("login berhasil") - for j in inventory : + for j in inventory : #pengumpulan inventaris barang pengguna if j[0]==i[0] : - player_inventory.append(j) - for j in monsterinventory : + player_inventory.append(j) + for j in monsterinventory : #pengumpulan inventaris monster pengguna if j[0]==i[0] : monster_inventory.append(j) - return player_inventory,monster_inventory,i[3],int(i[4]) + return player_inventory,monster_inventory,i[3],int(i[4]) #mengembalikan data inventaris (barang dan monster) dan role break - elif i[3] =='admin' : + elif i[3] =='admin' : #jika pengguna adalah admin return 1,1,i[3],1 else : - print("password salah") + print("password salah") #jika password salah return 0,0,0,0 break else : - print("username tidak ditemukan") - return 0,0,0,0 + print("username tidak ditemukan") #jika username tidak sesuai + return 0,0,0,0 -def register(user,inventory,monsterinventory,monster) : +def register(user,inventory,monsterinventory,monster) : #fungsi untuk register while True : - usernamebaru = input("Masukkan Username :") + usernamebaru = input("Masukkan Username :") #meminta input username baru dari pengguna + #pemeriksaan apakah username sudah terpakai for i in user : if i[1]== usernamebaru : print("Username sudah terpakai") break else : + #jika username belum terpakai, keluar dari loop break - passwordbaru = input("Masukkan password :") + passwordbaru = input("Masukkan password :") #meminta input password baru dari pengguna + #menampilkan pilihan monster untuk pengguna print('PILIH MONSTER PERTAMA ANDA :') for i in range(3) : print(f"{i+1}. {monster[i+1][1]}") - idpilihan = input("--->") - idbaru = len(user) - monsterinventory.append([str(idbaru),monster[int(idpilihan)][1],'1']) - user.append([str(idbaru),usernamebaru,passwordbaru,'agent','0']) + idpilihan = input("--->") #meminta pengguna untuk memilih monster pertama + idbaru = len(user) #menentukan id baru untuk pengguna + monsterinventory.append([str(idbaru),monster[int(idpilihan)][1],'1']) #menambahkan monster yang telah dipilih kelam monster inventory + user.append([str(idbaru),usernamebaru,passwordbaru,'agent','0']) #menambahkan pengguna baru ke daftar pengguna + #menambahkan item awal ke inventory pengguna baru inventory.append([str(idbaru),'healingpotion','0']) inventory.append([str(idbaru),'respotion','0']) inventory.append([str(idbaru),'strenghpotion','0']) @@ -77,13 +81,15 @@ def register(user,inventory,monsterinventory,monster) : player_inventory = [] monster_inventory =[] print("SELAMAT DATANG AGENT BARU") + #mengumpulkan inventaris barang milik pengguna baru for j in inventory : if j[0]==str(idbaru) : player_inventory.append(j) + #mengumpulkan inventaris monster milik pengguna baru for j in monsterinventory : if j[0]==str(idbaru) : monster_inventory.append(j) - return player_inventory,monster_inventory,'agent',0 + return player_inventory,monster_inventory,'agent',0 #mengembalikan data inventaris (barang dan monster) dan role @@ -114,5 +120,3 @@ def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) write_csv(path+"/monster_inventory.csv",monsterinventory) - - From 16053dd26c01b8e199f0fb15b9e6d6a9fef2b3d3 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 12:27:33 +0700 Subject: [PATCH 078/115] fix & refactor: validate & change variables name --- src/inventory.py | 118 ++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/inventory.py b/src/inventory.py index ffbd482..f1122da 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -1,70 +1,72 @@ -def inventory(userinventory,yourmonsterdata,monsterdata,role,coin) : - if role=='admin': #jika role player adalah admin +def inventory(userInventory, yourMonsData, monsterData, role, coin) : + if role == 'admin': print("Maaf! Anda tidak memiliki akses sebagai admin") else : print(f'jumlah OWCA coin anda saat ini : {coin}') while True : check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Item/Back): ') if check.lower() == 'item' : - number=1 - types=[] #list untuk type dari item yang tersedia - for i in userinventory: - if i[1] == 'Strength Potion' : - type = 'ATK potion' - elif i[1] == 'Resilience Potion' : - type = 'DEF potion' - elif i[1] == 'Healing Potion' : - type = 'HEAL potion' - elif i[1] == 'Monster Ball' : - type = 'MONSTER BALL' - types.append(type) - print(f'{number}. Type: {type}') - number+=1 + number = 1 + itemArray = [] + for i in userInventory: + itemArray.append(i[1]) + print(f'{number}. {i[1]}') + number += 1 + while True : - item_Number = input('Masukkan nomor item untuk menampilkan detail item (1/2/3/Back): ') - #cek apakah input sudah benar (yaitu 1/2/3/4) - if item_Number.lower() != 'back': - for i in range(4) : - if item_Number == str(i+1) : - break #jika output benar - else : #jika output salah - print('Nomor item tersebut tidak tersedia') - continue - item_Number = int(item_Number) - #menampilkan type dan jumlah item - print(f'Type: {types[item_Number-1]}') - print(f'Quantity: {userinventory[item_Number-1][2]}') - else : #jika input = back + itemNumber = input('Masukkan nomor item untuk menampilkan detail item (1/2/3/Back): ') + inputNum = True # validasi input selain 1/2/3/dst/back + for char in monsNumber: + if ord(char) < ord('0') or ord(char) > ord('9'): + inputNum = False + + if inputNum != False : + if itemNumber.lower() != 'back' : + if int(itemNumber) > len(itemArray) : + print('Nomor item tersebut tidak tersedia') # validasi input nomor item yang salah + else : + itemNumber = int(itemNumber) + print(f'Type: {itemArray[itemNumber-1]}') + print(f'Quantity: {userInventory[itemNumber-1][2]}') + elif itemNumber.lower() == 'back' : break + else : + print('Masukkan input yang benar') # validasi input itemNumber yang salah + elif check.lower() == 'monster' : - y = 0 - #menampilkan seluruh monster yang kita punya - for i in yourmonsterdata : - print(f"{y+1}. {i[1]}") - y+=1 + number = 1 + for i in yourMonsData : + print(f"{number}. {i[1]}") + number += 1 + while True : - mons_Number = input('Masukkan nomor monster untuk menampilkan detail monster (1/2/dst/Back): ') - if mons_Number.lower() != 'back' : - #validasi apakah input sudah benar (1,2,3,..len(monsterkita)) - for i in range(len(yourmonsterdata)) : - if mons_Number == str(i+1) : - break #jika input sudah benar - else : #jika input salah - print("Nomor monster tersebut tidak tersedia") - continue - mons_Number=int(mons_Number) - monsterlvl = int(yourmonsterdata[mons_Number-1][2]) - #menampilkan stats dari monster yg dipilih - for i in monsterdata : - if i[1]==yourmonsterdata[mons_Number-1][1] : - print(f'Nama : {i[1]}') - print(f'ATK Power : {int(i[2])+(monsterlvl-1)*(5/100)*(int(i[2]))}') - print(f'DEF Power : {int(i[3])+(monsterlvl-1)*(5/100)*(int(i[3]))}') - print(f'HP : {int(i[4])+(monsterlvl-1)*(5/100)*(int(i[4]))}') - print(f'Level : {monsterlvl}') - else : #jika input == break - break + monsNumber = input('Masukkan nomor monster untuk menampilkan detail monster (1/2/dst/Back): ') + inputNum = True + for char in monsNumber: + if ord(char) < ord('0') or ord(char) > ord('9'): + inputNum = False + + if inputNum != False : + if monsNumber.lower() != 'back': + if int(monsNumber) > len(yourMonsData) or int(monsNumber) < 1: + print('Nomor monster tersebut tidak tersedia') + else : + monsNumber = int(monsNumber) + monsLevel = int(yourMonsData[monsNumber-1][2]) + for i in monsterData : + if i[1] == yourMonsData[monsNumber-1][1] : + print(f'Nama : {i[1]}') + print(f'ATK Power : {int(i[2])+(monsLevel-1)*(5/100)*(int(i[2]))}') + print(f'DEF Power : {int(i[3])+(monsLevel-1)*(5/100)*(int(i[3]))}') + print(f'HP : {int(i[4])+(monsLevel-1)*(5/100)*(int(i[4]))}') + print(f'Level : {monsLevel}') + elif monsNumber.lower() == 'back' : + break + else : + print('Masukkan input yang benar') + elif check.lower() == 'back' : break - else : #jika input salah - print("Jenis item tersebut tidak ada") \ No newline at end of file + + else : + print("Mohon berikan input yang benar") \ No newline at end of file From 57659f7d903cda6f81ee0953deb98b889a9ba160 Mon Sep 17 00:00:00 2001 From: refinormdhn <19623028@std.stei.itb.ac.id> Date: Sun, 19 May 2024 12:31:40 +0700 Subject: [PATCH 079/115] fix : penambahan komen pada fungsi help --- src/help.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/help.py b/src/help.py index bbc1a54..f71df55 100644 --- a/src/help.py +++ b/src/help.py @@ -1,4 +1,5 @@ -def help(status,role) : +def help(status,role) : #jika pengguna belum login, status akan menjadi false dan mengeluarkan beberapa command umum + #command umum if status == False : print("List command yang dapat anda lakukan :") print("1. Login") @@ -9,8 +10,9 @@ def help(status,role) : print(" Menyimpan semua perubahan dalam sebuah folder") print("4. Exit") print(" Keluar dari program") - else : - if role == 'agent' : + else : #jika pengguna sudah login, tampilkan daftar perintah berdasarkan role pengguna + if role == 'agent' : #jika pengguna adalah agent + #command yang dapat dilakukan oleh agent print("List command yang dapat anda lakukan :") print("1. Battle") print(" 1v1 dengan monster random") @@ -26,7 +28,8 @@ def help(status,role) : print(" Tempat untuk menguji keberuntungan anda") print("7. Logout") print(" Keluar dari akun anda") - if role == 'admin' : + if role == 'admin' : #jika pengguna adalah admin + #command yang dapat dilakukan oleh admin print("List command yang dapat anda lakukan :") print("1. Shop") print(" Manage shop") From ef1a79af5b3a171daa6a59c6f2f8ac32ca366855 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 14:18:45 +0700 Subject: [PATCH 080/115] fix:fix a variable error --- src/inventory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inventory.py b/src/inventory.py index f1122da..01ef827 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -16,7 +16,7 @@ def inventory(userInventory, yourMonsData, monsterData, role, coin) : while True : itemNumber = input('Masukkan nomor item untuk menampilkan detail item (1/2/3/Back): ') inputNum = True # validasi input selain 1/2/3/dst/back - for char in monsNumber: + for char in itemNumber: if ord(char) < ord('0') or ord(char) > ord('9'): inputNum = False From 96dff1ed9ef3fe79ee7a54a70ccc1528477890d0 Mon Sep 17 00:00:00 2001 From: refinormdhn <19623028@std.stei.itb.ac.id> Date: Sun, 19 May 2024 14:58:26 +0700 Subject: [PATCH 081/115] feat : monster art --- data/data1/monster_art.csv | 291 +++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 data/data1/monster_art.csv diff --git a/data/data1/monster_art.csv b/data/data1/monster_art.csv new file mode 100644 index 0000000..e558a46 --- /dev/null +++ b/data/data1/monster_art.csv @@ -0,0 +1,291 @@ +1. Godzilla +⠀⠀⠀⠀⣾⠀⠀⠀⣠⣴⣶⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⢀⣀⣤⣴⣧⡀⠀⠿⠿⣿⣿⣿⣿⡄⣠⡄⠀⠀⠀⠀⠀⢠⡶⠀⠀⠀⠀⠀⠀⠀ +⠈⠉⣤⣿⣍⠛⠆⠀⠈⠙⠻⠿⣿⣿⣌⢁⣤⣶⣤⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀ +⢀⢐⡿⠿⢿⣿⣿⣿⣿⣿⣿⣶⣶⢻⣿⣆⠻⣿⠛⠀⠀⢿⣷⡀⠀⠀⠀⠀⠀⠀ +⠉⠟⠀⠀⠀⠀⠀⠉⠉⠛⣛⣛⣣⣿⣿⣿⣧⡰⣿⣿⡆⠈⠻⣿⣶⣀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣷⡘⢫⣤⣄⠀⠙⢿⣿⣷⣄⡀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⠿⠿⢿⣿⣿⣿⣌⠿⠟⠀⠀⠀⠙⢿⣿⣷⡄ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⢟⣵⣿⣿⣿⣎⣿⣿⣿⣦⡸⣿⠂⠀⠀⠈⣿⣿⣷ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⡿⣡⣿⣿⣿⣿⣷⣄⡀⠀⣀⣼⣿⣿⡇ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠫⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⠁⢀⣮⣝⡻⠿⢿⣿⣿⣿⣿⡿⠿⠟⠋⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⠘⠛⠛⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +2. Mimic +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⣀⣀⣤⣤⠀⣉⠑⠀⠠⣤⣤⣤⣤⣤⠀⠀⠚⢉⠀⡀⠀⠀⠀ +⠀⠀⣠⣴⣶⣶⠆⢀⣈⡉⠛⠀⠉⠀⠓⠒⠙⠛⠛⠛⠃⠒⠒⠀⠉⠠⠿⠦⠀⠀ +⠀⣸⣿⣿⡿⠋⣠⡿⠋⠀⢸⣿⠏⢸⣿⣿⠁⢻⣿⠃⠈⢿⡿⠀⣶⣶⠀⣶⡤⠀ +⠀⣿⣿⠟⢁⣼⠟⡁⢾⣧⠀⠋⠀⠈⢿⠇⠀⠀⠃⠀⠀⠘⠁⠀⢸⡟⠀⠙⠁⠀ +⠀⠸⠋⣠⡿⠃⣴⡇⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠁⠀⠀⠀⠀ +⠀⠀⢰⡟⠀⢀⠀⠉⡀⠀⠀⠀⠀⠀⣰⠀⠀⠀⠀⠀⠀⠀⠀⠀⣆⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠰⣿⡄⣴⣇⠀⣰⣇⠀⣰⣿⡇⠀⣴⡄⠀⢰⣆⠀⢰⣿⡄⢠⣷⡀⠀ +⠀⠀⠀⣶⣶⣤⣤⣍⡉⢀⣉⠙⠀⠛⠛⠓⠐⠛⠓⠀⠛⠛⠂⠚⠛⠁⣈⣉⠁⠀ +⠀⠀⠀⣿⣿⣿⣿⣿⠁⣼⣿⣿⣿⣿⣿⡇⢸⣿⠟⣿⡇⢸⣿⣿⣿⣿⣿⣿⠀⠀ +⠀⠀⠀⠸⣿⣿⣿⣿⠀⣿⣿⣿⣿⣿⣿⡇⢸⣿⠄⣿⡇⢸⣿⣿⣿⣿⣿⣿⠀⠀ +⠀⠀⠀⠄⠹⣿⡿⠋⠀⠙⢿⣿⣿⣿⣿⡇⢸⣿⣤⣿⡇⢸⣿⣿⣿⣿⣿⠟⠀⠀ +⠀⠀⠀⠀⠀⠉⠀⠺⠀⣧⡈⢻⣿⣿⣿⣷⣶⣶⣶⣶⣶⣾⣿⣿⣿⡿⠃⣰⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠁⠀⠀⠀⠀ + +3. Makima +⠀⠀⠀⠀⢀⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢂⠨⡆⠀⠀⠹⣧⠀⣀⣀⠀⠀⠀ +⠀⠀⠀⢀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣆⠘⡌⡄⣷⢀⠀⠀⣌⠇⠀⠀⠀⠀⠀ +⠀⠀⠀⠘⠀⠀⠀⢀⠀⠀⢀⣤⣾⢀⢹⡟⣧⣷⣧⢿⠀⢥⣀⢬⣻⡀⠀⠀⠀⠀ +⠀⠀⠀⠀⡀⠀⢠⣯⠀⣀⡾⣿⢿⡿⢺⣏⣽⣛⣷⣸⣴⣌⢗⠲⣽⡇⠀⠀⠀⠀ +⠀⠀⠀⢰⣇⢰⣿⣧⣼⣿⣳⢋⡟⠀⣾⠟⣿⣯⣼⠋⡏⡿⣔⡔⢻⣿⠀⠀⠀⠀ +⠀⠀⠀⢸⣿⣾⣿⣿⣏⣿⣿⡦⠀⠀⠈⠐⠊⠁⢸⠂⡇⠇⢈⡓⣜⠏⠀⠀⠀⠀ +⠀⠀⠀⣀⣿⡇⣻⣏⠟⠛⣿⣏⡄⠀⠀⠀⠀⠀⢸⠨⡇⠀⠀⣴⡟⠀⢀⠀⠀⠀ +⣄⠀⢿⠀⢹⣧⣿⠏⢆⠉⠉⠀⢇⣀⠂⠀⠀⠀⢸⠀⡇⠀⠀⣿⠯⠟⠛⠓⠀⠀ +⠀⠑⠨⢦⠀⡇⣿⠀⠀⠢⡀⠀⠀⠈⢀⣀⠀⠀⢸⣦⣇⠂⠀⢠⣄⡐⠲⠆⠀⠀ +⠀⠀⠀⠀⠀⢀⡿⡆⠀⡄⠎⠂⢄⠀⠉⠁⠀⠀⢸⣿⡇⠀⠀⠘⡐⠙⣄⡀⡀⠀ +⠀⠀⠀⠀⠀⢸⠁⠇⠀⡇⠐⠊⠰⣹⡖⡤⡄⠤⢺⡿⡇⠀⡠⠈⠀⠀⠈⠢⡍⠛ +⠀⠀⠀⠀⠀⢸⢠⠀⠀⠃⠀⠣⡀⣻⣿⠁⢡⠀⢸⡇⠗⠊⠀⠀⠀⠀⠀⣰⡇⠑ +⠀⠀⠀⠀⠀⠀⡘⠀⠀⡇⠀⠀⢰⣵⠇⠀⠙⠢⣼⣽⣢⠀⠀⠀⠀⢀⠼⠁⡇⠀ +⠀⠀⠀⠀⠀⠀⣷⡇⠀⠀⣀⠔⠊⡜⠀⢀⣼⣿⣿⣿⣿⠗⡄⠀⡀⡡⠁⠀⠀⠀ +⠀⠀⠀⠠⠀⠀⣿⣧⡀⠊⢠⠎⡘⢸⢀⡊⣽⣿⣿⣿⣏⠄⡚⠚⠚⠃⠀⠀⠀⠀ + +4. Jalangkung +⠀⠀⠀⠀⠀⢀⣀⠖⠀⠉⠉⡀⠦⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢀⣾⠇⠁⠰⠀⠁⢄⢈⡨⠄⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⢾⠀⠂⢈⠈⠠⠁⣅⡼⢤⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢿⡗⢶⣶⠆⢡⡊⠛⠱⠌⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠈⠺⡆⡤⢊⠩⢀⡀⠊⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠁⠁⢻⢧⣀⣀⢀⢠⣄⣄⢒⠰⡲⠆ +⠀⠀⠀⠀⠀⠀⢀⡀⡀⢤⢭⣾⡮⠃⡘⠛⠊⠊⠀⠂⠂⠀ +⠀⣀⣤⠀⠀⡇⠇⠃⠃⢀⠁⢛⣍⠀⠀⠀⠀⠀⠀⢀⠈⠀ +⠛⠙⢚⠀⠘⠀⡄⠀⠀⠀⠑⠈⣿⠀⠀⠗⠀⠁⠑⠀⠈⡀ +⠀⠀⠈⢇⠀⠀⠃⠂⠄⠊⡀⠀⣿⡇⠄⠀⠀⠃⠀⠀⠀⠁ +⠀⠀⠀⠨⠀⠁⠐⢀⢂⠒⠁⠀⠸⣿⠐⠀⠀⠀⢃⠀⢀⠀ +⠀⠀⠀⠀⢓⠀⠀⠁⠀⠂⠀⠀⢀⣄⢀⡀⡠⠐⠠⠁⠍⠈ +⠀⠀⠀⠀⠀⠂⡤⠄⠀⠳⢁⡘⠐⣟⡇⠀⠈⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠐⠀⠐⠀⠀⠀⠀⠀⠛⢞⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢓⠀⠀⠀⠀⠀⠀⠀ + +5. gigidi +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣷⣿⣶⣦⣄⣀⣀⣠⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠏⠙⠛⠛⠛⠉⠙⠿⡿⣿⣿⣶⣄⡀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠛⠒⠢⡄⠀⠀⠀⠀⠀⠠⣄⠈⠙⢿⣿⣆⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⠆⠀⠀⠀⢹⠀⠀⡤⠒⠒⠲⣄⠱⠀⠀⠹⣿⣆ +⠀⠀⠀⠀⠀⠀⠀⣀⠴⠊⠁⠈⠦⢄⣀⡤⠃⠀⢸⠶⠀⠀⠀⢸⠆⠀⣀⣴⣿⡿ +⠀⠀⠀⠀⢀⡴⠊⠁⠀⠀⠀⠀⢀⡠⠞⠁⢀⣀⠈⠣⢤⣠⠤⠊⠀⠀⣿⣿⡟⠃ +⠀⠀⢀⡔⠁⠀⠀⠀⠀⢀⠖⠊⠉⠀⠀⠀⠀⣸⠂⠀⠀⠀⠀⠀⠀⠀⠫⡯⠀⠀ +⠀⣠⠋⠀⠀⠀⠀⠀⢴⠂⠑⠦⠤⠤⠤⠴⠚⠁⠀⠀⠀⠀⠀⠀⠀⠀⢹⡅⠀⠀ +⢰⠃⠀⠀⠀⠀⠀⠀⠀⠙⢲⠤⢤⣤⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠈⡇⠀⠀ +⡎⠀⠀⠀⠀⠀⠀⠀⠀⠀⣨⠶⣦⣤⣄⣀⣀⣀⣀⣈⠆⠀⠀⠀⠀⠀⠀⡇⠀⠀ +⢇⠀⠀⠀⠀⠀⠀⠀⠀⠘⠦⡀⠀⠉⠛⢿⣛⡿⣻⠟⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀ +⠘⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀ +⠀⠈⢦⡀⠀⠀⠀⠀⠠⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀ +⠀⠀⠀⠑⢄⠀⠀⠀⠀⠀⠈⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠔⠁⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠙⠦⢤⣤⠭⠶⢄⡀⠀⠀⠀⠀⠀⠀⠀⢀⡤⠚⠁⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠲⢤⣀⣠⠤⠔⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +6. Gorlock +⣿⣷⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢼⠰⡇⢾⡇⢽⢺⣷⡄⢸⣷⣤⣽⣷⠻⣿⣶⣞⠿⢿⣿⣶⡤⢦⣶⠶⣶⣶⣴⢦⠙⠥⣷⣄⣉⣡⣴⣷⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⢰⣿⣷⣸⣿⣿⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣆⡹⠤⠶⢖⣹⣿⣿⣿⡿⢿⣿⠛⡄⢩⣦⣼⣯⣿⣾⣿⣧⣛⣚⡟⠙⣛⣷⡟⣿⣾⣿⣿⣿⠿⠿⢿⠉⢋⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠄⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⢗⣯⣭⡭⡙⣅⠹⡇⠄⢻⠀⣇⡼⠋⠈⠉⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣷⣽⣿⣿⣔⠁⠴⠂⣈⡃⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠄⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢽⣿⣿⣿⣿⣿⡿⣾⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡏⢸⠁⣶⡄⡷⢸⣆⠀⢸⣆⣠⠏⠀⠀⠀⠀⠀⠀⠀⠉⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡘⠛⣁⣦⣤⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣷⡈⠦⣩⡴⢖⣹⣿⣶⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⠿⢿⡟⠛⠉⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣭⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣯⣿⣿⣿⣿⣿⣿⣿⣿⣭⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣶⢖⣺⣭⣙⢻⠉⢿⢀⡙⢲⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣥⡴⠄⢡⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠇⡞⢡⣤⢸⡆⣷⠈⠉⠛⢿⣿⡄⢀⣴⣻⣿⣟⣛⠛⠒⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⡶⠚⢩⣆⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣇⠱⣌⣩⡬⢖⡏⠀⠀⠀⣀⠄⠀⠈⠉⠉⠛⠻⠿⠿⠦⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⠿⠟⢻⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣭⣯⣿⣿⣽⣿⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⣿⣿⣯⣿⣿⣽⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣷⡶⢶⣒⣛⡃⠀⠀⡔⠁⢀⣠⣀⣨⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡜⡄⢰⣿⣿⣿⣿⣿⣿⣿⡗⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⢱⠏⣩⣅⣇⣤⣤⣴⢶⣬⢥⣁⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣧⢀⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⠈⡦⠽⣫⡵⣾⣽⣻⣧⢨⠭⠭⠉⠓⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⡿⢿⠟⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣭⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⣿⣿ +⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡿⠛⠑⠛⠲⡌⢳⣿⣷⡿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⢣⠀⣶⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣽⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⢟⡡⠂⠡⢈⢈⣴⣼⣷⣭⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡞⠁⠀⠚⠃⢸⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⠛⣷⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⡿⣷⣄⠁⣖⣦⣿⣿⣿⢿⣿⡵⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣰⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠉⠻⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣇⣯⢸⡇⠲⠤⡀⠀⠀⠀⠀⠀⢿⣭⣟⣻⣿⣿⣿⡟⠉⣠⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠂⣌⣲⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⡇⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡾⣸⠁⠀⠀⠈⠂⠀⠀⠀⠀⠈⢻⠽⠿⠚⠉⢙⣻⣾⠛⠁⠀⠀⠀⠀⠀⠀⠀⠠⠄⣐⣢⣵⣾⣿⡿⣻⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⡇⠀⠀⠀⠀⠀⣀⣸⢛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣿⣿⣿⣿⣿ +⣿⣿⣧⠃⠀⠀⠀⠀⠈⠋⠀⠀⠀⡞⠁⠀⠀⢀⡔⡿⢻⣿⣾⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣽⣿⢳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣨⡤⠴⢶⣛⣯⢷⣞⣯⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠢⠤⣤⣮⣾⠥⢺⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠔⢩⣿⣷⡈⠗⣿⣿⣾⣿⣿⣿⣿⣿⣿⡿⣇⠀⠀⠀⠀⠀⠀⠀⢀⣀⡤⠔⠊⠀⠀⠉⢣⡀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣽⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠋⣽⠋⠠⣾⣿⡿⡟⠀⠀⠀⠀⠄⠀⠀⠀⠀⠀⢀⣾⣿⣿⣧⠠⣿⣿⣿⣿⡿⣿⣿⣿⣿⣧⡟⠀⠀⠀⠀⢀⣤⣴⠚⠉⠁⠀⠀⠀⠀⣀⣨⣷⣞⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⢃⡼⠃⠀⠀⣿⣿⣇⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣿⣦⣿⣷⢻⣿⣿⣭⣿⣿⣿⡟⠁⠀⠀⠀⢰⣿⣟⣻⣷⣄⣀⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣟⣩⣍⣛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⣾⠁⠀⠀⠀⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣿⣿⣿⢻⣿⡿⣿⣿⣿⣟⣿⡏⡇⠀⠀⠀⠀⠘⣿⣶⣯⣽⣾⣿⣿⣿⣿⠿⠿⠟⢛⣿⠇⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣯⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣽⣿⣿⣿ +⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠀⠈⣧⡀⠀⠀⠀⣿⣿⢻⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣘⣿⣿⣿⣿⣿⣿⣿⣷⡇⠀⠀⠀⠀⠀⠈⢻⢧⠿⠟⠛⠉⠹⣿⣆⣀⣰⣿⠋⠀⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿ +⡇⠀⠀⠀⠀⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⣦⣀⣰⣿⣿⣿⠀⢀⡀⢀⡀⠀⠀⠀⠀⠀⠀⣀⡴⢿⣿⣿⣿⣷⡺⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⢠⡇⠀⠀⠀⠀⠀⠀⠈⣿⣿⡏⢀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣀⣀⣤⣠⣔⣈⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢉⣿⣿⣿⣿⣭⠥⠤⠤⣍⣓⣦⣤⣤⣴⠞⠋⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠈⠣⣀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡧⢄⡀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⣿⣿ +⡏⢁⡠⢀⣞⣦⣉⠿⣦⣀⠀⡸⣆⠀⣀⡤⠖⠒⠉⣿⣿⣿⣿⡉⠻⠟⣛⣻⡿⠊⠙⠫⠄⡀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠈⠉⠒⠒⠒⠒⠶⣿⣿⣿⣿⡗⠊⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⡧⡟⣿⠿⣿⠉⣻⡆⢏⣻⣿⣿⣿⡟⠁⠀⠀⠀⠀⢿⣿⣿⡟⠙⠛⠛⠋⠉⠀⠀⠀⠀⠀⠈⠑⠢⢀⡘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⢷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⢿⠇⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣷⢳⣧⠐⣋⣴⠟⠁⠀⢎⢺⣿⡟⠀⠀⠀⠀⠀⠀⢸⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠌⢧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣹⣸⡁⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣧⣉⣻⣟⠁⠀⠀⠀⢎⣲⣿⠁⠀⠀⠀⠀⠀⠀⢸⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡎⡜⡹⣆⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⢿⣿⠇⠀⠀⠀⢠⣿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⠁⠀⠀⠀⠉⠁⢢⠀⠀⢺⢳⣇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⡜⡳⢯⣷⣤⣻⣄⠀⠀⠀⢐⣿⡿⢸⡿⠀⠀⣀⡀⢿⣿⡿⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⠀⠀⠀⠀⠀⢰⡇⠀⠐⢂⣻⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣬⣓⢏⣾⡿⠁⠉⠛⠶⣦⣾⣿⣿⣟⣧⠐⠀⠂⠄⣿⣿⡇⢸⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⡀⠀⣤⢤⣄⠀⠤⠤⠴⠶⣾⣿⡄⠀⠀⠀⠀⠀⠀⢸⣿⣿⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣷⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢉⢻⣿⣿⣎⣖⡇⠀⠀⠀⠀⠀⣿⣿⣿⡿⢿⣦⣬⣴⣾⣿⣿⠇⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⡇⠀⢺⣶⣞⣻⠓⠾⢭⣛⣿⣿⣷⡀⠀⠀⠀⠀⠀⢸⣿⣿⣚⢔⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣧⠈⠢⡘⣿⣿⣿⠀⠀⠀⠀⠀⠀⣿⣿⣿⡇⢹⡇⠐⣺⣿⣿⣿⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⠇⢹⡶⠽⣿⡿⠀⠀⠀⠀⠈⠉⠛⠻⠦⡀⠀⠀⠀⣾⣿⣿⣿⡾⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡿⣿⣿⣿⣿⣿⣿⣿⣷⡻⢦⣁⣱⣿⣿⡟⠀⠀⠀⠀⣴⡿⣿⣿⣿⣀⣄⣿⣜⣿⣿⣿⣇⡞⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⠆⠈⠚⠓⢦⡏⠀⠀⠀⠀⠀⠀⠀⢀⣠⣬⣷⣶⣶⣿⣿⣿⣿⣿⣿⣟⣦⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠙⢿⣿⣿⣿⣿⣿⣿⣷⡬⡙⣿⣿⣿⡇⠀⠀⠀⠈⢿⣇⣿⣿⣿⠛⡉⣿⣿⣿⠿⠛⢉⠂⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⣿⣿⡹⢯⡿⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⣿⡇⠀⢸⣿⣿⣿⣿⣿⣿⡞⢿⢿⣿⣿⣿⡁⠀⣠⡄⠀⠈⢻⣿⣿⣿⣼⣷⡿⣿⡁⡀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⠿⢿⣿⣷⣿⣿⣿⣿⣿⣿⠿⠿⠛⡉⢁⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⣿⣾⣿⣿⣿⣿⣻⣿⠰⣉⣞⣿⣿⡟⠴⣾⣟⣻⡷⢤⡒⢻⣿⣿⠉⢉⡀⠘⣷⠻⣧⠀⠀⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ + +7. Bunny +,\ + \\\,_ + \` ,\ + __,.-" =__) + ." ) + ,_/ , \/\_ + \_| )_-\ \_-` + `-----` `--` + +8. Roga +⠀⠀⠀⠀⠀⢀⠀⠠⠄⡀⠀⠀⠀⠀⠀⠀⠀⠠⢀⢀⣨⣅⣒⡠⡀⠀⠀⠀⠀ +⠀⠀⠀⠠⣢⣴⣶⣶⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣿⢶⣄⡀⠀⠀ +⠀⢀⣪⣾⣿⣿⣿⡋⠀⠀⣀⠀⠀⠀⠀⢸⣠⣤⡄⠀⠘⣿⣿⣿⡄⠹⢎⠄⠀ +⠀⢲⣿⣿⣿⠟⠁⠁⠀⠀⣿⠀⠀⠀⠀⢸⠀⢟⠃⠀⠀⢹⣿⣿⣯⠀⠀⢋⡄ +⠈⣿⡿⠛⠁⠀⠘⠀⠀⠀⢀⠀⣔⠀⠀⢸⣆⠘⢶⠀⠀⢸⣿⣿⣿⠀⠀⣀⢠ +⢸⣟⠀⠀⠀⠀⠀⢂⠀⣀⣙⣵⣻⡇⠀⣼⣿⣗⣉⣀⢀⣾⣿⣿⠟⡂⠅⠒⠁ +⠑⠀⠨⠅⣂⠄⡀⢀⠢⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠙⠻⠏⠃⠁⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠈⠁⡀⠀⠈⢻⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⢁⠀⠀⠀⠀⠀⠀⠀ +⡤⠀⠀⠀⠀⠀⠀⠡⡀⠀⣸⣿⣿⣿⣿⣿⣿⣿⠀⠀⢀⠄⠀⢸⣿⣿⣿⣿⣿ +⠀⠀⠀⠀⠀⠀⠀⠀⠈⡨⠋⠙⢟⠛⠿⠿⡿⠏⠁⡮⡀⠀⠀⠘⠛⠛⠛⠛⣻ +⠀⠀⠀⠀⠀⠀⠀⠀⡐⠀⠀⠀⣾⣧⢀⡰⠀⢰⣿⣿⣷⠀⠀⠀⠀⠀⠀⠱⣿ +⠀⠀⠀⠀⠀⠀⠀⠀⠇⠀⠀⠀⣿⣿⢿⣇⠀⣸⣿⣿⣿⠂⠀⠀⠀⠀⠀⠀⠀ +⣀⣀⣀⡀⠀⠀⠀⠀⠐⢄⣠⣴⡿⢋⠀⡈⠦⣿⣿⣿⠏⠀⠀⠤⣄⣤⣤⠄⠀ + +⣿⣿⣿⡿⠟⣉⣉⡉⠻⠿⠟⠋⠉⠉⠉⠉⠙⠛⢿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⠋⣴⣾⣿⣿⡿⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠦⣭⣙⢿⣿⣿⣿⣿⣿ +⣿⠃⣼⣿⣿⣿⣿⠁⠀⠀⠀⠀⢠⡤⠤⡀⠀⠀⠀⠀⠈⢽⣿⣿⣿⢿⣿⣿⣿ +⣿⢰⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠑⠏⠀⠀⠀⠠⠀⠀⠼⣿⣿⣿⣷⣿⣿⣿ +⣿⢸⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⡩⢼⠡⠀⠀⢹⡛⠿⠿⢟⣵⣿ +⣿⠠⢙⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣬⣭⣿⣯⡄⠀⢸⣿⣶⣶⠿⣷⢿ +⣿⣷⣄⠉⢿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠛⠛⡇⢀⡾⠋⠀⠀⠀⠀⢹ +⣿⣿⣿⣿⣦⣍⣛⠷⣠⡀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠤⡇⣸⠚⠠⡀⠀⠀⢀⣼ +⣿⣿⣿⣿⡿⠿⠛⠉⠡⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣸⣴⣾⣿⣿ +⣿⣿⠟⠁⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣶⣶⣾⣿⣿⣿⣿⣿⣿ +⣿⡏⠀⠀⠀⠀⢤⣶⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣇⢀⣤⡆⣠⣿⣿⡧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿ +⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿ + +9. Molded +⠀⠀⠀⠀⠀⣠⣶⣷⣦⡀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢠⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀ +⠀⠀⠀⣠⣾⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀ +⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀ +⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀ +⢸⣿⣿⡇⣾⣿⣿⣿⣿⣿⡟⠻⣿⣿⡀ +⢸⣿⣿⡇⢻⣿⣿⣿⣿⣿⣿⠀⢹⣿⡇ +⠘⣿⡿⠀⢸⣿⣿⣿⣿⣿⣿⠀⢠⣿⡇ +⢸⣿⣿⠀⣾⣿⣿⣿⣿⣿⣿⠀⢀⣿⡇ +⠈⢿⣿⡀⣿⣿⣿⣿⣿⣿⡏⠀⠈⠀⡇ +⠀⢸⣿⣿⢿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀ +⠀⠸⣿⡇⣼⣿⣿⢹⣿⣿⠀⠀⠀⠀⠀ +⠀⠀⣷⢳⢻⣿⣿⣸⣿⣿⠀⠀⠀⠀⠀ +⠀⠀⠸⠀⠈⣿⡇⣿⣿⣿⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⣿⣷⠙⠛⢿⣷⣦⠀⠀⠀ +⠀⠀⠀⠀⠀⠿⡿⠷⠀⠀⠈⠁⠀⠀⠀ + +10. Mohg +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠂⠰⡀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠒⡂⣒⠤⡀⠀⠀⠀⡠⢒⢙⠍⢒⢴⣅⠀⡠⣄⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⣦⠂⢭⡲⡇⡡⣻⣣⣀⡴⣑⣣⣐⠵⢪⣦⡥⣦⡳⠽⠀⠀⠀⠀⠀ +⠀⡠⡸⠿⡮⡰⣟⣨⣂⣸⣊⡭⣶⡊⠈⡖⣾⡘⢻⣑⢧⡧⣹⢥⡃⠀⠀⠀⠀ +⠀⢃⢲⣊⣹⣴⣙⣬⢿⢗⢻⠮⠀⠓⡚⠎⣶⠜⠻⢳⡯⡾⣯⣁⡆⠀⠀⠀⠀ +⠀⠀⠈⣃⢝⢫⠎⢿⣱⣋⣟⢫⢲⡂⣻⣻⢷⣫⡳⠼⡿⢯⢑⡏⠀⠀⠀⠰⠀ +⠀⠀⠀⠈⠊⠎⣒⣼⠎⣷⡓⢎⡿⡼⢞⣧⣩⣆⡏⠶⢿⠼⠉⠀⠀⠀⠀⠀⠀ +⠳⠀⠀⠀⠀⠀⠉⡛⠯⡑⡷⡿⡑⣓⡞⢭⣴⠇⣀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⢀⠤⡦⠪⢉⡛⢖⠂⣩⠉⠑⢐⠮⡶⢖⠓⠃⠫⢶⠄⡀⠀⠀⠀⠀⠀⠀ +⢀⠐⣊⢀⢠⠜⣐⢊⠁⠈⠀⠀⠈⠚⠑⢩⡫⠀⠀⠀⠀⣁⣱⠃⣂⠀⠀⠀⠀ +⠀⡇⡠⠊⢀⠌⢆⢌⠂⣀⠀⠀⢀⡐⠺⢮⠣⠄⡐⠠⢠⡀⢩⡄⡸⣆⡀⠀⠀ +⠤⠨⠜⠕⠀⠇⠀⢑⠸⢌⠥⢸⣆⠀⠀⠘⢚⡀⠀⠙⡄⣐⣀⠄⠩⠀⠃⠀⡀ +⠢⠠⠀⠀⢂⢁⠂⣂⠡⡒⠌⠍⢨⠒⠈⠙⡹⡋⠑⢆⠚⣂⡅⠉⣀⢈⠄⠀⠀ +⠀⡀⢢⠒⡘⠉⢔⠬⠝⡮⠢⠢⠊⢳⠂⡤⡺⠄⣀⠸⠁⠷⡀⡃⠒⠁⠢⠘⠄ +⠀⠠⢸⠀⠀⠀⠀⠸⠂⣈⣠⠌⢠⣀⠀⡈⡇⠀⢨⢨⠗⠙⢔⢄⠀⡁⣧⡸⠃ +⢀⠔⠁⠀⠀⠀⠀⠘⡭⠀⠙⡀⢫⠉⠡⢙⢫⠌⢡⢫⠀⠀⠀⠑⢥⠉⠀⢀⠄ +⠁⠀⠀⠀⠀⠀⢠⢌⡱⢦⣄⠠⠀⡀⠀⠘⠁⢀⢃⠪⡄⠀⠀⠀⠈⡖⠦⣁⠀ +⠀⠀⠀⠀⠀⠰⣚⣬⡢⡠⠀⠠⠀⠗⣀⡶⡰⡡⢲⠟⡀⠀⠀⠀⠀⠁⠛⠁⠀ +⠀⠀⠀⠀⠀⣆⠁⡒⢿⠊⣰⣆⠧⠀⡘⠂⠁⠀⠵⡫⠈⠆⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢐⢠⢂⠔⡁⡈⠀⢂⠙⠄⡀⠀⠀⠒⢀⠕⡡⠀⡄⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⢀⡫⢂⡂⡑⠐⡆⢹⠀⠓⠀⠀⠁⠀⠈⠀⠄⠀⠀⢐⡀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⣑⣁⠊⡰⠂⠠⠈⣢⢬⡄⠰⡠⠤⠤⠀⠁⣘⠔⠮⢀⠀⠀⠀⠀⠀ +⠀⠀⠀⢨⣦⡊⠈⡀⠀⠀⠀⡦⢒⢼⠄⠀⠀⠀⠀⡜⢀⡐⢢⢈⠀⠀⠀⠀⠀ +⠀⠀⠀⠈⠀⠊⢑⠔⡠⠀⢀⡀⠡⡁⡀⠀⠀⠀⠊⢀⡢⠵⠅⠊⠀⠀⠀⠀⠀ +⠀⠀⠀⢠⠀⠀⣷⠒⠈⢢⡈⣇⠨⠂⢌⡐⡒⠀⠠⠔⠀⢌⠌⣀⠀⠀⠀⠀⠀ +⠀⠀⠀⠈⣛⠀⠁⠀⠀⠠⡃⡟⠀⠐⠐⡁⡁⠑⠀⠀⢠⠃⠐⠀⠀⠀⠀⠀⠀ + +11. Malenia +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠔⠒⠀⠒⢠⡀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠋⠀⣀⠤⠤⠽⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠁⢠⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠀⢙⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⡄ +⠀⠀⠀⠀⠀⠀⠀⢀⠖⠁⠀⠀⠀⠉⠢⢄⠀⠀⠀⠀⠀⠀⡗⠃⢰ +⠀⠀⠀⢀⡢⠀⡰⠁⣀⡀⠀⠀⠀⠀⠀⠀⠑⢄⠀⠀⠀⠀⠇⠀⢸ +⢀⠆⢰⣦⡀⢰⠁⣾⣿⣿⠀⠀⠀⠀⠀⠀⠀⠈⢢⣀⡀⠜⠀⢠⠃ +⠈⠈⠈⢿⣿⣼⡀⠉⠉⠁⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⢀⡠⠔⠁⠀ +⠀⠀⠀⠈⢿⣿⣷⣄⠀⠀⠀⠀⣿⣿⣿⠀⠀⡠⠊⠉⠁⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⣿⡏⣷⠛⠢⣀⡀⠙⠛⣁⠤⠊⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⢀⣏⣿⠇⢸⠀⠈⡇⢹⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⢸⣻⣿⡇⠘⡇⠀⢣⢸⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⢀⣿⣾⣿⣷⡀⢹⠀⢸⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⢠⡿⠟⣿⣿⣿⣷⣄⣣⡠⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠁⠀⠀⠛⢿⣿⢿⣿⡟⢷⣽⠧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +12. Kraken +⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣶⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⣠⡤⣤⣄⣾⣿⣿⣿⣿⣿⣿⣷⣠⣀⣄⡀⠀⠀⠀⠀ +⠀⠀⠀⠀⠙⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣬⡿⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⢀⣼⠟⢿⣿⣿⣿⣿⣿⣿⡿⠘⣷⣄⠀⠀⠀⠀⠀ +⣰⠛⠛⣿⢠⣿⠋⠀⠀⢹⠻⣿⣿⡿⢻⠁⠀⠈⢿⣦⠀⠀⠀⠀ +⢈⣵⡾⠋⣿⣯⠀⠀⢀⣼⣷⣿⣿⣶⣷⡀⠀⠀⢸⣿⣀⣀⠀⠀ +⢾⣿⣀⠀⠘⠻⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⠿⣿⡁⠀⠀⠀ +⠈⠙⠛⠿⠿⠿⢿⣿⡿⣿⣿⡿⢿⣿⣿⣿⣷⣄⠀⠘⢷⣆⠀⠀ +⠀⠀⠀⠀⠀⢠⣿⠏⠀⣿⡏⠀⣼⣿⠛⢿⣿⣿⣆⠀⠀⣿⡇⡀ +⠀⠀⠀⠀⢀⣾⡟⠀⠀⣿⣇⠀⢿⣿⡀⠈⣿⡌⠻⠷⠾⠿⣻⠁ +⠀⠀⣠⣶⠟⠫⣤⠀⠀⢸⣿⠀⣸⣿⢇⡤⢼⣧⠀⠀⠀⢀⣿⠀ +⠀⣾⡏⠀⡀⣠⡟⠀⠀⢀⣿⣾⠟⠁⣿⡄⠀⠻⣷⣤⣤⡾⠋⠀ +⠀⠙⠷⠾⠁⠻⣧⣀⣤⣾⣿⠋⠀⠀⢸⣧⠀⠀⠀⠉⠁⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠈⠉⠉⠹⣿⣄⠀⠀⣸⡿⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠛⠿⠟⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀ + +13. Mothra +⠈⠱⣶⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⢾⣿⣿⣷⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⣼⣏⢭⡛⢿⣿⠲⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⣤⠴⠂ +⠀⢠⣿⣷⢵⢶⡾⠇⢹⣷⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⢞⡿⣟⣻⠋⠀⠀ +⠀⣸⡟⠈⢠⠀⣳⠂⡞⢣⡼⡶⡀⠀⠀⠀⠀⠀⣀⡴⣻⠋⣻⢶⣾⢏⠀⠀⠀ +⠀⠘⣿⣶⣾⣛⠛⠀⣶⣟⢞⡸⠸⡆⣰⣶⢆⡾⢃⡇⠇⠞⠃⠀⢻⡇⠀⠀⠀ +⠀⠀⠘⠻⠿⠿⠖⠐⠛⡻⢇⢦⣾⡷⢅⣯⣟⣼⢾⣃⣀⣶⣿⡔⠞⠁⠀⠀⠀ +⠀⠀⠀⠀⠀⡀⡤⣆⡡⢴⣲⣚⡏⣟⣭⡻⣽⣰⢦⡀⠉⠉⠉⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢠⣷⣿⣵⣫⣾⡿⠣⡝⢽⡎⣱⡞⣞⣻⣾⡆⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠘⠽⢿⠿⠿⠟⠁⠀⠅⣿⠁⠻⣿⣿⣿⠿⡇⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠂⠀⠀⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⡄ + +14. Parkinson +⠀⢀⣴⡾⢿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠈⢻⣧⡀⠙⣿⡆⠀⠀⡐⠉⠢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⣼⠟⣡⣾⠟⠁⠀⠀⢃⠀⠀⠇⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⣼⡏⣼⠋⠀⠀⠀⢀⣀⡈⢢⡔⠀⣠⠞⠉⠙⢿⣷⡀⠀⠀⠀⠀⠀⠀⠀ +⢠⣿⠀⢿⣦⣤⣤⣶⡟⣿⣿⣿⣿⣾⣅⠀⠀⠀⢸⣿⠃⠀⠀⠀⠀⠀⠀⠀ +⠘⣿⣆⠈⠙⠛⠛⠋⣸⣿⣿⣿⣿⣿⣿⠀⠀⠀⣸⡏⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠙⠿⣧⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⣿⠀⠀⢠⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠙⡇⠀⣿⣿⢻⣿⣿⣿⣿⣿⣿⠀⢀⣾⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⡇⠀⣿⣏⢸⣿⣿⣿⣿⣿⣿⠀⣸⡏⠀⠀⠀⠀⢀⣠⣴⣦⡄⠀ +⠀⠀⠛⠚⠀⠀⢿⣿⠈⢹⣿⣿⣿⣿⡇⠀⣿⡇⠀⠀⢀⣴⡿⠋⢉⣿⡿⠀ +⠀⠀⠀⠀⠀⠀⠘⣿⡄⠈⣿⣿⣿⣿⡇⠀⣿⣿⣦⣶⡿⠋⣠⣴⠟⠋⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⢻⣇⠀⣿⣿⣿⣿⣇⠀⠘⠛⠛⢉⣴⣾⣯⣤⣤⣄⠀⠀ +⠀⠀⠀⠀⠀⢸⠀⠈⣿⡀⣿⣿⣿⢻⣿⡀⠀⣠⣾⣿⣿⡿⠋⠉⠙⢿⣧⠀ +⠀⠀⠀⠀⠀⣸⠀⠀⢸⣇⣿⣿⣿⠈⠻⢿⣾⣿⣿⡿⠃⠠⢢⣰⠀⢈⣿⡆ +⠀⠀⠀⠀⡼⠃⠀⠀⠘⣿⢹⣿⡇⠀⢀⣿⣿⡏⢹⠀⠀⢤⠈⠉⠀⣸⣿⠇ +⠀⠀⢀⡾⠁⠀⠀⠀⢠⣿⢸⣿⠃⠀⢸⣿⡿⠀⢸⡄⠀⠈⢷⣶⣾⣿⡿⠀ +⠀⠀⣼⣧⠀⠀⠀⠀⣸⣿⢸⣿⠀⠀⢻⣿⣇⠀⣸⡇⠀⠀⠀⠉⠛⠋⠀⠀ +⠀⠀⣿⣿⣦⣤⣠⣾⣿⡏⠸⣿⡀⠀⠘⣿⣿⣶⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠘⠻⣿⣿⣿⣿⡟⠀⠀⠻⠁⠀⠀⠈⠛⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀ + +15. Ifrit + , ,, , + | || | ,/ _____ \. + \_||_/ ||_/ \_|| + || \_| . . |_/ + || | L | + ,|| |`==='| + |>| ___`> -<'___ + |>|\ / \ + \>| \ / , . . | + || \/ /| . | . | | + ||\ ` / | ___|___ | | ( + (( || `--' | _______ | | )) ( +( )\|| ( )\ | - --- - | -| ( ( \ )) +(\/ || ))/ ( | -- - -- | | )) ) \(( + ( ()||((( ())| | |( (( () ) \ No newline at end of file From 2718b59dfb44ac69f0cbed5af3e40f13bf15199f Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 16:00:01 +0700 Subject: [PATCH 082/115] feat: add validation and comment to shopmanagement --- src/shopCurrency.py | 368 ++++++++++++++++++++++++++------------------ 1 file changed, 222 insertions(+), 146 deletions(-) diff --git a/src/shopCurrency.py b/src/shopCurrency.py index 1fd6e93..90381c6 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -1,21 +1,5 @@ from monsterManagement import cekint -potionID = ["Type", "Healing Potion", "Resilience Potion", "Strength Potion", "Monster Ball"] - -#FUNGSI UNTUK MENYUSUN LIST POTION SHOP -def sortPotion(potionShop): - if potionShop[1][0] == "Resilience Potion": - potionShop[1][0],potionShop[2][0] = potionShop[2][0],potionShop[1][0] - if potionShop[3][0] == "Resilience Potion": - potionShop[3][0],potionShop[2][0] = potionShop[2][0],potionShop[3][0] - if potionShop[4][0] == "Resilience Potion": - potionShop[4][0],potionShop[2][0] = potionShop[2][0],potionShop[4][0] - if potionShop[1][0] == "Strength Potion": - potionShop[1][0],potionShop[3][0] = potionShop[3][0],potionShop[1][0] - if potionShop[4][0] == "Strength Potion": - potionShop[4][0],potionShop[3][0] = potionShop[3][0],potionShop[4][0] - if potionShop[1][0] == "Monster Ball": - potionShop[1][0],potionShop[4][0] = potionShop[4][0],potionShop[1][0] - return potionShop +itemID = ["Type", "Healing Potion", "Resilience Potion", "Strength Potion", "Monster Ball"] #TAMPILAN KASIR def shopInterface(): @@ -149,20 +133,20 @@ def shopOpen(role,potionShop,coin,userinventory,monsterdata,monstershop,yourmons def shopmanagement(potionShop,monstershop,monsterdata) : print(" ↤↤↤↤ SELAMAT DATANG KEMBALI ADMIN! ↦↦↦↦") print() - shopInterface() + shopInterface() #tampilkan kasir print() while True: pilihMenu = input(">>> Pilih aksi (lihat/tambah/ubah/hapus/keluar): ") - if pilihMenu == "lihat": - lihat_pilih = input(">>> Mau lihat apa? (monster/potion): ") - while lihat_pilih != "monster" and lihat_pilih != "potion": - lihat_pilih = input(">>> Pilih antara monster/potion: ") + if pilihMenu.lower() == "lihat": + lihat_pilih = input(">>> Mau lihat apa? (monster/item): ") + while lihat_pilih != "monster" and lihat_pilih != "item": + lihat_pilih = input(">>> Pilih antara monster/item: ") #jika input bukan monster/item if lihat_pilih == "monster": print("ID | Type\t| ATK Power\t| DEF Power\t| HP\t| Stok\t| Harga") for i in range(1,len(monstershop)): # Menampilkan setiap monster yang tersedia di Shop idMonsterLihat=int(monstershop[i][0]) print(f"{monsterdata[idMonsterLihat][0]} | {monsterdata[idMonsterLihat][1]}\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t| {monstershop[i][1]}\t| {monstershop[i][2]}") - elif lihat_pilih == "potion": + elif lihat_pilih == "item": print("ID | Type\t\t| Stok\t| Harga") for i in range(1,len(potionShop)): # Menampilkan setiap potion yang tersedia di Shop if potionShop[i][0] == "Healing Potion": @@ -175,16 +159,16 @@ def shopmanagement(potionShop,monstershop,monsterdata) : idPotion = 4 print(f"{idPotion} | {potionShop[i][0]}\t| {potionShop[i][1]}\t| {potionShop[i][2]}") - elif pilihMenu == "tambah": + elif pilihMenu.lower() == "tambah": idMonsterShop = [] for i in range(1,len(monstershop)): - idMonsterShop.append(monstershop[i][0]) + idMonsterShop.append(monstershop[i][0]) #membuat list yg berisi semua id monster yg terdapat dishop idMonsterData = [] for i in range(1,len(monsterdata)): - idMonsterData.append(monsterdata[i][0]) - tambah_pilih = input("Mau tambah apa? (monster/potion): ") - while tambah_pilih != "monster" and tambah_pilih != "potion": - tambah_pilih = (input(">>> Pilih antara monster/potion: ")) + idMonsterData.append(monsterdata[i][0]) #membuat list yg berisi semua id monster yg terdapat dimonster data + tambah_pilih = input("Mau tambah apa? (monster/item): ") + while tambah_pilih != "monster" and tambah_pilih != "item": + tambah_pilih = (input(">>> Pilih antara monster/item: ")) if tambah_pilih == "monster": print("ID | Type\t\t| ATK Power\t| DEF Power\t| HP\t|") for i in range(1,len(monsterdata)): # Menampilkan setiap monster yang tersedia di Shop @@ -195,149 +179,241 @@ def shopmanagement(potionShop,monstershop,monsterdata) : print(f"{i} | {monsterdata[idMonsterLihat][1]}\t\t| {monsterdata[idMonsterLihat][2]}\t\t| {monsterdata[idMonsterLihat][3]}\t\t| {monsterdata[idMonsterLihat][4]}\t|") print() idMonsterTambah = input(">>> Masukkan id monster: ") + #validasi kevalidan id while idMonsterTambah in idMonsterShop or idMonsterTambah not in idMonsterData: - if idMonsterTambah not in idMonsterData: + if idMonsterTambah not in idMonsterData: #jika id tidak ada pada data print("ID tidak valid! Pilih ID yang terdapat pada tabel!") idMonsterTambah = (input(">>> Masukkan id monster: ")) - elif idMonsterTambah in idMonsterShop: + elif idMonsterTambah in idMonsterShop: #jika id sudah ada dishop print("Monster sudah ada di Shop!") idMonsterTambah = (input(">>> Masukkan id monster: ")) - stokMonsterTambah = int(input(">>> Masukkan stok awal: ")) - hargaMonsterTambah = int(input(">>> Masukkan harga: ")) + stokMonsterTambah = (input(">>> Masukkan stok awal: ")) + while cekint(stokMonsterTambah) == False : #validasi integer + print("masukkan integer yg benar") + stokMonsterTambah = (input("Masukkan stok awal: ")) + hargaMonsterTambah = (input(">>> Masukkan harga: ")) + while cekint(hargaMonsterTambah) == False : #validasi integer + print("masukkan integer yg benar") + hargaMonsterTambah = (input("Masukkan harga : ")) addMonsterShop = [idMonsterTambah,str(stokMonsterTambah),str(hargaMonsterTambah)] monstershop.append(addMonsterShop) print(f"{monsterdata[int(idMonsterTambah)][1]} telah berhasil ditambahkan ke dalam Shop!") - elif tambah_pilih == "potion": + elif tambah_pilih == "item": + if len(potionShop)!=5 : #jika itemshop tidak keisi semua + print("ID | Type") potionFound = False countFalse = 0 - print("ID | Type") - for i in range(1,4): + for i in range(1,5): for j in range(1,len(potionShop)): - if potionID[i] in potionShop[j][0]: + if itemID[i] in potionShop[j][0]: potionFound = True break else: potionFound = False continue if potionFound == False: - print(f"{i} | {potionID[i]}") + print(f"{i} | {itemID[i]}") #menampilkan seluruh item yg tidak ada dishop countFalse += 1 - if countFalse == 0: - print("Semua Potion sudah tersedia pada Shop!") + if countFalse == 0: + print("Semua Item sudah tersedia pada Shop!") print() else: - idPotionTambah = int(input(">>> Masukkan id potion (1-4): ")) - while (idPotionTambah < 1 or idPotionTambah > 4): - print("id tidak valid!") - idPotionTambah = int(input(">>> Masukkan id potion (1-4): ")) - stokPotionTambah = int(input("Masukkan stok awal: ")) - hargaPotionTambah = int(input("Masukkan harga: ")) - newPotion = [potionID[idPotionTambah],str(stokPotionTambah),str(hargaPotionTambah)] + while True : + iditemTambah = (input(">>> Masukkan id item (1-4): ")) + #validasi integer + if cekint(iditemTambah) == False : + print("Masukkan integer yang benar") + continue + #validasi jika id<1 atau>4 + if (int(iditemTambah) < 1 or int(iditemTambah) > 4): + print("id tidak valid!") + continue + sudahadadishop = True + #validasi jika id sudah ada dishop + for i in potionShop : + if itemID[int(iditemTambah)]==i[0] : + print("Item sudah terdapat di shop") + break + else : + sudahadadishop =False + if sudahadadishop == True : + continue + break + stokPotionTambah = (input("Masukkan stok awal: ")) + #validasi integer + while cekint(stokPotionTambah) == False : + print("masukkan integer yg benar") + stokPotionTambah = (input("Masukkan stok awal: ")) + hargaPotionTambah = (input("Masukkan harga: ")) + #validasi integer + while cekint(hargaPotionTambah) == False : + print("masukkan integer yg benar") + hargaPotionTambah = (input("Masukkan harga :")) + newPotion = [itemID[int(iditemTambah)],str(stokPotionTambah),str(hargaPotionTambah)] potionShop.append(newPotion) - sortPotion(potionShop) - print(f"{potionID[idPotionTambah]} telah berhasil ditambahkan ke dalam Shop!") + print(f"{itemID[int(iditemTambah)]} telah berhasil ditambahkan ke dalam Shop!") print() - elif pilihMenu == "ubah": - ubah_pilih = input("Mau ubah apa? (monster/potion): ") - while ubah_pilih != "monster" and ubah_pilih != "potion": - ubah_pilih = (input(">>> Pilih antara monster/potion: ")) + elif pilihMenu.lower() == "ubah": + ubah_pilih = input("Mau ubah apa? (monster/item): ") + while ubah_pilih != "monster" and ubah_pilih != "item": + ubah_pilih = (input(">>> Pilih antara monster/item: ")) if ubah_pilih == "monster": - idMonsterUbah = (input(">>> Masukkan id monster: ")) # Nanti nambahin validasi - stokMonsterBaru = (input(">>> Masukkan stok baru: ")) - hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) - pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " - if (stokMonsterBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {int(stokMonsterBaru)}" - for i in range(len(monstershop)) : - if monstershop[i][0]==(idMonsterUbah) : - monstershop[i][1]=str(stokMonsterBaru) - if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): - pesanUbah += " dan " - if (hargaMonsterBaru != ""): - pesanUbah += f"dengan harga baru {int(hargaMonsterBaru)}" - for i in range(len(monstershop)) : - if monstershop[i][0]==(idMonsterUbah) : - monstershop[i][2]=str(hargaMonsterBaru) - pesanUbah += "!" - print(pesanUbah) - elif ubah_pilih == "potion": - idPotionUbah = int((input(">>> Masukkan id potion: "))) - while idPotionUbah < 1 or idPotionUbah > 4: - print("ID tidak valid!") - idPotionUbah = int((input(">>> Masukkan id potion: "))) - stokPotionBaru = int((input(">>> Masukkan stok baru: "))) - hargaPotionBaru = int((input(">>> Masukkan harga baru: "))) - pesanUbah = f"{potionID[int(idPotionUbah)]} telah berhasil diubah " - if (stokPotionBaru != ""): - pesanUbah += f"dengan stok baru sejumlah {stokPotionBaru}" - if (stokPotionBaru != "") and (hargaPotionBaru != ""): - pesanUbah += " dan " - if (hargaPotionBaru != ""): - pesanUbah += f"dengan harga baru {hargaPotionBaru}" - pesanUbah += "!" - for i in range(1,len(potionShop)): - if potionShop[i][0] == potionID[idPotionUbah]: - potionShop[i] = [potionID[idPotionUbah],stokPotionBaru,hargaPotionBaru] - else: + while True : + idMonsterUbah = (input(">>> Masukkan id monster: ")) + #validasi apakah id terdapat dishop + for i in monstershop : + if idMonsterUbah== i[0] : + break + else : + print('ID tersebut tidak tersedia') continue - print(pesanUbah) - print() + stokMonsterBaru = (input(">>> Masukkan stok baru: ")) + #validasi integer + while cekint(stokMonsterBaru)== False and stokMonsterBaru!="" : + print("Masukkan integer yg benar") + stokMonsterBaru = input('Masukkan stok baru:') + hargaMonsterBaru = (input(">>> Masukkan harga baru: ")) + #validasi integer + while cekint(hargaMonsterBaru)== False and hargaMonsterBaru!="" : + print("Masukkan integer yg benar") + hargaMonsterBaru = input('Masukkan stok baru:') + pesanUbah = f"{monsterdata[int(idMonsterUbah)][1]} telah berhasil diubah " + if (stokMonsterBaru != ""): #jika stok berubah + pesanUbah += f"dengan stok baru sejumlah {int(stokMonsterBaru)}" + for i in range(len(monstershop)) : + if monstershop[i][0]==(idMonsterUbah) : + monstershop[i][1]=str(stokMonsterBaru) + if (stokMonsterBaru != "") and (hargaMonsterBaru != ""): + pesanUbah += " dan " + if (hargaMonsterBaru != ""): #jika harga berubah + pesanUbah += f"dengan harga baru {int(hargaMonsterBaru)}" + for i in range(len(monstershop)) : + if monstershop[i][0]==(idMonsterUbah) : + monstershop[i][2]=str(hargaMonsterBaru) + pesanUbah += "!" + print(pesanUbah) + break + elif ubah_pilih == "item": + while True : + iditemUbah = input(">>> Masukkan id item: ") + #validasi integer + if cekint(iditemUbah)==False : + print("Masukkan integer yang benar") + continue + #validasi apakah id <1 atau >4 + if int(iditemUbah) > 4 or int(iditemUbah) < 1 : + print("Id tersebut tidak tersedia") + continue + #validasi apakah id tersebut terdapat dishop atau tidak + for i in potionShop: + if itemID[int(iditemUbah)]==i[0] : + break + else : + print("Id tersebut tidak tersedia") + continue + stokitemBaru = ((input(">>> Masukkan stok baru: "))) + #validasi integer + while cekint(stokitemBaru)== False and stokitemBaru!="": + print("Masukkan integer yg benar") + stokitemBaru = input('Masukkan stok baru:') + hargaitemBaru = ((input(">>> Masukkan harga baru: "))) + #validasi integer + while cekint(hargaitemBaru)== False and hargaitemBaru!="": + print("Masukkan integer yg benar") + hargaitemBaru = input('Masukkan harga baru:') + pesanUbah = f"{itemID[int(iditemUbah)]} telah berhasil diubah " + if (stokitemBaru != ""): #jika stok berubah + for i in range(len(potionShop)) : + if potionShop[i][0] == itemID[int(iditemUbah)] : + potionShop[i][1]=str(stokitemBaru) + pesanUbah += f"dengan stok baru sejumlah {stokitemBaru}" + if (stokitemBaru != "") and (hargaitemBaru != ""): + pesanUbah += " dan " + if (hargaitemBaru != ""): #jika harga berubah + for i in range(len(potionShop)) : + if potionShop[i][0] == itemID[int(iditemUbah)] : + potionShop[i][2]=str(hargaitemBaru) + pesanUbah += f"dengan harga baru {hargaitemBaru}" + pesanUbah += "!" + print(pesanUbah) + break - elif pilihMenu == "hapus": - hapusPilih = input(">>> Mau hapus apa? (monster/potion): ") - while hapusPilih != "monster" and hapusPilih != "potion": - hapusPilih = (input(">>> Pilih antara monster/potion: ")) - if hapusPilih == "monster": - idMonsterHapus = int(input(">>> Masukkan id monster: ")) - idMonsterShop = [] - for i in range(1,len(monstershop)): - idMonsterShop.append(monstershop[i][0]) - idMonsterData = [] - for i in range(1,len(monsterdata)): - idMonsterData.append(monsterdata[i][0]) - if str(idMonsterHapus) not in idMonsterShop: - print("Monster dengan ID tersebut tidak ada pada Shop!") - idMonsterHapus = int(input(">>> Masukkan id monster: ")) - - yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[idMonsterHapus][1]} dari Shop (y/n)? ") - if yakinHapus == "y": - newMonsterList = [['monster_id','stock','price']] - for i in range(1,len(monstershop)): - if monstershop[i][0] == str(idMonsterHapus): - continue - else: - newMonsterList.append(monstershop[i]) - monstershop = newMonsterList - print(f"{monsterdata[idMonsterHapus][1]} telah berhasil dihapus dari Shop!") - else: - print("Penghapusan dibatalkan!") - print() - continue - elif hapusPilih == "potion": - idPotionHapus = int(input(">>> Masukkan id potion: ")) - yakinHapus = input(f"Apakah anda yakin ingin menghapus {potionID[idPotionHapus]} dari Shop (y/n)? ") - if yakinHapus == "y": - print(potionShop) - newPotionList = [] - for i in range(len(potionShop)): - if potionShop[i][0] == potionID[idPotionHapus]: - continue - else: - newPotionList.append(potionShop[i]) - print(newPotionList) - potionShop = newPotionList - print(potionShop) - print(f"{potionID[int(idPotionHapus)]} telah berhasil dihapus dari Shop!") - print() - else: - print("Penghapusan dibatalkan!") - print() - continue + elif pilihMenu.lower() == "hapus": + hapusPilih = input(">>> Mau hapus apa? (monster/item): ") + while hapusPilih != "monster" and hapusPilih != "item": + hapusPilih = (input(">>> Pilih antara monster/item: ")) + if hapusPilih.lower() == "monster": + while True : + idMonsterHapus = (input(">>> Masukkan id monster: ")) + #validasi apakah id tersebut terdapat dishop atau tidak + for i in monstershop : + if idMonsterHapus == i[0] : + break + else : + print("Id tersebut tidak tersedia") + continue + idMonsterHapus=int(idMonsterHapus) + while True : + yakinHapus = input(f"Apakah anda yakin ingin menghapus {monsterdata[idMonsterHapus][1]} dari Shop (y/n)? ") + if yakinHapus.lower() == "y": #double check apakah benar ingin dihapus + newMonsterList = [['monster_id','stock','price']] + for i in range(1,len(monstershop)): + if monstershop[i][0] == str(idMonsterHapus): + continue + else: + newMonsterList.append(monstershop[i]) + monstershop = newMonsterList + print(f"{monsterdata[idMonsterHapus][1]} telah berhasil dihapus dari Shop!") + break + elif yakinHapus.lower() =='n': + print("Penghapusan dibatalkan!") + print() + break + else : + print("Masukkan Y/N") + break + elif hapusPilih.lower() == "item": + while True : + iditemHapus = (input(">>> Masukkan id item: ")) + #validasi integer + if cekint(iditemHapus)==False : + print("Masukkan integer yang benar") + continue + #validasi apakah >4 atau <1 + if int(iditemHapus) > 4 or int(iditemHapus) < 1 : + print("Id tersebut tidak tersedia") + continue + #validasi apakah id item terdapat dishop atau tidak + for i in potionShop: + if itemID[int(iditemHapus)]==i[0] : + break + else : + print("Id tersebut tidak tersedia") + continue + while True : + yakinHapus = input(f"Apakah anda yakin ingin menghapus {itemID[int(iditemHapus)]} dari Shop (y/n)? ") + if yakinHapus.lower() == "y": #double cek apakah ingin dihapus + newitemList = [] + for i in range(len(potionShop)): + if potionShop[i][0] == itemID[int(iditemHapus)]: + continue + else: + newitemList.append(potionShop[i]) + potionShop = newitemList + print(f"{itemID[int(iditemHapus)]} telah berhasil dihapus dari Shop!") + print() + break + elif yakinHapus.lower() =='n': + print("Penghapusan dibatalkan!") + print() + break + else : + print("masukkan (Y/N)") + break - else: # pilihMenu == "keluar" + elif pilihMenu.lower() == 'keluar': # pilihMenu == "keluar" print("Sampai bertemu lagi Admin!") return monstershop,potionShop - -# shopOpen("agent") -# shopOpen("admin") \ No newline at end of file + else : #jika aksi bukan tambah hapus ubah lihat dan keluar + print("aski tidak diketahui") \ No newline at end of file From 62da694b6db4540c89ec95658afa35c7f76a80f4 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 16:05:14 +0700 Subject: [PATCH 083/115] remove unnecessary lines --- src/monsterManagement.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 560bc8d..7ad01ae 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -1,7 +1,3 @@ -'''from csvParser import * -pathFileMonster = r"data\data1\monster.csv" -listMonster = csvReadInt(pathFileMonster)''' - # FUNGSI UNTUK PENAMBAHAN MONSTER # Fungsi - fungsi proses untuk mengecek validasi input data monster def cekint(input): @@ -203,7 +199,4 @@ def monsterManagement(listMonster): print("Teirma kasih telah mengunjungi database monster") break else : - print("Input tidak valid, input yang diterima hanya 0/1/2") - -# PENERAPAN FUNGSI -# monsterManagement() \ No newline at end of file + print("Input tidak valid, input yang diterima hanya 0/1/2") \ No newline at end of file From 7602497859f6c2188ed4ded133dcf649c9c236e9 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 16:12:27 +0700 Subject: [PATCH 084/115] remove unnecessary condition --- src/inventory.py | 3 --- src/laboratory.py | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/inventory.py b/src/inventory.py index 01ef827..597ddf4 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -1,7 +1,4 @@ def inventory(userInventory, yourMonsData, monsterData, role, coin) : - if role == 'admin': - print("Maaf! Anda tidak memiliki akses sebagai admin") - else : print(f'jumlah OWCA coin anda saat ini : {coin}') while True : check = input('Silakan pilih jenis item yang ingin diketahui Anda (Monster/Item/Back): ') diff --git a/src/laboratory.py b/src/laboratory.py index 73d0e86..0c7865d 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -1,7 +1,4 @@ def laboratory(yourmonsterdata,monsterdata,coin,role): - if role == 'admin' : #jika role adalah admin - print('Maaf! Anda tidak memiliki akses sebagai admin') - else : #role == 'agent' array_Harga = [100, 200, 400, 700] #list harga untuk mengupgrade level monster while True: @@ -76,5 +73,5 @@ def laboratory(yourmonsterdata,monsterdata,coin,role): break else: break - return coin + return coin From 1081edcdd93bb6ca62b865a53bf80e9a894df7b8 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 16:13:04 +0700 Subject: [PATCH 085/115] feat: add one helper line --- src/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.py b/src/main.py index fbff800..de58fae 100644 --- a/src/main.py +++ b/src/main.py @@ -21,6 +21,7 @@ monsShopData = data[5] loginStatus = False while True : + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") command = input("--->") if command.lower() == "login" : while True : @@ -44,6 +45,7 @@ if role.lower() == 'agent': while True : id = int(userInv[0][0]) + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") command = input("--->") if command.lower() == 'battle' : randomNumber = RNG(1, len(monsterData)) @@ -98,6 +100,7 @@ print(monsShopData) elif role == 'admin' : while True : + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") command = input("--->") if command.lower() == 'help': help(loginStatus, role) From ab3fa1eeb48f3362d45c36fd3f84d0c590ef7601 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 16:13:25 +0700 Subject: [PATCH 086/115] feat : add login success line for admin --- src/load.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/load.py b/src/load.py index 4e21525..91fa929 100644 --- a/src/load.py +++ b/src/load.py @@ -34,7 +34,7 @@ def login(user,inventory,monsterinventory) : #fungsi untuk login if i[3] =='agent' : #jika pengguna adalah agent player_inventory = [] monster_inventory =[] - print("login berhasil") + print("Login berhasil") for j in inventory : #pengumpulan inventaris barang pengguna if j[0]==i[0] : player_inventory.append(j) @@ -44,6 +44,7 @@ def login(user,inventory,monsterinventory) : #fungsi untuk login return player_inventory,monster_inventory,i[3],int(i[4]) #mengembalikan data inventaris (barang dan monster) dan role break elif i[3] =='admin' : #jika pengguna adalah admin + print("Login berhasil") return 1,1,i[3],1 else : print("password salah") #jika password salah From 3248735cb1ac437a21a8bfae62d5a5c4d8553a26 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 20:32:47 +0700 Subject: [PATCH 087/115] Move main.py outside src folder --- ok.py | 138 ++++++++++++++++++++++++++-- src/arena.py | 4 +- src/battle.py | 6 +- src/exit.py | 2 +- src/jackpot.py | 2 +- src/load.py | 3 +- src/main.py | 127 ------------------------- {data/data1 => src}/monster_art.csv | 0 src/monsterball.py | 2 +- src/shopCurrency.py | 2 +- 10 files changed, 138 insertions(+), 148 deletions(-) delete mode 100644 src/main.py rename {data/data1 => src}/monster_art.csv (100%) diff --git a/ok.py b/ok.py index 09c2a9a..c8d18be 100644 --- a/ok.py +++ b/ok.py @@ -1,10 +1,128 @@ -list=[1,2,3,4,5] -k=list[0] -m=list[1] -n=list[2] -list2=[k,m,n] -print(list) -print(list2) -list2[0]=list2[0]+1 -print(list) -print(list2) \ No newline at end of file +from src.load import * +from src.battle import * +from src.arena import* +from src.RandomNumberGenerator import * +from src.inventory import * +from src.shopCurrency import * +from src.help import * +from src.laboratory import * +from src.jackpot import * +import time +from src.exit import * +from src.monsterManagement import * +from src.readwritecsv import * + +data=load() +if data != [] : + userData = data[0] + inventoryData = data[1] + monsterData = data[2] + monsInvData = data[3] + itemShopData = data[4] + monsShopData = data[5] + loginStatus = False + while True : + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + command = input("--->") + if command.lower() == "login" : + while True : + userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) + if userInv != 0 and role != 0 and coin !=0 and yourMonsInv !=0 : + loginStatus = True + break + elif command.lower() == 'register' : + userInv, yourMonsInv, role, coin = register(userData, inventoryData, monsInvData, monsterData) + loginStatus = True + elif command.lower() == "help" : + help(loginStatus, "belumlogin") + elif command.lower() == 'save' : + save(inventoryData, monsterData, userData, monsShopData, itemShopData, monsInvData) + elif command.lower()=='exit' : + exit(userData, monsInvData, itemShopData, monsterData, monsShopData, inventoryData) + break + else : + print(f"command '{command}' tidak ada.") + if loginStatus == True : + if role.lower() == 'agent': + while True : + id = int(userInv[0][0]) + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + command = input("--->") + if command.lower() == 'battle' : + randomNumber = RNG(1, len(monsterData)) + time.sleep(2/10) + randomLevel = RNG(1,5) + opening(monsterData, randomNumber) + chosen = choose(yourMonsInv) + battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') + coin += battleCoin + userData[id][4] = str(coin) + print(userInv) + elif command.lower() == 'arena' : + arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) + coin += arenaCoin + userData[id][4] = str(coin) + elif command.lower() == 'inventory' : + inventory(userInv, yourMonsInv, monsterData, role, coin) + elif command.lower() == 'logout' : + t=0 + while True : + confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + if confirm.lower() == "y" : + print("Logout berhasil") + t = 1 + break + elif confirm.lower() == 'n' : + break + else : + print("mangsud?") + if t==1 : + loginStatus=False + break + elif command.lower() == 'shop' : + coin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) + userData[id][4] = str(coin) + elif command.lower() == 'help' : + help(loginStatus, role) + elif command.lower() == 'laboratory' : + coin = laboratory(yourMonsInv, monsterData, coin, role) + userData[id][4] = str(coin) + elif command.lower() == 'jackpot' : + coin = jackpot(id, coin, monsInvData, yourMonsInv) + userData[id][4] = str(coin) + else : + print(f"command '{command}' tidak ada.") + print(userInv) + print(inventoryData) + print(userData) + print(monsInvData) + print(yourMonsInv) + print(itemShopData) + print(monsShopData) + elif role == 'admin' : + while True : + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + command = input("--->") + if command.lower() == 'help': + help(loginStatus, role) + elif command.lower() == 'shop': + monsShopData, itemShopData = shopmanagement(itemShopData, monsShopData, monsterData) + elif command.lower() == 'logout' : + t=0 + while True : + confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + if confirm.lower() == "y" : + print("Logout berhasil") + t=1 + break + elif confirm.lower() =='n' : + break + else : + print("mangsud?") + if t==1 : + loginStatus = False + break + elif command.lower() == 'monster' : + monsterManagement(monsterData) + else : + print("apansih") \ No newline at end of file diff --git a/src/arena.py b/src/arena.py index 4afdda0..d0450bc 100644 --- a/src/arena.py +++ b/src/arena.py @@ -1,5 +1,5 @@ -from battle import * -from RandomNumberGenerator import * +from src.battle import * +from src.RandomNumberGenerator import * def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : #deklarasi variabel diff --git a/src/battle.py b/src/battle.py index efab39d..ad164cb 100644 --- a/src/battle.py +++ b/src/battle.py @@ -1,7 +1,7 @@ #import module yang dibutuhkan -from potion import * -from RandomNumberGenerator import * -from monsterball import * +from src.potion import * +from src.RandomNumberGenerator import * +from src.monsterball import * #fungsi untuk memilih monster yg ingin dipakai untuk battle def choose(yourmonsterdata) : diff --git a/src/exit.py b/src/exit.py index 049d7ad..461743e 100644 --- a/src/exit.py +++ b/src/exit.py @@ -1,4 +1,4 @@ -from load import save +from src.load import save def exit(user,monsterinventory,itemshop,monster,monstershop,iteminventory): confirmExit = input(("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) while confirmExit != "y" and confirmExit != "n": diff --git a/src/jackpot.py b/src/jackpot.py index 21fa9d9..de2693b 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -1,5 +1,5 @@ import time -from RandomNumberGenerator import RNG +from src.RandomNumberGenerator import RNG # fungsi prob untuk menghasilkan kemungkinan muncul masing-masing item def prob(RNG): diff --git a/src/load.py b/src/load.py index 91fa929..585b0cc 100644 --- a/src/load.py +++ b/src/load.py @@ -1,5 +1,4 @@ -from readwritecsv import * -from csvParser import * +from src.readwritecsv import * import os import argparse def load() : diff --git a/src/main.py b/src/main.py deleted file mode 100644 index de58fae..0000000 --- a/src/main.py +++ /dev/null @@ -1,127 +0,0 @@ -from load import * -from battle import * -from arena import* -from RandomNumberGenerator import * -from inventory import * -from shopCurrency import * -from help import * -from laboratory import * -from jackpot import * -import time -from exit import * -from monsterManagement import * - -data=load() -if data != [] : - userData = data[0] - inventoryData = data[1] - monsterData = data[2] - monsInvData = data[3] - itemShopData = data[4] - monsShopData = data[5] - loginStatus = False - while True : - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") - if command.lower() == "login" : - while True : - userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) - if userInv != 0 and role != 0 and coin !=0 and yourMonsInv !=0 : - loginStatus = True - break - elif command.lower() == 'register' : - userInv, yourMonsInv, role, coin = register(userData, inventoryData, monsInvData, monsterData) - loginStatus = True - elif command.lower() == "help" : - help(loginStatus, "belumlogin") - elif command.lower() == 'save' : - save(inventoryData, monsterData, userData, monsShopData, itemShopData, monsInvData) - elif command.lower()=='exit' : - exit(userData, monsInvData, itemShopData, monsterData, monsShopData, inventoryData) - break - else : - print(f"command '{command}' tidak ada.") - if loginStatus == True : - if role.lower() == 'agent': - while True : - id = int(userInv[0][0]) - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") - if command.lower() == 'battle' : - randomNumber = RNG(1, len(monsterData)) - time.sleep(2/10) - randomLevel = RNG(1,5) - opening(monsterData, randomNumber) - chosen = choose(yourMonsInv) - battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') - coin += battleCoin - userData[id][4] = str(coin) - print(userInv) - elif command.lower() == 'arena' : - arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) - coin += arenaCoin - userData[id][4] = str(coin) - elif command.lower() == 'inventory' : - inventory(userInv, yourMonsInv, monsterData, role, coin) - elif command.lower() == 'logout' : - t=0 - while True : - confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") - if confirm.lower() == "y" : - print("Logout berhasil") - t = 1 - break - elif confirm.lower() == 'n' : - break - else : - print("mangsud?") - if t==1 : - loginStatus=False - break - elif command.lower() == 'shop' : - coin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) - userData[id][4] = str(coin) - elif command.lower() == 'help' : - help(loginStatus, role) - elif command.lower() == 'laboratory' : - coin = laboratory(yourMonsInv, monsterData, coin, role) - userData[id][4] = str(coin) - elif command.lower() == 'jackpot' : - coin = jackpot(id, coin, monsInvData, yourMonsInv) - userData[id][4] = str(coin) - else : - print(f"command '{command}' tidak ada.") - print(userInv) - print(inventoryData) - print(userData) - print(monsInvData) - print(yourMonsInv) - print(itemShopData) - print(monsShopData) - elif role == 'admin' : - while True : - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") - if command.lower() == 'help': - help(loginStatus, role) - elif command.lower() == 'shop': - monsShopData, itemShopData = shopmanagement(itemShopData, monsShopData, monsterData) - elif command.lower() == 'logout' : - t=0 - while True : - confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") - if confirm.lower() == "y" : - print("Logout berhasil") - t=1 - break - elif confirm.lower() =='n' : - break - else : - print("mangsud?") - if t==1 : - loginStatus = False - break - elif command.lower() == 'monster' : - monsterManagement(monsterData) - else : - print("apansih") \ No newline at end of file diff --git a/data/data1/monster_art.csv b/src/monster_art.csv similarity index 100% rename from data/data1/monster_art.csv rename to src/monster_art.csv diff --git a/src/monsterball.py b/src/monsterball.py index 4eee6f2..8e19008 100644 --- a/src/monsterball.py +++ b/src/monsterball.py @@ -1,4 +1,4 @@ -from RandomNumberGenerator import * +from src.RandomNumberGenerator import * # Fungsi untuk fitur bonus Monster Ball def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventory,yourmonsterdata): diff --git a/src/shopCurrency.py b/src/shopCurrency.py index 90381c6..564473f 100644 --- a/src/shopCurrency.py +++ b/src/shopCurrency.py @@ -1,4 +1,4 @@ -from monsterManagement import cekint +from src.monsterManagement import cekint itemID = ["Type", "Healing Potion", "Resilience Potion", "Strength Potion", "Monster Ball"] #TAMPILAN KASIR From 9679be2e2e896398f4af8c64b055e75278c06eb0 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 20:33:33 +0700 Subject: [PATCH 088/115] Move main.py outside src folder --- main.py | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..c8d18be --- /dev/null +++ b/main.py @@ -0,0 +1,128 @@ +from src.load import * +from src.battle import * +from src.arena import* +from src.RandomNumberGenerator import * +from src.inventory import * +from src.shopCurrency import * +from src.help import * +from src.laboratory import * +from src.jackpot import * +import time +from src.exit import * +from src.monsterManagement import * +from src.readwritecsv import * + +data=load() +if data != [] : + userData = data[0] + inventoryData = data[1] + monsterData = data[2] + monsInvData = data[3] + itemShopData = data[4] + monsShopData = data[5] + loginStatus = False + while True : + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + command = input("--->") + if command.lower() == "login" : + while True : + userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) + if userInv != 0 and role != 0 and coin !=0 and yourMonsInv !=0 : + loginStatus = True + break + elif command.lower() == 'register' : + userInv, yourMonsInv, role, coin = register(userData, inventoryData, monsInvData, monsterData) + loginStatus = True + elif command.lower() == "help" : + help(loginStatus, "belumlogin") + elif command.lower() == 'save' : + save(inventoryData, monsterData, userData, monsShopData, itemShopData, monsInvData) + elif command.lower()=='exit' : + exit(userData, monsInvData, itemShopData, monsterData, monsShopData, inventoryData) + break + else : + print(f"command '{command}' tidak ada.") + if loginStatus == True : + if role.lower() == 'agent': + while True : + id = int(userInv[0][0]) + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + command = input("--->") + if command.lower() == 'battle' : + randomNumber = RNG(1, len(monsterData)) + time.sleep(2/10) + randomLevel = RNG(1,5) + opening(monsterData, randomNumber) + chosen = choose(yourMonsInv) + battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') + coin += battleCoin + userData[id][4] = str(coin) + print(userInv) + elif command.lower() == 'arena' : + arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) + coin += arenaCoin + userData[id][4] = str(coin) + elif command.lower() == 'inventory' : + inventory(userInv, yourMonsInv, monsterData, role, coin) + elif command.lower() == 'logout' : + t=0 + while True : + confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + if confirm.lower() == "y" : + print("Logout berhasil") + t = 1 + break + elif confirm.lower() == 'n' : + break + else : + print("mangsud?") + if t==1 : + loginStatus=False + break + elif command.lower() == 'shop' : + coin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) + userData[id][4] = str(coin) + elif command.lower() == 'help' : + help(loginStatus, role) + elif command.lower() == 'laboratory' : + coin = laboratory(yourMonsInv, monsterData, coin, role) + userData[id][4] = str(coin) + elif command.lower() == 'jackpot' : + coin = jackpot(id, coin, monsInvData, yourMonsInv) + userData[id][4] = str(coin) + else : + print(f"command '{command}' tidak ada.") + print(userInv) + print(inventoryData) + print(userData) + print(monsInvData) + print(yourMonsInv) + print(itemShopData) + print(monsShopData) + elif role == 'admin' : + while True : + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + command = input("--->") + if command.lower() == 'help': + help(loginStatus, role) + elif command.lower() == 'shop': + monsShopData, itemShopData = shopmanagement(itemShopData, monsShopData, monsterData) + elif command.lower() == 'logout' : + t=0 + while True : + confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + if confirm.lower() == "y" : + print("Logout berhasil") + t=1 + break + elif confirm.lower() =='n' : + break + else : + print("mangsud?") + if t==1 : + loginStatus = False + break + elif command.lower() == 'monster' : + monsterManagement(monsterData) + else : + print("apansih") \ No newline at end of file From 56f14f3aca1efc60e40fd182e0d98679725a2fa1 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 21:48:55 +0700 Subject: [PATCH 089/115] correction of wrong pic --- src/monster_art.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/monster_art.csv b/src/monster_art.csv index e558a46..58bf5f0 100644 --- a/src/monster_art.csv +++ b/src/monster_art.csv @@ -120,7 +120,7 @@ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⠿⢿⣿⣷⣿⣿⣿⣿⣿⣿⠿⠿⠛⡉⢁⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⣿⣾⣿⣿⣿⣿⣻⣿⠰⣉⣞⣿⣿⡟⠴⣾⣟⣻⡷⢤⡒⢻⣿⣿⠉⢉⡀⠘⣷⠻⣧⠀⠀⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 7. Bunny -,\ + ,\ \\\,_ \` ,\ __,.-" =__) From a45696217dd62c59bd19d9604a75ec53761c233d Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Sun, 19 May 2024 21:59:21 +0700 Subject: [PATCH 090/115] style : mempercantik tampilan awal battle dan arena --- main.py | 3 ++ src/arena.py | 58 ++++++++++++++++++++++--------- src/battle.py | 96 ++++++++++++++++++++++++++++++++++++++++----------- src/potion.py | 20 +++++------ 4 files changed, 131 insertions(+), 46 deletions(-) diff --git a/main.py b/main.py index c8d18be..7889a54 100644 --- a/main.py +++ b/main.py @@ -52,6 +52,9 @@ randomNumber = RNG(1, len(monsterData)) time.sleep(2/10) randomLevel = RNG(1,5) + confirm = battlerule() + if confirm.lower() == "n" : + continue opening(monsterData, randomNumber) chosen = choose(yourMonsInv) battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') diff --git a/src/arena.py b/src/arena.py index d0450bc..ff56d56 100644 --- a/src/arena.py +++ b/src/arena.py @@ -1,5 +1,44 @@ from src.battle import * from src.RandomNumberGenerator import * +def arenaart() : + print(f''' + T~~ + /" + T~~ |'| T~~ + T~~ | T~ WWWW| + | /"\ | | |/\T~~ + /"\ WWW /"\ |' |WW| + WWWWW/\| / \|'/\|/" + | /__\/]WWW[\/__\WWWW + |" WWWW'|I_I|'WWWW' | + | |' |/ - \|' |' | + |' | |LI=H=LI|' | | + | |' | |[_]| | |' | + | | |_|###|_| | | + '---'--'-/___\-'--'---' ''') + +def arenarule() : + arenaart() + print(""" +======================WELCOME TO THE ARENA====================== +ARENA MEKANISM : + 1. THERE WILL BE A TOTAL OF 5 STAGES IN THE ARENA, EACH STAGE YOU WILL BE BATTLING + A RANDOMLY SELECTED MONSTER + 2. YOUR ENEMY LEVEL WILL BE EQUAL TO THE STAGE NUMBER YOUR CURRENTLY ON + 3. DEFEATING EACH STAGE WILL GAVE YOU A REWARD, THE HIGHER THE STAGE, THE + THE GREATER THE REWARD + 4. IF YOU LOSE ONCE, THE ARENA WILL BE OVER + 5. IF YOU WIN ALL THE WAY, YOU WILL GET A BONUS REWARD + 6. POTIONS EFFECT ONLY LAST TILL THE END OF EACH STAGE + 7. MONSTER BALL IS PROHIBITED IN THE ARENA """) + while True : + confirm = input("PROCEED?(Y/N)--->") + if confirm.lower() =='y' : + return confirm + elif confirm.lower() =='n' : + return confirm + else : + print("BE CLEAR") def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : #deklarasi variabel @@ -7,21 +46,10 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : coins=0 totaldamageTaken = 0 totaldamageDealt = 0 - - print("DO YOU WANT TO ENTER THE ARENA? (Y/N)") #double cek dari user - inp = input("--->") - if inp.lower()=="n" : #jika tidak jadi + confirm = arenarule() + if confirm.lower()=="n" : #jika tidak jadi print("SEE U ANOTHER DAY") - elif inp.lower()=="y" : - print("==========WELCOME TO THE ARENA==========") - print("RULES :") - print("1. THERE WILL BE A TOTAL OF 5 STAGES IN THE ARENA, EACH STAGE") - print(" YOU HAVE TO FIGHT A MONSTER WITH EACH STAGE THE MONSTER WILL GET STRONGER") - print("2. DEFEATING A MONSTER IN EACH STAGE WILL REWARD YOU WITH COINS, THE HIGHER") - print(" THE STAGE THE BIGGER THE REWARD") - print("3. IF YOU LOSE ONCE, THE ARENA WILL BE OVER, IF YOU WIN ALL THE WAY") - print(" TO THE FIFTH STAGE YOU WILL GET MAXIMUM COINS") - + else : chosen = choose(yourmonsterdata) #fungsi untuk memilih monster dari pilihan monsterinventory stage = 1 for i in range(5) : #pemanggilan fungsi battle sebanyak maksimum 5 kali @@ -55,6 +83,4 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : print(f"TOTAL DAMAGE TAKEN : {totaldamageTaken}") print(f"TOTAL DAMAGE DEALT : {totaldamageDealt}") print("==========================================") - else : - print("Masukkan input yg benar(Y/N)--->") return coins \ No newline at end of file diff --git a/src/battle.py b/src/battle.py index ad164cb..e48c610 100644 --- a/src/battle.py +++ b/src/battle.py @@ -2,6 +2,48 @@ from src.potion import * from src.RandomNumberGenerator import * from src.monsterball import * +import time + +def battleart() : #fungsi tampilan awal + print(''' + |\ /) + /\_\\__ (_// +| `>\-` _._ //`) + \ /` \\ _.-`:::`-._ // + ` \|` ::: `|/ + | ::: | + |.....:::.....| + |:::::::::::::| + | ::: | + \ ::: / + \ ::: / + `-. ::: .-' + //`:::`\\ + // ' \\ + |/ \\''') + +def battlerule() : + battleart() + print(""" +BATTLE MEKANISM : + 1. YOU WILL FIGHT A RANDOMLY SELECTED MONSTER WITH A RANDOMLY SELECTED LEVEL + 2. IT IS TURN BASE 1V1 SYSTEM WITH THE YOU(THE PLAYER) ALWAYS MAKE THE FIRST MOVE + 3. IN EACH OF YOUR MOVE, YOU WILL BE GIVEN 4 CHOICES : ATTACK,USE POTION,USE MONSTERBALL OR QUIT + 4. THE ENEMY CAN ONLY ATTACK + 5. IF THE ENEMY HEALTH IS DOWN TO 0, YOU WIN THE BATTLE AND RANDOM AMOUNT OF GOLD + 6. IF YOUR MONSTER HEALTH IS DOWN TO ZERO, YOU WILL LOSE AND GET 0 GOLD + 7. YOU CAN ONLY USE EACH POTION ONCE AND THE EFFECT ONLY LAST TILL THE BATTLE ENDS + 8. FAILING TO CACTH THE ENEMY MONSTER WITH THE MONSTERBALL DOES NOT SKIP THEIR TURN + 9. IF YOU QUIT MID BATTLE, YOU WILL GET 0 GOLD +""") + while True : + confirm = input("PROCEED?(Y/N)--->") + if confirm.lower() =='y' : + return confirm + elif confirm.lower() =='n' : + return confirm + else : + print("BE CLEAR") #fungsi untuk memilih monster yg ingin dipakai untuk battle def choose(yourmonsterdata) : @@ -9,7 +51,7 @@ def choose(yourmonsterdata) : print("=======PLEASE CHOOSE A MONSTER=======") x=0 for i in yourmonsterdata : #menampilkan seluruh monster yg player punya - print(f"{x+1}. {i[1]}") + print(f"{x+1}. {(i[1]).upper()}") x+=1 chosen = input("(1/2/3/dst)--->") #input monster yg ingin dipilih k=0 @@ -27,7 +69,7 @@ def choose(yourmonsterdata) : def opening(monsterdata,random_number) : name = monsterdata[random_number][1] print(f'''============================================= ->>>>>>>>>{name} telah datang !!!<<<<<<<<< +>>>>>>>>>{name.upper()} HAS ARRIVED !!!<<<<<<<<< =============================================''' ) @@ -40,8 +82,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran name=yourmonsterdata[chosen-1][1] #nama monster anda #PROGRAM UTAMA ========================================================== - print("="*100) - print(f'{name} siap membantu') + print(f'{name.upper()} READY TO HELP') indeks=0 for i in file1 : #mencari indeks monster kita di file monster.csv @@ -65,13 +106,13 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran #menampilkan stat kedua monster saat battle print(f">>>>>>>>>>>>>>>>>TURN {turn}<<<<<<<<<<<<<<<<<<<<") print("=============================================") - print(f"ENEMY : {file1[random_number][1]}") + print(f"ENEMY : {file1[random_number][1].upper()}") print(f"HEALTH : {enemyhealth}") print(f"ATTACK : {enemyattack}") print(f"DEFENSE : {enemydefense}") print(f"LEVEL : {random_level}") print("=============================================") - print(f"YOUR MONSTER : {name}") + print(f"YOUR MONSTER : {name.upper()}") print(f"HEALTH : {yourhealth}") print(f"ATTACK : {yourattack}") print(f"DEFENSE : {yourdefense}") @@ -90,17 +131,25 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran action = (input("choose an action(1/2/3/4)--->")) if action=='1' : #ACTION ATTACK - damage = RNG(yourattack*(70/100),yourattack*(130/100)) + damagerng = RNG(70,130) + time.sleep(1/10) + damage = yourattack*(damagerng/100) if enemyhealth >= (damage-(enemydefense/100)*damage) : #menghitung damagedealt jika enemy belom mati damagedealt += (damage-(enemydefense/100)*damage) else : #jika enemy mati maka damagedealt hanya ditambah sebesar sisa darah enemy sebelum mati damagedealt += enemyhealth enemyhealth -= (damage-(enemydefense/100)*damage) enemyhealth = int(enemyhealth) + #MENAMPILKAN MEKANISME DAMAGE SERANGAN print("=============================================") print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") + print(f"ATTACK DAMAGE : {damage} (+{damagerng-100}%)") + print(f"REDUCED DAMAGE : {(enemydefense/100)*damage} ({enemydefense}%)") + print(f"TOTAL DAMAGE : {(damage-(enemydefense/100)*damage)}") if enemyhealth > 0 : #JIKA MONSTER BELOM MATI - print(f"ENEMY MONSTER HEALTH IS DOWN TO {enemyhealth}") + print(f"ENEMY MONSTER HEALTH IS DOWN TO : {enemyhealth}") + else : + print(f"ENEMY MONSTER HEALTH IS DOWN TO : {0}") elif action=='2' : #ACTION POTION while True : @@ -153,35 +202,37 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran continue elif type =='arena': #Jika mode arena action 3 adalah quit print('=============================================') - print('ANDA MENINGGALKAN PERTANDINGAN') + print('YOU LEFT THE BATTLE FIELD') print('=============================================') coin = 0 return coin,damagetaken,damagedealt elif action=='4' : - if type=='arena' : - print("opsi 4 tidak ada") + if type=='arena' : #TIDAK ADA OPSI 4 DI ARENA + print("OPTION 4 IS NOT AVAILABLE") continue - elif type=='battle' : - print('ANDA MENINGGALKAN PERTANDINGAN') + elif type=='battle' : #OPSI 4 DIBATTLE ADALAH QUIT + print('=============================================') + print('YOU LEFT THE BATTLE FIELD') + print('=============================================') coin = 0 return coin,damagetaken,damagedealt else : - print(f"opsi {action} tidak ada") + print(f"OPTION {action} IS NOT AVAILABLE") continue #Jika musuh darahnya sudah habis if enemyhealth <= 0 : print("=============================================") print("YOU DEFEATED YOUR ENEMY") - print("WOHOOOOOO") - print("="*100) + print("WELL DONE") coin = RNG(1,50) - print(f"YEEEEEY YOU GOT {coin} coin") + print(f"YOU GOT {coin} COINS") print("=============================================") return coin,damagetaken,damagedealt #Jika musuh masih hidup, musuh menyerang balik - damagemusuh=RNG(enemyattack*(70/100),enemyattack*(130/100)) + damagemusuhrng = RNG(70,130) + damagemusuh=enemyattack*(damagemusuhrng/100) print(f">>>>>>>>>>>>>{file1[random_number][1]} ATTACK BACK !!!<<<<<<<<<<<<") if yourhealth >= (damagemusuh - (yourdefense/100)*damagemusuh) : damagetaken += (damagemusuh - (yourdefense/100)*damagemusuh) #Jika monster kita masih hidup setelah serangan @@ -189,9 +240,14 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran damagetaken += yourhealth #jika monster kita mati setelah serangan yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) yourhealth = int(yourhealth) + #MENAMPILKAN MEKANISMA DAMAGE SERANGAN + print(f"ATTACK DAMAGE : {damagemusuh} (+{damagemusuhrng-100}%)") + print(f"REDUCED DAMAGE : {(yourdefense/100)*damagemusuh} ({yourdefense}%)") + print(f"TOTAL DAMAGE : {(damagemusuh - (yourdefense/100)*damagemusuh)}") if yourhealth >0 : #jika monster kita masih hidup - print(f"{name} HEALTH IS DOWN TO {yourhealth}") - print("=============================================") + print(f"{name} HEALTH IS DOWN TO : {yourhealth}") + else : + print(f"{name} HEALTH IS DOWN TO : {0}") #jika darah monster kita habis if yourhealth <= 0 : diff --git a/src/potion.py b/src/potion.py index a087606..abcca44 100644 --- a/src/potion.py +++ b/src/potion.py @@ -54,15 +54,15 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, if used_Pot_Array[0] == 0 : # mengecek pernah tidaknya potion strength digunakan used_Pot_Array[0] += 1 attack *= 105/100 - print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih kuat!!") + print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} FEELS A BIT MORE STRONGER") jumlahpot[0] -= 1 userInventory[indexPot[0]][2] = str(int(userInventory[indexPot[0]][2])-1) return attack # return nilai attack monster setelah menggunakan potion strength else : - print("Potion hanya bisa digunakan sekali") + print("POTION CAN ONLY BE USE ONCE") return 0 # return 0 untuk mengindikasi potion tidak bisa digunakan else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain") + print("YOU DONT HAVE THE POTION") return 0 elif pilihan == 2 : @@ -70,15 +70,15 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, if used_Pot_Array[1] == 0 : # mengecek pernah tidaknya potion resilience digunakan used_Pot_Array[1] += 1 defense *= 110/100 - print(f"Potion telah diminum {mons_Name}, {mons_Name} menjadi lebih sulit dilukai!!") + print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} FEELS A BIT MORE STURDIER ") jumlahpot[1] -=1 userInventory[indexPot[1]][2] = str(int(userInventory[indexPot[1]][2])-1) return defense # return nilai defense monster setelah menggunakan potion resilience else : - print("Potion hanya bisa digunakan sekali") + print("POTION CAN ONLY BE USE ONCE") return 0 else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + print("YOU DONT HAVE THE POTION") return 0 elif pilihan==3 : @@ -87,19 +87,19 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, used_Pot_Array[2] += 1 if HP * 125/100 <= max_HP : # mengecek penggunaan potion melebihi HP maksimum atau tidak HP *= 125/100 - print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") + print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} REGENERATES SOME OF HIS HEALTH") jumlahpot[2] -= 1 userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP # return nilai HP monster setelah menggunakan potion healing else : HP = max_HP - print(f"Potion telah diminum {mons_Name}, {mons_Name} beregenerasi dengan cepat sehingga hampir semua luka yang diterimanya menghilang!!") + print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} REGENERATES SOME OF HIS HEALTH") jumlahpot[2] -= 1 userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP else : - print("Potion hanya bisa digunakan sekali") + print("POTION CAN ONLY BE USE ONCE") return 0 else : - print("Sayangnya Anda tidak memiliki potion tersebut, silakan pilih potion lain: ") + print("YOU DONT HAVE THE POTION") return 0 \ No newline at end of file From f8449954aa1a217c4884589a1026eaad6510ffde Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 22:42:54 +0700 Subject: [PATCH 091/115] style: change login input text --- src/load.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/load.py b/src/load.py index 585b0cc..be20b68 100644 --- a/src/load.py +++ b/src/load.py @@ -25,12 +25,12 @@ def load() : return [] def login(user,inventory,monsterinventory) : #fungsi untuk login - username = input("username :") #input username - password = input("password :") #input password + username = input("username: ") #input username + password = input("password: ") #input password for i in user : if i[1] == username : #pemeriksaan apakah username sesuai if i[2] == password : #pemeriksaan apakah password sesuai - if i[3] =='agent' : #jika pengguna adalah agent + if i[3] == 'agent' : #jika pengguna adalah agent player_inventory = [] monster_inventory =[] print("Login berhasil") @@ -42,7 +42,7 @@ def login(user,inventory,monsterinventory) : #fungsi untuk login monster_inventory.append(j) return player_inventory,monster_inventory,i[3],int(i[4]) #mengembalikan data inventaris (barang dan monster) dan role break - elif i[3] =='admin' : #jika pengguna adalah admin + elif i[3] == 'admin' : #jika pengguna adalah admin print("Login berhasil") return 1,1,i[3],1 else : @@ -55,7 +55,7 @@ def login(user,inventory,monsterinventory) : #fungsi untuk login def register(user,inventory,monsterinventory,monster) : #fungsi untuk register while True : - usernamebaru = input("Masukkan Username :") #meminta input username baru dari pengguna + usernamebaru = input("Masukkan Username: ") #meminta input username baru dari pengguna #pemeriksaan apakah username sudah terpakai for i in user : if i[1]== usernamebaru : @@ -64,7 +64,7 @@ def register(user,inventory,monsterinventory,monster) : #fungsi untuk register else : #jika username belum terpakai, keluar dari loop break - passwordbaru = input("Masukkan password :") #meminta input password baru dari pengguna + passwordbaru = input("Masukkan password: ") #meminta input password baru dari pengguna #menampilkan pilihan monster untuk pengguna print('PILIH MONSTER PERTAMA ANDA :') for i in range(3) : From ff9bffbcfaf0317c02078c09c7e11d3fdd400586 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 22:47:29 +0700 Subject: [PATCH 092/115] refactor: remove not used variables laboratory command --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 7889a54..c93c56d 100644 --- a/main.py +++ b/main.py @@ -88,7 +88,7 @@ elif command.lower() == 'help' : help(loginStatus, role) elif command.lower() == 'laboratory' : - coin = laboratory(yourMonsInv, monsterData, coin, role) + coin = laboratory(yourMonsInv, coin, role) userData[id][4] = str(coin) elif command.lower() == 'jackpot' : coin = jackpot(id, coin, monsInvData, yourMonsInv) From 30f2cac06fb6b5bc0fcbdb9e27a5505c8fb36179 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 22:50:33 +0700 Subject: [PATCH 093/115] refactor: change variables name & add comments --- src/laboratory.py | 135 ++++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 63 deletions(-) diff --git a/src/laboratory.py b/src/laboratory.py index 0c7865d..77c7197 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -1,77 +1,86 @@ -def laboratory(yourmonsterdata,monsterdata,coin,role): - array_Harga = [100, 200, 400, 700] #list harga untuk mengupgrade level monster +def laboratory(yourMonsData, coin, role): + if role != 'admin' : + arrayHarga = [100, 200, 400, 700] # list harga untuk meng-upgrade level monster while True: print(f"JUMLAH COIN ANDA : {coin}") - #menampilkan seluruh monster yg kita miliki print('============ MONSTER LIST ============') - number=1 - for i in yourmonsterdata : - print(f"{number}. {i[1]}, LEVEL :{i[2]}") - number+=1 - #menampilkan harga untuk mengupgrade ke masing2 level + number = 1 + for i in yourMonsData : + print(f"{number}. {i[1]} LEVEL: {i[2]}") + number += 1 + print('============ UPGRADE PRICE ============') for i in range (1,5): - print(f'{i}. Level {i} -> Level {i+1}: {array_Harga[i-1]}') - idpilihan = input('Pilih monster yang ingin di-upgrade (1/2/dst/Back): ') - #validasi input - for i in range(len(yourmonsterdata)) : - if idpilihan== str(i+1) or idpilihan.lower()=='back' : - break #jika input benar - else : #jika input salah - print("Monster tersebut tidak tersedia") - continue + print(f'{i}. Level {i} --> Level {i+1}: {arrayHarga[i-1]}') + + pilihMons = input('Pilih monster yang ingin di-upgrade (1/2/dst/Back): ') + + inputMonsNum = True # validasi input selain 1/2/3/dst/back + for char in str(pilihMons) : + if ord(char) < ord('0') or ord(char) > ord('9'): + inputMonsNum = False - if idpilihan.lower() != 'back': - idpilihan = int(idpilihan) + if inputMonsNum != False : + pilihMons = int(pilihMons) while True: - if yourmonsterdata[idpilihan-1][2] != '5': #jika monster tidak maks level - up_level = input('Silakan pilih ke level berapa kah Anda ingin meng-upgrade monster Anda (1/2/dst/Back): ') - #periksa apakah input berupa int dari 1-5 atau back - for i in range(5) : - if up_level == str(i+1) or up_level.lower()=='back' : - break - else : - print("Masukkan level yg dituju dengan benar") - continue + if yourMonsData[pilihMons-1][2] != '5': + monsUpgrade = input('Silakan pilih ke level berapa kah Anda ingin meng-upgrade monster Anda (1/2/dst/Back): ') - if up_level.lower() != 'back': - if up_level <= yourmonsterdata[idpilihan-1][2] : #jika level yg dituju sudah tercapai - print("masa mau upgrade kelevel yg sama/lebihrendah si") - continue - else : #jika input benar dan sesuai - up_level = int(up_level) + inputMonsUp = True # validasi input selain 1/2/3/dst/back + for char in str(monsUpgrade) : + if ord(char) < ord('0') or ord(char) > ord('9'): + inputMonsUp = False + + print(monsUpgrade) + if inputMonsUp != False : + if monsUpgrade <= yourMonsData[pilihMons-1][2] : # validasi input upgrade level <= level saat ini + print("Masa mau upgrade ke level yg sama/lebih rendah sih.. Itu mah downgrade kak") + + elif int(monsUpgrade) > 5 : + print('Upgrade cuman sampai level 5 kakak, level di atas 5 itu level kesulitan tubes daspro') + + else : + monsUpgrade = int(monsUpgrade) harga = 0 - #menghitung harga yg dibutuhkan - for i in range (int(yourmonsterdata[idpilihan-1][2]), up_level): - harga += array_Harga[i-1] - print(f'{yourmonsterdata[idpilihan-1][1]} akan di-upgrade ke level {up_level}') - print(f'Harga untuk meng-upgrade {yourmonsterdata[idpilihan-1][1]} adalah {harga}') - while True : #double cek apakah benar mau di upgarde - lanjut = input('Lanjutkan upgrade (Y/N): ') + for i in range (int(yourMonsData[pilihMons-1][2]), monsUpgrade): # total harga upgrade + harga += arrayHarga[i-1] + + print(f'{yourMonsData[pilihMons-1][1]} akan di-upgrade ke level {monsUpgrade}') + print(f'Harga untuk meng-upgrade {yourMonsData[pilihMons-1][1]} adalah {harga}') + + while True : + lanjut = input('Lanjutkan upgrade (Y/N): ') # konfirmasi upgrade if lanjut.lower() == 'y': - if coin >= harga : #jika coin cukup - yourmonsterdata[idpilihan-1][2]=str(up_level) - coin -= harga - print(f'Selamat! {yourmonsterdata[idpilihan-1][1]} berhasil di-upgrade ke level {up_level}!') - print(f'Coin Anda tersisa {coin}') - break - else : #jika tidak cukup - print('Maaf! Anda tidak memiliki Coin yang cukup') - break - elif lanjut.lower() == 'n' : #jika tidak jadi upgrade - break - else : #jika input bukan y atau n - print("Mohon masukkan input yang benar") - continue - break - - else : #jika input == break - break - else : #jika sudah maks level + if coin >= harga : + yourMonsData[pilihMons-1][2] = str(monsUpgrade) + coin -= harga + print(f'Selamat! {yourMonsData[pilihMons-1][1]} berhasil di-upgrade ke level {monsUpgrade}!') + print(f'Coin Anda tersisa {coin}') + break + else : + print('Maaf! Anda tidak memiliki Coin yang cukup') + break + elif lanjut.lower() == 'n' : + break + else : + print("Mohon masukkan input yang benar") + print() + + elif monsUpgrade.lower() == 'back' : + break + else : + print("Masukkan input level yang benar") + print() + else : # jika level sudah max print('Maaf! Monster yang Anda pilih sudah memiliki level maksimum. Silakan pilih monster lain') break - else: - break - return coin + elif pilihMons.lower() == 'back' : + break + else : + print("Masukkan nomor monster yang benar") + print() + else : + print('Maaf! Anda tidak memiliki akses sebagai admin') + return coin \ No newline at end of file From 035e8a0f8b6cbe2e58a34fbcd95b7fad21383a5d Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 23:01:53 +0700 Subject: [PATCH 094/115] style & refactor: change some input text & change logout command code --- main.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/main.py b/main.py index c93c56d..ce4b48d 100644 --- a/main.py +++ b/main.py @@ -23,7 +23,7 @@ loginStatus = False while True : print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") + command = input("---> ") if command.lower() == "login" : while True : userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) @@ -47,7 +47,7 @@ while True : id = int(userInv[0][0]) print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") + command = input("---> ") if command.lower() == 'battle' : randomNumber = RNG(1, len(monsterData)) time.sleep(2/10) @@ -68,20 +68,18 @@ elif command.lower() == 'inventory' : inventory(userInv, yourMonsInv, monsterData, role, coin) elif command.lower() == 'logout' : - t=0 while True : - confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + confirm = input("Apakah anda yakin untuk logout?(Y/N)--> ") if confirm.lower() == "y" : print("Logout berhasil") - t = 1 + loginStatus = False break elif confirm.lower() == 'n' : break else : - print("mangsud?") - if t==1 : - loginStatus=False - break + print("Masukkan input yang benar") + if loginStatus == False : + break elif command.lower() == 'shop' : coin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) userData[id][4] = str(coin) From 16b7886185c63788f90d24121f30f43931263cbc Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 23:11:42 +0700 Subject: [PATCH 095/115] style & refactor: change input text & change logout command code (admin) --- main.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/main.py b/main.py index ce4b48d..e0713f8 100644 --- a/main.py +++ b/main.py @@ -109,21 +109,19 @@ elif command.lower() == 'shop': monsShopData, itemShopData = shopmanagement(itemShopData, monsShopData, monsterData) elif command.lower() == 'logout' : - t=0 while True : - confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") + confirm = input("Apakah anda yakin untuk logout?(Y/N)--> ") if confirm.lower() == "y" : print("Logout berhasil") - t=1 + loginStatus = False break - elif confirm.lower() =='n' : + elif confirm.lower() == 'n' : break else : - print("mangsud?") - if t==1 : - loginStatus = False - break + print("Masukkan input yang benar") + if loginStatus == False : + break elif command.lower() == 'monster' : monsterManagement(monsterData) else : - print("apansih") \ No newline at end of file + print(f"command '{command}' tidak ada.") \ No newline at end of file From f29b49e08e9f8f16b27b63091ff2022945422a65 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 23:21:15 +0700 Subject: [PATCH 096/115] style: change output text --- src/potion.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/potion.py b/src/potion.py index abcca44..968f4e5 100644 --- a/src/potion.py +++ b/src/potion.py @@ -54,15 +54,15 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, if used_Pot_Array[0] == 0 : # mengecek pernah tidaknya potion strength digunakan used_Pot_Array[0] += 1 attack *= 105/100 - print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} FEELS A BIT MORE STRONGER") + print(f"Potion STRENGTH telah diminum, {mons_Name} menjadi lebih KUAT!") jumlahpot[0] -= 1 userInventory[indexPot[0]][2] = str(int(userInventory[indexPot[0]][2])-1) return attack # return nilai attack monster setelah menggunakan potion strength else : - print("POTION CAN ONLY BE USE ONCE") + print("Potion STRENGTH hanya bisa digunakan sekali") return 0 # return 0 untuk mengindikasi potion tidak bisa digunakan else : - print("YOU DONT HAVE THE POTION") + print("Yahh.. Sayangnya Anda tidak memiliki potion RESILIENCE") return 0 elif pilihan == 2 : @@ -70,15 +70,15 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, if used_Pot_Array[1] == 0 : # mengecek pernah tidaknya potion resilience digunakan used_Pot_Array[1] += 1 defense *= 110/100 - print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} FEELS A BIT MORE STURDIER ") + print(f"Potion RESILIENCE telah diminum, {mons_Name} menjadi lebih SULIT DILUKAI!") jumlahpot[1] -=1 userInventory[indexPot[1]][2] = str(int(userInventory[indexPot[1]][2])-1) return defense # return nilai defense monster setelah menggunakan potion resilience else : - print("POTION CAN ONLY BE USE ONCE") + print("Potion RESILIENCE hanya bisa digunakan sekali") return 0 else : - print("YOU DONT HAVE THE POTION") + print("Yahh.. Sayangnya Anda tidak memiliki potion RESILIENCE") return 0 elif pilihan==3 : @@ -87,19 +87,19 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, used_Pot_Array[2] += 1 if HP * 125/100 <= max_HP : # mengecek penggunaan potion melebihi HP maksimum atau tidak HP *= 125/100 - print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} REGENERATES SOME OF HIS HEALTH") + print(f"Potion HEALING telah diminum, HP {mons_Name} telah REGENERASI!") jumlahpot[2] -= 1 userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP # return nilai HP monster setelah menggunakan potion healing else : HP = max_HP - print(f"POTION HAS BEEN CONSUMED, {mons_Name.upper()} REGENERATES SOME OF HIS HEALTH") + print(f"Potion HEALING telah diminum, HP {mons_Name} telah REGENERASI!") jumlahpot[2] -= 1 userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) return HP else : - print("POTION CAN ONLY BE USE ONCE") + print("Potion HEALING hanya bisa digunakan sekali") return 0 else : - print("YOU DONT HAVE THE POTION") + print("Yahh.. Sayangnya Anda tidak memiliki potion HEALING") return 0 \ No newline at end of file From a4571ffddee54dda4b4e6825ee0b6440396535d8 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Sun, 19 May 2024 23:34:28 +0700 Subject: [PATCH 097/115] style: change output text --- src/jackpot.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index de2693b..df4eaed 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -32,11 +32,11 @@ def gacha(id, coin, monsInv, yourMonsInv): print(f"{icon[indexItem1]} | {icon[indexItem2]} | {icon[indexItem3]}") if indexItem1 == indexItem2 and indexItem2 == indexItem3: - print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') if any(item[1] == "Gorlock" for item in monsInv): - print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') + print('JACKPOT!! KARENA GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') coin += 2000 else: + print('JACKPOT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') monsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list monsterInventory yourMonsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list yourMonsterInventory else: @@ -50,16 +50,17 @@ def jackpot(id, coin, monsInv , yourMonsInv): print("SELAMAT DATANG DI JACKPOT 888!!!") print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 500 COIN") print(f"COIN ANDA SAAT INI SEJUMLAH {coin} ") - print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") + print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???", end=" ") while True: inp = input("(Y/N)----->").lower() if inp == 'y': - confirm = input("APAKAH ANDA YAKIN? (Y/N) :").lower() + confirm = input("APAKAH ANDA YAKIN? (Y/N): ").lower() if confirm == 'y': - if coin >= 500: - coin = gacha(id, coin, monsInv, yourMonsInv) - coin -= 500 + if coin >= 500: + coin = gacha(id, coin, monsInv, yourMonsInv) + coin -= 500 + print() print(f'COIN ANDA TERSISA {coin} ') print("APAKAH ANDA INGIN MELANJUTKAN??", end=" ") else: From 50f223ae2ef9cbbce855fff8e64228846b17df9b Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 05:02:56 +0700 Subject: [PATCH 098/115] feat:add small changes --- data/data3/item_inventory.csv | 16 ++++ data/data3/item_shop.csv | 5 ++ data/data3/monster.csv | 16 ++++ data/data3/monster_inventory.csv | 9 ++ data/data3/monster_shop.csv | 4 + data/data3/user.csv | 9 ++ main.py | 6 +- ok.py | 145 ++++--------------------------- src/arena.py | 4 + src/battle.py | 18 ++-- src/help.py | 42 ++++++++- src/inventory.py | 1 + src/load.py | 28 +++++- 13 files changed, 162 insertions(+), 141 deletions(-) create mode 100644 data/data3/item_inventory.csv create mode 100644 data/data3/item_shop.csv create mode 100644 data/data3/monster.csv create mode 100644 data/data3/monster_inventory.csv create mode 100644 data/data3/monster_shop.csv create mode 100644 data/data3/user.csv diff --git a/data/data3/item_inventory.csv b/data/data3/item_inventory.csv new file mode 100644 index 0000000..6b9013e --- /dev/null +++ b/data/data3/item_inventory.csv @@ -0,0 +1,16 @@ +userid;type;quantity +1;Healing Potion;2 +1;Resilience Potion;3 +1;Strength Potion;2 +1;Monster Ball;2 +3;Healing Potion;2 +3;Resilience Potion;1 +3;Strength Potion;4 +3;Monster Ball;1 +2;Healing Potion;2 +2;Resilience Potion;2 +2;Strength Potion;9 +2;Monster Ball;5 +8;healingpotion;0 +8;respotion;0 +8;strenghpotion;0 \ No newline at end of file diff --git a/data/data3/item_shop.csv b/data/data3/item_shop.csv new file mode 100644 index 0000000..7e08cd5 --- /dev/null +++ b/data/data3/item_shop.csv @@ -0,0 +1,5 @@ +type;stock;price +Healing Potion;5;25 +Resilience Potion;5;30 +Strength Potion;5;40 +Monster Ball;5;100 \ No newline at end of file diff --git a/data/data3/monster.csv b/data/data3/monster.csv new file mode 100644 index 0000000..86babdf --- /dev/null +++ b/data/data3/monster.csv @@ -0,0 +1,16 @@ +id;type;atk_power;def_power;hp +1;Godzilla;70;32;540 +2;Mimic;45;28;600 +3;Makima;135;5;250 +4;Jalangkung;3700;12;650 +5;gigidi;54;19;420 +6;Gorlock;22;20;700 +7;Bunny;65;24;550 +8;Roga;88;8;222 +9;Molded;66;24;440 +10;Mohg;50;20;600 +11;Malenia;55;30;500 +12;Kraken;20;35;570 +13;Mothra;57;21;520 +14;Parkinson;44;31;470 +15;Ifrit;90;5;330 \ No newline at end of file diff --git a/data/data3/monster_inventory.csv b/data/data3/monster_inventory.csv new file mode 100644 index 0000000..86ccaab --- /dev/null +++ b/data/data3/monster_inventory.csv @@ -0,0 +1,9 @@ +id;monster;level +1;Mimic;1 +1;Makima;2 +1;Jalangkung;3 +2;Makima;1 +2;Mimic;1 +3;Jalangkung;2 +3;Mimic;1 +8;Godzilla;1 \ No newline at end of file diff --git a/data/data3/monster_shop.csv b/data/data3/monster_shop.csv new file mode 100644 index 0000000..41ee368 --- /dev/null +++ b/data/data3/monster_shop.csv @@ -0,0 +1,4 @@ +monster_id;stock;price +1;6;800 +2;13;300 +3;2;750 \ No newline at end of file diff --git a/data/data3/user.csv b/data/data3/user.csv new file mode 100644 index 0000000..bb27a11 --- /dev/null +++ b/data/data3/user.csv @@ -0,0 +1,9 @@ +id;username;password;role;coin +1;bagas;12345;agent;100000000000 +2;bagus;12345;agent;100 +3;bages;12345;agent;100 +4;bagos;12345;agent;100 +5;bagis;12345;agent;100 +6;june;12345;admin;9999 +7;juni;12345;admin;9999 +8;bagas123-_;ekif;agent;0 \ No newline at end of file diff --git a/main.py b/main.py index 7889a54..356e047 100644 --- a/main.py +++ b/main.py @@ -22,7 +22,7 @@ monsShopData = data[5] loginStatus = False while True : - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + print("Type 'help' to seek wisdom from the ALMIGHT GOD") command = input("--->") if command.lower() == "login" : while True : @@ -46,7 +46,7 @@ if role.lower() == 'agent': while True : id = int(userInv[0][0]) - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + print("Type 'help' to seek wisdom from the ALMIGHT GOD") command = input("--->") if command.lower() == 'battle' : randomNumber = RNG(1, len(monsterData)) @@ -104,7 +104,7 @@ print(monsShopData) elif role == 'admin' : while True : - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") + print("Type 'help' to seek wisdom from the ALMIGHT GOD") command = input("--->") if command.lower() == 'help': help(loginStatus, role) diff --git a/ok.py b/ok.py index c8d18be..4bc00ca 100644 --- a/ok.py +++ b/ok.py @@ -1,128 +1,19 @@ -from src.load import * -from src.battle import * -from src.arena import* -from src.RandomNumberGenerator import * -from src.inventory import * -from src.shopCurrency import * -from src.help import * -from src.laboratory import * -from src.jackpot import * -import time -from src.exit import * -from src.monsterManagement import * -from src.readwritecsv import * +def is_valid_string(input_string): + for char in input_string: + ascii_value = ord(char) + # Check if the character is a letter, number, hyphen, or underscore + valid = ( + (65 <= ascii_value <= 90) or # A-Z + (97 <= ascii_value <= 122) or # a-z + (48 <= ascii_value <= 57) or # 0-9 + ascii_value == 45 or # hyphen (-) + ascii_value == 95 # underscore (_) + ) + # If any character is not valid, return False + if valid == False: + return False + return True + +# Example usage: +print(is_valid_string("---___#")) -data=load() -if data != [] : - userData = data[0] - inventoryData = data[1] - monsterData = data[2] - monsInvData = data[3] - itemShopData = data[4] - monsShopData = data[5] - loginStatus = False - while True : - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") - if command.lower() == "login" : - while True : - userInv, yourMonsInv, role, coin = login(userData, inventoryData, monsInvData) - if userInv != 0 and role != 0 and coin !=0 and yourMonsInv !=0 : - loginStatus = True - break - elif command.lower() == 'register' : - userInv, yourMonsInv, role, coin = register(userData, inventoryData, monsInvData, monsterData) - loginStatus = True - elif command.lower() == "help" : - help(loginStatus, "belumlogin") - elif command.lower() == 'save' : - save(inventoryData, monsterData, userData, monsShopData, itemShopData, monsInvData) - elif command.lower()=='exit' : - exit(userData, monsInvData, itemShopData, monsterData, monsShopData, inventoryData) - break - else : - print(f"command '{command}' tidak ada.") - if loginStatus == True : - if role.lower() == 'agent': - while True : - id = int(userInv[0][0]) - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") - if command.lower() == 'battle' : - randomNumber = RNG(1, len(monsterData)) - time.sleep(2/10) - randomLevel = RNG(1,5) - opening(monsterData, randomNumber) - chosen = choose(yourMonsInv) - battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') - coin += battleCoin - userData[id][4] = str(coin) - print(userInv) - elif command.lower() == 'arena' : - arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) - coin += arenaCoin - userData[id][4] = str(coin) - elif command.lower() == 'inventory' : - inventory(userInv, yourMonsInv, monsterData, role, coin) - elif command.lower() == 'logout' : - t=0 - while True : - confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") - if confirm.lower() == "y" : - print("Logout berhasil") - t = 1 - break - elif confirm.lower() == 'n' : - break - else : - print("mangsud?") - if t==1 : - loginStatus=False - break - elif command.lower() == 'shop' : - coin = shopOpen(role, itemShopData, coin, userInv, monsterData, monsShopData, yourMonsInv, monsInvData) - userData[id][4] = str(coin) - elif command.lower() == 'help' : - help(loginStatus, role) - elif command.lower() == 'laboratory' : - coin = laboratory(yourMonsInv, monsterData, coin, role) - userData[id][4] = str(coin) - elif command.lower() == 'jackpot' : - coin = jackpot(id, coin, monsInvData, yourMonsInv) - userData[id][4] = str(coin) - else : - print(f"command '{command}' tidak ada.") - print(userInv) - print(inventoryData) - print(userData) - print(monsInvData) - print(yourMonsInv) - print(itemShopData) - print(monsShopData) - elif role == 'admin' : - while True : - print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") - command = input("--->") - if command.lower() == 'help': - help(loginStatus, role) - elif command.lower() == 'shop': - monsShopData, itemShopData = shopmanagement(itemShopData, monsShopData, monsterData) - elif command.lower() == 'logout' : - t=0 - while True : - confirm = input("Apakah anda yakin untuk logout?(Y/N)-->") - if confirm.lower() == "y" : - print("Logout berhasil") - t=1 - break - elif confirm.lower() =='n' : - break - else : - print("mangsud?") - if t==1 : - loginStatus = False - break - elif command.lower() == 'monster' : - monsterManagement(monsterData) - else : - print("apansih") \ No newline at end of file diff --git a/src/arena.py b/src/arena.py index ff56d56..e6f0515 100644 --- a/src/arena.py +++ b/src/arena.py @@ -66,6 +66,10 @@ def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : break else : #monster kita menang stage += 1 + print("STAGE CLEARED") + print() + if stage != 6 : + print("PREPARING NEXT STAGE") for i in range(1,stage) : coins += reward[i-1] diff --git a/src/battle.py b/src/battle.py index e48c610..4e012c2 100644 --- a/src/battle.py +++ b/src/battle.py @@ -135,7 +135,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran time.sleep(1/10) damage = yourattack*(damagerng/100) if enemyhealth >= (damage-(enemydefense/100)*damage) : #menghitung damagedealt jika enemy belom mati - damagedealt += (damage-(enemydefense/100)*damage) + damagedealt += (int(damage-(enemydefense/100)*damage)+1) else : #jika enemy mati maka damagedealt hanya ditambah sebesar sisa darah enemy sebelum mati damagedealt += enemyhealth enemyhealth -= (damage-(enemydefense/100)*damage) @@ -143,7 +143,10 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran #MENAMPILKAN MEKANISME DAMAGE SERANGAN print("=============================================") print(">>>>>>>>>>>>>>>YOU ATTACKED !!!<<<<<<<<<<<<<<") - print(f"ATTACK DAMAGE : {damage} (+{damagerng-100}%)") + if damagerng < 100 : + print(f"ATTACK DAMAGE : {damage} ({damagerng-100}%)") + else : + print(f"ATTACK DAMAGE : {damage} (+{damagerng-100}%)") print(f"REDUCED DAMAGE : {(enemydefense/100)*damage} ({enemydefense}%)") print(f"TOTAL DAMAGE : {(damage-(enemydefense/100)*damage)}") if enemyhealth > 0 : #JIKA MONSTER BELOM MATI @@ -197,6 +200,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran if type =='battle' : #Jika mode battle action 3 adalah monster ball success = monsterball(random_number,random_level,userinventory,monsterdata,monsterinventory,yourmonsterdata) if success==1 : + print("") return 0,damagetaken,damagedealt elif success ==2 : #Jika gagal continue @@ -226,7 +230,8 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print("YOU DEFEATED YOUR ENEMY") print("WELL DONE") coin = RNG(1,50) - print(f"YOU GOT {coin} COINS") + if type.lower() == 'battle' : + print(f"YOU GOT {coin} COINS") print("=============================================") return coin,damagetaken,damagedealt @@ -235,13 +240,16 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran damagemusuh=enemyattack*(damagemusuhrng/100) print(f">>>>>>>>>>>>>{file1[random_number][1]} ATTACK BACK !!!<<<<<<<<<<<<") if yourhealth >= (damagemusuh - (yourdefense/100)*damagemusuh) : - damagetaken += (damagemusuh - (yourdefense/100)*damagemusuh) #Jika monster kita masih hidup setelah serangan + damagetaken += int(damagemusuh - (yourdefense/100)*damagemusuh) +1 #Jika monster kita masih hidup setelah serangan else : damagetaken += yourhealth #jika monster kita mati setelah serangan yourhealth -= (damagemusuh - (yourdefense/100)*damagemusuh) yourhealth = int(yourhealth) #MENAMPILKAN MEKANISMA DAMAGE SERANGAN - print(f"ATTACK DAMAGE : {damagemusuh} (+{damagemusuhrng-100}%)") + if damagemusuhrng < 100 : + print(f"ATTACK DAMAGE : {damagemusuh} ({damagemusuhrng-100}%)") + else : + print(f"ATTACK DAMAGE : {damagemusuh} (+{damagemusuhrng-100}%)") print(f"REDUCED DAMAGE : {(yourdefense/100)*damagemusuh} ({yourdefense}%)") print(f"TOTAL DAMAGE : {(damagemusuh - (yourdefense/100)*damagemusuh)}") if yourhealth >0 : #jika monster kita masih hidup diff --git a/src/help.py b/src/help.py index f71df55..e0665c0 100644 --- a/src/help.py +++ b/src/help.py @@ -1,7 +1,30 @@ +def godServant() : + print(""" + .---. + / ,-- + .--. ( (^_^) ) .--. + ,' \ (.-`-'(_) / `. + / `-/ \ `. \-' +: (_,' . / (.\_ ") \ . `._) : +| `-'(_,\ \ / /._)`-' | +| . `.\,O,'.' . : | +| . : ! /\_ /\ ! . ! | +| ! |-'-| : ""T"" : |-'-| | | +| |-' `-'| H |`-' `-| | +`-' | H .:| `-' + | . H !|| + | : H :!| + | ! H !|| + | | H ||| + | | H ||| + /_,'V.L|. +""") + def help(status,role) : #jika pengguna belum login, status akan menjadi false dan mengeluarkan beberapa command umum #command umum + godServant() if status == False : - print("List command yang dapat anda lakukan :") + print("List commands you can call :") print("1. Login") print(" Login ke akun admin/agent") print("2. Register") @@ -10,10 +33,15 @@ def help(status,role) : #jika pengguna belum login, status akan menjadi false da print(" Menyimpan semua perubahan dalam sebuah folder") print("4. Exit") print(" Keluar dari program") + print() + print("Footnote :") + print("1. Anda belum login silahkan login terlebih dahulu atau melaukan register") + print("2. Pastikan input yang anda masukkan sudah tepat atau sesuai perintah program") + print("3. Jangan lupa untuk save program sebelum exit") else : #jika pengguna sudah login, tampilkan daftar perintah berdasarkan role pengguna if role == 'agent' : #jika pengguna adalah agent #command yang dapat dilakukan oleh agent - print("List command yang dapat anda lakukan :") + print("List commands you can call :") print("1. Battle") print(" 1v1 dengan monster random") print("2. Arena") @@ -28,13 +56,21 @@ def help(status,role) : #jika pengguna belum login, status akan menjadi false da print(" Tempat untuk menguji keberuntungan anda") print("7. Logout") print(" Keluar dari akun anda") + print() + print("Footnote :") + print("1. Pastikan input yang dimasukkan sesuai dengan perintah program") + print("2. Jangan lupa untuk save program setelah logout") if role == 'admin' : #jika pengguna adalah admin #command yang dapat dilakukan oleh admin - print("List command yang dapat anda lakukan :") + print("List commands you can call :") print("1. Shop") print(" Manage shop") print("2. Monster") print(" Manage monster") print("3. Logout") print(" Keluar dari akun anda") + print() + print("Footnote :") + print("1. Pastikan input yang dimasukkan sesuai dengan perintah program") + print("2. Jangan lupa untuk save program setelah logout") \ No newline at end of file diff --git a/src/inventory.py b/src/inventory.py index 597ddf4..1895ea4 100644 --- a/src/inventory.py +++ b/src/inventory.py @@ -63,6 +63,7 @@ def inventory(userInventory, yourMonsData, monsterData, role, coin) : print('Masukkan input yang benar') elif check.lower() == 'back' : + print("Sampai jumpa lagi !!") break else : diff --git a/src/load.py b/src/load.py index 585b0cc..5f16aa5 100644 --- a/src/load.py +++ b/src/load.py @@ -56,14 +56,35 @@ def login(user,inventory,monsterinventory) : #fungsi untuk login def register(user,inventory,monsterinventory,monster) : #fungsi untuk register while True : usernamebaru = input("Masukkan Username :") #meminta input username baru dari pengguna - #pemeriksaan apakah username sudah terpakai + status = False + for char in usernamebaru: + ascii_value = ord(char) + # Check if the character is a letter, number, hyphen, or underscore + valid = ( + (65 <= ascii_value <= 90) or # A-Z + (97 <= ascii_value <= 122) or # a-z + (48 <= ascii_value <= 57) or # 0-9 + ascii_value == 45 or # strip (-) + ascii_value == 95 # underscore (_) + ) + # If any character is not valid, return False + if valid == False: + print("Username hanya boleh mengandung huruf,angka,strip dan underscore") + break + else : + status = True + if status == False : + continue for i in user : if i[1]== usernamebaru : print("Username sudah terpakai") + status = False break else : - #jika username belum terpakai, keluar dari loop - break + status = True + if status == False : + continue + break passwordbaru = input("Masukkan password :") #meminta input password baru dari pengguna #menampilkan pilihan monster untuk pengguna print('PILIH MONSTER PERTAMA ANDA :') @@ -112,6 +133,7 @@ def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) write_csv(path+"/monster_inventory.csv",monsterinventory) + print() else : os.mkdir(path) write_csv(path+"/item_inventory.csv",inventory) From 022c42b7166c3403711a31806e6727456b2ab5a1 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 05:18:39 +0700 Subject: [PATCH 099/115] change a massage --- main.py | 2 +- src/jackpot.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index f894001..e0713f8 100644 --- a/main.py +++ b/main.py @@ -102,7 +102,7 @@ print(monsShopData) elif role == 'admin' : while True : - print("Type 'help' to seek wisdom from the ALMIGHT GOD") + print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") command = input("--->") if command.lower() == 'help': help(loginStatus, role) diff --git a/src/jackpot.py b/src/jackpot.py index de2693b..df4eaed 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -32,11 +32,11 @@ def gacha(id, coin, monsInv, yourMonsInv): print(f"{icon[indexItem1]} | {icon[indexItem2]} | {icon[indexItem3]}") if indexItem1 == indexItem2 and indexItem2 == indexItem3: - print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') if any(item[1] == "Gorlock" for item in monsInv): - print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') + print('JACKPOT!! KARENA GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') coin += 2000 else: + print('JACKPOT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') monsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list monsterInventory yourMonsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list yourMonsterInventory else: @@ -50,16 +50,17 @@ def jackpot(id, coin, monsInv , yourMonsInv): print("SELAMAT DATANG DI JACKPOT 888!!!") print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 500 COIN") print(f"COIN ANDA SAAT INI SEJUMLAH {coin} ") - print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") + print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???", end=" ") while True: inp = input("(Y/N)----->").lower() if inp == 'y': - confirm = input("APAKAH ANDA YAKIN? (Y/N) :").lower() + confirm = input("APAKAH ANDA YAKIN? (Y/N): ").lower() if confirm == 'y': - if coin >= 500: - coin = gacha(id, coin, monsInv, yourMonsInv) - coin -= 500 + if coin >= 500: + coin = gacha(id, coin, monsInv, yourMonsInv) + coin -= 500 + print() print(f'COIN ANDA TERSISA {coin} ') print("APAKAH ANDA INGIN MELANJUTKAN??", end=" ") else: From dc10d818a1f1f28252c3d3f7daeb224cfc98376e Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 05:20:49 +0700 Subject: [PATCH 100/115] feat:add small detail --- src/jackpot.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index df4eaed..de2693b 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -32,11 +32,11 @@ def gacha(id, coin, monsInv, yourMonsInv): print(f"{icon[indexItem1]} | {icon[indexItem2]} | {icon[indexItem3]}") if indexItem1 == indexItem2 and indexItem2 == indexItem3: + print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') if any(item[1] == "Gorlock" for item in monsInv): - print('JACKPOT!! KARENA GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') + print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') coin += 2000 else: - print('JACKPOT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') monsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list monsterInventory yourMonsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list yourMonsterInventory else: @@ -50,17 +50,16 @@ def jackpot(id, coin, monsInv , yourMonsInv): print("SELAMAT DATANG DI JACKPOT 888!!!") print("ANDA DAPAT MENDAPATKAN GORLOCK THE DESTROYER DENGAN HARGA 500 COIN") print(f"COIN ANDA SAAT INI SEJUMLAH {coin} ") - print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???", end=" ") + print("APAKAH ANDA INGIN MENCOBA KEBERUNTUNGAN ANDA???") while True: inp = input("(Y/N)----->").lower() if inp == 'y': - confirm = input("APAKAH ANDA YAKIN? (Y/N): ").lower() + confirm = input("APAKAH ANDA YAKIN? (Y/N) :").lower() if confirm == 'y': - if coin >= 500: - coin = gacha(id, coin, monsInv, yourMonsInv) - coin -= 500 - print() + if coin >= 500: + coin = gacha(id, coin, monsInv, yourMonsInv) + coin -= 500 print(f'COIN ANDA TERSISA {coin} ') print("APAKAH ANDA INGIN MELANJUTKAN??", end=" ") else: From e68a38e74d7a4d1d1fa4976cc0a66f8be01471ff Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 05:50:32 +0700 Subject: [PATCH 101/115] remove unnecessary line --- src/laboratory.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/laboratory.py b/src/laboratory.py index 77c7197..5e066fa 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -32,7 +32,6 @@ def laboratory(yourMonsData, coin, role): if ord(char) < ord('0') or ord(char) > ord('9'): inputMonsUp = False - print(monsUpgrade) if inputMonsUp != False : if monsUpgrade <= yourMonsData[pilihMons-1][2] : # validasi input upgrade level <= level saat ini print("Masa mau upgrade ke level yg sama/lebih rendah sih.. Itu mah downgrade kak") From c7ae25bad45c4bc1cea11a8fb5f3cab29407d305 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 07:09:03 +0700 Subject: [PATCH 102/115] feat:add small massage --- src/laboratory.py | 1 + src/load.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/laboratory.py b/src/laboratory.py index 5e066fa..46d47fb 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -75,6 +75,7 @@ def laboratory(yourMonsData, coin, role): print('Maaf! Monster yang Anda pilih sudah memiliki level maksimum. Silakan pilih monster lain') break elif pilihMons.lower() == 'back' : + print("Sampai bertemu lagi !") break else : print("Masukkan nomor monster yang benar") diff --git a/src/load.py b/src/load.py index f4dcd04..8045ffe 100644 --- a/src/load.py +++ b/src/load.py @@ -76,7 +76,7 @@ def register(user,inventory,monsterinventory,monster) : #fungsi untuk register if status == False : continue for i in user : - if i[1]== usernamebaru : + if i[1]== usernamebaru : #jika username sudah terpakai print("Username sudah terpakai") status = False break From 22ced04f5c3c5d27dfc98c4a2b11ae11a1d690d0 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 08:14:55 +0700 Subject: [PATCH 103/115] feat: add validation for negative number --- src/monsterManagement.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/monsterManagement.py b/src/monsterManagement.py index 7ad01ae..3093268 100644 --- a/src/monsterManagement.py +++ b/src/monsterManagement.py @@ -33,7 +33,12 @@ def checkAttack(attack): while True: if cekint(attack): # bila keseluruhan attack berupa angka attack = int(attack) # ubah menjadi integer agar dapat dioperasikan + if attack < 0 : + print("Masa attack mines yg bener aje") + attack = str(input("Masukkan attack power : ")) + continue break + else : # terdapat character yang bukan angka print("Masukkan bukan bertipe integer, coba lagi!") attack = str(input("Masukkan attack power : ")) # input berupa string karena untuk pengecekan isdigit() @@ -57,6 +62,10 @@ def checkHp(hp): while True: if cekint(hp): # keseluruhan hp berupa angka hp = int(hp) # ubah menjadi integer agar dapat dioperasikan + if hp < 0 : + print("masa hp mines yang bener aje") + hp = str(input("Masukkan hp : ")) + continue break else : # terdapat character yang bukan angka pada hp print("Masukkan bukan bertipe integer, coba lagi!") From 54fbfa843ec77cb5bc0530bad5ce1cc7f68f2f6d Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Mon, 20 May 2024 08:28:03 +0700 Subject: [PATCH 104/115] fix: input error bug --- src/laboratory.py | 119 +++++++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/src/laboratory.py b/src/laboratory.py index 46d47fb..1e184ac 100644 --- a/src/laboratory.py +++ b/src/laboratory.py @@ -15,68 +15,81 @@ def laboratory(yourMonsData, coin, role): print(f'{i}. Level {i} --> Level {i+1}: {arrayHarga[i-1]}') pilihMons = input('Pilih monster yang ingin di-upgrade (1/2/dst/Back): ') - - inputMonsNum = True # validasi input selain 1/2/3/dst/back + inputMons = True # validasi input selain 1/2/3/dst/back for char in str(pilihMons) : if ord(char) < ord('0') or ord(char) > ord('9'): - inputMonsNum = False + inputMons = False + + if pilihMons.lower() == 'back' : # input = back + print("Sampai bertemu lagi !") + break + + if int(pilihMons) > len(yourMonsData) or int(pilihMons) < 1 : # input > jumlah monster atau input < 1 + inputMons = False - if inputMonsNum != False : - pilihMons = int(pilihMons) - while True: - if yourMonsData[pilihMons-1][2] != '5': - monsUpgrade = input('Silakan pilih ke level berapa kah Anda ingin meng-upgrade monster Anda (1/2/dst/Back): ') - - inputMonsUp = True # validasi input selain 1/2/3/dst/back - for char in str(monsUpgrade) : - if ord(char) < ord('0') or ord(char) > ord('9'): - inputMonsUp = False - - if inputMonsUp != False : - if monsUpgrade <= yourMonsData[pilihMons-1][2] : # validasi input upgrade level <= level saat ini - print("Masa mau upgrade ke level yg sama/lebih rendah sih.. Itu mah downgrade kak") + if inputMons != False : + inputMonsNum = True # validasi input selain 1/2/3/dst/back + for char in str(pilihMons) : + if ord(char) < ord('0') or ord(char) > ord('9'): + inputMonsNum = False + + if inputMonsNum != False : + pilihMons = int(pilihMons) + while True: + if yourMonsData[pilihMons-1][2] != '5': + monsUpgrade = input('Silakan pilih ke level berapa kah Anda ingin meng-upgrade monster Anda (1/2/dst/Back): ') + + inputMonsUp = True # validasi input selain 1/2/3/dst/back + for char in str(monsUpgrade) : + if ord(char) < ord('0') or ord(char) > ord('9'): + inputMonsUp = False + + if inputMonsUp != False : + if monsUpgrade <= yourMonsData[pilihMons-1][2] : # validasi input upgrade level <= level saat ini + print("Masa mau upgrade ke level yg sama/lebih rendah sih.. Itu mah downgrade kak") - elif int(monsUpgrade) > 5 : - print('Upgrade cuman sampai level 5 kakak, level di atas 5 itu level kesulitan tubes daspro') + elif int(monsUpgrade) > 5 : + print('Upgrade cuman sampai level 5 kakak, level di atas 5 itu level kesulitan tubes daspro') - else : - monsUpgrade = int(monsUpgrade) - harga = 0 - for i in range (int(yourMonsData[pilihMons-1][2]), monsUpgrade): # total harga upgrade - harga += arrayHarga[i-1] + else : + monsUpgrade = int(monsUpgrade) + harga = 0 + for i in range (int(yourMonsData[pilihMons-1][2]), monsUpgrade): # total harga upgrade + harga += arrayHarga[i-1] - print(f'{yourMonsData[pilihMons-1][1]} akan di-upgrade ke level {monsUpgrade}') - print(f'Harga untuk meng-upgrade {yourMonsData[pilihMons-1][1]} adalah {harga}') + print(f'{yourMonsData[pilihMons-1][1]} akan di-upgrade ke level {monsUpgrade}') + print(f'Harga untuk meng-upgrade {yourMonsData[pilihMons-1][1]} adalah {harga}') - while True : - lanjut = input('Lanjutkan upgrade (Y/N): ') # konfirmasi upgrade - if lanjut.lower() == 'y': - if coin >= harga : - yourMonsData[pilihMons-1][2] = str(monsUpgrade) - coin -= harga - print(f'Selamat! {yourMonsData[pilihMons-1][1]} berhasil di-upgrade ke level {monsUpgrade}!') - print(f'Coin Anda tersisa {coin}') - break - else : - print('Maaf! Anda tidak memiliki Coin yang cukup') - break - elif lanjut.lower() == 'n' : - break - else : - print("Mohon masukkan input yang benar") - print() + while True : + lanjut = input('Lanjutkan upgrade (Y/N): ') # konfirmasi upgrade + if lanjut.lower() == 'y': + if coin >= harga : + yourMonsData[pilihMons-1][2] = str(monsUpgrade) + coin -= harga + print(f'Selamat! {yourMonsData[pilihMons-1][1]} berhasil di-upgrade ke level {monsUpgrade}!') + print(f'Coin Anda tersisa {coin}') + break + else : + print('Maaf! Anda tidak memiliki Coin yang cukup') + break + elif lanjut.lower() == 'n' : + break + else : + print("Masukkan input yang benar") + print() - elif monsUpgrade.lower() == 'back' : + elif monsUpgrade.lower() == 'back' : + break + else : + print("Masukkan input level yang benar") + print() + else : # jika level sudah max + print('Maaf! Monster yang Anda pilih sudah memiliki level maksimum. Silakan pilih monster lain') break - else : - print("Masukkan input level yang benar") - print() - else : # jika level sudah max - print('Maaf! Monster yang Anda pilih sudah memiliki level maksimum. Silakan pilih monster lain') - break - elif pilihMons.lower() == 'back' : - print("Sampai bertemu lagi !") - break + elif inputMonsNum == 'back': + break + else: + print('Masukkan input yang benar') else : print("Masukkan nomor monster yang benar") print() From c521303e546cdb931a6fde2cf180de5936f2b114 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 08:43:37 +0700 Subject: [PATCH 105/115] fix : fix an error in exit --- src/exit.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/exit.py b/src/exit.py index 461743e..44db483 100644 --- a/src/exit.py +++ b/src/exit.py @@ -1,10 +1,10 @@ from src.load import save def exit(user,monsterinventory,itemshop,monster,monstershop,iteminventory): - confirmExit = input(("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) - while confirmExit != "y" and confirmExit != "n": - confirmExit = input(print("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n)")) - if confirmExit == "y": + confirmExit = input(("Apakah Anda mau melakukan penyimpanan file yang sudah diubah (y/n) :")) + while confirmExit.lower() != "y" and confirmExit.lower() != "n": + confirmExit = input(("Masukkan y/n saja :")) + if confirmExit.lower() == "y": save(iteminventory,monster,user,monstershop,itemshop,monsterinventory) print("Program berhasil disave dan ditutup!") - else: # confirmExit =="n - print("Program berhasil ditutup!") \ No newline at end of file + elif confirmExit.lower() == "n" : + print("Program berhasil ditutup!") From bf84dcc78a1381bd5d8fcaa23d8eec9c937397d5 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 09:03:17 +0700 Subject: [PATCH 106/115] feat: add small detail --- data/data4/item_inventory.csv | 13 +++++++++++++ data/data4/item_shop.csv | 5 +++++ data/data4/monster.csv | 17 +++++++++++++++++ data/data4/monster_inventory.csv | 8 ++++++++ data/data4/monster_shop.csv | 3 +++ data/data4/user.csv | 8 ++++++++ main.py | 1 - src/arena.py | 2 +- src/battle.py | 4 ++-- src/jackpot.py | 5 +++-- src/load.py | 12 +++++++----- src/monsterball.py | 23 +++++++++++------------ 12 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 data/data4/item_inventory.csv create mode 100644 data/data4/item_shop.csv create mode 100644 data/data4/monster.csv create mode 100644 data/data4/monster_inventory.csv create mode 100644 data/data4/monster_shop.csv create mode 100644 data/data4/user.csv diff --git a/data/data4/item_inventory.csv b/data/data4/item_inventory.csv new file mode 100644 index 0000000..82b2573 --- /dev/null +++ b/data/data4/item_inventory.csv @@ -0,0 +1,13 @@ +userid;type;quantity +1;Healing Potion;2 +1;Resilience Potion;3 +1;Strength Potion;2 +1;Monster Ball;2 +3;Healing Potion;2 +3;Resilience Potion;1 +3;Strength Potion;4 +3;Monster Ball;1 +2;Healing Potion;2 +2;Resilience Potion;2 +2;Strength Potion;9 +2;Monster Ball;5 \ No newline at end of file diff --git a/data/data4/item_shop.csv b/data/data4/item_shop.csv new file mode 100644 index 0000000..7e08cd5 --- /dev/null +++ b/data/data4/item_shop.csv @@ -0,0 +1,5 @@ +type;stock;price +Healing Potion;5;25 +Resilience Potion;5;30 +Strength Potion;5;40 +Monster Ball;5;100 \ No newline at end of file diff --git a/data/data4/monster.csv b/data/data4/monster.csv new file mode 100644 index 0000000..2de3d0a --- /dev/null +++ b/data/data4/monster.csv @@ -0,0 +1,17 @@ +id;type;atk_power;def_power;hp +1;Godzilla;70;32;540 +2;Mimic;45;28;600 +3;Makima;135;5;250 +4;Jalangkung;3700;12;650 +5;gigidi;54;19;420 +6;Gorlock;22;20;700 +7;Bunny;65;24;550 +8;Roga;88;8;222 +9;Molded;66;24;440 +10;Mohg;50;20;600 +11;Malenia;55;30;500 +12;Kraken;20;35;570 +13;Mothra;57;21;520 +14;Parkinson;44;31;470 +15;Ifrit;90;5;330 +16;ohio;100;10;10 \ No newline at end of file diff --git a/data/data4/monster_inventory.csv b/data/data4/monster_inventory.csv new file mode 100644 index 0000000..f38ffeb --- /dev/null +++ b/data/data4/monster_inventory.csv @@ -0,0 +1,8 @@ +id;monster;level +1;Mimic;5 +1;Makima;2 +1;Jalangkung;3 +2;Makima;1 +2;Mimic;1 +3;Jalangkung;2 +3;Mimic;1 \ No newline at end of file diff --git a/data/data4/monster_shop.csv b/data/data4/monster_shop.csv new file mode 100644 index 0000000..e920ed1 --- /dev/null +++ b/data/data4/monster_shop.csv @@ -0,0 +1,3 @@ +monster_id;stock;price +1;6;800 +3;2;750 \ No newline at end of file diff --git a/data/data4/user.csv b/data/data4/user.csv new file mode 100644 index 0000000..9a132df --- /dev/null +++ b/data/data4/user.csv @@ -0,0 +1,8 @@ +id;username;password;role;coin +1;bagas;12345;agent;99999993760 +2;bagus;12345;agent;100 +3;bages;12345;agent;100 +4;bagos;12345;agent;100 +5;bagis;12345;agent;100 +6;june;12345;admin;9999 +7;juni;12345;admin;9999 \ No newline at end of file diff --git a/main.py b/main.py index e0713f8..d47ed5b 100644 --- a/main.py +++ b/main.py @@ -60,7 +60,6 @@ battleCoin,damageTaken,damageDealt = battle(monsterData, monsInvData, yourMonsInv, userInv, chosen, randomNumber, randomLevel, 'battle') coin += battleCoin userData[id][4] = str(coin) - print(userInv) elif command.lower() == 'arena' : arenaCoin = arena(monsterData, monsInvData, yourMonsInv, userInv) coin += arenaCoin diff --git a/src/arena.py b/src/arena.py index e6f0515..0d81d48 100644 --- a/src/arena.py +++ b/src/arena.py @@ -42,7 +42,7 @@ def arenarule() : def arena(monsterdata,monsterinventory,yourmonsterdata,userinventory) : #deklarasi variabel - reward = [20,35,50,75,90] #coins gain from defeating each stage + reward = [30,45,60,75,90] #coins gain from defeating each stage coins=0 totaldamageTaken = 0 totaldamageDealt = 0 diff --git a/src/battle.py b/src/battle.py index 4e012c2..ab59317 100644 --- a/src/battle.py +++ b/src/battle.py @@ -200,7 +200,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran if type =='battle' : #Jika mode battle action 3 adalah monster ball success = monsterball(random_number,random_level,userinventory,monsterdata,monsterinventory,yourmonsterdata) if success==1 : - print("") + print(f"{file1[random_number][1].upper()} IS ADDED TO YOUR INVENTORY") return 0,damagetaken,damagedealt elif success ==2 : #Jika gagal continue @@ -229,7 +229,7 @@ def battle(monsterdata,monsterinventory,yourmonsterdata,userinventory,chosen,ran print("=============================================") print("YOU DEFEATED YOUR ENEMY") print("WELL DONE") - coin = RNG(1,50) + coin = RNG(1,100) if type.lower() == 'battle' : print(f"YOU GOT {coin} COINS") print("=============================================") diff --git a/src/jackpot.py b/src/jackpot.py index de2693b..65f9b35 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -28,8 +28,9 @@ def gacha(id, coin, monsInv, yourMonsInv): indexItem2 = prob(RNG2) indexItem3 = prob(RNG3) totalcoin = iconValue[indexItem1] + iconValue[indexItem2] + iconValue[indexItem3] - + print("==========================") print(f"{icon[indexItem1]} | {icon[indexItem2]} | {icon[indexItem3]}") + print("==========================") if indexItem1 == indexItem2 and indexItem2 == indexItem3: print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') @@ -73,4 +74,4 @@ def jackpot(id, coin, monsInv , yourMonsInv): elif inp == 'n': return coin else: - print("Masukkan input yang benar") + print("Masukkan input yang benar") \ No newline at end of file diff --git a/src/load.py b/src/load.py index 8045ffe..ecd54fa 100644 --- a/src/load.py +++ b/src/load.py @@ -19,7 +19,7 @@ def load() : monsterinventory = read_csv(path+"/monster_inventory.csv") itemshop=read_csv(path+"/item_shop.csv") monstershop=read_csv(path+"/monster_shop.csv") - return [user,inventory,monster,monsterinventory,itemshop,monstershop] + return [user,inventory,monster,monsterinventory,itemshop,monstershop] #return semua variabel utama else: # folder tidak ditemukan print(f"Folder \"{path}\" tidak ditemukan.") return [] @@ -124,17 +124,17 @@ def write(path,data) : def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : # ALGORITMA - path = "data/" + input("Masukkan nama folder: ") + path = "data/" + input("Masukkan nama folder: ") #path folder tujuan print("Saving...") - if (os.path.exists(path)) : + if (os.path.exists(path)) : #jika folder sudah ada write_csv(path+"/item_inventory.csv",inventory) write_csv(path+"/user.csv",user) write_csv(path+"/monster.csv",monster) write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) write_csv(path+"/monster_inventory.csv",monsterinventory) - print() - else : + print(f"Berhasil melakukan Save pada folder {path}") + else : #jika folder belum ada os.mkdir(path) write_csv(path+"/item_inventory.csv",inventory) write_csv(path+"/user.csv",user) @@ -142,3 +142,5 @@ def save(inventory,monster,user,monstershop,itemshop,monsterinventory) : write_csv(path+"/monster_shop.csv",monstershop) write_csv(path+"/item_shop.csv",itemshop) write_csv(path+"/monster_inventory.csv",monsterinventory) + print(f"Membuat folder baru {path}") + print(f"Berhasil melakukan Save pada folder {path}") diff --git a/src/monsterball.py b/src/monsterball.py index 8e19008..8f0aa5a 100644 --- a/src/monsterball.py +++ b/src/monsterball.py @@ -4,7 +4,6 @@ def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventory,yourmonsterdata): jumlahball = int(userinventory[3][2]) chance = RNG(1,100) - print(chance) success = 0 if jumlahball >= 1 : # Cek apakah player memiliki monster bal; for i in yourmonsterdata : # Looping untuk cek apakah monster yang ingin ditangkap sudah ada di inventory @@ -13,41 +12,41 @@ def monsterball(monsterid,monsterlevel,userinventory,monsterdata,monsterinventor success= 2 return success else : # bila monster tidak dimiliki player - print('WHOOSSHHH anda melempar monster ball') + print('WHOOSSHHH YOU THROWED THE MONSTER BALL') jumlahball -=1 # 1 bola sudah digunakan userinventory[3][2]=str(jumlahball) if monsterlevel==1 : # bila monster yang dilawan level 1, maka chance player mendapatkan monster tersebut 75% if chance>=1 and chance<=75 : - print('ANDA DAPAT!!') + print('SUCCESS!!') success = 1 else : - print('yaah ga dapet') + print('THE MONSTER ESCAPED THE BALL!!') elif monsterlevel==2 : # monster level 2, chance 50% if chance>=1 and chance<=50 : - print('ANDA DAPAT!!') + print('SUCCESS!!') success = 1 else : print('yaah ga dapet') elif monsterlevel==3 : # monster level 3, chance 25% if chance>=1 and chance<=25 : - print('ANDA DAPAT!!') + print('SUCCESS!!') success = 1 else : - print('yaah ga dapet') + print('THE MONSTER ESCAPED THE BALL!!') elif monsterlevel==4 : # monster level 4, chance 10% if chance>=1 and chance<=10 : - print('ANDA DAPAT!!') + print('SUCCESS!!') success = 1 else : - print('yaah ga dapet') + print('THE MONSTER ESCAPED THE BALL!!') elif monsterlevel==5 : # monster level 5, chance 5% if chance>=1 and chance<=5 : - print('ANDA DAPAT!!') + print('SUCCESS!!') success = 1 else : - print('yaah ga dapet') + print('THE MONSTER ESCAPED THE BALL!!') else : # Player tidak memiliki monster ball - print('Anda tidak memiliki monster ball') + print('YOU DONT HAVE A MONSTER BALL') success = 2 if success==1 : # success = 1 berarti monster success ditangkap dan monster ditambah ke inventory player yourmonsterdata.append([userinventory[0][0],monsterdata[monsterid][1],str(monsterlevel)]) From cc75ea0f4a9499f5ee68ff34d6eb4a8cbf6e5563 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Mon, 20 May 2024 09:43:16 +0700 Subject: [PATCH 107/115] style: change wrong output text at strength potion --- src/potion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/potion.py b/src/potion.py index 968f4e5..242fda0 100644 --- a/src/potion.py +++ b/src/potion.py @@ -62,7 +62,7 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, print("Potion STRENGTH hanya bisa digunakan sekali") return 0 # return 0 untuk mengindikasi potion tidak bisa digunakan else : - print("Yahh.. Sayangnya Anda tidak memiliki potion RESILIENCE") + print("Yahh.. Sayangnya Anda tidak memiliki potion STRENGTH") return 0 elif pilihan == 2 : From e4711be4de6a1b2a003219c865d74246057ec2bc Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Mon, 20 May 2024 09:54:40 +0700 Subject: [PATCH 108/115] refactor: remove doubled program at healing potion --- src/potion.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/potion.py b/src/potion.py index 242fda0..244851f 100644 --- a/src/potion.py +++ b/src/potion.py @@ -86,17 +86,13 @@ def potion(jumlahpot, indexPot, used_Pot_Array, userInventory, attack, defense, if used_Pot_Array[2] == 0 : # mengecek pernah tidaknya potion healing digunakan used_Pot_Array[2] += 1 if HP * 125/100 <= max_HP : # mengecek penggunaan potion melebihi HP maksimum atau tidak - HP *= 125/100 - print(f"Potion HEALING telah diminum, HP {mons_Name} telah REGENERASI!") - jumlahpot[2] -= 1 - userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) - return HP # return nilai HP monster setelah menggunakan potion healing + HP *= 125/100 # return nilai HP monster setelah menggunakan potion healing else : HP = max_HP - print(f"Potion HEALING telah diminum, HP {mons_Name} telah REGENERASI!") - jumlahpot[2] -= 1 - userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) - return HP + print(f"Potion HEALING telah diminum, HP {mons_Name} telah REGENERASI!") + jumlahpot[2] -= 1 + userInventory[indexPot[2]][2] = str(int(userInventory[indexPot[2]][2])-1) + return HP else : print("Potion HEALING hanya bisa digunakan sekali") return 0 From a92fac349a69cba15c11877300a80523797745a1 Mon Sep 17 00:00:00 2001 From: usernamedarren <19623168@std.stei.itb.ac.id> Date: Mon, 20 May 2024 11:30:58 +0700 Subject: [PATCH 109/115] style: change jackpot reward output text --- src/jackpot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jackpot.py b/src/jackpot.py index 65f9b35..5cf98ee 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -33,9 +33,9 @@ def gacha(id, coin, monsInv, yourMonsInv): print("==========================") if indexItem1 == indexItem2 and indexItem2 == indexItem3: - print('SELAMAT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') + print('JACKPOT!! ANDA MENDAPATKAN GORLOCK THE DESTROYER! DESTROY EVERYTHING!') if any(item[1] == "Gorlock" for item in monsInv): - print('SELAMAT!! GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') + print('GORLOCK SUDAH ANDA MILIKI, GORLOCK AKAN DIUBAH KE O.W.C.A Coin sebanyak 2000 Coin') coin += 2000 else: monsInv.append([str(id),"Gorlock",'1']) # append Gorlock ke list monsterInventory From 93b6082e09e5311e7b450971583c91497e8c58c3 Mon Sep 17 00:00:00 2001 From: Ghifaruru <16523058@std.stei.itb.ac.id> Date: Mon, 20 May 2024 11:42:03 +0700 Subject: [PATCH 110/115] feat: add detai; --- main.py | 7 ------- src/jackpot.py | 2 ++ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/main.py b/main.py index d47ed5b..2464fd7 100644 --- a/main.py +++ b/main.py @@ -92,13 +92,6 @@ userData[id][4] = str(coin) else : print(f"command '{command}' tidak ada.") - print(userInv) - print(inventoryData) - print(userData) - print(monsInvData) - print(yourMonsInv) - print(itemShopData) - print(monsShopData) elif role == 'admin' : while True : print("Ketik 'Help' untuk mendapatkan petunjuk dari Almighty God") diff --git a/src/jackpot.py b/src/jackpot.py index 65f9b35..29ff927 100644 --- a/src/jackpot.py +++ b/src/jackpot.py @@ -68,10 +68,12 @@ def jackpot(id, coin, monsInv , yourMonsInv): print("SILAKAN COBA JACKPOT DI WAKTU LAIN") break elif confirm == 'n': + print("Sampai bertemu lagi :)") return coin else: print("Masukkan input yang benar") elif inp == 'n': + print("Sampai bertemu lagi :)") return coin else: print("Masukkan input yang benar") \ No newline at end of file From 9a05408742bfa0cbdad5a3b60cd2b0e2ac557464 Mon Sep 17 00:00:00 2001 From: 19623238-Favian <148781301+19623238-Favian@users.noreply.github.com> Date: Mon, 20 May 2024 11:53:16 +0700 Subject: [PATCH 111/115] docs: Uploaded Form MoM Asistensi 1 dan 2 --- doc/MoM Asistensi 1.pdf | Bin 0 -> 1020869 bytes doc/MoM Asistensi 2.pdf | Bin 0 -> 1797847 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/MoM Asistensi 1.pdf create mode 100644 doc/MoM Asistensi 2.pdf diff --git a/doc/MoM Asistensi 1.pdf b/doc/MoM Asistensi 1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f36875b86bd598ce319e3cbe44a657bd1869a7f5 GIT binary patch literal 1020869 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%0AXHbQ{eD;!*9t^oy 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 <9E@)8BRZ-EkbaGF-8U|?y8J=tQakw<`7c_T; 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