View on GitHub

ITMO-PE

My study notes about Program Engineering at University ITMO

MainPage/AI System/Lab1

Лабораторная 1. Создание базы знаний и выполнение запросов в Prolog

Требуется создать базу знаний в языке программирования Prolog и реализовать набор запросов, используя эту базу знаний. Задача направлена на развитие навыков работы с фактами, предикатами, и правилами в логическом программировании.
需要用 Prolog 编程语言创建一个知识库,并使用该知识库实现一组查询。 该任务旨在培养逻辑编程中处理事实、谓词和规则的技能。

Задание

Критерии оценки 评估标准

Тематики БЗ BZ主题

Любая, связанная с играми. Например,
任何与游戏有关的东西。 例如,

Example 1

%facts%
age(son,22).
age(daught,18).
age(dad,47).
age(mom,41).
age(grandpa_mom,64).
age(grandma_mom,57).
age(uncle_liao,49).
age(uncle,35).
age(uncle_lin,38).
age(grandpa_dad,70).
age(grandma_dad,62).
age(cosin_sister_liao,26).
age(cosin_brother_liao,22).
age(cosin_brother,17).
age(cosin_sister,13).
age(aunt_liao,44).
age(aunt,36).
man(son).
man(dad).
man(uncle).
man(grandpa_mom).
man(cosin_brother).
man(grandpa_dad).
man(uncle_liao).
man(cosin_brother_liao).
man(uncle_lin).
woman(cosin_sister_liao).
woman(aunt_liao).
woman(grandma_dad).
woman(daught).
woman(mom).
woman(aunt).
woman(cosin_sister).
woman(grandma_mom).
parent(uncle_liao,cosin_brother_liao).
parent(uncle_liao,cosin_sister_liao).
parent(aunt_liao,cosin_brother_liao).
parent(aunt_liao,cosin_sister_liao).
parent(mom,son).
parent(mom,daught).
parent(dad,son).
parent(dad,daught).
parent(grandpa_mom,mom).
parent(grandma_mom,mom).
parent(grandpa_mom,uncle).
parent(grandma_mom,uncle).
parent(grandma_mom,uncle_lin).
parent(grandpa_mom,uncle_lin).
parent(uncle,cosin_sister).
parent(uncle,cosin_brother).
parent(aunt,cosin_brother).
parent(aunt,cosin_sister).
parent(grandpa_dad,dad).
parent(grandma_dad,dad).
parent(grandma_dad,uncle_liao).
parent(grandpa_dad,uncle_liao).
couple(mom,dad).
couple(grandpa_dad,grandma_dad).
couple(grandpa_mom, grandma_mom).
couple(aunt,uncle).
couple(aunt_liao,uncle_liao).
couple(dad,mom).
couple(grandma_dad,grandpa_dad).
couple(grandma_mom, grandpa_mom).
couple(uncle,aunt).
couple(uncle_liao,aunt_liao).
%rules%
%couple(A,B):- couple(B,A),!.%
son(A,B):-parent(B,A), man(A).
daught(A,B):-parent(B,A),woman(A).
dad(A,B):-parent(A,B),man(A).
mom(A,B):-parent(A,B),woman(A).
brother(A,B):- dad(F1,A), dad(F2,B),F1=F2, mom(M1,A), mom(M2,A), M1=M2, man(A),\+A=B.
sister(A,B):- dad(F1,A), dad(F2,B),F1=F2, mom(M1,A), mom(M2,B), M1=M2, woman(A),\+A=B.
husband(A,B):-couple(A,B),man(A),woman(B).
wife(A,B):-couple(A,B),woman(A),man(B).
%two possibility for uncle
possibility_u1(A,B):-man(A),mom(M,B),sister(M,A).
possibility_u2(A,B):-man(A),dad(D,B),brother(D,A).
uncle(A,B):-possibility_u1(A,B);possibility_u2(A,B).
aunt(A,B):- uncle(C,B),wife(A,C).
grandparent(A,B):-parent(C,B), parent(A,C).
is_adult(A):- age(A,Age),Age>18.

Example 2

% 定义宝可梦
pokemon(charmander, fire, 50).
pokemon(squirtle, water, 50).

% 定义宝可梦招式
move(flamethrower, fire, 30).
move(water_gun, water, 25).

% 主循环
start_battle :-
    write('宝可梦对战开始!'), nl,
    choose_pokemon(Pokemon1),
    choose_pokemon(Pokemon2),
    battle(Pokemon1, Pokemon2).

% 玩家选择宝可梦
choose_pokemon(Pokemon) :-
    write('请选择一个宝可梦 (charmander/squirtle): '),
    read(Pokemon),
    (   pokemon(Pokemon, _, _) ->
        write('你选择了 '), write(Pokemon), nl
    ;   write('无效的宝可梦,请重新选择。'), nl,
        choose_pokemon(Pokemon)
    ).

% 进行对战
battle(Pokemon1, Pokemon2) :-
    write(Pokemon1), write(' 对战 '), write(Pokemon2), nl,
    write('请选择一个招式 (flamethrower/water_gun): '),
    read(Move),
    (   move(Move, Type, Power),
        pokemon(Pokemon1, Type, HP1),
        pokemon(Pokemon2, Type, HP2),
        NewHP2 is HP2 - Power,
        NewHP2 > 0 ->
        write(Pokemon1), write(' 使用 '), write(Move), write(' 攻击了 '), write(Pokemon2), nl,
        write(Pokemon2), write(' 的HP减少到 '), write(NewHP2), nl,
        battle(Pokemon2, Pokemon1, NewHP2, HP1)
    ;   write('无效的招式,请重新选择。'), nl,
        battle(Pokemon1, Pokemon2)
    ).

% 宝可梦2反击
battle(Pokemon1, Pokemon2, HP2, HP1) :-
    write(Pokemon2), write(' 反击了 '), write(Pokemon1), nl,
    write(Pokemon1), write(' 的HP减少到 '), write(HP1), nl,
    (   HP1 > 0 ->
        write('请选择一个招式 (flamethrower/water_gun): '),
        read(Move),
        (   move(Move, Type, Power),
            pokemon(Pokemon2, Type, _),
            NewHP1 is HP1 - Power,
            NewHP1 > 0 ->
            write(Pokemon2), write(' 使用 '), write(Move), write(' 攻击了 '), write(Pokemon1), nl,
            write(Pokemon1), write(' 的HP减少到 '), write(NewHP1), nl,
            battle(Pokemon1, Pokemon2, HP2, NewHP1)
        ;   write('无效的招式,请重新选择。'), nl,
            battle(Pokemon1, Pokemon2, HP2, HP1)
        )
    ;   write(Pokemon1), write(' 被打败了!游戏结束。'), nl
    ).

% 主入口
:- start_battle.

% 宝可梦属性
pokemon(皮卡丘, ).
pokemon(杰尼龟, ).
pokemon(小火龙, ).

% 宝可梦技能
skill(电击, , 30).
skill(水枪, , 25).
skill(火焰牙, , 28).

% 宝可梦对战规则
can_attack(X, Y) :- 
    pokemon(X, TypeX),
    pokemon(Y, TypeY),
    skill(_, TypeX, _),
    skill(_, TypeY, _),
    X \= Y.

% 攻击计算
attack(Pokemon, Skill, Damage) :-
    pokemon(Pokemon, Type),
    skill(Skill, Type, Power),
    Damage is Power.

% 对战逻辑
battle(Pokemon1, Pokemon2) :-
    can_attack(Pokemon1, Pokemon2),
    write(Pokemon1), write(' 使用技能:'), read(Skill),
    attack(Pokemon1, Skill, Damage),
    write(Pokemon1), write(' 对 '), write(Pokemon2), write(' 造成了 '), write(Damage), write(' 点伤害!'), nl,
    NewHP is 100 - Damage,
    write(Pokemon2), write(' 的剩余生命值为 '), write(NewHP), nl.

% 主入口
start_battle :-
    write('请输入第一个宝可梦:'), read(Pokemon1),
    write('请输入第二个宝可梦:'), read(Pokemon2),
    battle(Pokemon1, Pokemon2).
% 定义宝可梦的属性(名字、类型、HP、攻击力)
pokemon(charmander, fire, 60, 50).
pokemon(squirtle, water, 65, 45).
pokemon(bulbasaur, grass, 70, 40).

% 定义宝可梦的招式(名字、类型、威力)
move(flamethrower, fire, 40).
move(watergun, water, 35).
move(vine_whip, grass, 30).

% 玩家选择宝可梦
choose_pokemon(Pokemon) :-
    write('请选择宝可梦 (charmander/squirtle/bulbasaur): '),
    read(Pokemon),
    (   pokemon(Pokemon, _, _, _) ->
        write('你选择了:'), write(Pokemon), nl
    ;   write('无效的选择,请重新选择。'), nl,
        choose_pokemon(Pokemon)
    ).

% 玩家选择招式
choose_move(Move) :-
    write('请选择招式 (flamethrower/watergun/vine_whip): '),
    read(Move),
    (   move(Move, _, _) ->
        write('你使用了:'), write(Move), nl
    ;   write('无效的选择,请重新选择。'), nl,
        choose_move(Move)
    ).

% 宝可梦对战
battle :-
    write('宝可梦对战开始!'), nl,
    choose_pokemon(PlayerPokemon),
    choose_pokemon(ComputerPokemon),
    battle_loop(PlayerPokemon, ComputerPokemon).

% 宝可梦对战主循环
battle_loop(PlayerPokemon, ComputerPokemon) :-
    write('玩家选择招式:'), nl,
    choose_move(PlayerMove),
    random_move(ComputerMove),
    perform_move(PlayerMove, PlayerPokemon, ComputerPokemon, NewComputerPokemon),
    perform_move(ComputerMove, NewComputerPokemon, PlayerPokemon, NewPlayerPokemon),
    display_battle_status(NewPlayerPokemon, NewComputerPokemon),
    (   has_won(NewPlayerPokemon) ->
        write('恭喜你,你赢了!'), nl
    ;   has_won(NewComputerPokemon) ->
        write('电脑赢了,再接再厉!'), nl
    ;   battle_loop(NewPlayerPokemon, NewComputerPokemon)
    ).

% 随机选择电脑招式
random_move(Move) :-
    random_member(Move, [flamethrower, watergun, vine_whip]).

% 执行招式
perform_move(Move, Attacker, Defender, NewDefender) :-
    move(Move, Type, Power),
    pokemon(Defender, DefType, HP, DefHP),
    calculate_damage(Type, Power, DefType, Damage),
    NewDefHP is max(0, DefHP - Damage),
    NewDefender =.. [pokemon, Defender, DefType, HP, NewDefHP].

% 计算伤害
calculate_damage(Type, Power, DefType, Damage) :-
    effectiveness(Type, DefType, Multiplier),
    Damage is Power * Multiplier.

% 计算招式效果
effectiveness(fire, grass, 2.0).
effectiveness(fire, water, 0.5).
effectiveness(water, fire, 2.0).
effectiveness(water, grass, 0.5).
effectiveness(grass, water, 2.0).
effectiveness(grass, fire, 0.5).
effectiveness(_, _, 1.0).

% 显示战斗状态
display_battle_status(PlayerPokemon, ComputerPokemon) :-
    write('玩家的宝可梦:'), nl,
    display_pokemon(PlayerPokemon),
    write('电脑的宝可梦:'), nl,
    display_pokemon(ComputerPokemon).

% 显示宝可梦信息
display_pokemon(pokemon(Name, Type, HP, _)) :-
    write('名字:'), write(Name), nl,
    write('类型:'), write(Type), nl,
    write('HP:'), write(HP), nl.

% 判断是否赢得比赛
has_won(pokemon(_, _, HP, _)) :-
    HP =< 0.

% 主入口
:- battle.