From 142e2f3f2a884eab58fa8dc27532fb16d52e7a34 Mon Sep 17 00:00:00 2001 From: MatyasZsombor Date: Sun, 15 Jun 2025 23:40:57 +0200 Subject: [PATCH] Finished code decoupling --- adventure.pl | 817 +----------------------------- game_assets/climbing_system.pl | 42 ++ game_assets/combat_system.pl | 188 +++++++ game_assets/command_processing.pl | 99 ++++ game_assets/commands.pl | 68 +++ game_assets/crafting_system.pl | 45 ++ game_assets/game_state.pl | 46 ++ game_assets/hacking_system.pl | 75 +++ game_assets/inventory.pl | 31 ++ game_assets/items.pl | 21 + game_assets/konami_code.pl | 40 ++ game_assets/locations.pl | 29 +- game_assets/npcs.pl | 22 +- game_assets/obstacles.pl | 57 +++ game_assets/parkour_minigames.pl | 85 ++++ 15 files changed, 833 insertions(+), 832 deletions(-) create mode 100644 game_assets/climbing_system.pl create mode 100644 game_assets/combat_system.pl create mode 100644 game_assets/command_processing.pl create mode 100644 game_assets/commands.pl create mode 100644 game_assets/crafting_system.pl create mode 100644 game_assets/game_state.pl create mode 100644 game_assets/hacking_system.pl create mode 100644 game_assets/inventory.pl create mode 100644 game_assets/konami_code.pl create mode 100644 game_assets/obstacles.pl create mode 100644 game_assets/parkour_minigames.pl diff --git a/adventure.pl b/adventure.pl index 67c99e5..143cc7d 100644 --- a/adventure.pl +++ b/adventure.pl @@ -1,33 +1,24 @@ % SkyNet: The Wings of Deception % Von Zsombor Matyas und Jonas Hinterdorfer -:- include('game_assets/locations.pl'). +% ========== INCLUDES ========== +:- include('game_assets/climbing_system.pl'). +:- include('game_assets/combat_system.pl'). +:- include('game_assets/command_processing.pl'). +:- include('game_assets/commands.pl'). +:- include('game_assets/crafting_system.pl'). +:- include('game_assets/endings.pl'). +:- include('game_assets/game_state.pl'). +:- include('game_assets/hacking_system.pl'). +:- include('game_assets/inventory.pl'). :- include('game_assets/items.pl'). +:- include('game_assets/konami_code.pl'). +:- include('game_assets/locations.pl'). :- include('game_assets/npcs.pl'). +:- include('game_assets/obstacles.pl'). +:- include('game_assets/parkour_minigames.pl'). :- include('game_assets/utilities.pl'). -% ========== GAME STATE ========== -:- dynamic(player_location/1). -:- dynamic(player_health/1). -:- dynamic(player_inventory/1). -:- dynamic(game_state/2). -:- dynamic(npc_location/2). -:- dynamic(enemy_location/2). -:- dynamic(item_location/2). -:- dynamic(discovered/1). -:- dynamic(enemy/4). -:- dynamic(enemy_hacked/1). -:- dynamic(hack_attempted/1). -:- dynamic(obstacle/3). -:- dynamic(box_unlocked/1). -:- dynamic(in_combat/1). -:- dynamic(combat_turn/1). -:- dynamic(konami_sequence/1). -:- dynamic(konami_position/1). -:- dynamic(emp_used_in_combat/1). -:- dynamic(drone_cooldown/2). -:- dynamic(health_recovery_used/2). - % ========== INITIALIZATION ========== init_game :- % Clear any existing state @@ -96,785 +87,5 @@ normal_loop :- !, game_loop. -combat_loop(Enemy) :- - enemy(Enemy, DisplayName, Health, _), - nl, - write('=== KAMPF GEGEN '), write(DisplayName), write(' ==='), nl, - write('Feind Gesundheit: '), write(Health), nl, - player_health(PlayerHealth), - write('Deine Gesundheit: '), write(PlayerHealth), nl, - health_recovery_used(Enemy, RecoveryUsed), - RemainingRecovery is 2 - RecoveryUsed, - write('Heilungen übrig: '), write(RemainingRecovery), write('/2'), nl, - write('Verfügbare Aktionen: angriff, verwende(item), heile'), nl, nl, - write('> '), - read_line(Command), - process_combat_command(Command, Enemy), - check_game_state, - !, - game_loop. - -init_konami :- - retractall(konami_sequence(_)), - retractall(konami_position(_)), - assertz(konami_sequence([oben, oben, unten, unten, links, rechts, links, rechts, b, a])), - assertz(konami_position(0)). - -% ========== INPUT PROCESSING ========== -read_line(Command) :- - read(Input), - parse_input(Input, Command). - -parse_input(Input, [Input]) :- - atom(Input), !. - -parse_input(Input, Command) :- - compound(Input), - Input =.. Command, !. - -parse_input(_, [unknown]). - -% ========== COMMAND PROCESSING ========== -check_konami_input(Input) :- - (konami_position(_) -> true ; init_konami), - konami_position(Pos), - konami_sequence(Sequence), - nth0(Pos, Sequence, Expected), - (Input = Expected -> - (NewPos is Pos + 1, - retract(konami_position(Pos)), - assertz(konami_position(NewPos)), - length(Sequence, SeqLength), - (NewPos >= SeqLength -> - unlock_konami_code ; - true)) ; - (retract(konami_position(_)), - assertz(konami_position(0)), - write('Invalide Code, Hinweis: Contra.'), nl)). - -unlock_konami_code :- - game_state(konami_unlocked, false), - write('*** KONAMI CODE AKTIVIERT! ***'), nl, - write('Ein geheimnisvoller Master-Schlüssel materialisiert sich in deinem Inventar!'), nl, - write('Dieses Artefakt gewährt dir vollständigen Zugriff auf alle Systeme...'), nl, - assertz(player_inventory(master_schluessel)), - retract(game_state(konami_unlocked, false)), - assertz(game_state(konami_unlocked, true)), - retract(konami_position(_)), - assertz(konami_position(0)), - !. - -unlock_konami_code :- - write('Der Konami Code wurde bereits aktiviert!'), nl, - retract(konami_position(_)), - assertz(konami_position(0)). - -process_command([oben]) :- check_konami_input(oben). -process_command([unten]) :- check_konami_input(unten). -process_command([links]) :- check_konami_input(links). -process_command([rechts]) :- check_konami_input(rechts). -process_command([a]) :- check_konami_input(a). -process_command([b]) :- check_konami_input(b). - -process_command([beende]) :- - end_game. - -process_command([hilfe]) :- - write('Verfügbare Befehle:'), nl, - write('- schaue: Beschreibung des aktuellen Ortes'), nl, - write('- gehe(richtung): Bewege dich zu einem anderen Ort'), nl, - write('- nimm(gegenstand): Nimm einen Gegenstand auf'), nl, - write('- verwende(gegenstand): Verwende einen Gegenstand'), nl, - write('- rede(person): Spreche mit einer Person'), nl, - write('- angriff(feind): Beginne Kampf gegen einen Feind'), nl, - write('- baue(item): Baue einen Gegenstand (nur in Werkstatt)'), nl, - write('- hack(ziel): Hacke ein Ziel'), nl, - write('- klettere: Klettere auf Dächer/Türme'), nl, - write('- inventar: Zeige dein Inventar'), nl, - write('- status: Zeige deinen Status'), nl, - write('- Richtungsbefehle: oben, unten, links, rechts, a, b'), nl, - write(' (Könnte für etwas Besonderes nützlich sein...)'), nl. - -process_command([schaue]) :- - look_around. - -process_command([gehe, Direction]) :- - move_player(Direction). - -process_command([nimm, Item]) :- - take_item(Item). - -process_command([verwende, Item]) :- - use_item(Item). - -process_command([rede, Person]) :- - talk_to(Person). - -process_command([angriff, Enemy]) :- - start_combat(Enemy). - -process_command([baue, Item]) :- - craft_item(Item). - -process_command([hack, Target]) :- - hack_target(Target). - -process_command([klettere]) :- - climb_action. - -process_command([inventar]) :- - show_inventory. - -process_command([status]) :- - show_status. - -process_command([clear]) :- - clear_screen. - -% ========== CHEAT CODES (for testing) ========== -process_command([cheat, heal]) :- - retract(player_health(_)), - assertz(player_health(100)), - write('Gesundheit wiederhergestellt!'), nl. - -process_command([cheat, items]) :- - assertz(player_inventory(spule)), - assertz(player_inventory(batterie)), - assertz(player_inventory(kondensator)), - assertz(player_inventory(emp_granate)), - assertz(player_inventory(emp_granate)), - assertz(player_inventory(parkour_handschuhe)), - assertz(player_inventory(drohnen_motor)), - assertz(player_inventory(steuerungsmodul)), - assertz(player_inventory(heilspray)), - write('Alle Items erhalten!'), nl. - -process_command([cheat, teleport, LOC]) :- - retract(player_location(_)), - assertz(player_location(LOC)). - -process_command([cheat, generator_components]) :- - assertz(player_inventory(spule)), - assertz(player_inventory(batterie)), - assertz(player_inventory(kondensator)), - write('EMP-Generator Komponenten erhalten!'), nl. - -process_command([cheat, generator_components]) :- - assertz(player_inventory(spule)), - assertz(player_inventory(batterie)), - assertz(player_inventory(kondensator)), - write('EMP-Generator Komponenten erhalten!'), nl. - -process_command(_) :- - write('Unbekannter Befehl. Verwende "hilfe" für eine Liste der Befehle.'), nl. - -% ========== COMBAT COMMANDS ========== -process_combat_command([angriff], Enemy) :- - combat_attack(Enemy). - -process_combat_command([verwende, Item], Enemy) :- - combat_use_item(Item, Enemy). - -process_combat_command([heile], Enemy) :- - combat_heal(Enemy). - -process_combat_command(_, _) :- - write('Ungültige Kampfaktion! Verwende: angriff oder verwende(item)'), nl. - -% ========== CORE GAME MECHANICS ========== -look_around :- - player_location(Loc), - location(Loc, Name, Desc), - write(Name), nl, - write(Desc), nl, - list_items_here(Loc), - list_npcs_here(Loc), - list_enemies_here(Loc), - list_exits(Loc), - check_obstacles_here(Loc). - -list_items_here(Loc) :- - findall(Item, item_location(Item, Loc), Items), - (Items = [] -> true ; - (write('Gegenstände hier: '), write_list(Items), nl)). - -list_npcs_here(Loc) :- - findall(NPC, npc_location(NPC, Loc), NPCs), - (NPCs = [] -> true ; - (write('Personen hier: '), write_list(NPCs), nl)). - -list_enemies_here(Loc) :- - findall(Enemy, enemy_location(Enemy, Loc), Enemies), - (Enemies = [] -> true ; - (write('Feinde hier: '), write_list(Enemies), nl)). - -list_exits(Loc) :- - findall(Exit, connected(Loc, Exit), Exits), - (Exits = [] -> write('Keine Ausgänge.') ; - (write('Ausgänge: '), write_list(Exits))), nl. - -check_obstacles_here(Loc) :- - findall(obstacle(Loc, Exit, ObstacleType), obstacle(Loc, Exit, ObstacleType), Obstacles), - (Obstacles = [] -> true ; list_obstacles(Obstacles)). - -% ========== MOVEMENT WITH OBSTACLES ========== -move_player(Direction) :- - player_location(CurrentLoc), - connected(CurrentLoc, Direction), - (obstacle(CurrentLoc, Direction, ObstacleType) -> - handle_obstacle(ObstacleType, Direction) ; - (retract(player_location(CurrentLoc)), - assertz(player_location(Direction)), - write('Du gehst nach '), write(Direction), nl, - trigger_location_event(Direction))), - !. - -move_player(_) :- - write('Du kannst nicht dorthin gehen.'), nl. - - -handle_obstacle(hohe_mauer, Direction) :- - (player_inventory(parkour_handschuhe) -> - (write('Du kletterst mit den Parkour-Handschuhen über die hohe Mauer!'), nl, - player_location(CurrentLoc), - retract(obstacle(CurrentLoc, Direction, hohe_mauer)), - retract(player_location(CurrentLoc)), - assertz(player_location(Direction)), - write('Du gehst nach '), write(Direction), nl) ; - write('Eine hohe Mauer blockiert deinen Weg! Du brauchst Parkour-Handschuhe.'), nl). - -handle_obstacle(drone_swarm, Direction) :- - (player_inventory(kampfdrohne) -> - (write('Deine Kampfdrohne bekämpft den feindlichen Schwarm!'), nl, - write('Die Drohnen werden zerstört und der Weg ist frei!'), nl, - player_location(CurrentLoc), - retract(obstacle(CurrentLoc, Direction, drone_swarm)), - retract(player_location(CurrentLoc)), - assertz(player_location(Direction)), - write('Du gehst nach '), write(Direction), nl) ; - write('Ein Schwarm aggressiver Drohnen blockiert den Weg! Du brauchst eine Kampfdrohne.'), nl). - -handle_obstacle(security_system, Direction) :- - (player_inventory(emp_generator) -> - (write('Du aktivierst den EMP-Generator! Das Sicherheitssystem bricht zusammen!'), nl, - player_location(CurrentLoc), - retract(obstacle(CurrentLoc, Direction, security_system)), - retract(player_location(CurrentLoc)), - assertz(player_location(Direction)), - write('Du gehst nach '), write(Direction), nl) ; - write('Ein Hochsicherheitssystem blockiert den Zugang! Du brauchst einen EMP-Generator.'), nl). - -% ========== INVENTORY MANAGEMENT ========== -take_item(ItemName) :- - player_location(Loc), - item_location(ItemName, Loc), - retract(item_location(ItemName, Loc)), - assertz(player_inventory(ItemName)), - item(ItemName, DisplayName, _), - write('Du nimmst '), write(DisplayName), write(' auf.'), nl, - !. - -take_item(_) :- - write('Diesen Gegenstand kannst du hier nicht finden.'), nl. - -use_item(ItemName) :- - player_inventory(ItemName), - execute_item_use(ItemName), - !. - -use_item(_) :- - write('Du hast diesen Gegenstand nicht oder kannst ihn nicht verwenden.'), nl. - -show_inventory :- - write('Dein Inventar:'), nl, - findall(Item, player_inventory(Item), Items), - (Items = [] -> write('Dein Inventar ist leer.') ; list_inventory_items(Items)), nl. - -list_inventory_items([]). -list_inventory_items([H|T]) :- - item(H, DisplayName, Desc), - write('- '), write(DisplayName), write(': '), write(Desc), nl, - list_inventory_items(T). - -% ========== ITEM USAGE ========== -execute_item_use(laptop) :- - player_location(htl_labor), - write('Du hackst dich in die Schulserver ein und analysierst die Drohnen-Aufnahmen.'), nl, - write('SCHOCKIERENDE ENTDECKUNG: Die Vögel sind Überwachungsdrohnen!'), nl, - !. - -execute_item_use(heilspray) :- - player_health(Health), - (Health >= 100 -> - write('Du hast bereits volle Gesundheit!'), nl ; - (NewHealth is min(100, Health + 30), - retract(player_health(Health)), - assertz(player_health(NewHealth)), - write('Du verwendest das Heilspray und gewinnst 30 Gesundheitspunkte!'), nl, - retract(player_inventory(heilspray)))), - !. - -execute_item_use(_) :- - write('Du kannst diesen Gegenstand hier nicht verwenden.'), nl. - -% ========== TURN-BASED COMBAT SYSTEM ========== -start_combat(EnemyName) :- - player_location(Loc), - enemy_location(EnemyName, Loc), - assertz(drone_cooldown(EnemyName, 0)), - assertz(health_recovery_used(EnemyName, 0)), - write('Du beginnst den Kampf gegen '), enemy(EnemyName, DisplayName, _, _), - write(DisplayName), write('!'), nl, - assertz(in_combat(EnemyName)), - !. - -start_combat(_) :- - write('Hier ist kein Feind zum Angreifen.'), nl. - -combat_attack(Enemy) :- - get_random_damage(Damage), - enemy(Enemy, DisplayName, Health, Desc), - NewHealth is Health - Damage, - write('Du greifst '), write(DisplayName), write(' an und verursachst '), - write(Damage), write(' Schaden!'), nl, - retract(enemy(Enemy, DisplayName, Health, Desc)), - (NewHealth =< 0 -> - (write(DisplayName), write(' wurde besiegt!'), nl, - defeat_enemy(Enemy)) ; - (assertz(enemy(Enemy, DisplayName, NewHealth, Desc)), - enemy_turn(Enemy))). - -combat_use_item(ItemName, Enemy) :- - player_inventory(ItemName), - execute_combat_item_use(ItemName, Enemy), - !. - -combat_use_item(_, _) :- - write('Du hast diesen Gegenstand nicht!'), nl. - -combat_heal(Enemy) :- - health_recovery_used(Enemy, Used), - Used >= 2, - write('Du hast bereits alle Heilungen in diesem Kampf verbraucht!'), nl, - !. - -combat_heal(_) :- - player_health(CurrentHealth), - CurrentHealth >= 100, - write('Du hast bereits volle Gesundheit!'), nl, - !. - -combat_heal(Enemy) :- - health_recovery_used(Enemy, Used), - Used < 2, - random(19, 31, HealAmount), - player_health(CurrentHealth), - NewHealth is min(100, CurrentHealth + HealAmount), - HealedAmount is NewHealth - CurrentHealth, - retract(player_health(CurrentHealth)), - assertz(player_health(NewHealth)), - NewUsed is Used + 1, - retract(health_recovery_used(Enemy, Used)), - assertz(health_recovery_used(Enemy, NewUsed)), - write('Du heilst dich selbst und gewinnst '), write(HealedAmount), - write(' Gesundheitspunkte!'), nl, - RemainingUses is 2 - NewUsed, - write('Verbleibende Heilungen: '), write(RemainingUses), nl, - enemy_turn(Enemy). - -execute_combat_item_use(emp_granate, Enemy) :- - emp_used_in_combat(Enemy), - write('Du hast bereits eine EMP-Granate in diesem Kampf verwendet!'), nl, - !. - -execute_combat_item_use(emp_granate, Enemy) :- - enemy(Enemy, DisplayName, Health, Desc), - assertz(emp_used_in_combat(Enemy)), - (Enemy = die_kraehe -> - (write('Du schwächst die Krähe mit der EMP-Granate!'), nl, - retract(game_state(crow_weakened, false)), - assertz(game_state(crow_weakened, true)), - retract(player_inventory(emp_granate))) ; - (Damage = 40, - NewHealth is Health - Damage, - write('Die EMP-Granate verursacht '), write(Damage), write(' Schaden!'), nl, - retract(enemy(Enemy, DisplayName, Health, Desc)), - retract(player_inventory(emp_granate)), - (NewHealth =< 0 -> - (write(DisplayName), write(' wurde besiegt!'), nl, - defeat_enemy(Enemy)) ; - (assertz(enemy(Enemy, DisplayName, NewHealth, Desc)), - enemy_turn(Enemy))))). - -execute_combat_item_use(kampfdrohne, Enemy) :- - drone_cooldown(Enemy, Cooldown), - Cooldown > 0, - write('Deine Kampfdrohne lädt noch auf! Cooldown: '), write(Cooldown), write(' Runden.'), nl, - !. - -execute_combat_item_use(kampfdrohne, Enemy) :- - enemy(Enemy, DisplayName, Health, Desc), - Damage = 25, - NewHealth is Health - Damage, - write('Deine Kampfdrohne greift an und verursacht '), write(Damage), write(' Schaden!'), nl, - write('Die Drohne muss sich jetzt 2 Runden lang aufladen.'), nl, - % Set cooldown to 2 turns - retract(drone_cooldown(Enemy, _)), - assertz(drone_cooldown(Enemy, 2)), - retract(enemy(Enemy, DisplayName, Health, Desc)), - (NewHealth =< 0 -> - (write(DisplayName), write(' wurde besiegt!'), nl, - defeat_enemy(Enemy)) ; - (assertz(enemy(Enemy, DisplayName, NewHealth, Desc)), - enemy_turn(Enemy))). - -execute_combat_item_use(heilspray, _) :- - execute_item_use(heilspray). - -execute_combat_item_use(Item, _) :- - \+ member(Item, [emp_granate, kampfdrohne, heilspray]), - item(Item, DisplayName, _), - write(DisplayName), write(' kann nicht im Kampf verwendet werden!'), nl. - -execute_combat_item_use(Item, _) :- - write(Item), write(' kann nicht im Kampf verwendet werden!'), nl. - -enemy_turn(Enemy) :- - drone_cooldown(Enemy, Cooldown), - (Cooldown > 0 -> - (NewCooldown is Cooldown - 1, - retract(drone_cooldown(Enemy, Cooldown)), - assertz(drone_cooldown(Enemy, NewCooldown))) ; - true), - enemy(Enemy, DisplayName, _, _), - (Enemy = die_kraehe, game_state(crow_weakened, false) -> - crow_mind_control ; - normal_enemy_attack(Enemy, DisplayName)). - -normal_enemy_attack(_, DisplayName) :- - get_random_enemy_damage(Damage), - damage_player(Damage), - write(DisplayName), write(' greift an und verursacht '), - write(Damage), write(' Schaden!'), nl. - -crow_mind_control :- - write('Die Krähe übernimmt die Kontrolle über deinen Verstand!'), nl, - write('Du schlägst dich selbst!'), nl, - damage_player(20), - write('Du verursachst dir '), write(20), write(' Schaden!'), nl. - -defeat_enemy(EnemyName) :- - retract(enemy_location(EnemyName, _)), - retract(in_combat(EnemyName)), - handle_enemy_defeat(EnemyName), - retractall(emp_used_in_combat(EnemyName)), - retractall(drone_cooldown(EnemyName, _)), - retractall(health_recovery_used(EnemyName, _)), - nl. - -handle_enemy_defeat(tauben_schwarm) :- - write('Die Tauben explodieren! Du findest ein Heilspray und einen Drohnen-Motor in den Trümmern.'), nl, - player_location(Loc), - assertz(item_location(drohnen_motor, Loc)), - assertz(item_location(heilspray, Loc)). - -handle_enemy_defeat(storch_drohne) :- - write('Die Storch-Drohne lässt ein Steuerungsmodul und EMP-Granaten fallen!'), nl, - player_location(Loc), - assertz(item_location(steuerungsmodul, Loc)), - assertz(item_location(emp_granate, Loc)). - -handle_enemy_defeat(die_kraehe) :- - write('Die Krähe ist besiegt! Das Drohnen-Netzwerk wankt...'), nl, - write('Du stehst vor der Hauptkonsole von Aviary Control.'), nl, - write('Plötzlich erscheint eine Nachricht auf dem Bildschirm:'), nl, - write('"Beeindruckend, John. Du hast es bis hierher geschafft."'), nl, - write('"Aber jetzt musst du eine Wahl treffen..."'), nl, - final_choice. - - -% ========== CRAFTING SYSTEM ========== -craft_item(emp_generator) :- - player_location(htl_werkstatt), - player_inventory(spule), - player_inventory(batterie), - player_inventory(kondensator), - write('Du baust aus Spule, Batterie und Kondensator einen EMP-Generator!'), nl, - retract(player_inventory(spule)), - retract(player_inventory(batterie)), - retract(player_inventory(kondensator)), - assertz(player_inventory(emp_generator)), - retract(game_state(emp_built, false)), - assertz(game_state(emp_built, true)), - !. - -craft_item(emp_generator) :- - player_location(htl_werkstatt), - write('Du brauchst: Elektro-Spule, Hochleistungsbatterie und Kondensator.'), nl, - !. - -craft_item(emp_generator) :- - write('Du kannst nur in der HTL Leonding Werkstatt bauen.'), nl, - !. - -craft_item(kampfdrohne) :- - player_location(htl_werkstatt), - player_inventory(drohnen_motor), - player_inventory(steuerungsmodul), - write('Du baust aus Motor und Steuerungsmodul eine Kampfdrohne!'), nl, - retract(player_inventory(drohnen_motor)), - retract(player_inventory(steuerungsmodul)), - assertz(player_inventory(kampfdrohne)), - !. - -craft_item(kampfdrohne) :- - player_location(htl_werkstatt), - write('Du brauchst: Drohnen-Motor und Steuerungsmodul um eine Kampfdrohne zu bauen.'), nl, - !. - -craft_item(kampfdrohne) :- - write('Du kannst nur in der HTL Leonding Werkstatt bauen.'), nl, - !. - -craft_item(_) :- - write('Du kannst diesen Gegenstand nicht bauen.'), nl. - -% ========== HACKING MINI-GAMES ========== -hack_target(box) :- - player_location(Loc), - player_inventory(laptop), - hacking_minigame(Loc), - !. - -hack_target(_) :- - write('Du kannst dieses Ziel nicht hacken oder hast keinen Laptop.'), nl. - -hacking_minigame(altstadt) :- - box_unlocked(altstadt_box), - write('Diese Box wurde bereits gehackt.'), nl, - !. - -hacking_minigame(altstadt) :- - write('=== HACKING MINI-GAME ==='), nl, - write('Entschlüssele den Code: 1001 + 0110 = ?'), nl, - write('Gib das Ergebnis in binär ein: '), - read(Answer), - (Answer = 1111 -> - (write('Korrekt! Du findest eine Elektro-Spule in der Box!'), nl, - assertz(player_inventory(spule)), - assertz(box_unlocked(altstadt_box))) ; - (write('Falsch! Versuch es nochmal.'), nl, - fail)). - -hacking_minigame(donauufer) :- - box_unlocked(donauufer_box), - write('Diese Box wurde bereits gehackt.'), nl, - !. - -hacking_minigame(donauufer) :- - write('=== HACKING MINI-GAME ==='), nl, - write('SQL Injection: Welcher Befehl umgeht die Passwort-Abfrage?'), nl, - write('1) DROP TABLE users'), nl, - write('2) \' OR \'1\'=\'1'), nl, - write('3) SELECT * FROM passwords'), nl, - write('Deine Wahl (1-3): '), - read(Answer), - (Answer = 2 -> - (write('Korrekt! Du findest eine Hochleistungsbatterie in der Box!'), nl, - assertz(player_inventory(batterie)), - assertz(box_unlocked(donauufer_box))) ; - (write('Falsch! Versuch es nochmal.'), nl, - fail)). - -hacking_minigame(poestlingberg) :- - box_unlocked(poestlingberg_box), - write('Diese Box wurde bereits gehackt.'), nl, - !. - -hacking_minigame(poestlingberg) :- - player_inventory(kampfdrohne), - write('=== DROHNEN-HACKING ==='), nl, - write('Deine Kampfdrohne verbindet sich mit der Box...'), nl, - write('Netzwerk-Port-Scan: Welcher Port ist für SSH Standard?'), nl, - write('1) Port 80'), nl, - write('2) Port 22'), nl, - write('3) Port 443'), nl, - write('Deine Wahl (1-3): '), - read(Answer), - (Answer = 2 -> - (write('Korrekt! Du findest einen Kondensator in der Box!'), nl, - assertz(player_inventory(kondensator)), - assertz(box_unlocked(poestlingberg_box))) ; - (write('Falsch! Versuch es nochmal.'), nl, - fail)). - -hacking_minigame(poestlingberg) :- - write('Du brauchst eine Kampfdrohne um diese Box zu hacken.'), nl. - -hacking_minigame(_) :- - write('Hier gibt es nichts zu hacken.'), nl. - -% ========== CLIMBING SYSTEM ========== -climb_action :- - player_location(altstadt), - player_inventory(parkour_handschuhe), - write('=== PARKOUR KLETTERN ==='), nl, - write('Du beginnst den Aufstieg...'), nl, - parkour_minigame_altstadt, - !. - -climb_action :- - player_location(altstadt), - write('Du brauchst Parkour-Handschuhe um auf das Dach zu klettern.'), nl, - !. - -climb_action :- - player_location(donauufer), - player_inventory(parkour_handschuhe), - write('=== TURM KLETTERN ==='), nl, - write('Du kletterst den hohen Industrieturm hinauf...'), nl, - climbing_minigame_donauufer, - !. - -climb_action :- - player_location(donauufer), - write('Du brauchst Parkour-Handschuhe um auf den Turm zu klettern.'), nl, - !. - -climb_action :- - player_location(poestlingberg), - player_inventory(parkour_handschuhe), - write('=== ÜBERWACHUNGSTURM KLETTERN ==='), nl, - write('Du kletterst den gefährlichen Überwachungsturm hinauf...'), nl, - climbing_minigame_poestlingberg, - !. - -climb_action :- - player_location(poestlingberg), - write('Du brauchst Parkour-Handschuhe um auf den Überwachungsturm zu klettern.'), nl, - !. - -climb_action :- - write('Hier gibt es nichts zum Klettern.'), nl. - -% ========== PARKOUR-MINIGAMES ========== -parkour_minigame_altstadt :- - write('Sequenz-Challenge: Wiederhole die Bewegungsfolge!'), nl, - random_member(Sequence, [[sprung, rolle, kletter], [rolle, sprung, balance], [kletter, sprung, rolle]]), - write('Merke dir: '), write_sequence(Sequence), nl, - write('Warte...'), nl, sleep(2), - clear_screen, - write('Jetzt wiederhole die Sequenz:'), nl, - write('Gib die Sequenz als Liste ein, z.B. [sprung, rolle, kletter].'), nl, - write('Verfügbare Bewegungen: sprung, rolle, kletter, balance'), nl, - write('> '), - read_sequence(UserSequence), - (UserSequence = Sequence -> - (write('Perfekte Ausführung! Du erreichst das Dach sicher!'), nl, - write('Du findest eine verschlossene Box auf dem Dach.'), nl, - write('Verwende "hack(box)" um sie zu öffnen.'), nl) ; - (write('Falsche Sequenz! Du rutschst ab und verlierst 10 Gesundheit.'), nl, - damage_player(10))). - -climbing_minigame_donauufer :- - write('Balance-Challenge: Halte das Gleichgewicht!'), nl, - write('Drücke abwechselnd "links" und "rechts" um das Gleichgewicht zu halten.'), nl, - write('Du musst 5 mal korrekt reagieren!'), nl, - balance_challenge(5, 0). - -balance_challenge(0, Success) :- - Success >= 4, - write('Excellent! Du hast den Turm erfolgreich erklommen!'), nl, - write('Oben ist ein elektrisches Schutzschild um eine Box.'), nl, - write('Du brauchst eine EMP-Granate um das Schild zu deaktivieren.'), nl, - (player_inventory(emp_granate) -> - (write('Du verwendest die EMP-Granate! Das Schild fällt aus!'), nl, - retract(player_inventory(emp_granate)), - write('Verwende "hack(box)" um die Box zu öffnen.'), nl) ; - true), - !. - -balance_challenge(0, Success) :- - Success < 4, - write('Du verlierst das Gleichgewicht und fällst! 15 Schaden!'), nl, - damage_player(15), - !. - -balance_challenge(Remaining, Success) :- - Remaining > 0, - random_member(Direction, [links, rechts]), - write('Das Gebäude schwankt nach '), write(Direction), write('! Schnell reagieren:'), nl, - write('> '), - read(Response), - NewRemaining is Remaining - 1, - (Response = Direction -> - (write('Gut! Gleichgewicht gehalten.'), nl, - NewSuccess is Success + 1) ; - (write('Falsch! Du wackelst gefährlich.'), nl, - NewSuccess = Success)), - balance_challenge(NewRemaining, NewSuccess). - -climbing_minigame_poestlingberg :- - write('Stealth-Klettern: Vermeide die Überwachungskameras!'), nl, - write('Du musst die richtige Route wählen um unentdeckt zu bleiben.'), nl, - stealth_climbing_challenge. - -stealth_climbing_challenge :- - write('Stufe 1: Kamera schwenkt von links nach rechts. Wann bewegst du dich?'), nl, - write('1) Wenn die Kamera nach links schaut'), nl, - write('2) Wenn die Kamera nach rechts schaut'), nl, - write('3) Wenn die Kamera geradeaus schaut'), nl, - write('> '), - read(Choice1), - (Choice1 = 1 -> - (write('Richtig! Du nutzt den toten Winkel.'), nl, - write('Stufe 2: Zwei Kameras kreuzen sich. Wann bewegst du dich?'), nl, - write('1) Gleichzeitig mit beiden'), nl, - write('2) Zwischen den Schwenkbewegungen'), nl, - write('3) Wenn eine Kamera defekt ist'), nl, - write('> '), - read(Choice2), - (Choice2 = 2 -> - (write('Perfekt! Du erreichst die Spitze unentdeckt!'), nl, - write('Du findest eine schwer gesicherte Box.'), nl, - write('Diese Box benötigt eine Kampfdrohne zum Hacken.'), nl) ; - (write('Entdeckt! Alarm! Du verlierst 20 Gesundheit beim hastigen Rückzug.'), nl, - damage_player(20)))) ; - (write('Entdeckt! Du musst schnell fliehen und verlierst 15 Gesundheit.'), nl, - damage_player(15))). - - -% ========== GAME STATE MANAGEMENT ========== -check_game_state :- - player_health(Health), - (Health =< 0 -> - (retractall(in_combat(_)), - end_game(defeat), - !, fail) ; - true). - -show_status :- - player_health(Health), - write('=== STATUS ==='), nl, - write('Gesundheit: '), write(Health), nl, - (player_inventory(kampfdrohne) -> - write('Kampfdrohne: ✓ Gebaut'), nl ; - (write('Kampfdrohne Komponenten:'), nl, - (player_inventory(drohnen_motor) -> write(' Drohnen-Motor: ✓') ; write(' Drohnen-Motor: ✗')), nl, - (player_inventory(steuerungsmodul) -> write(' Steuerungsmodul: ✓') ; write(' Steuerungsmodul: ✗')), nl)), - (game_state(emp_built, true) -> - write('EMP-Generator: ✓ Gebaut'), nl ; - (write('EMP-Generator Komponenten:'), nl, - (player_inventory(spule) -> write(' Elektro-Spule: ✓') ; write(' Elektro-Spule: ✗')), nl, - (player_inventory(batterie) -> write(' Batterie: ✓') ; write(' Batterie: ✗')), nl, - (player_inventory(kondensator) -> write(' Kondensator: ✓') ; write(' Kondensator: ✗')), nl)), - write('=============='), nl. - -% ========== HELP PREDICATES ========== -hilfe :- process_command([hilfe]). -schaue :- process_command([schaue]). -inventar :- process_command([inventar]). -status :- process_command([status]). - % Start predicate to begin the game :- initialization(start_game). \ No newline at end of file diff --git a/game_assets/climbing_system.pl b/game_assets/climbing_system.pl new file mode 100644 index 0000000..b86907f --- /dev/null +++ b/game_assets/climbing_system.pl @@ -0,0 +1,42 @@ +% ========== CLIMBING SYSTEM ========== +climb_action :- + player_location(altstadt), + player_inventory(parkour_handschuhe), + write('=== PARKOUR KLETTERN ==='), nl, + write('Du beginnst den Aufstieg...'), nl, + parkour_minigame_altstadt, + !. + +climb_action :- + player_location(altstadt), + write('Du brauchst Parkour-Handschuhe um auf das Dach zu klettern.'), nl, + !. + +climb_action :- + player_location(donauufer), + player_inventory(parkour_handschuhe), + write('=== TURM KLETTERN ==='), nl, + write('Du kletterst den hohen Industrieturm hinauf...'), nl, + climbing_minigame_donauufer, + !. + +climb_action :- + player_location(donauufer), + write('Du brauchst Parkour-Handschuhe um auf den Turm zu klettern.'), nl, + !. + +climb_action :- + player_location(poestlingberg), + player_inventory(parkour_handschuhe), + write('=== ÜBERWACHUNGSTURM KLETTERN ==='), nl, + write('Du kletterst den gefährlichen Überwachungsturm hinauf...'), nl, + climbing_minigame_poestlingberg, + !. + +climb_action :- + player_location(poestlingberg), + write('Du brauchst Parkour-Handschuhe um auf den Überwachungsturm zu klettern.'), nl, + !. + +climb_action :- + write('Hier gibt es nichts zum Klettern.'), nl. \ No newline at end of file diff --git a/game_assets/combat_system.pl b/game_assets/combat_system.pl new file mode 100644 index 0000000..bd3c6dd --- /dev/null +++ b/game_assets/combat_system.pl @@ -0,0 +1,188 @@ +% ========== MAIN COMBAT LOOP ========== +combat_loop(Enemy) :- + enemy(Enemy, DisplayName, Health, _), + nl, + write('=== KAMPF GEGEN '), write(DisplayName), write(' ==='), nl, + write('Feind Gesundheit: '), write(Health), nl, + player_health(PlayerHealth), + write('Deine Gesundheit: '), write(PlayerHealth), nl, + health_recovery_used(Enemy, RecoveryUsed), + RemainingRecovery is 2 - RecoveryUsed, + write('Heilungen übrig: '), write(RemainingRecovery), write('/2'), nl, + write('Verfügbare Aktionen: angriff, heile, verwende(item)'), nl, nl, + write('> '), + read_line(Command), + process_combat_command(Command, Enemy), + check_game_state, + !, + game_loop. + +% ========== COMBAT COMMANDS ========== +process_combat_command([angriff], Enemy) :- + combat_attack(Enemy). + +process_combat_command([verwende, Item], Enemy) :- + combat_use_item(Item, Enemy). + +process_combat_command([heile], Enemy) :- + combat_heal(Enemy). + +process_combat_command(_, _) :- + write('Ungültige Kampfaktion! Verwende: angriff, heile oder verwende(item)'), nl. + +% ========== TURN-BASED COMBAT SYSTEM ========== +start_combat(EnemyName) :- + player_location(Loc), + enemy_location(EnemyName, Loc), + assertz(drone_cooldown(EnemyName, 0)), + assertz(health_recovery_used(EnemyName, 0)), + write('Du beginnst den Kampf gegen '), enemy(EnemyName, DisplayName, _, _), + write(DisplayName), write('!'), nl, + assertz(in_combat(EnemyName)), + !. + +start_combat(_) :- + write('Hier ist kein Feind zum Angreifen.'), nl. + +combat_attack(Enemy) :- + get_random_damage(Damage), + enemy(Enemy, DisplayName, Health, Desc), + NewHealth is Health - Damage, + write('Du greifst '), write(DisplayName), write(' an und verursachst '), + write(Damage), write(' Schaden!'), nl, + retract(enemy(Enemy, DisplayName, Health, Desc)), + (NewHealth =< 0 -> + (write(DisplayName), write(' wurde besiegt!'), nl, + defeat_enemy(Enemy)) ; + (assertz(enemy(Enemy, DisplayName, NewHealth, Desc)), + enemy_turn(Enemy))). + +combat_use_item(ItemName, Enemy) :- + player_inventory(ItemName), + execute_combat_item_use(ItemName, Enemy), + !. + +combat_use_item(_, _) :- + write('Du hast diesen Gegenstand nicht!'), nl. + +combat_heal(Enemy) :- + health_recovery_used(Enemy, Used), + Used >= 2, + write('Du hast bereits alle Heilungen in diesem Kampf verbraucht!'), nl, + !. + +combat_heal(_) :- + player_health(CurrentHealth), + CurrentHealth >= 100, + write('Du hast bereits volle Gesundheit!'), nl, + !. + +combat_heal(Enemy) :- + health_recovery_used(Enemy, Used), + Used < 2, + random(19, 31, HealAmount), + player_health(CurrentHealth), + NewHealth is min(100, CurrentHealth + HealAmount), + HealedAmount is NewHealth - CurrentHealth, + retract(player_health(CurrentHealth)), + assertz(player_health(NewHealth)), + NewUsed is Used + 1, + retract(health_recovery_used(Enemy, Used)), + assertz(health_recovery_used(Enemy, NewUsed)), + write('Du heilst dich selbst und gewinnst '), write(HealedAmount), + write(' Gesundheitspunkte!'), nl, + RemainingUses is 2 - NewUsed, + write('Verbleibende Heilungen: '), write(RemainingUses), nl, + enemy_turn(Enemy). + +% ========== COMBAT ITEMS ========== +execute_combat_item_use(emp_granate, Enemy) :- + emp_used_in_combat(Enemy), + write('Du hast bereits eine EMP-Granate in diesem Kampf verwendet!'), nl, + !. + +execute_combat_item_use(emp_granate, Enemy) :- + enemy(Enemy, DisplayName, Health, Desc), + assertz(emp_used_in_combat(Enemy)), + (Enemy = die_kraehe -> + (write('Du schwächst die Krähe mit der EMP-Granate!'), nl, + retract(game_state(crow_weakened, false)), + assertz(game_state(crow_weakened, true)), + retract(player_inventory(emp_granate))) ; + (Damage = 40, + NewHealth is Health - Damage, + write('Die EMP-Granate verursacht '), write(Damage), write(' Schaden!'), nl, + retract(enemy(Enemy, DisplayName, Health, Desc)), + retract(player_inventory(emp_granate)), + (NewHealth =< 0 -> + (write(DisplayName), write(' wurde besiegt!'), nl, + defeat_enemy(Enemy)) ; + (assertz(enemy(Enemy, DisplayName, NewHealth, Desc)), + enemy_turn(Enemy))))). + +execute_combat_item_use(kampfdrohne, Enemy) :- + drone_cooldown(Enemy, Cooldown), + Cooldown > 0, + write('Deine Kampfdrohne lädt noch auf! Cooldown: '), write(Cooldown), write(' Runden.'), nl, + !. + +execute_combat_item_use(kampfdrohne, Enemy) :- + enemy(Enemy, DisplayName, Health, Desc), + Damage = 25, + NewHealth is Health - Damage, + write('Deine Kampfdrohne greift an und verursacht '), write(Damage), write(' Schaden!'), nl, + write('Die Drohne muss sich jetzt 2 Runden lang aufladen.'), nl, + % Set cooldown to 2 turns + retract(drone_cooldown(Enemy, _)), + assertz(drone_cooldown(Enemy, 2)), + retract(enemy(Enemy, DisplayName, Health, Desc)), + (NewHealth =< 0 -> + (write(DisplayName), write(' wurde besiegt!'), nl, + defeat_enemy(Enemy)) ; + (assertz(enemy(Enemy, DisplayName, NewHealth, Desc)), + enemy_turn(Enemy))). + +execute_combat_item_use(heilspray, _) :- + execute_item_use(heilspray). + +execute_combat_item_use(Item, _) :- + \+ member(Item, [emp_granate, kampfdrohne, heilspray]), + item(Item, DisplayName, _), + write(DisplayName), write(' kann nicht im Kampf verwendet werden!'), nl. + +execute_combat_item_use(Item, _) :- + write(Item), write(' kann nicht im Kampf verwendet werden!'), nl. + +% ========== ENEMY-ATTACKS/DEFEAT ========== +enemy_turn(Enemy) :- + drone_cooldown(Enemy, Cooldown), + (Cooldown > 0 -> + (NewCooldown is Cooldown - 1, + retract(drone_cooldown(Enemy, Cooldown)), + assertz(drone_cooldown(Enemy, NewCooldown))) ; + true), + enemy(Enemy, DisplayName, _, _), + (Enemy = die_kraehe, game_state(crow_weakened, false) -> + crow_mind_control ; + normal_enemy_attack(Enemy, DisplayName)). + +normal_enemy_attack(_, DisplayName) :- + get_random_enemy_damage(Damage), + damage_player(Damage), + write(DisplayName), write(' greift an und verursacht '), + write(Damage), write(' Schaden!'), nl. + +crow_mind_control :- + write('Die Krähe übernimmt die Kontrolle über deinen Verstand!'), nl, + write('Du schlägst dich selbst!'), nl, + damage_player(20), + write('Du verursachst dir '), write(20), write(' Schaden!'), nl. + +defeat_enemy(EnemyName) :- + retract(enemy_location(EnemyName, _)), + retract(in_combat(EnemyName)), + handle_enemy_defeat(EnemyName), + retractall(emp_used_in_combat(EnemyName)), + retractall(drone_cooldown(EnemyName, _)), + retractall(health_recovery_used(EnemyName, _)), + nl. \ No newline at end of file diff --git a/game_assets/command_processing.pl b/game_assets/command_processing.pl new file mode 100644 index 0000000..0142f99 --- /dev/null +++ b/game_assets/command_processing.pl @@ -0,0 +1,99 @@ +% ========== INPUT PROCESSING ========== +read_line(Command) :- + read(Input), + parse_input(Input, Command). + +parse_input(Input, [Input]) :- + atom(Input), !. + +parse_input(Input, Command) :- + compound(Input), + Input =.. Command, !. + +parse_input(_, [unknown]). + +% ========== COMMAND PROCESSING ========== +process_command([oben]) :- check_konami_input(oben). +process_command([unten]) :- check_konami_input(unten). +process_command([links]) :- check_konami_input(links). +process_command([rechts]) :- check_konami_input(rechts). +process_command([a]) :- check_konami_input(a). +process_command([b]) :- check_konami_input(b). + +process_command([beende]) :- + end_game. + +process_command([hilfe]) :- + help. + +process_command([schaue]) :- + look_around. + +process_command([gehe, Direction]) :- + move_player(Direction). + +process_command([nimm, Item]) :- + take_item(Item). + +process_command([verwende, Item]) :- + use_item(Item). + +process_command([rede, Person]) :- + talk_to(Person). + +process_command([angriff, Enemy]) :- + start_combat(Enemy). + +process_command([baue, Item]) :- + craft_item(Item). + +process_command([hack, Target]) :- + hack_target(Target). + +process_command([klettere]) :- + climb_action. + +process_command([inventar]) :- + show_inventory. + +process_command([status]) :- + show_status. + +process_command([clear]) :- + clear_screen. + +% ========== CHEAT CODES (FOR TESTING) ========== +process_command([cheat, heal]) :- + retract(player_health(_)), + assertz(player_health(100)), + write('Gesundheit wiederhergestellt!'), nl. + +process_command([cheat, items]) :- + assertz(player_inventory(spule)), + assertz(player_inventory(batterie)), + assertz(player_inventory(kondensator)), + assertz(player_inventory(emp_granate)), + assertz(player_inventory(emp_granate)), + assertz(player_inventory(parkour_handschuhe)), + assertz(player_inventory(drohnen_motor)), + assertz(player_inventory(steuerungsmodul)), + assertz(player_inventory(heilspray)), + write('Alle Items erhalten!'), nl. + +process_command([cheat, teleport, LOC]) :- + retract(player_location(_)), + assertz(player_location(LOC)). + +process_command([cheat, generator_components]) :- + assertz(player_inventory(spule)), + assertz(player_inventory(batterie)), + assertz(player_inventory(kondensator)), + write('EMP-Generator Komponenten erhalten!'), nl. + +process_command([cheat, generator_components]) :- + assertz(player_inventory(drohnen_motor)), + assertz(player_inventory(steuerungsmodul)), + write('Kampfdrone Komponenten erhalten!'), nl. + +process_command(_) :- + write('Unbekannter Befehl. Verwende "hilfe" für eine Liste der Befehle.'), nl. \ No newline at end of file diff --git a/game_assets/commands.pl b/game_assets/commands.pl new file mode 100644 index 0000000..788b53f --- /dev/null +++ b/game_assets/commands.pl @@ -0,0 +1,68 @@ +% ========== MOVEMENT ========== +move_player(Direction) :- + player_location(CurrentLoc), + connected(CurrentLoc, Direction), + (obstacle(CurrentLoc, Direction, ObstacleType) -> + handle_obstacle(ObstacleType, Direction) ; + (retract(player_location(CurrentLoc)), + assertz(player_location(Direction)), + write('Du gehst nach '), write(Direction), nl + )), + !. + +move_player(_) :- + write('Du kannst nicht dorthin gehen.'), nl. + +% ========== LOOKING ========== +look_around :- + player_location(Loc), + location(Loc, Name, Desc), + write(Name), nl, + write(Desc), nl, + list_items_here(Loc), + list_npcs_here(Loc), + list_enemies_here(Loc), + list_exits(Loc), + list_obstacles_here(Loc). + +list_items_here(Loc) :- + findall(Item, item_location(Item, Loc), Items), + (Items = [] -> true ; + (write('Gegenstände hier: '), write_list(Items), nl)). + +list_npcs_here(Loc) :- + findall(NPC, npc_location(NPC, Loc), NPCs), + (NPCs = [] -> true ; + (write('Personen hier: '), write_list(NPCs), nl)). + +list_enemies_here(Loc) :- + findall(Enemy, enemy_location(Enemy, Loc), Enemies), + (Enemies = [] -> true ; + (write('Feinde hier: '), write_list(Enemies), nl)). + +list_exits(Loc) :- + findall(Exit, connected(Loc, Exit), Exits), + (Exits = [] -> write('Keine Ausgänge.') ; + (write('Ausgänge: '), write_list(Exits))), nl. + +list_obstacles_here(Loc) :- + findall(obstacle(Loc, Exit, ObstacleType), obstacle(Loc, Exit, ObstacleType), Obstacles), + (Obstacles = [] -> true ; list_obstacles(Obstacles)). + +% ========== HELP ========== +help :- write('Verfügbare Befehle:'), nl, + write('- schaue: Beschreibung des aktuellen Ortes'), nl, + write('- gehe(richtung): Bewege dich zu einem anderen Ort'), nl, + write('- nimm(gegenstand): Nimm einen Gegenstand auf'), nl, + write('- verwende(gegenstand): Verwende einen Gegenstand'), nl, + write('- rede(person): Spreche mit einer Person'), nl, + write('- angriff(feind): Beginne Kampf gegen einen Feind'), nl, + write('- baue(item): Baue einen Gegenstand (nur in Werkstatt)'), nl, + write('- hack(ziel): Hacke ein Ziel'), nl, + write('- klettere: Klettere auf Dächer/Türme'), nl, + write('- inventar: Zeige dein Inventar'), nl, + write('- status: Zeige deinen Status'), nl, + write('- beende: Schließt das Spiel'), nl, + write('- clear: Löscht den Terminalbildschirm'), nl, + write('- Richtungsbefehle: oben, unten, links, rechts, a, b'), nl, + write(' (Könnte für etwas Besonderes nützlich sein...)'), nl. \ No newline at end of file diff --git a/game_assets/crafting_system.pl b/game_assets/crafting_system.pl new file mode 100644 index 0000000..52af3c7 --- /dev/null +++ b/game_assets/crafting_system.pl @@ -0,0 +1,45 @@ +% ========== CRAFTING SYSTEM ========== +craft_item(emp_generator) :- + player_location(htl_werkstatt), + player_inventory(spule), + player_inventory(batterie), + player_inventory(kondensator), + write('Du baust aus Spule, Batterie und Kondensator einen EMP-Generator!'), nl, + retract(player_inventory(spule)), + retract(player_inventory(batterie)), + retract(player_inventory(kondensator)), + assertz(player_inventory(emp_generator)), + retract(game_state(emp_built, false)), + assertz(game_state(emp_built, true)), + !. + +craft_item(emp_generator) :- + player_location(htl_werkstatt), + write('Du brauchst: Elektro-Spule, Hochleistungsbatterie und Kondensator.'), nl, + !. + +craft_item(emp_generator) :- + write('Du kannst nur in der HTL Leonding Werkstatt bauen.'), nl, + !. + +craft_item(kampfdrohne) :- + player_location(htl_werkstatt), + player_inventory(drohnen_motor), + player_inventory(steuerungsmodul), + write('Du baust aus Motor und Steuerungsmodul eine Kampfdrohne!'), nl, + retract(player_inventory(drohnen_motor)), + retract(player_inventory(steuerungsmodul)), + assertz(player_inventory(kampfdrohne)), + !. + +craft_item(kampfdrohne) :- + player_location(htl_werkstatt), + write('Du brauchst: Drohnen-Motor und Steuerungsmodul um eine Kampfdrohne zu bauen.'), nl, + !. + +craft_item(kampfdrohne) :- + write('Du kannst nur in der HTL Leonding Werkstatt bauen.'), nl, + !. + +craft_item(_) :- + write('Du kannst diesen Gegenstand nicht bauen.'), nl. \ No newline at end of file diff --git a/game_assets/game_state.pl b/game_assets/game_state.pl new file mode 100644 index 0000000..9fd5372 --- /dev/null +++ b/game_assets/game_state.pl @@ -0,0 +1,46 @@ +% ========== GAME STATE ========== +:- dynamic(player_location/1). +:- dynamic(player_health/1). +:- dynamic(player_inventory/1). +:- dynamic(game_state/2). +:- dynamic(npc_location/2). +:- dynamic(enemy_location/2). +:- dynamic(item_location/2). +:- dynamic(enemy/4). +:- dynamic(enemy_hacked/1). +:- dynamic(hack_attempted/1). +:- dynamic(obstacle/3). +:- dynamic(box_unlocked/1). +:- dynamic(in_combat/1). +:- dynamic(combat_turn/1). +:- dynamic(emp_used_in_combat/1). +:- dynamic(drone_cooldown/2). +:- dynamic(health_recovery_used/2). +:- dynamic(konami_sequence/1). +:- dynamic(konami_position/1). + +% ========== GAME STATE MANAGEMENT ========== +check_game_state :- + player_health(Health), + (Health =< 0 -> + (retractall(in_combat(_)), + end_game(defeat), + !, fail) ; + true). + +show_status :- + player_health(Health), + write('=== STATUS ==='), nl, + write('Gesundheit: '), write(Health), nl, + (player_inventory(kampfdrohne) -> + write('Kampfdrohne: ✓ Gebaut'), nl ; + (write('Kampfdrohne Komponenten:'), nl, + (player_inventory(drohnen_motor) -> write(' Drohnen-Motor: ✓') ; write(' Drohnen-Motor: ✗')), nl, + (player_inventory(steuerungsmodul) -> write(' Steuerungsmodul: ✓') ; write(' Steuerungsmodul: ✗')), nl)), + (game_state(emp_built, true) -> + write('EMP-Generator: ✓ Gebaut'), nl ; + (write('EMP-Generator Komponenten:'), nl, + (player_inventory(spule) -> write(' Elektro-Spule: ✓') ; write(' Elektro-Spule: ✗')), nl, + (player_inventory(batterie) -> write(' Batterie: ✓') ; write(' Batterie: ✗')), nl, + (player_inventory(kondensator) -> write(' Kondensator: ✓') ; write(' Kondensator: ✗')), nl)), + write('=============='), nl. \ No newline at end of file diff --git a/game_assets/hacking_system.pl b/game_assets/hacking_system.pl new file mode 100644 index 0000000..395610b --- /dev/null +++ b/game_assets/hacking_system.pl @@ -0,0 +1,75 @@ +% ========== HACKING SYSTEM ========== +hack_target(box) :- + player_location(Loc), + player_inventory(laptop), + hacking_minigame(Loc), + !. + +hack_target(_) :- + write('Du kannst dieses Ziel nicht hacken oder hast keinen Laptop.'), nl. + +% ========== HACKING MINI-GAMES ========== +hacking_minigame(altstadt) :- + box_unlocked(altstadt_box), + write('Diese Box wurde bereits gehackt.'), nl, + !. + +hacking_minigame(altstadt) :- + write('=== HACKING MINI-GAME ==='), nl, + write('Entschlüssele den Code: 1001 + 0110 = ?'), nl, + write('Gib das Ergebnis in binär ein: '), + read(Answer), + (Answer = 1111 -> + (write('Korrekt! Du findest eine Elektro-Spule in der Box!'), nl, + assertz(player_inventory(spule)), + assertz(box_unlocked(altstadt_box))) ; + (write('Falsch! Versuch es nochmal.'), nl, + fail)). + +hacking_minigame(donauufer) :- + box_unlocked(donauufer_box), + write('Diese Box wurde bereits gehackt.'), nl, + !. + +hacking_minigame(donauufer) :- + write('=== HACKING MINI-GAME ==='), nl, + write('SQL Injection: Welcher Befehl umgeht die Passwort-Abfrage?'), nl, + write('1) DROP TABLE users'), nl, + write('2) \' OR \'1\'=\'1'), nl, + write('3) SELECT * FROM passwords'), nl, + write('Deine Wahl (1-3): '), + read(Answer), + (Answer = 2 -> + (write('Korrekt! Du findest eine Hochleistungsbatterie in der Box!'), nl, + assertz(player_inventory(batterie)), + assertz(box_unlocked(donauufer_box))) ; + (write('Falsch! Versuch es nochmal.'), nl, + fail)). + +hacking_minigame(poestlingberg) :- + box_unlocked(poestlingberg_box), + write('Diese Box wurde bereits gehackt.'), nl, + !. + +hacking_minigame(poestlingberg) :- + player_inventory(kampfdrohne), + write('=== DROHNEN-HACKING ==='), nl, + write('Deine Kampfdrohne verbindet sich mit der Box...'), nl, + write('Netzwerk-Port-Scan: Welcher Port ist für SSH Standard?'), nl, + write('1) Port 80'), nl, + write('2) Port 22'), nl, + write('3) Port 443'), nl, + write('Deine Wahl (1-3): '), + read(Answer), + (Answer = 2 -> + (write('Korrekt! Du findest einen Kondensator in der Box!'), nl, + assertz(player_inventory(kondensator)), + assertz(box_unlocked(poestlingberg_box))) ; + (write('Falsch! Versuch es nochmal.'), nl, + fail)). + +hacking_minigame(poestlingberg) :- + write('Du brauchst eine Kampfdrohne um diese Box zu hacken.'), nl. + +hacking_minigame(_) :- + write('Hier gibt es nichts zu hacken.'), nl. \ No newline at end of file diff --git a/game_assets/inventory.pl b/game_assets/inventory.pl new file mode 100644 index 0000000..0a8b9d9 --- /dev/null +++ b/game_assets/inventory.pl @@ -0,0 +1,31 @@ +% ========== INVENTORY MANAGEMENT ========== +take_item(ItemName) :- + player_location(Loc), + item_location(ItemName, Loc), + retract(item_location(ItemName, Loc)), + assertz(player_inventory(ItemName)), + item(ItemName, DisplayName, _), + write('Du nimmst '), write(DisplayName), write(' auf.'), nl, + !. + +take_item(_) :- + write('Diesen Gegenstand kannst du hier nicht finden.'), nl. + +use_item(ItemName) :- + player_inventory(ItemName), + execute_item_use(ItemName), + !. + +use_item(_) :- + write('Du hast diesen Gegenstand nicht oder kannst ihn nicht verwenden.'), nl. + +show_inventory :- + write('Dein Inventar:'), nl, + findall(Item, player_inventory(Item), Items), + (Items = [] -> write('Dein Inventar ist leer.') ; list_inventory_items(Items)), nl. + +list_inventory_items([]). +list_inventory_items([H|T]) :- + item(H, DisplayName, Desc), + write('- '), write(DisplayName), write(': '), write(Desc), nl, + list_inventory_items(T). \ No newline at end of file diff --git a/game_assets/items.pl b/game_assets/items.pl index a2ba719..b67daab 100644 --- a/game_assets/items.pl +++ b/game_assets/items.pl @@ -21,3 +21,24 @@ init_items :- assertz(item_location(emp_granate, htl_werkstatt)), assertz(item_location(parkour_handschuhe, altstadt)), assertz(item_location(heilspray, htl_labor)). + +% ========== ITEM USAGE ========== +execute_item_use(laptop) :- + player_location(htl_labor), + write('Du hackst dich in die Schulserver ein und analysierst die Drohnen-Aufnahmen.'), nl, + write('SCHOCKIERENDE ENTDECKUNG: Die Vögel sind Überwachungsdrohnen!'), nl, + !. + +execute_item_use(heilspray) :- + player_health(Health), + (Health >= 100 -> + write('Du hast bereits volle Gesundheit!'), nl ; + (NewHealth is min(100, Health + 30), + retract(player_health(Health)), + assertz(player_health(NewHealth)), + write('Du verwendest das Heilspray und gewinnst 30 Gesundheitspunkte!'), nl, + retract(player_inventory(heilspray)))), + !. + +execute_item_use(_) :- + write('Du kannst diesen Gegenstand hier nicht verwenden.'), nl. \ No newline at end of file diff --git a/game_assets/konami_code.pl b/game_assets/konami_code.pl new file mode 100644 index 0000000..0e08f8d --- /dev/null +++ b/game_assets/konami_code.pl @@ -0,0 +1,40 @@ +% ========== KONAMI CODE ========== +check_konami_input(Input) :- + (konami_position(_) -> true ; init_konami), + konami_position(Pos), + konami_sequence(Sequence), + nth0(Pos, Sequence, Expected), + (Input = Expected -> + (NewPos is Pos + 1, + retract(konami_position(Pos)), + assertz(konami_position(NewPos)), + length(Sequence, SeqLength), + (NewPos >= SeqLength -> + unlock_konami_code ; + true)) ; + (retract(konami_position(_)), + assertz(konami_position(0)), + write('Invalide Code, Hinweis: Contra.'), nl)). + +init_konami :- + retractall(konami_sequence(_)), + retractall(konami_position(_)), + assertz(konami_sequence([oben, oben, unten, unten, links, rechts, links, rechts, b, a])), + assertz(konami_position(0)). + +unlock_konami_code :- + game_state(konami_unlocked, false), + write('*** KONAMI CODE AKTIVIERT! ***'), nl, + write('Ein geheimnisvoller Master-Schlüssel materialisiert sich in deinem Inventar!'), nl, + write('Dieses Artefakt gewährt dir vollständigen Zugriff auf alle Systeme...'), nl, + assertz(player_inventory(master_schluessel)), + retract(game_state(konami_unlocked, false)), + assertz(game_state(konami_unlocked, true)), + retract(konami_position(_)), + assertz(konami_position(0)), + !. + +unlock_konami_code :- + write('Der Konami Code wurde bereits aktiviert!'), nl, + retract(konami_position(_)), + assertz(konami_position(0)). \ No newline at end of file diff --git a/game_assets/locations.pl b/game_assets/locations.pl index 61403cc..9b961d5 100644 --- a/game_assets/locations.pl +++ b/game_assets/locations.pl @@ -27,31 +27,4 @@ connected(donauufer, altstadt). connected(donauufer, poestlingberg). connected(poestlingberg, donauufer). connected(poestlingberg, aviary_hq). -connected(aviary_hq, poestlingberg). - -% ========== OBSTACLES ========== -init_obstacles :- - % Obstacle between altstadt and donauufer - assertz(obstacle(altstadt, donauufer, hohe_mauer)), - assertz(obstacle(donauufer, altstadt, hohe_mauer)), - - % Obstacle between donauufer and poestlingberg - assertz(obstacle(donauufer, poestlingberg, drone_swarm)), - assertz(obstacle(poestlingberg, donauufer, drone_swarm)), - - % Obstacle to aviary_hq - assertz(obstacle(poestlingberg, aviary_hq, security_system)), - assertz(obstacle(aviary_hq, poestlingberg, security_system)). - -list_obstacles([]). -list_obstacles([obstacle(_, Exit, ObstacleType)|T]) :- - write('HINDERNIS nach '), write(Exit), write(': '), - describe_obstacle(ObstacleType), nl, - list_obstacles(T). - -describe_obstacle(hohe_mauer) :- - write('Hohe Mauer - benötigt Parkour-Handschuhe zum Klettern'). -describe_obstacle(drone_swarm) :- - write('Drohnen-Schwarm - benötigt Kampfdrohne zur Abwehr'). -describe_obstacle(security_system) :- - write('Hochsicherheitssystem - benötigt EMP-Generator'). \ No newline at end of file +connected(aviary_hq, poestlingberg). \ No newline at end of file diff --git a/game_assets/npcs.pl b/game_assets/npcs.pl index 39320b1..ec4e898 100644 --- a/game_assets/npcs.pl +++ b/game_assets/npcs.pl @@ -66,4 +66,24 @@ init_enemies :- assertz(enemy_location(tauben_schwarm, altstadt)), assertz(enemy_location(storch_drohne, donauufer)), - assertz(enemy_location(die_kraehe, aviary_hq)). \ No newline at end of file + assertz(enemy_location(die_kraehe, aviary_hq)). + +handle_enemy_defeat(tauben_schwarm) :- + write('Die Tauben explodieren! Du findest ein Heilspray und einen Drohnen-Motor in den Trümmern.'), nl, + player_location(Loc), + assertz(item_location(drohnen_motor, Loc)), + assertz(item_location(heilspray, Loc)). + +handle_enemy_defeat(storch_drohne) :- + write('Die Storch-Drohne lässt ein Steuerungsmodul und EMP-Granaten fallen!'), nl, + player_location(Loc), + assertz(item_location(steuerungsmodul, Loc)), + assertz(item_location(emp_granate, Loc)). + +handle_enemy_defeat(die_kraehe) :- + write('Die Krähe ist besiegt! Das Drohnen-Netzwerk wankt...'), nl, + write('Du stehst vor der Hauptkonsole von Aviary Control.'), nl, + write('Plötzlich erscheint eine Nachricht auf dem Bildschirm:'), nl, + write('"Beeindruckend, John. Du hast es bis hierher geschafft."'), nl, + write('"Aber jetzt musst du eine Wahl treffen..."'), nl, + final_choice. \ No newline at end of file diff --git a/game_assets/obstacles.pl b/game_assets/obstacles.pl new file mode 100644 index 0000000..5f3543a --- /dev/null +++ b/game_assets/obstacles.pl @@ -0,0 +1,57 @@ +% ========== OBSTACLES ========== +init_obstacles :- + % Obstacle between altstadt and donauufer + assertz(obstacle(altstadt, donauufer, hohe_mauer)), + assertz(obstacle(donauufer, altstadt, hohe_mauer)), + + % Obstacle between donauufer and poestlingberg + assertz(obstacle(donauufer, poestlingberg, drone_swarm)), + assertz(obstacle(poestlingberg, donauufer, drone_swarm)), + + % Obstacle to aviary_hq + assertz(obstacle(poestlingberg, aviary_hq, security_system)), + assertz(obstacle(aviary_hq, poestlingberg, security_system)). + +describe_obstacle(hohe_mauer) :- + write('Hohe Mauer - benötigt Parkour-Handschuhe zum Klettern'). +describe_obstacle(drone_swarm) :- + write('Drohnen-Schwarm - benötigt Kampfdrohne zur Abwehr'). +describe_obstacle(security_system) :- + write('Hochsicherheitssystem - benötigt EMP-Generator'). + +list_obstacles([]). +list_obstacles([obstacle(_, Exit, ObstacleType)|T]) :- + write('HINDERNIS nach '), write(Exit), write(': '), + describe_obstacle(ObstacleType), nl, + list_obstacles(T). + +handle_obstacle(hohe_mauer, Direction) :- + (player_inventory(parkour_handschuhe) -> + (write('Du kletterst mit den Parkour-Handschuhen über die hohe Mauer!'), nl, + player_location(CurrentLoc), + retract(obstacle(CurrentLoc, Direction, hohe_mauer)), + retract(player_location(CurrentLoc)), + assertz(player_location(Direction)), + write('Du gehst nach '), write(Direction), nl) ; + write('Eine hohe Mauer blockiert deinen Weg! Du brauchst Parkour-Handschuhe.'), nl). + +handle_obstacle(drone_swarm, Direction) :- + (player_inventory(kampfdrohne) -> + (write('Deine Kampfdrohne bekämpft den feindlichen Schwarm!'), nl, + write('Die Drohnen werden zerstört und der Weg ist frei!'), nl, + player_location(CurrentLoc), + retract(obstacle(CurrentLoc, Direction, drone_swarm)), + retract(player_location(CurrentLoc)), + assertz(player_location(Direction)), + write('Du gehst nach '), write(Direction), nl) ; + write('Ein Schwarm aggressiver Drohnen blockiert den Weg! Du brauchst eine Kampfdrohne.'), nl). + +handle_obstacle(security_system, Direction) :- + (player_inventory(emp_generator) -> + (write('Du aktivierst den EMP-Generator! Das Sicherheitssystem bricht zusammen!'), nl, + player_location(CurrentLoc), + retract(obstacle(CurrentLoc, Direction, security_system)), + retract(player_location(CurrentLoc)), + assertz(player_location(Direction)), + write('Du gehst nach '), write(Direction), nl) ; + write('Ein Hochsicherheitssystem blockiert den Zugang! Du brauchst einen EMP-Generator.'), nl). \ No newline at end of file diff --git a/game_assets/parkour_minigames.pl b/game_assets/parkour_minigames.pl new file mode 100644 index 0000000..9e19fef --- /dev/null +++ b/game_assets/parkour_minigames.pl @@ -0,0 +1,85 @@ +% ========== PARKOUR-MINIGAMES ========== +parkour_minigame_altstadt :- + write('Sequenz-Challenge: Wiederhole die Bewegungsfolge!'), nl, + random_member(Sequence, [[sprung, rolle, kletter], [rolle, sprung, balance], [kletter, sprung, rolle]]), + write('Merke dir: '), write_sequence(Sequence), nl, + write('Warte...'), nl, sleep(2), + clear_screen, + write('Jetzt wiederhole die Sequenz:'), nl, + write('Gib die Sequenz als Liste ein, z.B. [sprung, rolle, kletter].'), nl, + write('Verfügbare Bewegungen: sprung, rolle, kletter, balance'), nl, + write('> '), + read_sequence(UserSequence), + (UserSequence = Sequence -> + (write('Perfekte Ausführung! Du erreichst das Dach sicher!'), nl, + write('Du findest eine verschlossene Box auf dem Dach.'), nl, + write('Verwende "hack(box)" um sie zu öffnen.'), nl) ; + (write('Falsche Sequenz! Du rutschst ab und verlierst 10 Gesundheit.'), nl, + damage_player(10))). + +climbing_minigame_donauufer :- + write('Balance-Challenge: Halte das Gleichgewicht!'), nl, + write('Drücke abwechselnd "links" und "rechts" um das Gleichgewicht zu halten.'), nl, + write('Du musst 5 mal korrekt reagieren!'), nl, + balance_challenge(5, 0). + +balance_challenge(0, Success) :- + Success >= 4, + write('Excellent! Du hast den Turm erfolgreich erklommen!'), nl, + write('Oben ist ein elektrisches Schutzschild um eine Box.'), nl, + write('Du brauchst eine EMP-Granate um das Schild zu deaktivieren.'), nl, + (player_inventory(emp_granate) -> + (write('Du verwendest die EMP-Granate! Das Schild fällt aus!'), nl, + retract(player_inventory(emp_granate)), + write('Verwende "hack(box)" um die Box zu öffnen.'), nl) ; + true), + !. + +balance_challenge(0, Success) :- + Success < 4, + write('Du verlierst das Gleichgewicht und fällst! 15 Schaden!'), nl, + damage_player(15), + !. + +balance_challenge(Remaining, Success) :- + Remaining > 0, + random_member(Direction, [links, rechts]), + write('Das Gebäude schwankt nach '), write(Direction), write('! Schnell reagieren:'), nl, + write('> '), + read(Response), + NewRemaining is Remaining - 1, + (Response = Direction -> + (write('Gut! Gleichgewicht gehalten.'), nl, + NewSuccess is Success + 1) ; + (write('Falsch! Du wackelst gefährlich.'), nl, + NewSuccess = Success)), + balance_challenge(NewRemaining, NewSuccess). + +climbing_minigame_poestlingberg :- + write('Stealth-Klettern: Vermeide die Überwachungskameras!'), nl, + write('Du musst die richtige Route wählen um unentdeckt zu bleiben.'), nl, + stealth_climbing_challenge. + +stealth_climbing_challenge :- + write('Stufe 1: Kamera schwenkt von links nach rechts. Wann bewegst du dich?'), nl, + write('1) Wenn die Kamera nach links schaut'), nl, + write('2) Wenn die Kamera nach rechts schaut'), nl, + write('3) Wenn die Kamera geradeaus schaut'), nl, + write('> '), + read(Choice1), + (Choice1 = 1 -> + (write('Richtig! Du nutzt den toten Winkel.'), nl, + write('Stufe 2: Zwei Kameras kreuzen sich. Wann bewegst du dich?'), nl, + write('1) Gleichzeitig mit beiden'), nl, + write('2) Zwischen den Schwenkbewegungen'), nl, + write('3) Wenn eine Kamera defekt ist'), nl, + write('> '), + read(Choice2), + (Choice2 = 2 -> + (write('Perfekt! Du erreichst die Spitze unentdeckt!'), nl, + write('Du findest eine schwer gesicherte Box.'), nl, + write('Diese Box benötigt eine Kampfdrohne zum Hacken.'), nl) ; + (write('Entdeckt! Alarm! Du verlierst 20 Gesundheit beim hastigen Rückzug.'), nl, + damage_player(20)))) ; + (write('Entdeckt! Du musst schnell fliehen und verlierst 15 Gesundheit.'), nl, + damage_player(15))). \ No newline at end of file