273 lines
6.6 KiB
Prolog
273 lines
6.6 KiB
Prolog
% hier kommt der ganze logik bums hin
|
|
|
|
% Der aktuelle Spieler wird hiermit gesetzt damit das später
|
|
% nicht bei jedem Aufruf angegeben werden muss
|
|
:- assert( current_player(1) ).
|
|
|
|
% Damit vorherige action points (=0) auch in der ersten Runde exisiteren, sonst err
|
|
:-
|
|
assert( turn_action_points(1, 0) ),
|
|
assert( turn_action_points(2, 0) ).
|
|
|
|
% Verhindern von "Unknown procedure" in last_turn
|
|
:- % player_turn(Player,Turn,Tokens)
|
|
assert( player_turn(1, 0, 0) ),
|
|
assert( player_turn(1, -1, 0) ),
|
|
assert( player_turn(2, 0, 0) ),
|
|
assert( player_turn(2, -1, 0) ).
|
|
|
|
% Verändern der Player Tokens hierüber
|
|
change_player_tokens(TokensNew) :-
|
|
TokensNew >= 0,
|
|
current_player(Player),
|
|
player_tokens(Player, Tokens),
|
|
retract( player_tokens(Player, Tokens) ),
|
|
assert( player_tokens(Player, TokensNew) ).
|
|
|
|
change_player_tokens_decrement :-
|
|
current_player(Player),
|
|
player_tokens(Player, Tokens),
|
|
TokensDecrement is Tokens - 1,
|
|
change_player_tokens(TokensDecrement).
|
|
|
|
|
|
% Gibt den Betrag der Zahl zurück
|
|
betrag(In, Out) :-
|
|
(
|
|
In >= 0,
|
|
Out is In
|
|
), !
|
|
;
|
|
(
|
|
Out is -In
|
|
).
|
|
|
|
|
|
% Prüft ob Einheiten sich in angrenzenden feldern befinden
|
|
einheit_attackable(X1, Y1, X2, Y2) :-
|
|
betrag(X1 - X2, Xd),
|
|
betrag(Y1 - Y2, Yd),
|
|
Distance is Xd + Yd,
|
|
Distance < 2.
|
|
|
|
|
|
% Bewegt die Einheit des aktuellen Spielers an position Xold, Yold
|
|
% auf position Xnew, Ynew
|
|
einheit_move(Xold, Yold, Xnew, Ynew) :-
|
|
% Den aktuellen Spieler abfragen
|
|
current_player(Player),
|
|
|
|
% Es darf keine Einheit auf dem Zielfeld bereits vorhanden sein
|
|
\+ einheit_active(_, _, Xnew, Ynew, _),
|
|
|
|
% Errechnen der verbleibenden Tokens
|
|
betrag(Xold - Xnew, Xmove),
|
|
betrag(Yold - Ynew, Ymove),
|
|
player_tokens(Player, Tokens),
|
|
|
|
TokensNew is Tokens - Xmove - Ymove,
|
|
TokensNew >= 0,
|
|
|
|
% Die vorhandenen Tokens des Spielers aktualisieren
|
|
% Falls der Spieler nicht genug Tokens hat wird das hier false
|
|
change_player_tokens(TokensNew),
|
|
|
|
% Die Einheitv on der alten Position nehmen
|
|
retract( einheit_active(Player, Type, Xold, Yold, Defense) ),
|
|
|
|
% Die Einheit an die neue Position setzen
|
|
assert( einheit_active(Player, Type, Xnew, Ynew, Defense) ),
|
|
!.
|
|
|
|
|
|
% Lässt zwei Einheiten gegeneinander Kämpfen
|
|
% Die Einheit des aktuellen Spielers auf Xattack, Yattack
|
|
% greift die Einheit des anderen auf Xdefend, Ydefend an
|
|
einheit_attack(Xattack, Yattack, Xdefend, Ydefend) :-
|
|
%Prüfen ob die Einheit angegriffen werden kann
|
|
einheit_attackable(Xattack, Yattack, Xdefend, Ydefend),
|
|
|
|
% Player token abziehen für den angriff-move
|
|
% Falls nix übrig wird der angriff abgebrochen da false
|
|
change_player_tokens_decrement,
|
|
|
|
% Info für kämpfende Einheiten abrufen
|
|
current_player(Player),
|
|
einheit_active(Player, TypeAttack, Xattack, Yattack, _),
|
|
einheit_active(PlayerDefend, TypeDefend, Xdefend, Ydefend, HP),
|
|
|
|
% Friendly Fire verhindern
|
|
\+ Player = PlayerDefend,
|
|
|
|
% Info für Einheiten-Typen abrufen
|
|
einheit(TypeAttack, AP, _, _, _, _),
|
|
einheit(TypeDefend, _, _, MultDef, _, _),
|
|
|
|
% Mutliplikator für Angriff ermitteln
|
|
feld(Xattack, Yattack, Von),
|
|
feld(Xdefend, Ydefend, Nach),
|
|
feldMultiplier(Von, Nach, MultAP),
|
|
|
|
% Finale AP berechnen
|
|
APmitMult is AP * MultAP,
|
|
|
|
% Den Kampf durchführen
|
|
(
|
|
(% Entweder die Einheit überlebt
|
|
einheit_alive(APmitMult, HP, HPnew, MultDef),
|
|
retract( einheit_active(PlayerDefend, TypeDefend,
|
|
Xdefend, Ydefend, HP) ),
|
|
assert( einheit_active(PlayerDefend, TypeDefend,
|
|
Xdefend, Ydefend, HPnew) )
|
|
), !
|
|
;
|
|
(% Oder halt nicht
|
|
einheit_delete(Xdefend, Ydefend)
|
|
)
|
|
),
|
|
!.
|
|
|
|
|
|
% Lässt eine Einheit bewegen, oder wenn der Platz schon belegt ist, angreifen
|
|
% Der Zug wird danach automatisch beendet
|
|
einheit_action(Xold, Yold, Xnew, Ynew) :-
|
|
% Sicher gehen, dass nichts out of bounds geht
|
|
Xnew > -1, Xnew < 5,
|
|
Ynew > -1, Ynew < 5,
|
|
|
|
( % Bewege Einheit oder greife damit an, falls möglich
|
|
einheit_move(Yold, Xold, Ynew, Xnew),
|
|
!;
|
|
einheit_attack(Yold, Xold, Ynew, Xnew)
|
|
),
|
|
|
|
(
|
|
current_player(Player),
|
|
player_tokens(Player, Tokens),
|
|
\+ Tokens > 0,
|
|
end_turn,
|
|
!
|
|
;
|
|
true
|
|
).
|
|
|
|
einheit_alive(AP, HP, HPnew, HPmult) :-
|
|
% berechnen der differenz nach anwenden des multplikators
|
|
HPwm is HP * HPmult,
|
|
PwmDiff is HPwm - AP,
|
|
|
|
% berechnen des Reduktionsverhältnis von HP
|
|
Pratio is PwmDiff / HPwm,
|
|
|
|
% berechnen der neuen HP und prüfen ob einheit alive
|
|
HPnew is HP * Pratio,
|
|
HPnew > 0.
|
|
|
|
|
|
% Entfernt eine Einheit vom Spielfeld an Position X, Y
|
|
einheit_delete(X, Y) :-
|
|
retract( einheit_active(_, _, X, Y, _) ).
|
|
|
|
|
|
get_color_of_fieldType(FieldTypeInt, Color) :-
|
|
feldType(_, FieldTypeInt, Color).
|
|
|
|
|
|
% Aktualisieren des aktuellen Spielers geht hiermit
|
|
change_player_to(Player) :-
|
|
retract( current_player(_X) ),
|
|
assert( current_player(Player) ).
|
|
|
|
|
|
% Ein Spieler ist entweder current_player oder inactive_player
|
|
% je nach dem ob dieser gerade am Zug ist oder nicht
|
|
inactive_player(Player) :-
|
|
current_player(Player1),
|
|
player(Player1),
|
|
player(Player),
|
|
Player1 \= Player.
|
|
|
|
% Das hier muss an jedem Rundenende ausgeführt werden um den
|
|
% aktuellen Spieler zu wechseln
|
|
change_player :-
|
|
inactive_player(Player),
|
|
change_player_to(Player),
|
|
!.
|
|
|
|
|
|
% game_over ist true wenn das game over ist - surprise surprise
|
|
% Gibt den Gewinner zurück
|
|
game_over(Winner) :-
|
|
current_player(Active),
|
|
inactive_player(Inactive),
|
|
(
|
|
\+ einheit_active(Inactive,_,_,_,_),
|
|
Winner is Active, !
|
|
;
|
|
\+ einheit_active(Active,_,_,_,_),
|
|
Winner is Inactive
|
|
).
|
|
|
|
|
|
|
|
% Falls das Spiel vorbei ist, mach nix
|
|
end_turn :-
|
|
game_over(Winner),
|
|
game_over_gui(Winner),
|
|
write("Game Over!"), nl,
|
|
|
|
write("Player "),
|
|
write(Winner),
|
|
write(" wins!"),
|
|
reset_game.
|
|
|
|
% Beendet den Aktuellen Zug des Spielers
|
|
end_turn :-
|
|
% Die verbleibenden Tokens als Turn Speichern
|
|
current_player(Player),
|
|
player_tokens(Player, Tokens),
|
|
last_turn(LastTurn),
|
|
NewTurn is LastTurn + 1,
|
|
assert( player_turn(Player, NewTurn, Tokens) ),
|
|
|
|
% Die neue Anzahl an Tokens berechnen und setzen
|
|
calc_tokens(Tcalc),
|
|
change_player_tokens(Tcalc),
|
|
|
|
% Den Spieler wechseln
|
|
change_player,!.
|
|
|
|
|
|
% Gibt aus der wie vielte Turn der höchste gespeicherte ist
|
|
% für den aktuellen Spieler
|
|
last_turn(Turn) :-
|
|
current_player(Player),
|
|
findall(X, player_turn(Player,X,_), Turns),
|
|
max_member(Turn, Turns).
|
|
|
|
last_turn(Turn) :-
|
|
Turn is 0.
|
|
|
|
|
|
% der shizz hier ist nicht getestet, sollte aber funzen
|
|
% Berechnet die Summe aus Tokens des aktuellen und vergangenen Zuges
|
|
calc_tokens(Tokens) :-
|
|
% Aktuellen Spieler herausfinden
|
|
current_player(Player),
|
|
|
|
% Tokens die Pro Runde dazukommen herausfinden
|
|
player_tokens_per_turn(Player, Tbase),
|
|
|
|
% Tokens aus der letzten (aktuellen) und vorletzten Runde holen
|
|
last_turn(LastTurn),
|
|
player_turn(Player, LastTurn, Tlast),
|
|
|
|
% Neue Anzahl der Tokens berechnen
|
|
(
|
|
Tlast > Tbase,
|
|
Tokens is 2 * Tbase, !
|
|
;
|
|
Tokens is Tlast + Tbase
|
|
).
|
|
|