% SkyNet: The Wings of Deception % Von Zsombor Matyas und Jonas Hinterdorfer :- include('game_assets/locations.pl'). :- include('game_assets/items.pl'). :- include('game_assets/npcs.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 retractall(player_location(_)), retractall(player_health(_)), retractall(game_state(_, _)), retractall(obstacle(_, _, _)), retractall(box_unlocked(_)), retractall(in_combat(_)), retractall(combat_turn(_)), retractall(enemy_hacked(_)), retractall(hack_attempted(_)), retractall(crow_weakened(_)), retractall(emp_used_in_combat(_)), retractall(drone_cooldown(_, _)), retractall(health_recovery_used(_, _)), % Initialize random number generator randomize, % Set initial game state assertz(player_location(htl_labor)), assertz(player_health(100)), assertz(game_state(wren_met, false)), assertz(game_state(emp_built, false)), assertz(game_state(crow_weakened, false)), assertz(game_state(components_explained, false)), assertz(game_state(konami_unlocked, false)), assertz(drone_cooldown(none, 0)), % Initialize obstacles init_obstacles. % ========== MAIN GAME PREDICATES ========== start_game :- init_game, init_items, init_npcs, init_enemies, %clear_screen, write('=== SKYNET: WINGS OF DECEPTION ==='), nl, write('Ein Text-Adventure von Jonas Hinterdorfer und Zsombor Matyas'), nl, nl, intro_story, game_loop. intro_story :- write('Du bist John Miller, 17 Jahre alt und Schüler der HTL Linz.'), nl, write('Heute Morgen wurdest du von einem aggressiven Taubenschwarm attackiert.'), nl, write('Ihre Augen glühten rot und ihre Bewegungen waren unnatürlich präzise...'), nl, write('Jetzt sitzt du im Cybersicherheitslabor und analysierst die Aufnahmen.'), nl, nl, write('Für alle verfügbare Befehle schreibe \'hilfe.\''), nl, write('Bsp: \'verwende(laptop).\''), nl, nl. game_loop :- (in_combat(Enemy) -> combat_loop(Enemy) ; normal_loop). normal_loop :- player_location(Loc), location(Loc, Name, _), write('Du befindest dich in: '), write(Name), nl, write('> '), read_line(Command), process_command(Command), nl, check_game_state, !, 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))). % ========== NPC INTERACTIONS ========== talk_to(PersonName) :- player_location(Loc), npc_location(PersonName, Loc), handle_conversation(PersonName), !. talk_to(_) :- write('Diese Person ist nicht hier.'), nl. handle_conversation(wren) :- game_state(wren_met, false), write('Wren: "John! Ich habe auf dich gewartet. Ich weiß von den Drohnen."'), nl, write('Wren: "Es gibt eine Organisation namens Aviary Control. Wir müssen sie stoppen!"'), nl, write('Wren: "Du brauchst einen EMP-Generator um in ihr Hauptquartier einzudringen."'), nl, write('Wren: "Sammle diese Komponenten: Elektro-Spule, Hochleistungsbatterie und Kondensator."'), nl, write('Wren: "Die Spule findest du in einer Box auf einem Dach in der Altstadt."'), nl, write('Wren: "Die Batterie ist in einer Box auf einem Turm im Donauufer versteckt."'), nl, write('Wren: "Der Kondensator ist im Pöstlingberg-Turm, aber du brauchst eine Kampfdrohne."'), nl, write('Wren: "Baue deine eigene Kampfdrohne! Besiege Tauben für einen Motor und Störche für Steuerung."'), nl, write('Wren: "Baue alles dann in der HTL Leonding Werkstatt zusammen."'), nl, write('Wren gibt dir EMP-Granaten für den Anfang.'), nl, assertz(player_inventory(emp_granate)), assertz(player_inventory(emp_granate)), retract(game_state(wren_met, false)), assertz(game_state(wren_met, true)), retract(game_state(components_explained, false)), assertz(game_state(components_explained, true)), !. handle_conversation(wren) :- game_state(components_explained, true), game_state(emp_built, false), write('Wren: "Vergiss nicht: Du brauchst alle drei Komponenten für den EMP-Generator!"'), nl, write('Wren: "Elektro-Spule (Altstadt-Dach), Batterie (Donauufer-Turm), Kondensator (Pöstlingberg)."'), nl, write('Wren: "Verwende Parkour-Handschuhe zum Klettern und deine Kampfdrohne im Pöstlingberg."'), nl, !. handle_conversation(wren) :- game_state(emp_built, true), write('Wren: "Perfekt! Mit dem EMP-Generator kannst du ins Aviary HQ eindringen!"'), nl, write('Wren: "Pass auf die Krähe auf - schwäche sie mit EMP-Granaten, sonst kontrolliert sie dich!"'), nl, !. handle_conversation(wren) :- write('Wren: "Viel Glück, John. Die Zukunft der Menschheit liegt in deinen Händen."'), nl. % ========== LOCATION EVENTS ========== trigger_location_event(donauufer) :- enemy_location(storch_drohne, donauufer), write('WARNUNG: Eine Storch-Drohne patroulliert hier!'), nl, write('Verwende "angriff(storch_drohne)" um den Kampf zu beginnen.'), nl. trigger_location_event(aviary_hq) :- enemy_location(die_kraehe, aviary_hq), write('Du betrittst das Hauptquartier von Aviary Control!'), nl, write('Die Krähe erwartet dich bereits...'), nl, write('WARNUNG: Die Krähe kann dich kontrollieren! Schwäche sie mit EMP-Granaten!'), nl. trigger_location_event(_). % ========== 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).