Final day of changes for 7DRL 2025 - Crypt of Sokoban game code
This commit is contained in:
parent
5b259d0b38
commit
f594998dc3
|
@ -1,5 +1,6 @@
|
|||
import mcrfpy
|
||||
import random
|
||||
from cos_itemdata import itemdata
|
||||
#t = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
||||
t = mcrfpy.Texture("assets/kenney_TD_MR_IP.png", 16, 16)
|
||||
#def iterable_entities(grid):
|
||||
|
@ -110,7 +111,7 @@ class COSEntity(): #mcrfpy.Entity): # Fake mcrfpy.Entity integration; engine bu
|
|||
self.do_move(tx, ty)
|
||||
|
||||
class Equippable:
|
||||
def __init__(self, hands = 0, hp_healing = 0, damage = 0, defense = 0, zap_damage = 1, zap_cooldown = 10, sprite = 129):
|
||||
def __init__(self, hands = 0, hp_healing = 0, damage = 0, defense = 0, zap_damage = 1, zap_cooldown = 10, sprite = 129, boost=None, text="", text_color=(255, 255, 255), value=0):
|
||||
self.hands = hands
|
||||
self.hp_healing = hp_healing
|
||||
self.damage = damage
|
||||
|
@ -118,8 +119,12 @@ class Equippable:
|
|||
self.zap_damage = zap_damage
|
||||
self.zap_cooldown = zap_cooldown
|
||||
self.zap_cooldown_remaining = 0
|
||||
self.sprite = self.sprite
|
||||
self.sprite = sprite
|
||||
self.quality = 0
|
||||
self.text = text
|
||||
self.text_color = text_color
|
||||
self.boost = boost
|
||||
self.value = value
|
||||
|
||||
def tick(self):
|
||||
if self.zap_cooldown_remaining:
|
||||
|
@ -128,7 +133,7 @@ class Equippable:
|
|||
|
||||
def __repr__(self):
|
||||
cooldown_str = f'({self.zap_cooldown_remaining} rounds until ready)'
|
||||
return f"<Equippable hands={self.hands}, hp_healing={self.hp_healing}, damage={self.damage}, defense={self.defense}, zap_damage={self.zap_damage}, zap_cooldown={self.zap_cooldown}{cooldown_str if self.zap_cooldown_remaining else ''}, sprite={self.sprite}>"
|
||||
return f"<Equippable text={self.text}, hands={self.hands}, hp_healing={self.hp_healing}, damage={self.damage}, defense={self.defense}, zap_damage={self.zap_damage}, zap_cooldown={self.zap_cooldown}{cooldown_str if self.zap_cooldown_remaining else ''}, sprite={self.sprite}>"
|
||||
|
||||
def classify(self):
|
||||
categories = []
|
||||
|
@ -147,6 +152,54 @@ class Equippable:
|
|||
else:
|
||||
return "Erratic: " + ', '.join(categories)
|
||||
|
||||
def consume(self, consumer):
|
||||
if self.boost == "green_pot":
|
||||
consumer.base_damage += self.value
|
||||
elif self.boost == "blue_pot":
|
||||
b = self.value
|
||||
while b: #split bonus between damage and faster cooldown
|
||||
bonus = random.choice(["damage", "cooldown", "range"])
|
||||
if bonus == "damage":
|
||||
consumer.base_zap_damage += 1
|
||||
elif bonus == "cooldown":
|
||||
consumer.base_zap_cooldown += 1
|
||||
else:
|
||||
consumer.base_zap_range += 1
|
||||
b -= 1
|
||||
elif self.boost == "grey_pot":
|
||||
consumer.base_defense += self.value
|
||||
elif self.boost == "sm_grey_pot":
|
||||
consumer.luck += self.value
|
||||
elif self.hp_healing:
|
||||
consumer.hp += self.hp_healing
|
||||
if consumer.hp > consumer.max_hp: consumer.hp = consumer.max_hp
|
||||
|
||||
def do_zap(self, caster, entities):
|
||||
if self.zap_damage == 0:
|
||||
print("This item can't zap.")
|
||||
return False
|
||||
if self.zap_cooldown_remaining != 0:
|
||||
print("zap is cooling down.")
|
||||
return False
|
||||
fx, fy = caster.draw_pos
|
||||
x, y = int(fx), int (fy)
|
||||
dist = lambda tx, ty: abs(int(tx) - x) + abs(int(ty) - y)
|
||||
targets = []
|
||||
for e in entities:
|
||||
if type(e) != EnemyEntity: continue
|
||||
if dist(*e.draw_pos) > caster.base_zap_range:
|
||||
continue
|
||||
if e.hp <= 0: continue
|
||||
targets.append(e)
|
||||
if not targets:
|
||||
print("No targets found in range.")
|
||||
return False
|
||||
target = random.choice(targets)
|
||||
print(f"Zap! {target}")
|
||||
target.get_zapped(self.zap_damage)
|
||||
self.zap_cooldown_remaining = self.zap_cooldown
|
||||
return True
|
||||
|
||||
#def compare(self, other):
|
||||
# my_class = self.classify()
|
||||
# o_class = other.classify()
|
||||
|
@ -169,6 +222,9 @@ class PlayerEntity(COSEntity):
|
|||
self.archetype = None
|
||||
self.equipped = []
|
||||
self.inventory = []
|
||||
self.base_zap_damage = 0
|
||||
self.base_zap_cooldown = 0
|
||||
self.base_zap_range = 4
|
||||
|
||||
def tick(self):
|
||||
for i in self.equipped:
|
||||
|
@ -183,19 +239,48 @@ class PlayerEntity(COSEntity):
|
|||
def calc_defense(self):
|
||||
defense = self.base_defense
|
||||
for i in self.equipped:
|
||||
defense += i.damage
|
||||
defense += i.defense
|
||||
return defense
|
||||
|
||||
def do_zap(self):
|
||||
pass
|
||||
for i in self.equipped:
|
||||
if i.zap_damage and i.zap_cooldown_remaining == 0:
|
||||
if i.do_zap(self, self.game.entities):
|
||||
break
|
||||
else:
|
||||
print("Couldn't zap")
|
||||
|
||||
def bump(self, other, dx, dy, test=False):
|
||||
if type(other) == BoulderEntity:
|
||||
print("Boulder hit w/ knockback!")
|
||||
return self.game.pull_boulder_move((-dx, -dy), other)
|
||||
print(f"oof, ouch, {other} bumped the player - {other.base_damage} damage from {other}")
|
||||
#print(f"oof, ouch, {other} bumped the player - {other.base_damage} damage from {other}")
|
||||
self.hp = max(self.hp - max(other.base_damage - self.calc_defense(), 0), 0)
|
||||
|
||||
def receive(self, equip):
|
||||
print(equip)
|
||||
if (equip.hands == 0):
|
||||
if len([i for i in self.inventory if i is not None]) < 3:
|
||||
if None in self.inventory:
|
||||
self.inventory[self.inventory.index(None)] = equip
|
||||
else:
|
||||
self.inventory.append(equip)
|
||||
return
|
||||
else:
|
||||
print("something something, consumable GUI")
|
||||
elif (equip.hands == 1):
|
||||
if len(self.equipped) < 2:
|
||||
self.equipped.append(equip)
|
||||
return
|
||||
else:
|
||||
print("Something something, 1h GUI")
|
||||
else: # equip.hands == 2:
|
||||
if len(self.equipped) == 0:
|
||||
self.equipped.append(equip)
|
||||
return
|
||||
else:
|
||||
print("Something something, 2h GUI")
|
||||
|
||||
def respawn(self, avoid=None):
|
||||
# find spawn point
|
||||
x_max, y_max = g.size
|
||||
|
@ -287,7 +372,7 @@ class ExitEntity(COSEntity):
|
|||
#TODO - player go down a level logic
|
||||
if type(other) == PlayerEntity:
|
||||
self.game.depth += 1
|
||||
print(f"welcome to level {self.game.depth}")
|
||||
#print(f"welcome to level {self.game.depth}")
|
||||
self.game.create_level(self.game.depth)
|
||||
self.game.swap_level(self.game.level, self.game.spawn_point)
|
||||
|
||||
|
@ -346,10 +431,12 @@ class EnemyEntity(COSEntity):
|
|||
return
|
||||
|
||||
# slow movement (doesn't affect ability to attack)
|
||||
if self.moved_last < 0:
|
||||
if self.moved_last > 0:
|
||||
self.moved_last -= 1
|
||||
#print(f"Deducting move cooldown, now {self.moved_last} / {self.move_cooldown}")
|
||||
return
|
||||
else:
|
||||
#print(f"Restaring move cooldown - {self.move_cooldown}")
|
||||
self.moved_last = self.move_cooldown
|
||||
|
||||
# if player is not nearby, wander
|
||||
|
@ -359,35 +446,94 @@ class EnemyEntity(COSEntity):
|
|||
|
||||
# if can_push and player in a line: KICK
|
||||
if self.can_push:
|
||||
if int(x) == int(px):
|
||||
pass # vertical kick
|
||||
elif int(y) == int(py):
|
||||
pass # horizontal kick
|
||||
if int(x) == int(px):# vertical kick
|
||||
self.try_move(0, 1 if y < py else -1)
|
||||
elif int(y) == int(py):# horizontal kick
|
||||
self.try_move(1 if x < px else -1, 0)
|
||||
|
||||
# else, nearby pursue
|
||||
towards = []
|
||||
dist = lambda dx, dy: abs(px - (x + dx)) + abs(py - (y + dy))
|
||||
current_dist = dist(0, 0)
|
||||
for d in ((1, 0), (0, 1), (-1, 0), (1, 0)):
|
||||
if dist(*d) <= current_dist + 0.75: towards.append(d)
|
||||
print(current_dist, towards)
|
||||
target_dir = random.choice(towards)
|
||||
#current_dist = dist(0, 0)
|
||||
#for d in ((1, 0), (0, 1), (-1, 0), (1, 0)):
|
||||
# if dist(*d) <= current_dist + 0.75: towards.append(d)
|
||||
#print(current_dist, towards)
|
||||
if px >= x:
|
||||
towards.append((1, 0))
|
||||
if px <= x:
|
||||
towards.append((-1, 0))
|
||||
if py >= y:
|
||||
towards.append((0, 1))
|
||||
if py <= y:
|
||||
towards.append((0, -1))
|
||||
towards = [p for p in towards if self.game.grid.at((int(x + p[0]), int(y + p[1]))).walkable]
|
||||
towards.sort(key = lambda p: dist(*p))
|
||||
target_dir = towards[0]
|
||||
self.try_move(*target_dir)
|
||||
|
||||
def get_zapped(self, d):
|
||||
self.hp -= d
|
||||
self.hp = max(self.hp, 0)
|
||||
if self.hp == 0:
|
||||
self._entity.sprite_number = self.base_sprite + 246
|
||||
self.draw_order = 1
|
||||
print(f"Player zapped for {d}. HP = {self.hp}")
|
||||
|
||||
|
||||
class TreasureEntity(COSEntity):
|
||||
def __init__(self, x, y, treasure_table=None, *, game):
|
||||
self.draw_order = 6
|
||||
super().__init__(game.grid, x, y, 89, game=game)
|
||||
self.popped = False
|
||||
self.treasure_table = treasure_table
|
||||
|
||||
def generate(self):
|
||||
items = list(self.treasure_table.keys())
|
||||
weights = [self.treasure_table[k] for k in items]
|
||||
item = random.choices(items, weights=weights)[0]
|
||||
bonus_stats_max = (self.game.depth + (self.game.player.luck*2)) * 0.66
|
||||
bonus_stats = random.randint(0, int(bonus_stats_max))
|
||||
bonus_colors = {1: (192, 255, 192), 2: (128, 128, 192), 3: (255, 192, 255),
|
||||
4: (255, 192, 192), 5: (255, 0, 0)}
|
||||
|
||||
data = itemdata[item]
|
||||
if item in ("sword", "sword2", "sword3", "axe", "axe2", "axe3"):
|
||||
equip = Equippable(hands=data.handedness, sprite=data.sprite, damage=data.base_value+bonus_stats, text=data.base_name)
|
||||
elif item in ("buckler", "shield"):
|
||||
equip = Equippable(hands=data.handedness, sprite=data.sprite, defense=data.base_value+bonus_stats, text=data.base_name)
|
||||
elif item in ("wand", "staff", "staff2"):
|
||||
equip = Equippable(hands=data.handedness, sprite=data.sprite, zap_damage=data.base_value[0], zap_cooldown=data.base_value[1], text=data.base_name)
|
||||
if bonus_stats:
|
||||
b = bonus_stats
|
||||
while b: # split bonus between damage and faster cooldown
|
||||
if equip.zap_cooldown == 2 or random.random() > 0.66:
|
||||
equip.zap_damage += 1
|
||||
else:
|
||||
equip.zap_cooldown -= 1
|
||||
b -= 1
|
||||
elif item == "red_pot":
|
||||
equip = Equippable(hands=data.handedness, sprite=data.sprite, hp_healing=data.base_value+bonus_stats, text=data.base_name)
|
||||
elif item in ("blue_pot", "green_pot", "grey_pot", "sm_grey_pot"):
|
||||
print(f"Permanent stat boost ({item})")
|
||||
equip = Equippable(hands=data.handedness, sprite=data.sprite, text=data.base_name, boost=item, value=data.base_value + bonus_stats)
|
||||
else:
|
||||
print(f"Unfound item: {item}")
|
||||
equip = Equippable()
|
||||
|
||||
if bonus_stats:
|
||||
equip.text = equip.text + f" (+{bonus_stats})"
|
||||
equip.text_color = bonus_colors[bonus_stats if bonus_stats <=5 else 5]
|
||||
return equip
|
||||
|
||||
def bump(self, other, dx, dy, test=False):
|
||||
if type(other) != PlayerEntity:
|
||||
return False
|
||||
if self.popped:
|
||||
print("It's already open.")
|
||||
return
|
||||
return True
|
||||
print("Take me, I'm yours!")
|
||||
self._entity.sprite_number = 91
|
||||
self.popped = True
|
||||
|
||||
#print(self.treasure_table)
|
||||
other.receive(self.generate())
|
||||
return False
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class ItemData:
|
||||
min_lv: int
|
||||
max_lv: int
|
||||
base_wt: float
|
||||
sprite: int
|
||||
base_value: int
|
||||
base_name: str
|
||||
affinity: str # player archetype that makes it more common
|
||||
handedness: int
|
||||
|
||||
itemdata = {
|
||||
"buckler": ItemData(min_lv = 1, max_lv = 10, base_wt = 0.25, sprite=101, base_value=1,
|
||||
base_name="Buckler", affinity="knight", handedness=1),
|
||||
|
||||
"shield": ItemData(min_lv = 2, max_lv = 99, base_wt = 0.15, sprite=102, base_value=2,
|
||||
base_name="Shield", affinity="knight", handedness=1),
|
||||
|
||||
"sword": ItemData(min_lv = 1, max_lv = 10, base_wt = 0.25, sprite=103, base_value=1,
|
||||
base_name="Shortsword", affinity="knight", handedness=1),
|
||||
|
||||
"sword2": ItemData(min_lv = 2, max_lv = 16, base_wt = 0.15, sprite=104, base_value=2,
|
||||
base_name="Longsword", affinity="knight", handedness=1),
|
||||
|
||||
"sword3": ItemData(min_lv = 5, max_lv = 99, base_wt = 0.08, sprite=105, base_value=5,
|
||||
base_name="Claymore", affinity="knight", handedness=2),
|
||||
|
||||
"axe": ItemData(min_lv = 1, max_lv = 10, base_wt = 0.25, sprite=119, base_value=1,
|
||||
base_name="Hatchet", affinity="viking", handedness=1),
|
||||
|
||||
"axe2": ItemData(min_lv = 2, max_lv = 16, base_wt = 0.15, sprite=120, base_value=4,
|
||||
base_name="Broad Axe", affinity="viking", handedness=2),
|
||||
|
||||
"axe3": ItemData(min_lv = 5, max_lv = 99, base_wt = 0.08, sprite=121, base_value=6,
|
||||
base_name="Bearded Axe", affinity="viking", handedness=2),
|
||||
|
||||
"wand": ItemData(min_lv = 1, max_lv = 10, base_wt = 0.25, sprite=132, base_value=(1, 10),
|
||||
base_name="Wand", affinity="wizard", handedness=1),
|
||||
|
||||
"staff": ItemData(min_lv = 2, max_lv = 16, base_wt = 0.15, sprite=130, base_value=(2, 8),
|
||||
base_name="Sceptre", affinity="wizard", handedness=2),
|
||||
|
||||
"staff2": ItemData(min_lv = 5, max_lv = 99, base_wt = 0.08, sprite=131, base_value=(3, 7),
|
||||
base_name="Wizard's Staff", affinity="wizard", handedness=2),
|
||||
|
||||
"red_pot": ItemData(min_lv = 1, max_lv = 99, base_wt = 0.25, sprite=115, base_value=1,
|
||||
base_name="Health Potion", affinity=None, handedness=0),
|
||||
|
||||
"blue_pot": ItemData(min_lv = 1, max_lv = 99, base_wt = 0.10, sprite=116, base_value=1,
|
||||
base_name="Sorcery Potion", affinity="wizard", handedness=0),
|
||||
|
||||
"green_pot": ItemData(min_lv = 1, max_lv = 99, base_wt = 0.10, sprite=114, base_value=1,
|
||||
base_name="Strength Potion", affinity="viking", handedness=0),
|
||||
|
||||
"grey_pot": ItemData(min_lv = 1, max_lv = 99, base_wt = 0.10, sprite=113, base_value=1,
|
||||
base_name="Defense Potion", affinity="knight", handedness=0),
|
||||
|
||||
"sm_grey_pot": ItemData(min_lv = 1, max_lv = 99, base_wt = 0.05, sprite=125, base_value=1,
|
||||
base_name="Luck Potion", affinity=None, handedness=0),
|
||||
}
|
|
@ -105,7 +105,7 @@ class Level:
|
|||
self.height = height
|
||||
#self.graph = [(0, 0, width, height)]
|
||||
self.graph = RoomGraph( (0, 0, width, height) )
|
||||
self.grid = mcrfpy.Grid(width, height, t, (10, 10), (1014, 758))
|
||||
self.grid = mcrfpy.Grid(width, height, t, (10, 5), (1014, 700))
|
||||
self.highlighted = -1 #debug view feature
|
||||
self.walled_rooms = [] # for tracking "hallway rooms" vs "walled rooms"
|
||||
|
||||
|
@ -236,18 +236,25 @@ class Level:
|
|||
for f in room_plan:
|
||||
#feature_coords.append((f, room_coord(room, margin=4 if f in ("boulder",) else 1)))
|
||||
# boulders are breaking my brain. If I can't get boulders away from walls with margin, I'm just going to dig them out.
|
||||
if f == "boulder":
|
||||
x, y = room_coord(room, margin=0)
|
||||
if x < 2: x += 1
|
||||
if y < 2: y += 1
|
||||
if x > self.grid.grid_size[0] - 2: x -= 1
|
||||
if y > self.grid.grid_size[1] - 2: y -= 1
|
||||
for _x in (1, 0, -1):
|
||||
for _y in (1, 0, -1):
|
||||
self.grid.at((x + _x, y + _y)).walkable = True
|
||||
feature_coords.append((f, (x, y)))
|
||||
else:
|
||||
feature_coords.append((f, room_coord(room, margin=0)))
|
||||
#if f == "boulder":
|
||||
# x, y = room_coord(room, margin=0)
|
||||
# if x < 2: x += 1
|
||||
# if y < 2: y += 1
|
||||
# if x > self.grid.grid_size[0] - 2: x -= 1
|
||||
# if y > self.grid.grid_size[1] - 2: y -= 1
|
||||
# for _x in (1, 0, -1):
|
||||
# for _y in (1, 0, -1):
|
||||
# self.grid.at((x + _x, y + _y)).walkable = True
|
||||
# feature_coords.append((f, (x, y)))
|
||||
#else:
|
||||
# feature_coords.append((f, room_coord(room, margin=0)))
|
||||
fcoord = None
|
||||
while not fcoord:
|
||||
fc = room_coord(room, margin=0)
|
||||
if not self.grid.at(fc).walkable: continue
|
||||
if fc in [_i[1] for _i in feature_coords]: continue
|
||||
fcoord = fc
|
||||
feature_coords.append((f, fcoord))
|
||||
print(feature_coords[-1])
|
||||
|
||||
## Hallway generation
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import mcrfpy
|
||||
import code
|
||||
|
||||
#t = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) # 12, 11)
|
||||
t = mcrfpy.Texture("assets/kenney_TD_MR_IP.png", 16, 16) # 12, 11)
|
||||
btn_tex = mcrfpy.Texture("assets/48px_ui_icons-KenneyNL.png", 48, 48)
|
||||
|
@ -9,6 +11,7 @@ frame_color = (64, 64, 128)
|
|||
import random
|
||||
import cos_entities as ce
|
||||
import cos_level as cl
|
||||
from cos_itemdata import itemdata
|
||||
#import cos_tiles as ct
|
||||
|
||||
class Resources:
|
||||
|
@ -53,7 +56,8 @@ class Crypt:
|
|||
|
||||
self.level_plan = {
|
||||
1: [("spawn", "button", "boulder"), ("exit")],
|
||||
2: [("spawn", "button", "boulder"), ("rat"), ("exit")],
|
||||
2: [("spawn", "button", "treasure", "treasure", "treasure", "rat", "rat", "boulder"), ("exit")],
|
||||
#2: [("spawn", "button", "boulder"), ("rat"), ("exit")],
|
||||
3: [("spawn", "button", "boulder"), ("rat"), ("exit")],
|
||||
4: [("spawn", "button", "rat"), ("boulder", "rat", "treasure"), ("exit")],
|
||||
5: [("spawn", "button", "rat"), ("boulder", "rat"), ("exit")],
|
||||
|
@ -99,6 +103,7 @@ class Crypt:
|
|||
mcrfpy.Caption((25, 130 + 95 * i), "x", font, fill_color=(255, 255, 255)) for i in range(5)
|
||||
]
|
||||
for i in self.inv_captions:
|
||||
i.size = 16
|
||||
self.sidebar.children.append(i)
|
||||
|
||||
liminal_void = mcrfpy.Grid(1, 1, t, (0, 0), (16, 16))
|
||||
|
@ -177,7 +182,11 @@ class Crypt:
|
|||
self.inv_sprites[i].sprite_number = item.sprite
|
||||
if i > 1:
|
||||
self.key_captions[i - 2].sprite_number = 384 + (i - 2)
|
||||
self.inv_captions[i].text = "Blah"
|
||||
if item.zap_cooldown_remaining:
|
||||
self.inv_captions[i].text = f"[{item.zap_cooldown_remaining}] {item.text})"
|
||||
else:
|
||||
self.inv_captions[i].text = item.text
|
||||
self.inv_captions[i].fill_color = item.text_color
|
||||
|
||||
def lv_planner(self, target_level):
|
||||
"""Plan room sequence in levels > 9"""
|
||||
|
@ -210,47 +219,27 @@ class Crypt:
|
|||
|
||||
def treasure_planner(self, treasure_level):
|
||||
"""Plan treasure contents at all levels"""
|
||||
item_minlv = {
|
||||
"buckler": 1,
|
||||
"shield": 2,
|
||||
"sword": 1,
|
||||
"sword2": 2,
|
||||
"sword3": 5,
|
||||
"axe": 1,
|
||||
"axe2": 2,
|
||||
"axe3": 5,
|
||||
"wand": 1,
|
||||
"staff": 2,
|
||||
"staff2": 5,
|
||||
"red_pot": 3,
|
||||
"blue_pot": 6,
|
||||
"green_pot": 6,
|
||||
"grey_pot": 6,
|
||||
"sm_grey_pot": 1
|
||||
}
|
||||
base_wts = {
|
||||
("buckler", "shield"): 0.25, # defensive items
|
||||
("sword", "sword2", "axe", "axe2"): 0.4, #1h weapons
|
||||
("sword3", "axe3"): 0.25, #2h weapons
|
||||
("wand", "staff", "staff2"): 0.15, #magic weapons
|
||||
("red_pot",): 0.25, #health
|
||||
("blue_pot", "green_pot", "grey_pot", "sm_grey_pot"): 0.2 #stat upgrade potions
|
||||
}
|
||||
|
||||
# find item name in base_wts key (base weight of the category)
|
||||
base_weight = lambda s: base_wts[list([t for t in base_wts.keys() if s in t])[0]]
|
||||
weights = {d[0]: base_weight(d[0]) for d in item_minlv.items() if treasure_level > d[1]}
|
||||
if self.player.archetype is None:
|
||||
prefs = []
|
||||
elif self.player.archetype == "viking":
|
||||
prefs = ["axe2", "axe3", "green_pot"]
|
||||
elif self.player.archetype == "knight":
|
||||
prefs = ["sword2", "shield", "grey_pot"]
|
||||
elif self.player.archetype == "wizard":
|
||||
prefs = ["staff", "staff2", "blue_pot"]
|
||||
for i in prefs:
|
||||
if i in weights: weights[i] *= 3
|
||||
|
||||
#base_weight = lambda s: base_wts[list([t for t in base_wts.keys() if s in t])[0]]
|
||||
#weights = {d[0]: base_weight(d[0]) for d in item_minlv.items() if treasure_level > d[1]}
|
||||
#if self.player.archetype is None:
|
||||
# prefs = []
|
||||
#elif self.player.archetype == "viking":
|
||||
# prefs = ["axe2", "axe3", "green_pot"]
|
||||
#elif self.player.archetype == "knight":
|
||||
# prefs = ["sword2", "shield", "grey_pot"]
|
||||
#elif self.player.archetype == "wizard":
|
||||
# prefs = ["staff", "staff2", "blue_pot"]
|
||||
#for i in prefs:
|
||||
# if i in weights: weights[i] *= 3
|
||||
weights = {}
|
||||
for item in itemdata:
|
||||
data = itemdata[item]
|
||||
if data.min_lv > treasure_level or treasure_level > data.max_lv: continue
|
||||
weights[item] = data.base_wt
|
||||
if self.player.archetype is not None and data.affinity == self.player.archetype:
|
||||
weights[item] *= 3
|
||||
return weights
|
||||
|
||||
def start(self):
|
||||
|
@ -317,10 +306,37 @@ class Crypt:
|
|||
def cos_keys(self, key, state):
|
||||
d = None
|
||||
if state == "end": return
|
||||
elif key == "Grave":
|
||||
code.InteractiveConsole(locals=globals()).interact()
|
||||
return
|
||||
elif key == "Z":
|
||||
self.player.do_zap()
|
||||
self.enemy_turn()
|
||||
return
|
||||
elif key == "W": d = (0, -1)
|
||||
elif key == "A": d = (-1, 0)
|
||||
elif key == "S": d = (0, 1)
|
||||
elif key == "D": d = (1, 0)
|
||||
elif key == "Num1":
|
||||
if len(self.player.inventory) > 0:
|
||||
self.player.inventory[0].consume(self.player)
|
||||
self.player.inventory[0] = None
|
||||
self.enemy_turn()
|
||||
else:
|
||||
print("No item")
|
||||
elif key == "Num2":
|
||||
if len(self.player.inventory) > 1:
|
||||
self.player.inventory[1].consume(self.player)
|
||||
self.player.inventory[1] = None
|
||||
else:
|
||||
print("No item")
|
||||
elif key == "Num3":
|
||||
if len(self.player.inventory) > 2:
|
||||
self.player.inventory[2].consume(self.player)
|
||||
self.player.inventory[2] = None
|
||||
else:
|
||||
print("No item")
|
||||
|
||||
#elif key == "M": self.level.generate()
|
||||
#elif key == "R":
|
||||
# self.level.reset()
|
||||
|
@ -345,8 +361,8 @@ class Crypt:
|
|||
self.enemy_turn()
|
||||
elif key == "X":
|
||||
self.pull_boulder_search()
|
||||
#else:
|
||||
# print(key)
|
||||
else:
|
||||
print(key)
|
||||
if d:
|
||||
self.entities.sort(key = lambda e: e.draw_order, reverse=False)
|
||||
self.player.try_move(*d)
|
||||
|
@ -356,8 +372,13 @@ class Crypt:
|
|||
self.entities.sort(key = lambda e: e.draw_order, reverse=False)
|
||||
for e in self.entities:
|
||||
e.act()
|
||||
# end of enemy turn = player turn
|
||||
for i in self.player.equipped:
|
||||
i.tick()
|
||||
self.gui_update()
|
||||
|
||||
|
||||
|
||||
def pull_boulder_search(self):
|
||||
for dx, dy in ( (0, -1), (-1, 0), (1, 0), (0, 1) ):
|
||||
for e in self.entities:
|
||||
|
@ -405,9 +426,9 @@ class SweetButton:
|
|||
pos:"Tuple[int, int]",
|
||||
caption:str, font=font, font_size=24, font_color=(255,255,255), font_outline_color=(0, 0, 0), font_outline_width=2,
|
||||
shadow_offset = 8, box_width=200, box_height = 80, shadow_color=(64, 64, 86), box_color=(96, 96, 160),
|
||||
icon=4, icon_scale=1.75, click=lambda *args: None):
|
||||
icon=4, icon_scale=1.75, shadow=True, click=lambda *args: None):
|
||||
self.ui = ui
|
||||
self.shadow_box = mcrfpy.Frame
|
||||
#self.shadow_box = mcrfpy.Frame
|
||||
x, y = pos
|
||||
|
||||
# box w/ drop shadow
|
||||
|
@ -416,7 +437,8 @@ class SweetButton:
|
|||
self.base_frame.click = self.do_click
|
||||
|
||||
# drop shadow won't need configured, append directly
|
||||
self.base_frame.children.append(mcrfpy.Frame(0, 0, box_width, box_height, fill_color = shadow_color))
|
||||
if shadow:
|
||||
self.base_frame.children.append(mcrfpy.Frame(0, 0, box_width, box_height, fill_color = shadow_color))
|
||||
|
||||
# main button is where the content lives
|
||||
self.main_button = mcrfpy.Frame(shadow_offset, shadow_offset, box_width, box_height, fill_color = box_color)
|
||||
|
@ -472,8 +494,56 @@ class MainMenu:
|
|||
|
||||
components = []
|
||||
# demo grid
|
||||
#components.append(
|
||||
# )
|
||||
self.demo = cl.Level(20, 20)
|
||||
self.grid = self.demo.grid
|
||||
self.grid.zoom = 1.75
|
||||
coords = self.demo.generate(
|
||||
[("boulder", "boulder", "rat", "cyclops", "boulder"), ("spawn"), ("rat", "big rat"), ("button", "boulder", "exit")]
|
||||
)
|
||||
self.entities = []
|
||||
self.add_entity = lambda e: self.entities.append(e)
|
||||
#self.create_level = lambda *args: None
|
||||
buttons = []
|
||||
#self.depth = 20
|
||||
for k, v in sorted(coords, key=lambda i: i[0]): # "button" before "exit"; "button", "button", "door", "exit" -> alphabetical is correct sequence
|
||||
if k == "spawn":
|
||||
self.player = ce.PlayerEntity(game=self)
|
||||
self.player.draw_pos = v
|
||||
#if self.player:
|
||||
# self.add_entity(self.player)
|
||||
# #self.player.draw_pos = v
|
||||
# self.spawn_point = v
|
||||
elif k == "boulder":
|
||||
ce.BoulderEntity(v[0], v[1], game=self)
|
||||
elif k == "treasure":
|
||||
ce.TreasureEntity(v[0], v[1], treasure_table = {}, game=self)
|
||||
elif k == "button":
|
||||
buttons.append(v)
|
||||
elif k == "exit":
|
||||
btn = buttons.pop(0)
|
||||
ce.ExitEntity(v[0], v[1], btn[0], btn[1], game=self)
|
||||
elif k == "rat":
|
||||
ce.EnemyEntity(*v, game=self)
|
||||
elif k == "big rat":
|
||||
ce.EnemyEntity(*v, game=self, base_damage=2, hp=4, sprite=124)
|
||||
elif k == "cyclops":
|
||||
ce.EnemyEntity(*v, game=self, base_damage=3, hp=8, sprite=109, base_defense=2, can_push=True, move_cooldown=0)
|
||||
#self.demo = cl.Level(20, 20)
|
||||
#self.create_level(self.depth)
|
||||
for e in self.entities:
|
||||
self.grid.entities.append(e._entity)
|
||||
def just_wiggle(*args):
|
||||
try:
|
||||
self.player.try_move(*random.choice(((1, 0),(-1, 0),(0, 1),(0, -1))))
|
||||
for e in self.entities:
|
||||
e.act()
|
||||
except:
|
||||
pass
|
||||
mcrfpy.setTimer("demo_motion", just_wiggle, 100)
|
||||
components.append(
|
||||
self.demo.grid
|
||||
)
|
||||
|
||||
|
||||
# title text
|
||||
drop_shadow = mcrfpy.Caption((150, 10), "Crypt Of Sokoban", font, fill_color=(96, 96, 96), outline_color=(192, 0, 0))
|
||||
|
@ -499,7 +569,7 @@ class MainMenu:
|
|||
|
||||
# button - PLAY
|
||||
#playbtn = mcrfpy.Frame(284, 548, 456, 120, fill_color =
|
||||
play_btn = SweetButton(self.ui, (284, 548), "PLAY", box_width=456, box_height=110, icon=1, icon_scale=2.0, click=self.play)
|
||||
play_btn = SweetButton(self.ui, (20, 248), "PLAY", box_width=200, box_height=110, icon=1, icon_scale=2.0, click=self.play)
|
||||
components.append(play_btn.base_frame)
|
||||
|
||||
# button - config menu pane
|
||||
|
@ -514,16 +584,17 @@ class MainMenu:
|
|||
|
||||
# button - music toggle
|
||||
music_btn = SweetButton(self.ui, (10+256*2, 678), "Music\nON", icon=12, click=self.music_toggle)
|
||||
self.music_enabled = True
|
||||
self.music_volume = 40
|
||||
resources.music_enabled = True
|
||||
resources.music_volume = 40
|
||||
components.append(music_btn.base_frame)
|
||||
|
||||
# button - sfx toggle
|
||||
sfx_btn = SweetButton(self.ui, (10+256*3, 678), "SFX\nON", icon=0, click=self.sfx_toggle)
|
||||
self.sfx_enabled = True
|
||||
self.sfx_volume = 40
|
||||
resources.sfx_enabled = True
|
||||
resources.sfx_volume = 40
|
||||
components.append(sfx_btn.base_frame)
|
||||
|
||||
|
||||
[self.ui.append(e) for e in components]
|
||||
|
||||
def toast_say(self, txt, delay=10):
|
||||
|
@ -577,9 +648,9 @@ class MainMenu:
|
|||
|
||||
def music_toggle(self, sweet_btn, args):
|
||||
if args[3] == "end": return
|
||||
self.music_enabled = not self.music_enabled
|
||||
print(f"music: {self.music_enabled}")
|
||||
if self.music_enabled:
|
||||
resources.music_enabled = not resources.music_enabled
|
||||
print(f"music: {resources.music_enabled}")
|
||||
if resources.music_enabled:
|
||||
mcrfpy.setMusicVolume(self.music_volume)
|
||||
sweet_btn.text = "Music is ON"
|
||||
sweet_btn.sprite_number = 12
|
||||
|
@ -591,9 +662,9 @@ class MainMenu:
|
|||
|
||||
def sfx_toggle(self, sweet_btn, args):
|
||||
if args[3] == "end": return
|
||||
self.sfx_enabled = not self.sfx_enabled
|
||||
print(f"sfx: {self.sfx_enabled}")
|
||||
if self.sfx_enabled:
|
||||
resources.sfx_enabled = not resources.sfx_enabled
|
||||
#print(f"sfx: {resources.sfx_enabled}")
|
||||
if resources.sfx_enabled:
|
||||
mcrfpy.setSoundVolume(self.sfx_volume)
|
||||
sweet_btn.text = "SFX are ON"
|
||||
sweet_btn.sprite_number = 0
|
||||
|
|
Loading…
Reference in New Issue