ysn-rfd/text-dataset-tiny-code-script-py-format
USED of tahamajs/medicine_ds_persian for .parquet file USED of Alijafarixcs2/persian-it-llama2-2k for .parquet file USED of Abirate/english_quotes for .jsonl file NEW FILES (05/12/2025) NEW FILES (12/26/2025) NEW FILES (02/15/2026)
31.6k
1import os
2import sys
3import json
4import random
5import time
6import math
7import pickle
8import importlib
9from enum import Enum
10from dataclasses import dataclass, field
11from typing import Dict, List, Optional, Tuple, Callable, Any, Union
12from abc import ABC, abstractmethod
13
14# Color codes for terminal output
15class Colors:
16 RESET = '\033[0m'
17 BLACK = '\033[30m'
18 RED = '\033[31m'
19 GREEN = '\033[32m'
20 YELLOW = '\033[33m'
21 BLUE = '\033[34m'
22 MAGENTA = '\033[35m'
23 CYAN = '\033[36m'
24 WHITE = '\033[37m'
25 BRIGHT_BLACK = '\033[90m'
26 BRIGHT_RED = '\033[91m'
27 BRIGHT_GREEN = '\033[92m'
28 BRIGHT_YELLOW = '\033[93m'
29 BRIGHT_BLUE = '\033[94m'
30 BRIGHT_MAGENTA = '\033[95m'
31 BRIGHT_CYAN = '\033[96m'
32 BRIGHT_WHITE = '\033[97m'
33 BG_BLACK = '\033[40m'
34 BG_RED = '\033[41m'
35 BG_GREEN = '\033[42m'
36 BG_YELLOW = '\033[43m'
37 BG_BLUE = '\033[44m'
38 BG_MAGENTA = '\033[45m'
39 BG_CYAN = '\033[46m'
40 BG_WHITE = '\033[47m'
41
42# Game Enums
43class Direction(Enum):
44 NORTH = "north"
45 SOUTH = "south"
46 EAST = "east"
47 WEST = "west"
48 NORTHEAST = "northeast"
49 NORTHWEST = "northwest"
50 SOUTHEAST = "southeast"
51 SOUTHWEST = "southwest"
52 UP = "up"
53 DOWN = "down"
54
55class SkillType(Enum):
56 COMBAT = "combat"
57 MAGIC = "magic"
58 STEALTH = "stealth"
59 CRAFTING = "crafting"
60 SOCIAL = "social"
61 SURVIVAL = "survival"
62
63class Weather(Enum):
64 CLEAR = "clear"
65 CLOUDY = "cloudy"
66 RAINY = "rainy"
67 STORMY = "stormy"
68 SNOWY = "snowy"
69 FOGGY = "foggy"
70
71class TimeOfDay(Enum):
72 DAWN = "dawn"
73 MORNING = "morning"
74 NOON = "noon"
75 AFTERNOON = "afternoon"
76 DUSK = "dusk"
77 EVENING = "evening"
78 NIGHT = "night"
79 MIDNIGHT = "midnight"
80
81# Data Classes
82@dataclass
83class Position:
84 x: int = 0
85 y: int = 0
86 z: int = 0
87
88@dataclass
89class Stats:
90 health: int = 100
91 max_health: int = 100
92 mana: int = 50
93 max_mana: int = 50
94 stamina: int = 100
95 max_stamina: int = 100
96 hunger: int = 100
97 max_hunger: int = 100
98 thirst: int = 100
99 max_thirst: int = 100
100 experience: int = 0
101 level: int = 1
102
103 def level_up(self):
104 self.level += 1
105 self.experience = 0
106 self.max_health += 10
107 self.health = self.max_health
108 self.max_mana += 5
109 self.mana = self.max_mana
110 self.max_stamina += 5
111 self.stamina = self.max_stamina
112
113@dataclass
114class Skill:
115 name: str
116 type: SkillType
117 level: int = 1
118 experience: int = 0
119 max_experience: int = 100
120
121 def gain_experience(self, amount: int):
122 self.experience += amount
123 while self.experience >= self.max_experience:
124 self.experience -= self.max_experience
125 self.level += 1
126 self.max_experience = int(self.max_experience * 1.5)
127 return True # Leveled up
128 return False
129
130@dataclass
131class Item:
132 id: str
133 name: str
134 description: str
135 value: int = 0
136 weight: float = 1.0
137 consumable: bool = False
138 equippable: bool = False
139 stackable: bool = True
140 max_stack: int = 99
141 effects: Dict[str, Any] = field(default_factory=dict)
142
143 def use(self, player):
144 if self.consumable:
145 for stat, value in self.effects.items():
146 if hasattr(player.stats, stat):
147 current = getattr(player.stats, stat)
148 max_stat = getattr(player.stats, f"max_{stat}")
149 setattr(player.stats, stat, min(max_stat, current + value))
150 return True
151 return False
152
153@dataclass
154class Weapon(Item):
155 damage: int = 10
156 damage_type: str = "physical"
157 two_handed: bool = False
158 range: int = 1
159
160 def __post_init__(self):
161 self.equippable = True
162
163@dataclass
164class Armor(Item):
165 defense: int = 5
166 armor_type: str = "light"
167 slot: str = "chest"
168
169 def __post_init__(self):
170 self.equippable = True
171
172@dataclass
173class Quest:
174 id: str
175 name: str
176 description: str
177 objectives: List[str]
178 rewards: Dict[str, Any]
179 completed: bool = False
180 active: bool = False
181
182@dataclass
183class NPC:
184 id: str
185 name: str
186 description: str
187 dialogue: Dict[str, List[str]]
188 location_id: str
189 hostile: bool = False
190 stats: Stats = field(default_factory=Stats)
191 inventory: List[Item] = field(default_factory=list)
192 quests: List[Quest] = field(default_factory=list)
193 faction: str = "neutral"
194
195 def talk(self, topic="greeting"):
196 if topic in self.dialogue:
197 return random.choice(self.dialogue[topic])
198 return "I don't have anything to say about that."
199
200@dataclass
201class Location:
202 id: str
203 name: str
204 description: str
205 exits: Dict[Direction, str] = field(default_factory=dict)
206 items: List[Item] = field(default_factory=list)
207 npcs: List[NPC] = field(default_factory=list)
208 discovered: bool = False
209 indoor: bool = False
210 position: Position = field(default_factory=Position)
211
212 def add_exit(self, direction: Direction, location_id: str):
213 self.exits[direction] = location_id
214
215 def add_item(self, item: Item):
216 self.items.append(item)
217
218 def add_npc(self, npc: NPC):
219 self.npcs.append(npc)
220
221 def remove_item(self, item: Item):
222 if item in self.items:
223 self.items.remove(item)
224 return True
225 return False
226
227 def remove_npc(self, npc: NPC):
228 if npc in self.npcs:
229 self.npcs.remove(npc)
230 return True
231 return False
232
233# Plugin System
234class Plugin(ABC):
235 @abstractmethod
236 def initialize(self, game):
237 pass
238
239 @abstractmethod
240 def get_commands(self) -> Dict[str, Callable]:
241 return {}
242
243# Game Classes
244class GameWorld:
245 def __init__(self):
246 self.locations: Dict[str, Location] = {}
247 self.global_time: int = 0 # Game time in minutes
248 self.weather: Weather = Weather.CLEAR
249 self.time_of_day: TimeOfDay = TimeOfDay.MORNING
250 self.day_count: int = 1
251
252 def add_location(self, location: Location):
253 self.locations[location.id] = location
254
255 def get_location(self, location_id: str) -> Optional[Location]:
256 return self.locations.get(location_id)
257
258 def update_time(self, minutes: int = 1):
259 self.global_time += minutes
260 # Update day count (each day is 1440 minutes)
261 self.day_count = (self.global_time // 1440) + 1
262
263 # Update time of day (each period is 3 hours = 180 minutes)
264 time_periods = list(TimeOfDay)
265 period_index = (self.global_time // 180) % len(time_periods)
266 self.time_of_day = time_periods[period_index]
267
268 # Randomly change weather
269 if random.random() < 0.05: # 5% chance of weather change
270 self.weather = random.choice(list(Weather))
271
272 def get_time_description(self) -> str:
273 return f"Day {self.day_count}, {self.time_of_day.value.capitalize()}, Weather: {self.weather.value.capitalize()}"
274
275class Player:
276 def __init__(self, name: str):
277 self.name: str = name
278 self.location_id: str = "start"
279 self.stats: Stats = Stats()
280 self.inventory: Dict[str, Tuple[Item, int]] = {} # item_id: (item, quantity)
281 self.equipped: Dict[str, Item] = {} # slot: item
282 self.skills: Dict[str, Skill] = {
283 "combat": Skill("Combat", SkillType.COMBAT),
284 "magic": Skill("Magic", SkillType.MAGIC),
285 "stealth": Skill("Stealth", SkillType.STEALTH),
286 "crafting": Skill("Crafting", SkillType.CRAFTING),
287 "social": Skill("Social", SkillType.SOCIAL),
288 "survival": Skill("Survival", SkillType.SURVIVAL)
289 }
290 self.quests: List[Quest] = []
291 self.known_locations: List[str] = ["start"]
292 self.faction_reputation: Dict[str, int] = {}
293
294 def add_item(self, item: Item, quantity: int = 1):
295 if item.id in self.inventory:
296 current_item, current_quantity = self.inventory[item.id]
297 if item.stackable:
298 new_quantity = min(current_quantity + quantity, item.max_stack)
299 self.inventory[item.id] = (current_item, new_quantity)
300 return quantity - (new_quantity - current_quantity) # Return leftover quantity
301 else:
302 # For non-stackable items, add multiple entries
303 for _ in range(quantity):
304 self.inventory[f"{item.id}_{len(self.inventory)}"] = (item, 1)
305 return 0
306 else:
307 self.inventory[item.id] = (item, quantity)
308 return 0
309
310 def remove_item(self, item_id: str, quantity: int = 1) -> bool:
311 if item_id in self.inventory:
312 item, current_quantity = self.inventory[item_id]
313 if current_quantity <= quantity:
314 del self.inventory[item_id]
315 return True
316 else:
317 self.inventory[item_id] = (item, current_quantity - quantity)
318 return True
319 return False
320
321 def has_item(self, item_id: str, quantity: int = 1) -> bool:
322 if item_id in self.inventory:
323 _, current_quantity = self.inventory[item_id]
324 return current_quantity >= quantity
325 return False
326
327 def equip_item(self, item_id: str) -> bool:
328 if item_id in self.inventory:
329 item, _ = self.inventory[item_id]
330 if item.equippable:
331 # Determine slot based on item type
332 if isinstance(item, Weapon):
333 slot = "weapon"
334 elif isinstance(item, Armor):
335 slot = item.slot
336 else:
337 slot = "accessory"
338
339 # Unequip current item if any
340 if slot in self.equipped:
341 self.add_item(self.equipped[slot])
342
343 # Equip new item
344 self.equipped[slot] = item
345 self.remove_item(item_id)
346 return True
347 return False
348
349 def unequip_item(self, slot: str) -> bool:
350 if slot in self.equipped:
351 item = self.equipped[slot]
352 self.add_item(item)
353 del self.equipped[slot]
354 return True
355 return False
356
357 def get_total_defense(self) -> int:
358 defense = 0
359 for item in self.equipped.values():
360 if isinstance(item, Armor):
361 defense += item.defense
362 return defense
363
364 def get_total_damage(self) -> int:
365 damage = 5 # Base damage
366 if "weapon" in self.equipped:
367 weapon = self.equipped["weapon"]
368 if isinstance(weapon, Weapon):
369 damage = weapon.damage
370 return damage
371
372 def gain_experience(self, amount: int):
373 self.stats.experience += amount
374 exp_needed = self.stats.level * 100 # Simple formula
375 while self.stats.experience >= exp_needed:
376 self.stats.experience -= exp_needed
377 self.stats.level_up()
378 exp_needed = self.stats.level * 100
379 return True # Leveled up
380 return False
381
382 def add_quest(self, quest: Quest):
383 self.quests.append(quest)
384 quest.active = True
385
386 def complete_quest(self, quest_id: str) -> bool:
387 for quest in self.quests:
388 if quest.id == quest_id and quest.active and not quest.completed:
389 quest.completed = True
390 # Apply rewards
391 if "experience" in quest.rewards:
392 self.gain_experience(quest.rewards["experience"])
393 if "items" in quest.rewards:
394 for item_id, quantity in quest.rewards["items"].items():
395 # This would need a reference to the game world to get the actual item
396 pass
397 if "reputation" in quest.rewards:
398 for faction, amount in quest.rewards["reputation"].items():
399 if faction in self.faction_reputation:
400 self.faction_reputation[faction] += amount
401 else:
402 self.faction_reputation[faction] = amount
403 return True
404 return False
405
406 def update_vitals(self):
407 # Decrease hunger and thirst over time
408 self.stats.hunger = max(0, self.stats.hunger - 1)
409 self.stats.thirst = max(0, self.stats.thirst - 1)
410
411 # Apply effects of hunger and thirst
412 if self.stats.hunger == 0:
413 self.stats.health = max(0, self.stats.health - 2)
414 if self.stats.thirst == 0:
415 self.stats.health = max(0, self.stats.health - 3)
416
417 # Regenerate health, mana, and stamina slowly
418 if self.stats.health < self.stats.max_health:
419 self.stats.health = min(self.stats.max_health, self.stats.health + 1)
420 if self.stats.mana < self.stats.max_mana:
421 self.stats.mana = min(self.stats.max_mana, self.stats.mana + 1)
422 if self.stats.stamina < self.stats.max_stamina:
423 self.stats.stamina = min(self.stats.max_stamina, self.stats.stamina + 2)
424
425class CombatSystem:
426 @staticmethod
427 def attack(attacker, defender):
428 # Calculate damage
429 base_damage = attacker.get_total_damage() if hasattr(attacker, 'get_total_damage') else 10
430
431 # Add some randomness
432 damage = max(1, base_damage + random.randint(-2, 2))
433
434 # Apply defense
435 defense = defender.get_total_defense() if hasattr(defender, 'get_total_defense') else 0
436 damage = max(1, damage - defense // 2)
437
438 # Apply damage
439 defender.stats.health = max(0, defender.stats.health - damage)
440
441 return damage
442
443 @staticmethod
444 def check_flee(player, npc) -> bool:
445 # Base chance to flee is 50%, modified by player's level vs NPC's level
446 base_chance = 0.5
447 level_diff = player.stats.level - npc.stats.level
448 chance = base_chance + (level_diff * 0.1)
449 chance = max(0.1, min(0.9, chance)) # Clamp between 10% and 90%
450
451 return random.random() < chance
452
453class Game:
454 def __init__(self):
455 self.world = GameWorld()
456 self.player = None
457 self.running = True
458 self.plugins: Dict[str, Plugin] = {}
459 self.commands: Dict[str, Callable] = {}
460 self.combat = CombatSystem()
461 self.in_combat = False
462 self.current_opponent = None
463
464 # Initialize core commands
465 self.register_command("help", self.cmd_help)
466 self.register_command("quit", self.cmd_quit)
467 self.register_command("look", self.cmd_look)
468 self.register_command("go", self.cmd_go)
469 self.register_command("take", self.cmd_take)
470 self.register_command("inventory", self.cmd_inventory)
471 self.register_command("use", self.cmd_use)
472 self.register_command("equip", self.cmd_equip)
473 self.register_command("unequip", self.cmd_unequip)
474 self.register_command("talk", self.cmd_talk)
475 self.register_command("attack", self.cmd_attack)
476 self.register_command("flee", self.cmd_flee)
477 self.register_command("quests", self.cmd_quests)
478 self.register_command("skills", self.cmd_skills)
479 self.register_command("time", self.cmd_time)
480 self.register_command("save", self.cmd_save)
481 self.register_command("load", self.cmd_load)
482 self.register_command("wait", self.cmd_wait)
483 self.register_command("status", self.cmd_status)
484 self.register_command("drop", self.cmd_drop)
485 self.register_command("examine", self.cmd_examine)
486 self.register_command("map", self.cmd_map)
487 self.register_command("rest", self.cmd_rest)
488 self.register_command("plugins", self.cmd_plugins)
489
490 # Initialize the game world
491 self.initialize_world()
492
493 def register_command(self, name: str, func: Callable):
494 self.commands[name] = func
495
496 def load_plugin(self, plugin_path: str):
497 try:
498 spec = importlib.util.spec_from_file_location("plugin", plugin_path)
499 plugin_module = importlib.util.module_from_spec(spec)
500 spec.loader.exec_module(plugin_module)
501
502 # Get plugin class (should be named "Plugin")
503 if hasattr(plugin_module, "Plugin"):
504 plugin_class = getattr(plugin_module, "Plugin")
505 plugin = plugin_class()
506 plugin.initialize(self)
507
508 # Register plugin commands
509 plugin_commands = plugin.get_commands()
510 for name, func in plugin_commands.items():
511 self.register_command(name, func)
512
513 self.plugins[plugin_path] = plugin
514 return True
515 except Exception as e:
516 print(f"{Colors.RED}Error loading plugin: {e}{Colors.RESET}")
517 return False
518
519 def unload_plugin(self, plugin_path: str):
520 if plugin_path in self.plugins:
521 plugin = self.plugins[plugin_path]
522 plugin_commands = plugin.get_commands()
523
524 # Unregister plugin commands
525 for name in plugin_commands:
526 if name in self.commands:
527 del self.commands[name]
528
529 del self.plugins[plugin_path]
530 return True
531 return False
532
533 def initialize_world(self):
534 # Create starting location
535 start_location = Location(
536 id="start",
537 name="Starting Village",
538 description="A small village surrounded by forests and mountains. There's a path leading north to the forest and east to the mountains.",
539 position=Position(0, 0, 0)
540 )
541
542 # Create forest location
543 forest_location = Location(
544 id="forest",
545 name="Dark Forest",
546 description="A dense forest with tall trees and little light. You can hear strange sounds in the distance.",
547 position=Position(0, 1, 0)
548 )
549
550 # Create mountain location
551 mountain_location = Location(
552 id="mountain",
553 name="Mountain Pass",
554 description="A narrow path through the mountains. It's cold and windy here.",
555 position=Position(1, 0, 0)
556 )
557
558 # Create cave location
559 cave_location = Location(
560 id="cave",
561 name="Mysterious Cave",
562 description="A dark cave with glowing crystals on the walls. You can hear dripping water.",
563 position=Position(0, 0, -1),
564 indoor=True
565 )
566
567 # Create village shop
568 shop_location = Location(
569 id="shop",
570 name="Village Shop",
571 description="A small shop with various items for sale. The shopkeeper looks friendly.",
572 position=Position(-1, 0, 0),
573 indoor=True
574 )
575
576 # Connect locations
577 start_location.add_exit(Direction.NORTH, "forest")
578 start_location.add_exit(Direction.EAST, "mountain")
579 start_location.add_exit(Direction.WEST, "shop")
580
581 forest_location.add_exit(Direction.SOUTH, "start")
582 forest_location.add_exit(Direction.DOWN, "cave")
583
584 mountain_location.add_exit(Direction.WEST, "start")
585
586 cave_location.add_exit(Direction.UP, "forest")
587
588 shop_location.add_exit(Direction.EAST, "start")
589
590 # Add items to locations
591 # Starting village items
592 start_location.add_item(Item(
593 id="apple",
594 name="Apple",
595 description="A fresh red apple. Looks delicious.",
596 value=5,
597 consumable=True,
598 effects={"hunger": 20}
599 ))
600
601 start_location.add_item(Item(
602 id="bread",
603 name="Bread",
604 description="A loaf of bread. Still warm.",
605 value=10,
606 consumable=True,
607 effects={"hunger": 40}
608 ))
609
610 # Forest items
611 forest_location.add_item(Weapon(
612 id="sword",
613 name="Rusty Sword",
614 description="An old rusty sword. Better than nothing.",
615 value=25,
616 damage=15,
617 weight=3.0
618 ))
619
620 forest_location.add_item(Item(
621 id="herb",
622 name="Healing Herb",
623 description="A green herb with medicinal properties.",
624 value=15,
625 consumable=True,
626 effects={"health": 20}
627 ))
628
629 # Cave items
630 cave_location.add_item(Item(
631 id="crystal",
632 name="Magic Crystal",
633 description="A glowing crystal that hums with magical energy.",
634 value=100,
635 consumable=True,
636 effects={"mana": 50}
637 ))
638
639 # Shop items
640 shop_location.add_item(Weapon(
641 id="dagger",
642 name="Dagger",
643 description="A sharp dagger. Good for quick attacks.",
644 value=30,
645 damage=10,
646 weight=1.0
647 ))
648
649 shop_location.add_item(Armor(
650 id="leather_armor",
651 name="Leather Armor",
652 description="Simple armor made of leather. Provides basic protection.",
653 value=50,
654 defense=10,
655 armor_type="light",
656 slot="chest"
657 ))
658
659 # Add NPCs
660 # Village elder
661 elder = NPC(
662 id="elder",
663 name="Village Elder",
664 description="An old man with a long white beard and wise eyes.",
665 dialogue={
666 "greeting": [
667 "Welcome to our humble village, young adventurer.",
668 "Ah, a new face. What brings you to our village?"
669 ],
670 "quest": [
671 "We have a problem with wolves in the forest. Could you help us?",
672 "The forest to the north has become dangerous. Please investigate."
673 ],
674 "help": [
675 "You can use 'go [direction]' to move around.",
676 "Try 'talk [npc]' to interact with people."
677 ]
678 },
679 location_id="start"
680 )
681
682 # Add quest to elder
683 wolf_quest = Quest(
684 id="wolf_problem",
685 name="Wolf Problem",
686 description="Deal with the wolves in the forest.",
687 objectives=["Kill 5 wolves"],
688 rewards={
689 "experience": 100,
690 "items": {"gold": 50}
691 }
692 )
693 elder.quests.append(wolf_quest)
694
695 # Shopkeeper
696 shopkeeper = NPC(
697 id="shopkeeper",
698 name="Shopkeeper",
699 description="A friendly-looking person with a big smile.",
700 dialogue={
701 "greeting": [
702 "Welcome to my shop! Feel free to browse.",
703 "Hello! Looking for something special?"
704 ],
705 "buy": [
706 "What would you like to buy?",
707 "Everything here is for sale, just name it."
708 ],
709 "sell": [
710 "What do you want to sell me?",
711 "I'll give you a fair price for your items."
712 ]
713 },
714 location_id="shop"
715 )
716
717 # Forest wolf
718 wolf = NPC(
719 id="wolf",
720 name="Wolf",
721 description="A wild wolf with sharp teeth and hungry eyes.",
722 dialogue={},
723 location_id="forest",
724 hostile=True,
725 stats=Stats(health=50, max_health=50)
726 )
727
728 # Add NPCs to locations
729 start_location.add_npc(elder)
730 shop_location.add_npc(shopkeeper)
731 forest_location.add_npc(wolf)
732
733 # Add locations to world
734 self.world.add_location(start_location)
735 self.world.add_location(forest_location)
736 self.world.add_location(mountain_location)
737 self.world.add_location(cave_location)
738 self.world.add_location(shop_location)
739
740 def start(self):
741 self.clear_screen()
742 self.print_title()
743
744 # Character creation
745 name = input(f"{Colors.CYAN}Enter your character's name: {Colors.RESET}")
746 self.player = Player(name)
747
748 # Welcome message
749 self.print_wrapped(f"{Colors.GREEN}Welcome, {self.player.name}!{Colors.RESET}")
750 self.print_wrapped("You find yourself in a small village. Your adventure begins here.")
751 self.print_wrapped("Type 'help' for a list of commands.")
752 self.print_separator()
753
754 # Main game loop
755 while self.running:
756 if not self.in_combat:
757 # Update game world
758 self.world.update_time()
759 self.player.update_vitals()
760
761 # Check if player is dead
762 if self.player.stats.health <= 0:
763 self.game_over()
764 break
765
766 # Display location
767 self.display_location()
768
769 # Get player input
770 try:
771 command_input = input(f"{Colors.YELLOW}> {Colors.RESET}").strip().lower()
772 if not command_input:
773 continue
774
775 # Parse command
776 parts = command_input.split()
777 command = parts[0]
778 args = parts[1:] if len(parts) > 1 else []
779
780 # Execute command
781 if command in self.commands:
782 self.commands[command](args)
783 else:
784 print(f"{Colors.RED}Unknown command: {command}{Colors.RESET}")
785 print(f"{Colors.CYAN}Type 'help' for a list of commands.{Colors.RESET}")
786
787 except KeyboardInterrupt:
788 print("\nGoodbye!")
789 self.running = False
790 except EOFError:
791 print("\nGoodbye!")
792 self.running = False
793 except Exception as e:
794 print(f"{Colors.RED}Error: {e}{Colors.RESET}")
795
796 def game_over(self):
797 self.clear_screen()
798 print(f"{Colors.RED}========================================{Colors.RESET}")
799 print(f"{Colors.RED} GAME OVER{Colors.RESET}")
800 print(f"{Colors.RED}========================================{Colors.RESET}")
801 print(f"{Colors.WHITE}You have died.{Colors.RESET}")
802 print(f"{Colors.WHITE}Level reached: {self.player.stats.level}{Colors.RESET}")
803 print(f"{Colors.WHITE}Experience gained: {self.player.stats.experience}{Colors.RESET}")
804 print(f"{Colors.RED}========================================{Colors.RESET}")
805 self.running = False
806
807 def clear_screen(self):
808 os.system('cls' if os.name == 'nt' else 'clear')
809
810 def print_title(self):
811 print(f"{Colors.BRIGHT_CYAN}")
812 print("========================================")
813 print(" ULTIMATE OPEN WORLD GAME ")
814 print("========================================")
815 print(f"{Colors.RESET}")
816
817 def print_separator(self):
818 print(f"{Colors.BRIGHT_BLACK}----------------------------------------{Colors.RESET}")
819
820 def print_wrapped(self, text, width=80):
821 words = text.split()
822 lines = []
823 current_line = []
824 current_length = 0
825
826 for word in words:
827 if current_length + len(word) + 1 <= width:
828 current_line.append(word)
829 current_length += len(word) + 1
830 else:
831 lines.append(' '.join(current_line))
832 current_line = [word]
833 current_length = len(word)
834
835 if current_line:
836 lines.append(' '.join(current_line))
837
838 for line in lines:
839 print(line)
840
841 def display_location(self):
842 location = self.world.get_location(self.player.location_id)
843 if not location:
844 return
845
846 # Mark location as discovered
847 if not location.discovered:
848 location.discovered = True
849 if location.id not in self.player.known_locations:
850 self.player.known_locations.append(location.id)
851
852 # Display location name
853 print(f"{Colors.BRIGHT_GREEN}{location.name}{Colors.RESET}")
854
855 # Display location description
856 self.print_wrapped(f"{Colors.WHITE}{location.description}{Colors.RESET}")
857
858 # Display time and weather
859 print(f"{Colors.CYAN}{self.world.get_time_description()}{Colors.RESET}")
860
861 # Display exits
862 if location.exits:
863 exits = ", ".join([d.value for d in location.exits.keys()])
864 print(f"{Colors.YELLOW}Exits: {exits}{Colors.RESET}")
865
866 # Display items
867 if location.items:
868 item_names = [f"{item.name} ({quantity})" if item.stackable else item.name
869 for item, quantity in [(item, 1) for item in location.items]]
870 print(f"{Colors.GREEN}Items: {', '.join(item_names)}{Colors.RESET}")
871
872 # Display NPCs
873 if location.npcs:
874 npc_names = [npc.name for npc in location.npcs]
875 print(f"{Colors.MAGENTA}People: {', '.join(npc_names)}{Colors.RESET}")
876
877 self.print_separator()
878
879 # Command implementations
880 def cmd_help(self, args):
881 print(f"{Colors.CYAN}Available commands:{Colors.RESET}")
882 for command in sorted(self.commands.keys()):
883 print(f" {Colors.YELLOW}{command}{Colors.RESET}")
884 print(f"\n{Colors.CYAN}For more information on a command, type: help [command]{Colors.RESET}")
885
886 def cmd_quit(self, args):
887 print(f"{Colors.YELLOW}Are you sure you want to quit? (y/n){Colors.RESET}")
888 response = input("> ").strip().lower()
889 if response == 'y':
890 self.running = False
891
892 def cmd_look(self, args):
893 self.display_location()
894
895 def cmd_go(self, args):
896 if not args:
897 print(f"{Colors.RED}Go where?{Colors.RESET}")
898 return
899
900 direction_str = args[0]
901 try:
902 direction = Direction(direction_str)
903 except ValueError:
904 print(f"{Colors.RED}Invalid direction: {direction_str}{Colors.RESET}")
905 return
906
907 location = self.world.get_location(self.player.location_id)
908 if not location:
909 return
910
911 if direction in location.exits:
912 # Check for hostile NPCs that might block the way
913 for npc in location.npcs:
914 if npc.hostile and npc.stats.health > 0:
915 print(f"{Colors.RED}{npc.name} blocks your path!{Colors.RESET}")
916 self.start_combat(npc)
917 return
918
919 # Move to the new location
920 self.player.location_id = location.exits[direction]
921 print(f"{Colors.GREEN}You go {direction.value}.{Colors.RESET}")
922
923 # Update time (movement takes time)
924 self.world.update_time(5)
925
926 # Consume stamina
927 self.player.stats.stamina = max(0, self.player.stats.stamina - 5)
928
929 # Check for random encounters
930 if random.random() < 0.1: # 10% chance of random encounter
931 self.random_encounter()
932 else:
933 print(f"{Colors.RED}You can't go {direction.value} from here.{Colors.RESET}")
934
935 def cmd_take(self, args):
936 if not args:
937 print(f"{Colors.RED}Take what?{Colors.RESET}")
938 return
939
940 item_name = ' '.join(args)
941 location = self.world.get_location(self.player.location_id)
942 if not location:
943 return
944
945 # Find the item
946 for item in location.items:
947 if item.name.lower() == item_name.lower():
948 # Add to player inventory
949 leftover = self.player.add_item(item)
950 if leftover == 0:
951 location.remove_item(item)
952 print(f"{Colors.GREEN}You take the {item.name}.{Colors.RESET}")
953 else:
954 print(f"{Colors.YELLOW}You can only carry {item.max_stack} {item.name}s.{Colors.RESET}")
955 return
956
957 print(f"{Colors.RED}There is no {item_name} here.{Colors.RESET}")
958
959 def cmd_inventory(self, args):
960 if not self.player.inventory:
961 print(f"{Colors.YELLOW}Your inventory is empty.{Colors.RESET}")
962 return
963
964 print(f"{Colors.CYAN}Inventory:{Colors.RESET}")
965 for item_id, (item, quantity) in self.player.inventory.items():
966 if item.stackable:
967 print(f" {Colors.GREEN}{item.name} x{quantity}{Colors.RESET} - {item.description}")
968 else:
969 print(f" {Colors.GREEN}{item.name}{Colors.RESET} - {item.description}")
970
971 # Show equipped items
972 if self.player.equipped:
973 print(f"\n{Colors.CYAN}Equipped:{Colors.RESET}")
974 for slot, item in self.player.equipped.items():
975 print(f" {Colors.YELLOW}{slot}: {item.name}{Colors.RESET}")
976
977 def cmd_use(self, args):
978 if not args:
979 print(f"{Colors.RED}Use what?{Colors.RESET}")
980 return
981
982 item_name = ' '.join(args)
983
984 # Find the item in inventory
985 for item_id, (item, quantity) in self.player.inventory.items():
986 if item.name.lower() == item_name.lower():
987 if item.use(self.player):
988 if item.consumable:
989 if quantity > 1:
990 self.player.inventory[item_id] = (item, quantity - 1)
991 else:
992 self.player.remove_item(item_id)
993 print(f"{Colors.GREEN}You use the {item.name}.{Colors.RESET}")
994 else:
995 print(f"{Colors.RED}You can't use the {item.name}.{Colors.RESET}")
996 return
997
998 print(f"{Colors.RED}You don't have a {item_name}.{Colors.RESET}")
999
1000 def cmd_equip(self, args):
1001 if not args:
1002 print(f"{Colors.RED}Equip what?{Colors.RESET}")
1003 return
1004
1005 item_name = ' '.join(args)
1006
1007 # Find the item in inventory
1008 for item_id, (item, quantity) in self.player.inventory.items():
1009 if item.name.lower() == item_name.lower():
1010 if self.player.equip_item(item_id):
1011 print(f"{Colors.GREEN}You equip the {item.name}.{Colors.RESET}")
1012 else:
1013 print(f"{Colors.RED}You can't equip the {item.name}.{Colors.RESET}")
1014 return
1015
1016 print(f"{Colors.RED}You don't have a {item_name}.{Colors.RESET}")
1017
1018 def cmd_unequip(self, args):
1019 if not args:
1020 print(f"{Colors.RED}Unequip what?{Colors.RESET}")
1021 return
1022
1023 slot = args[0].lower()
1024
1025 if self.player.unequip_item(slot):
1026 print(f"{Colors.GREEN}You unequip your {slot}.{Colors.RESET}")
1027 else:
1028 print(f"{Colors.RED}You don't have anything equipped in that slot.{Colors.RESET}")
1029
1030 def cmd_talk(self, args):
1031 if not args:
1032 print(f"{Colors.RED}Talk to whom?{Colors.RESET}")
1033 return
1034
1035 npc_name = ' '.join(args)
1036 location = self.world.get_location(self.player.location_id)
1037 if not location:
1038 return
1039
1040 # Find the NPC
1041 for npc in location.npcs:
1042 if npc.name.lower() == npc_name.lower():
1043 # Get dialogue topic
1044 topic = "greeting"
1045 if len(args) > 1:
1046 topic = ' '.join(args[1:])
1047
1048 # Get dialogue
1049 dialogue = npc.talk(topic)
1050 print(f"{Colors.MAGENTA}{npc.name}: {dialogue}{Colors.RESET}")
1051
1052 # Check for quests
1053 if topic == "quest" and npc.quests:
1054 for quest in npc.quests:
1055 if not quest.completed and not any(q.id == quest.id for q in self.player.quests):
1056 self.player.add_quest(quest)
1057 print(f"{Colors.GREEN}New quest: {quest.name}{Colors.RESET}")
1058 print(f"{Colors.WHITE}{quest.description}{Colors.RESET}")
1059
1060 return
1061
1062 print(f"{Colors.RED}There is no one named {npc_name} here.{Colors.RESET}")
1063
1064 def cmd_attack(self, args):
1065 if not args:
1066 print(f"{Colors.RED}Attack whom?{Colors.RESET}")
1067 return
1068
1069 npc_name = ' '.join(args)
1070 location = self.world.get_location(self.player.location_id)
1071 if not location:
1072 return
1073
1074 # Find the NPC
1075 for npc in location.npcs:
1076 if npc.name.lower() == npc_name.lower():
1077 if not npc.hostile:
1078 print(f"{Colors.RED}You can't attack {npc.name}.{Colors.RESET}")
1079 return
1080
1081 self.start_combat(npc)
1082 return
1083
1084 print(f"{Colors.RED}There is no one named {npc_name} here.{Colors.RESET}")
1085
1086 def cmd_flee(self, args):
1087 if not self.in_combat:
1088 print(f"{Colors.RED}You're not in combat.{Colors.RESET}")
1089 return
1090
1091 if self.combat.check_flee(self.player, self.current_opponent):
1092 print(f"{Colors.GREEN}You successfully flee from combat.{Colors.RESET}")
1093 self.end_combat()
1094
1095 # Move to a random adjacent location
1096 location = self.world.get_location(self.player.location_id)
1097 if location and location.exits:
1098 directions = list(location.exits.keys())
1099 random_direction = random.choice(directions)
1100 self.player.location_id = location.exits[random_direction]
1101 print(f"{Colors.GREEN}You run away to the {random_direction.value}.{Colors.RESET}")
1102 else:
1103 print(f"{Colors.RED}You fail to flee!{Colors.RESET}")
1104 # Enemy gets a free attack
1105 damage = self.combat.attack(self.current_opponent, self.player)
1106 print(f"{Colors.RED}{self.current_opponent.name} attacks you for {damage} damage!{Colors.RESET}")
1107
1108 if self.player.stats.health <= 0:
1109 self.game_over()
1110
1111 def cmd_quests(self, args):
1112 if not self.player.quests:
1113 print(f"{Colors.YELLOW}You don't have any active quests.{Colors.RESET}")
1114 return
1115
1116 print(f"{Colors.CYAN}Active Quests:{Colors.RESET}")
1117 for quest in self.player.quests:
1118 if quest.active and not quest.completed:
1119 print(f" {Colors.YELLOW}{quest.name}{Colors.RESET}")
1120 print(f" {quest.description}")
1121 print(f" Objectives: {', '.join(quest.objectives)}")
1122
1123 print(f"\n{Colors.CYAN}Completed Quests:{Colors.RESET}")
1124 for quest in self.player.quests:
1125 if quest.completed:
1126 print(f" {Colors.GREEN}{quest.name}{Colors.RESET}")
1127
1128 def cmd_skills(self, args):
1129 print(f"{Colors.CYAN}Skills:{Colors.RESET}")
1130 for skill_name, skill in self.player.skills.items():
1131 print(f" {Colors.YELLOW}{skill.name}: Level {skill.level} ({skill.experience}/{skill.max_experience} XP){Colors.RESET}")
1132
1133 def cmd_time(self, args):
1134 print(f"{Colors.CYAN}{self.world.get_time_description()}{Colors.RESET}")
1135
1136 def cmd_save(self, args):
1137 save_name = args[0] if args else "save1"
1138 save_data = {
1139 "player": self.player,
1140 "world": self.world,
1141 "in_combat": self.in_combat,
1142 "current_opponent": self.current_opponent
1143 }
1144
1145 try:
1146 with open(f"{save_name}.sav", "wb") as f:
1147 pickle.dump(save_data, f)
1148 print(f"{Colors.GREEN}Game saved as {save_name}.{Colors.RESET}")
1149 except Exception as e:
1150 print(f"{Colors.RED}Failed to save game: {e}{Colors.RESET}")
1151
1152 def cmd_load(self, args):
1153 save_name = args[0] if args else "save1"
1154
1155 try:
1156 with open(f"{save_name}.sav", "rb") as f:
1157 save_data = pickle.load(f)
1158
1159 self.player = save_data["player"]
1160 self.world = save_data["world"]
1161 self.in_combat = save_data["in_combat"]
1162 self.current_opponent = save_data["current_opponent"]
1163
1164 print(f"{Colors.GREEN}Game loaded from {save_name}.{Colors.RESET}")
1165 except Exception as e:
1166 print(f"{Colors.RED}Failed to load game: {e}{Colors.RESET}")
1167
1168 def cmd_wait(self, args):
1169 minutes = 30 # Default wait time
1170 if args:
1171 try:
1172 minutes = int(args[0])
1173 except ValueError:
1174 print(f"{Colors.RED}Invalid time: {args[0]}{Colors.RESET}")
1175 return
1176
1177 print(f"{Colors.YELLOW}You wait for {minutes} minutes...{Colors.RESET}")
1178 self.world.update_time(minutes)
1179 self.player.update_vitals()
1180
1181 # Random events while waiting
1182 if random.random() < 0.2: # 20% chance of something happening
1183 self.random_event()
1184
1185 def cmd_status(self, args):
1186 print(f"{Colors.CYAN}Character Status:{Colors.RESET}")
1187 print(f" Name: {self.player.name}")
1188 print(f" Level: {self.player.stats.level}")
1189 print(f" Experience: {self.player.stats.experience}")
1190 print(f" Health: {self.player.stats.health}/{self.player.stats.max_health}")
1191 print(f" Mana: {self.player.stats.mana}/{self.player.stats.max_mana}")
1192 print(f" Stamina: {self.player.stats.stamina}/{self.player.stats.max_stamina}")
1193 print(f" Hunger: {self.player.stats.hunger}/{self.player.stats.max_hunger}")
1194 print(f" Thirst: {self.player.stats.thirst}/{self.player.stats.max_thirst}")
1195 print(f" Defense: {self.player.get_total_defense()}")
1196 print(f" Damage: {self.player.get_total_damage()}")
1197
1198 def cmd_drop(self, args):
1199 if not args:
1200 print(f"{Colors.RED}Drop what?{Colors.RESET}")
