From 03c110bea21fc2dee49944c0a79d225557c69f3e Mon Sep 17 00:00:00 2001 From: Pat Wick Date: Sun, 3 Mar 2024 20:11:56 -0500 Subject: [PATCH] started implementing level gen and char creation The levels off the start (mostly for testing) are hard-coded, but I would like to eventually integrate at least some element of randomness to them to give it a more dynamic feel from one playthrough to another. That will also save me effort in having to design each individual level, but it does mean that I need to make sure I don't have the randomly generated levels somehow lock the player out of advancing the game. For character creation eventually the warrior will be a melee based character while the mage and rogue will be ranged characters - I'm not sure how ranged attacks will work in the terminal, but that's the next thing on my list to test. From there, I want to start interacting with enemies and have both dynamic monster difficulty from level to level and a level-up system for the player to scale with the monsters. Probably not going to get to all 100 levels the original game has, but I would like to get to a point where I through Sauron and Morgoth at the player and have that feel like it matters. If I can get 5 levels and a halfway decent combat system, I'll be floored and probably spend my entire summer developing this project... --- __pycache__/dungeon.cpython-310.pyc | Bin 0 -> 747 bytes __pycache__/map.cpython-310.pyc | Bin 0 -> 1829 bytes __pycache__/player.cpython-310.pyc | Bin 0 -> 1202 bytes __pycache__/wall.cpython-310.pyc | Bin 0 -> 455 bytes angband.py | 36 ++++++++++++++++++++ dungeon.py | 27 +++++++++++++++ map.py | 49 ++++++++++++++++++++++++++++ player.py | 48 +++++++++++++++++++++++++++ poetry.lock | 6 ++-- wall.py | 6 ++++ 10 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 __pycache__/dungeon.cpython-310.pyc create mode 100644 __pycache__/map.cpython-310.pyc create mode 100644 __pycache__/player.cpython-310.pyc create mode 100644 __pycache__/wall.cpython-310.pyc create mode 100644 angband.py create mode 100644 dungeon.py create mode 100644 map.py create mode 100644 player.py create mode 100644 wall.py diff --git a/__pycache__/dungeon.cpython-310.pyc b/__pycache__/dungeon.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..356562853ede5e3849a9a6c21e8c1b339e568f3e GIT binary patch literal 747 zcmY*WJ#X7E5Is_o^bJmKZq#fzb8M;Ft_J)x97@+sWZsFS`4as*~ z|0<0zl-`opR~VuvJLj<3eAs1335T(5g0aZ*H=ct8~c!3)zPeP@r6(ih#uJ^2$~Wxbx*hO znepZE8WXHlT{MNNj9Xs^sAlQLTt)m-d~W+8GV zF)4TXB-vI)^D$Xv_d;W%RdTpsy#8SVAqv_R;=-2X5_MR_9tMY2$H(p2D7IQ#g%BnZ zqEvFbvVJVYW}B^!JNGKnQq;u*n(p4;6|z~FcpogVm@k^P0nSjic4h zIJsKs9@WxzctWww*}?jR`jRLBm+ij+i=CJaS)UDgpY=Ka7l*BOHe&61a*iFGwuhNu Px^LvOJ+-!PbJqC}xS*xz literal 0 HcmV?d00001 diff --git a/__pycache__/map.cpython-310.pyc b/__pycache__/map.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..493dbad692449298af40e4f519fa554aa9fb5dce GIT binary patch literal 1829 zcmah~OK;mo5Z+xrM7`WZNo~PM5vPZsI>bs5pvb{+3#4doMgg}dAk+|OEiJPmMS96p zaXYl9UwhO@x{ptAQ)V#Jt@u}_KJh8QBX19!>`F4>XzRh)=@HsgxG%-Bq5vHei< zP*pHD;?Kw3<0KBc=_DMCy0JeB$HV?4%#ZtnLGWfLnbR6c7x{-g_S3#~4M5Wv5 zsjlrrVU`b)INhycyFVzG+wA$>!^BszAIM>lZSO?Mz>l(B7>n3T`4h3XFtRp;$={>= z&rtRD3WhmhC=>T!p-%j?oYu+FfS}W5(rB|wZ@H2s$qK$;Nl}r_hBKiEkmf&@`x~;B zFEK`wVn2Ym@;#T(lvq~YwYGSdYQZ8b&n{pgJnClYbd*0H1|3(|N^Z08d7!Ill7)Gg zj5BTJNvhq$B+rvr+fi_oYe$8{9ErDR>67)7 zW?|t(i#m!O8(>tI6-X_>5&zgi zZDIZWklw(14WxTZNMh5p?!g8i*#M3Ch-df7E@y2va@2#%aL-Bl@BbhP4K8ShHmqyN zdUEoaAE$@ z`~9^10`E1nJX+GSsC|cMkpdKKL0h2a6KEUr&!L?WhjxtrAvF0PLzjN%+<)~+aZB*( z9#WbU2zG-zwSo%eK{hc=tLDT{Cyw_7I;3MK_vu(R?zA z72W;XP0dF_5&znr;5(t{`ZC>O&X-}+Y_?LAoj8$CqhOaVvy3utum-1}C%mfX HHCq1yjmlF& literal 0 HcmV?d00001 diff --git a/__pycache__/player.cpython-310.pyc b/__pycache__/player.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53a088e2ff3f3431b3d7d08e838e036e633604e6 GIT binary patch literal 1202 zcmZuwUvJYe5VsvCO}lIiG`1opp5P%8T7`H6gf_t#Xs8=(2vH$fS?sl0+oU)hrBn9A zKFIb6AIYzXhkXQifjjq)%7i1I@8Y|k?|x@z^Yaw~!&HB&&?V#t8neRzV;yFG2ZSV& zc1V{tC?#7&GU=QV>3n4kCixx--AnKxAvNbv>)T&*}=eAhne38p-6*D z0tmF>NY>!ek^GD_TkQ)_p&_cCs`UY!*kU+)E;#ACBki_j;H)DDF^dX4xi-poZL$|5p_73}qiwVO z4oX3e$VYbSobrMmQAs}&9a@dGnO-g&=~PL<580`kdT6bTt%9Ai!o8s2&CZ>%=3?bG zngh;`)m*@NR5%6Dyh0{8XjQE>#d$Nu*()p#GB`U!uMQ0Q+nXQ6>&+MYri|L#S6eUl z^&Av(NkL2;p6|S`8xI}c?P??^nqEvR2n1)`5zxiDd6^h>i4H&K-t-w05DwO}? zE~h6eBL3@M4}H9=$h{DzB1AWn z$3U1cfe@dLqt1Az9JeAJ#eJpqB4&rrNmo(aMu7*;2;^SlWk$C=0O1o(As^;D!IIsn jhmM)EuV&4br;$RtGlOGcZ6p0Bqr{#fc{x%Zly0!UE9n$r literal 0 HcmV?d00001 diff --git a/__pycache__/wall.cpython-310.pyc b/__pycache__/wall.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ac7ff27db930010527c0e4fe06cd63e200a8fea GIT binary patch literal 455 zcmY*Uy-ve05VoBZg{oaT^%c6*LQF^qRbpW4!hn?JWNbsNCUI~QML;(?@C3XAuavR8 z1rv9HO5vpMeth@cefHDon4!&g2m6Zgi;AH|Sga7$4BZVg%aapSuLWVGCeHr)lY!zf4K!^4M9UbQ~*GZUMS6K<-VGQ9c29YE<^uIn^5# vl&))6W8ty5#cr;#JQijWhNGjvQYi literal 0 HcmV?d00001 diff --git a/angband.py b/angband.py new file mode 100644 index 0000000..99ee75e --- /dev/null +++ b/angband.py @@ -0,0 +1,36 @@ +from retro.game import Game +from player import Player +from dungeon import Dungeon +from random import sample +from wall import Wall +from map import ( + board_edges, + inner_board, + level_one, +) + +print("Welcome to AngBAD (a poor representation of Angband)!\n") + +race = input("Choose your race (Human, Elf, Dwarf): ").capitalize() +while race not in ["Human", "Elf", "Dwarf"]: + print("Invalid race. Please choose Human, Elf, or Dwarf.") + race = input("Choose your race (Human, Elf, Dwarf): ").capitalize() + +class_ = input("Choose your class (Warrior, Mage, Rogue): ").capitalize() +while class_ not in ["Warrior", "Mage", "Rogue"]: + print("Invalid class. Please choose Warrior, Mage, or Rogue.") + class_ = input("Choose your class (Warrior, Mage, Rogue): ").capitalize() + +print(f"\nYou've chosen to play as a {race} {class_}.") +input("Press Enter to continue. Good luck!") + +board_size = (25,25) +x,y = board_size +walls = [Wall(position) for position in board_edges(board_size)] +level = [Wall(position) for position in level_one(board_size)] +game = Game(walls + level, {}, board_size = board_size) +game.add_agent(Player((x//2,y//2),race,class_)) + + + +game.play() \ No newline at end of file diff --git a/dungeon.py b/dungeon.py new file mode 100644 index 0000000..585f823 --- /dev/null +++ b/dungeon.py @@ -0,0 +1,27 @@ +# dungeon.py +# ------------ +# By Pat Wick +# This module defines a dungeon generation algorithm. I +# still need to figure out what that might actually mean + +class Dungeon: + board_size = (10,10) + board_width = 10 + board_height = 10 + position = (0,0) + dungeon_map = [["."] * board_width] * board_height + + + for row in range(board_height): + for col in range(board_width): + if row == 0 or row == board_height-1: + dungeon_map[row][col] = "#" + else: + if col == 0 or col == board_width-1: + dungeon_map[row][col] = "#" + else: + dungeon_map[row][col] = "." + + def __init__(self, position): + self.position = position + self.name = "dungeon" \ No newline at end of file diff --git a/map.py b/map.py new file mode 100644 index 0000000..108950e --- /dev/null +++ b/map.py @@ -0,0 +1,49 @@ +from retro.game import Game +from random import sample +from player import Player +from wall import Wall + +def board_edges(board_size): + x,y = board_size + positions = [] + top = [(i,0) for i in range(x)] + bottom = [(i,y-1) for i in range(x)] + left = [(0,j) for j in range(1,y-1)] + right = [(x-1,j) for j in range(1,y-1)] + return top + bottom + left + right + +def inner_board(board_size): + x,y = board_size + positions = [] + for i in range(1,x-1): + for j in range(1,y-1): + positions.append((i,j)) + return positions + +def level_one(board_size): + x,y = board_size + positions = [] + for i in range(1,x-1): + for j in range(1,y//4): + if i <= x // 4 or i >= x - (x // 4): + positions.append((i,j)) + for i in range(1,x//4): + for j in range((y - (y // 4)), y-1): + positions.append((i,j)) + + # for i in range(1,x-1): + # for j in range(1,y-1): + # if i >=4 and i <= 7 or i >= 13 and i <= 16: + # if j >= 4 and j <= 7 or j >= 13 and j <= 16: + # positions.append((i,j)) + return positions + +def level_two(board_size): + x,y = board_size + positions = [] + for i in range(1,x-1): + for j in range(1,y-1): + if i >=4 and i <= 7 or i >= 13 and i <= 16: + if j >= 4 and j <= 7 or j >= 13 and j <= 16: + positions.append((i,j)) + return positions \ No newline at end of file diff --git a/player.py b/player.py new file mode 100644 index 0000000..6d35182 --- /dev/null +++ b/player.py @@ -0,0 +1,48 @@ +# player.py +# ------------ +# By Pat Wick +# This module defines a player agent class. This is intended +# to be used in an implementation of an adventure game but could +# generally be adapted for other player character uses. + +from retro.agent import ArrowKeyAgent + +class Player: + character = "O" + name = "player" + level = 1 + + def __init__(self, position, race, class_): + self.position = position + if class_.capitalize() == "Warrior": + self.color = "red" + elif class_.capitalize() == "Rogue": + self.color = "green" + else: + self.color = "blue" + + def handle_keystroke(self, keystroke, game): + x, y = self.position + if keystroke.name in ("KEY_LEFT", "KEY_RIGHT"): + if keystroke.name == "KEY_LEFT": + new_position = (x - 1, y) + else: + new_position = (x + 1, y) + if game.on_board(new_position): + if game.is_empty(new_position): + self.position = new_position + + if keystroke.name in ("KEY_DOWN", "KEY_UP"): + if keystroke.name == "KEY_DOWN": + new_position = (x, y + 1) + else: + new_position = (x, y - 1) + if game.on_board(new_position): + if game.is_empty(new_position): + self.position = new_position + + def get_agent_in_position(self, position, game): + + agents = game.get_agents_by_position()[position] + if agents: + return agents[0] \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index c447dd7..8fa1998 100644 --- a/poetry.lock +++ b/poetry.lock @@ -393,13 +393,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "retro-games" -version = "0.1.2" +version = "0.1.3" description = "A simple framework for Terminal-based games" optional = false python-versions = ">=3.10,<4.0" files = [ - {file = "retro_games-0.1.2-py3-none-any.whl", hash = "sha256:5f906c2755c7ab7328120a1f38164e806c6d27e7433d47995648bda01817284b"}, - {file = "retro_games-0.1.2.tar.gz", hash = "sha256:b6cb2212c6c8fba011b37a36e638477922d2de8cb5834412963e1cbd240d9a8f"}, + {file = "retro_games-0.1.3-py3-none-any.whl", hash = "sha256:7567c3a65cf5deb855bded8db810a66902b9706349dde415b6254de087a6d8f9"}, + {file = "retro_games-0.1.3.tar.gz", hash = "sha256:a95fbeacdf903761b4c70522dd25f858d9802dcd701e900b95b7535f0014f266"}, ] [package.dependencies] diff --git a/wall.py b/wall.py new file mode 100644 index 0000000..65c2930 --- /dev/null +++ b/wall.py @@ -0,0 +1,6 @@ +class Wall: + #name = "wall" + character = "█" + + def __init__(self,position): + self.position = position \ No newline at end of file