You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

978 lines
38 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

% ===============================================
% ПОЛНЫЙ АКИНАТОР - ЗАДАНИЕ 6
% Реализация полной системы акинатора
% ===============================================
% ===============================================
% БАЗА ЗНАНИЙ: ОБЪЕКТЫ И ХАРАКТЕРИСТИКИ
% ===============================================
% Животные (30 объектов)
object(собака).
object(кошка).
object(попугай).
object(хомяк).
object(рыбка).
object(черепаха).
object(канарейка).
object(кролик).
object(лев).
object(тигр).
object(слон).
object(жираф).
object(зебра).
object(волк).
object(медведь).
object(лиса).
object(олень).
object(заяц).
object(орел).
object(сова).
object(ворон).
object(голубь).
object(ласточка).
object(игуана).
object(змея).
object(лягушка).
object(крокодил).
object(бабочка).
object(пчела).
object(муравей).
% Вопросы для классификации
question(is_domestic, 'Это домашнее животное?').
question(has_fur, 'Есть ли у животного шерсть или мех?').
question(can_fly, 'Умеет ли животное летать?').
question(is_large, 'Это крупное животное (больше кошки)?').
question(is_predator, 'Это хищник?').
question(lives_in_water, 'Живет ли животное в воде?').
question(is_mammal, 'Это млекопитающее?').
question(has_stripes, 'Есть ли у животного полосы?').
question(is_nocturnal, 'Это ночное животное?').
question(can_swim, 'Умеет ли животное плавать?').
% Характеристики объектов (расширенная база знаний)
% Домашние животные
characteristic(собака, is_domestic, yes).
characteristic(собака, has_fur, yes).
characteristic(собака, can_fly, no).
characteristic(собака, is_large, yes).
characteristic(собака, is_predator, no).
characteristic(собака, lives_in_water, no).
characteristic(собака, is_mammal, yes).
characteristic(собака, has_stripes, no).
characteristic(собака, is_nocturnal, no).
characteristic(собака, can_swim, yes).
characteristic(кошка, is_domestic, yes).
characteristic(кошка, has_fur, yes).
characteristic(кошка, can_fly, no).
characteristic(кошка, is_large, no).
characteristic(кошка, is_predator, yes).
characteristic(кошка, lives_in_water, no).
characteristic(кошка, is_mammal, yes).
characteristic(кошка, has_stripes, no).
characteristic(кошка, is_nocturnal, yes).
characteristic(кошка, can_swim, no).
characteristic(попугай, is_domestic, yes).
characteristic(попугай, has_fur, no).
characteristic(попугай, can_fly, yes).
characteristic(попугай, is_large, no).
characteristic(попугай, is_predator, no).
characteristic(попугай, lives_in_water, no).
characteristic(попугай, is_mammal, no).
characteristic(попугай, has_stripes, no).
characteristic(попугай, is_nocturnal, no).
characteristic(попугай, can_swim, no).
characteristic(хомяк, is_domestic, yes).
characteristic(хомяк, has_fur, yes).
characteristic(хомяк, can_fly, no).
characteristic(хомяк, is_large, no).
characteristic(хомяк, is_predator, no).
characteristic(хомяк, lives_in_water, no).
characteristic(хомяк, is_mammal, yes).
characteristic(хомяк, has_stripes, no).
characteristic(хомяк, is_nocturnal, yes).
characteristic(хомяк, can_swim, no).
characteristic(рыбка, is_domestic, yes).
characteristic(рыбка, has_fur, no).
characteristic(рыбка, can_fly, no).
characteristic(рыбка, is_large, no).
characteristic(рыбка, is_predator, no).
characteristic(рыбка, lives_in_water, yes).
characteristic(рыбка, is_mammal, no).
characteristic(рыбка, has_stripes, no).
characteristic(рыбка, is_nocturnal, no).
characteristic(рыбка, can_swim, yes).
characteristic(черепаха, is_domestic, yes).
characteristic(черепаха, has_fur, no).
characteristic(черепаха, can_fly, no).
characteristic(черепаха, is_large, no).
characteristic(черепаха, is_predator, no).
characteristic(черепаха, lives_in_water, no).
characteristic(черепаха, is_mammal, no).
characteristic(черепаха, has_stripes, no).
characteristic(черепаха, is_nocturnal, no).
characteristic(черепаха, can_swim, yes).
characteristic(канарейка, is_domestic, yes).
characteristic(канарейка, has_fur, no).
characteristic(канарейка, can_fly, yes).
characteristic(канарейка, is_large, no).
characteristic(канарейка, is_predator, no).
characteristic(канарейка, lives_in_water, no).
characteristic(канарейка, is_mammal, no).
characteristic(канарейка, has_stripes, no).
characteristic(канарейка, is_nocturnal, no).
characteristic(канарейка, can_swim, no).
characteristic(кролик, is_domestic, yes).
characteristic(кролик, has_fur, yes).
characteristic(кролик, can_fly, no).
characteristic(кролик, is_large, no).
characteristic(кролик, is_predator, no).
characteristic(кролик, lives_in_water, no).
characteristic(кролик, is_mammal, yes).
characteristic(кролик, has_stripes, no).
characteristic(кролик, is_nocturnal, no).
characteristic(кролик, can_swim, no).
% Дикие хищники
characteristic(лев, is_domestic, no).
characteristic(лев, has_fur, yes).
characteristic(лев, can_fly, no).
characteristic(лев, is_large, yes).
characteristic(лев, is_predator, yes).
characteristic(лев, lives_in_water, no).
characteristic(лев, is_mammal, yes).
characteristic(лев, has_stripes, no).
characteristic(лев, is_nocturnal, yes).
characteristic(лев, can_swim, no).
characteristic(тигр, is_domestic, no).
characteristic(тигр, has_fur, yes).
characteristic(тигр, can_fly, no).
characteristic(тигр, is_large, yes).
characteristic(тигр, is_predator, yes).
characteristic(тигр, lives_in_water, no).
characteristic(тигр, is_mammal, yes).
characteristic(тигр, has_stripes, yes).
characteristic(тигр, is_nocturnal, yes).
characteristic(тигр, can_swim, yes).
characteristic(волк, is_domestic, no).
characteristic(волк, has_fur, yes).
characteristic(волк, can_fly, no).
characteristic(волк, is_large, yes).
characteristic(волк, is_predator, yes).
characteristic(волк, lives_in_water, no).
characteristic(волк, is_mammal, yes).
characteristic(волк, has_stripes, no).
characteristic(волк, is_nocturnal, yes).
characteristic(волк, can_swim, no).
characteristic(медведь, is_domestic, no).
characteristic(медведь, has_fur, yes).
characteristic(медведь, can_fly, no).
characteristic(медведь, is_large, yes).
characteristic(медведь, is_predator, yes).
characteristic(медведь, lives_in_water, no).
characteristic(медведь, is_mammal, yes).
characteristic(медведь, has_stripes, no).
characteristic(медведь, is_nocturnal, no).
characteristic(медведь, can_swim, yes).
characteristic(лиса, is_domestic, no).
characteristic(лиса, has_fur, yes).
characteristic(лиса, can_fly, no).
characteristic(лиса, is_large, no).
characteristic(лиса, is_predator, yes).
characteristic(лиса, lives_in_water, no).
characteristic(лиса, is_mammal, yes).
characteristic(лиса, has_stripes, no).
characteristic(лиса, is_nocturnal, yes).
characteristic(лиса, can_swim, no).
% Дикие травоядные
characteristic(слон, is_domestic, no).
characteristic(слон, has_fur, no).
characteristic(слон, can_fly, no).
characteristic(слон, is_large, yes).
characteristic(слон, is_predator, no).
characteristic(слон, lives_in_water, no).
characteristic(слон, is_mammal, yes).
characteristic(слон, has_stripes, no).
characteristic(слон, is_nocturnal, no).
characteristic(слон, can_swim, yes).
characteristic(жираф, is_domestic, no).
characteristic(жираф, has_fur, no).
characteristic(жираф, can_fly, no).
characteristic(жираф, is_large, yes).
characteristic(жираф, is_predator, no).
characteristic(жираф, lives_in_water, no).
characteristic(жираф, is_mammal, yes).
characteristic(жираф, has_stripes, no).
characteristic(жираф, is_nocturnal, no).
characteristic(жираф, can_swim, no).
characteristic(зебра, is_domestic, no).
characteristic(зебра, has_fur, no).
characteristic(зебра, can_fly, no).
characteristic(зебра, is_large, yes).
characteristic(зебра, is_predator, no).
characteristic(зебра, lives_in_water, no).
characteristic(зебра, is_mammal, yes).
characteristic(зебра, has_stripes, yes).
characteristic(зебра, is_nocturnal, no).
characteristic(зебра, can_swim, no).
characteristic(олень, is_domestic, no).
characteristic(олень, has_fur, yes).
characteristic(олень, can_fly, no).
characteristic(олень, is_large, yes).
characteristic(олень, is_predator, no).
characteristic(олень, lives_in_water, no).
characteristic(олень, is_mammal, yes).
characteristic(олень, has_stripes, no).
characteristic(олень, is_nocturnal, no).
characteristic(олень, can_swim, yes).
characteristic(заяц, is_domestic, no).
characteristic(заяц, has_fur, yes).
characteristic(заяц, can_fly, no).
characteristic(заяц, is_large, no).
characteristic(заяц, is_predator, no).
characteristic(заяц, lives_in_water, no).
characteristic(заяц, is_mammal, yes).
characteristic(заяц, has_stripes, no).
characteristic(заяц, is_nocturnal, no).
characteristic(заяц, can_swim, no).
% Птицы
characteristic(орел, is_domestic, no).
characteristic(орел, has_fur, no).
characteristic(орел, can_fly, yes).
characteristic(орел, is_large, yes).
characteristic(орел, is_predator, yes).
characteristic(орел, lives_in_water, no).
characteristic(орел, is_mammal, no).
characteristic(орел, has_stripes, no).
characteristic(орел, is_nocturnal, no).
characteristic(орел, can_swim, no).
characteristic(сова, is_domestic, no).
characteristic(сова, has_fur, no).
characteristic(сова, can_fly, yes).
characteristic(сова, is_large, no).
characteristic(сова, is_predator, yes).
characteristic(сова, lives_in_water, no).
characteristic(сова, is_mammal, no).
characteristic(сова, has_stripes, no).
characteristic(сова, is_nocturnal, yes).
characteristic(сова, can_swim, no).
characteristic(ворон, is_domestic, no).
characteristic(ворон, has_fur, no).
characteristic(ворон, can_fly, yes).
characteristic(ворон, is_large, no).
characteristic(ворон, is_predator, no).
characteristic(ворон, lives_in_water, no).
characteristic(ворон, is_mammal, no).
characteristic(ворон, has_stripes, no).
characteristic(ворон, is_nocturnal, no).
characteristic(ворон, can_swim, no).
characteristic(голубь, is_domestic, no).
characteristic(голубь, has_fur, no).
characteristic(голубь, can_fly, yes).
characteristic(голубь, is_large, no).
characteristic(голубь, is_predator, no).
characteristic(голубь, lives_in_water, no).
characteristic(голубь, is_mammal, no).
characteristic(голубь, has_stripes, no).
characteristic(голубь, is_nocturnal, no).
characteristic(голубь, can_swim, no).
characteristic(ласточка, is_domestic, no).
characteristic(ласточка, has_fur, no).
characteristic(ласточка, can_fly, yes).
characteristic(ласточка, is_large, no).
characteristic(ласточка, is_predator, no).
characteristic(ласточка, lives_in_water, no).
characteristic(ласточка, is_mammal, no).
characteristic(ласточка, has_stripes, no).
characteristic(ласточка, is_nocturnal, no).
characteristic(ласточка, can_swim, no).
% Рептилии и земноводные
characteristic(игуана, is_domestic, no).
characteristic(игуана, has_fur, no).
characteristic(игуана, can_fly, no).
characteristic(игуана, is_large, no).
characteristic(игуана, is_predator, no).
characteristic(игуана, lives_in_water, no).
characteristic(игуана, is_mammal, no).
characteristic(игуана, has_stripes, no).
characteristic(игуана, is_nocturnal, no).
characteristic(игуана, can_swim, yes).
characteristic(змея, is_domestic, no).
characteristic(змея, has_fur, no).
characteristic(змея, can_fly, no).
characteristic(змея, is_large, no).
characteristic(змея, is_predator, yes).
characteristic(змея, lives_in_water, no).
characteristic(змея, is_mammal, no).
characteristic(змея, has_stripes, no).
characteristic(змея, is_nocturnal, yes).
characteristic(змея, can_swim, yes).
characteristic(лягушка, is_domestic, no).
characteristic(лягушка, has_fur, no).
characteristic(лягушка, can_fly, no).
characteristic(лягушка, is_large, no).
characteristic(лягушка, is_predator, no).
characteristic(лягушка, lives_in_water, yes).
characteristic(лягушка, is_mammal, no).
characteristic(лягушка, has_stripes, no).
characteristic(лягушка, is_nocturnal, no).
characteristic(лягушка, can_swim, yes).
characteristic(крокодил, is_domestic, no).
characteristic(крокодил, has_fur, no).
characteristic(крокодил, can_fly, no).
characteristic(крокодил, is_large, yes).
characteristic(крокодил, is_predator, yes).
characteristic(крокодил, lives_in_water, yes).
characteristic(крокодил, is_mammal, no).
characteristic(крокодил, has_stripes, no).
characteristic(крокодил, is_nocturnal, no).
characteristic(крокодил, can_swim, yes).
% Насекомые
characteristic(бабочка, is_domestic, no).
characteristic(бабочка, has_fur, no).
characteristic(бабочка, can_fly, yes).
characteristic(бабочка, is_large, no).
characteristic(бабочка, is_predator, no).
characteristic(бабочка, lives_in_water, no).
characteristic(бабочка, is_mammal, no).
characteristic(бабочка, has_stripes, no).
characteristic(бабочка, is_nocturnal, no).
characteristic(бабочка, can_swim, no).
characteristic(пчела, is_domestic, no).
characteristic(пчела, has_fur, no).
characteristic(пчела, can_fly, yes).
characteristic(пчела, is_large, no).
characteristic(пчела, is_predator, no).
characteristic(пчела, lives_in_water, no).
characteristic(пчела, is_mammal, no).
characteristic(пчела, has_stripes, yes).
characteristic(пчела, is_nocturnal, no).
characteristic(пчела, can_swim, no).
characteristic(муравей, is_domestic, no).
characteristic(муравей, has_fur, no).
characteristic(муравей, can_fly, no).
characteristic(муравей, is_large, no).
characteristic(муравей, is_predator, no).
characteristic(муравей, lives_in_water, no).
characteristic(муравей, is_mammal, no).
characteristic(муравей, has_stripes, no).
characteristic(муравей, is_nocturnal, no).
characteristic(муравей, can_swim, no).
% ===============================================
% ОСНОВНАЯ ЛОГИКА АКИНАТОРА
% ===============================================
% Глобальные переменные для подсчета статистики
:- dynamic(questions_asked/1).
:- dynamic(session_stats/3). % session_stats(correct_guesses, wrong_guesses, total_questions)
% Инициализация статистики
init_stats :-
retractall(questions_asked(_)),
retractall(session_stats(_, _, _)),
assert(questions_asked(0)),
assert(session_stats(0, 0, 0)).
% Запуск акинатора
start_akinator :-
write('========================================'), nl,
write(' ДОБРО ПОЖАЛОВАТЬ В АКИНАТОР!'), nl,
write('========================================'), nl, nl,
write('Я попытаюсь угадать животное, которое вы загадали.'), nl,
write('Отвечайте на вопросы словами "yes", "no" или "quit".'), nl, nl,
show_available_animals,
nl,
init_stats,
main_game_loop.
% Показать доступных животных
show_available_animals :-
write('Доступные животные для загадывания:'), nl,
findall(Animal, object(Animal), Animals),
show_animals_list(Animals, 1).
show_animals_list([], _).
show_animals_list([Animal|Rest], N) :-
write(N), write('. '), write(Animal),
( (N mod 6 =:= 0) -> nl ; write(' ') ),
N1 is N + 1,
show_animals_list(Rest, N1).
% Основной игровой цикл
main_game_loop :-
write('Загадайте животное и нажмите Enter...'), nl,
read(_),
retractall(answer(_, _)),
start_questioning.
% Начало опроса
start_questioning :-
write('Начинаем игру! Отвечайте yes/no на вопросы:'), nl,
write('========================================='), nl,
ask_questions_intelligently.
% Интеллектуальный алгоритм задавания вопросов
ask_questions_intelligently :-
% Получить текущих кандидатов
get_current_candidates(Candidates),
length(Candidates, CandidateCount),
( CandidateCount =:= 0 ->
handle_no_candidates
; CandidateCount =:= 1 ->
handle_single_candidate(Candidates)
; CandidateCount =< 3 ->
handle_few_candidates(Candidates)
; % Много кандидатов - задать лучший вопрос
find_best_question(Candidates, BestQuestion),
ask_question(BestQuestion),
ask_questions_intelligently
).
% Получить текущих кандидатов на основе ответов
get_current_candidates(Candidates) :-
findall(Object,
(object(Object),
forall(answer(Question, Answer),
characteristic(Object, Question, Answer))),
Candidates).
% Найти лучший вопрос для разделения кандидатов
find_best_question(Candidates, BestQuestion) :-
findall(Question,
(question(Question, _),
\+ answer(Question, _)),
AvailableQuestions),
( AvailableQuestions = [] ->
BestQuestion = is_domestic % Запасной вариант
; find_most_balanced_question(AvailableQuestions, Candidates, BestQuestion)
).
% Найти наиболее сбалансированный вопрос
find_most_balanced_question([Question], _, Question) :- !.
find_most_balanced_question([Q1|RestQuestions], Candidates, BestQuestion) :-
calculate_question_balance(Q1, Candidates, Balance1),
find_most_balanced_question(RestQuestions, Candidates, Q2),
calculate_question_balance(Q2, Candidates, Balance2),
( Balance1 =< Balance2 ->
BestQuestion = Q1
; BestQuestion = Q2
).
% Вычислить сбалансированность вопроса (чем меньше, тем лучше)
calculate_question_balance(Question, Candidates, Balance) :-
findall(Obj,
(member(Obj, Candidates),
characteristic(Obj, Question, yes)),
YesCandidates),
findall(Obj,
(member(Obj, Candidates),
characteristic(Obj, Question, no)),
NoCandidates),
length(YesCandidates, YesCount),
length(NoCandidates, NoCount),
Balance is abs(YesCount - NoCount).
% Обработка случая, когда нет кандидатов
handle_no_candidates :-
write('Странно... Я не могу найти животное с такими характеристиками.'), nl,
write('Возможно, вы ошиблись в ответах или загадали животное, которого нет в моей базе.'), nl,
write('Какое животное вы загадали? '),
read(Mystery),
learn_from_failure(Mystery),
ask_play_again.
% Обработка случая с одним кандидатом
handle_single_candidate([Candidate]) :-
increment_questions_asked,
write('Я думаю, вы загадали: '), write(Candidate), write('!'), nl,
write('Правильно? (yes/no): '),
read(Response),
handle_guess_response(Response, Candidate).
% Обработка случая с несколькими кандидатами (2-3)
handle_few_candidates(Candidates) :-
write('У меня осталось несколько вариантов: '),
write_list(Candidates), nl,
% Попробуем угадать самый вероятный
select_most_likely(Candidates, MostLikely),
increment_questions_asked,
write('Я думаю, это: '), write(MostLikely), write('?'), nl,
write('Правильно? (yes/no): '),
read(Response),
( Response = yes ->
handle_correct_guess(MostLikely)
; Response = no ->
remove_candidate(MostLikely, Candidates, RemainingCandidates),
( RemainingCandidates = [] ->
handle_no_candidates
; RemainingCandidates = [LastCandidate] ->
handle_single_candidate([LastCandidate])
; handle_few_candidates(RemainingCandidates)
)
; write('Пожалуйста, ответьте yes или no.'), nl,
handle_few_candidates(Candidates)
).
% Выбрать наиболее вероятного кандидата
select_most_likely([First|_], First). % Простая стратегия - первый в списке
% Удалить кандидата из списка
remove_candidate(_, [], []).
remove_candidate(Candidate, [Candidate|Rest], Rest) :- !.
remove_candidate(Candidate, [Other|Rest], [Other|NewRest]) :-
remove_candidate(Candidate, Rest, NewRest).
% Задать вопрос пользователю
ask_question(Question) :-
increment_questions_asked,
question(Question, Text),
write('Вопрос: '), write(Text), write(' (yes/no/quit): '),
read(Response),
handle_response(Question, Response).
% Обработка ответа на вопрос
handle_response(_, quit) :-
write('Спасибо за игру! До свидания!'), nl,
show_session_stats, !.
handle_response(Question, yes) :-
assert(answer(Question, yes)).
handle_response(Question, no) :-
assert(answer(Question, no)).
handle_response(Question, _) :-
write('Пожалуйста, ответьте yes, no или quit.'), nl,
ask_question(Question).
% Обработка ответа на догадку
handle_guess_response(yes, Animal) :-
handle_correct_guess(Animal).
handle_guess_response(no, Animal) :-
handle_wrong_guess(Animal).
handle_guess_response(quit, _) :-
write('Спасибо за игру! До свидания!'), nl,
show_session_stats.
handle_guess_response(_, Animal) :-
write('Пожалуйста, ответьте yes, no или quit.'), nl,
write('Я думаю, это '), write(Animal), write('. Правильно? '),
read(Response),
handle_guess_response(Response, Animal).
% Обработка правильной догадки
handle_correct_guess(Animal) :-
write('Отлично! Я угадал '), write(Animal), write('!'), nl,
increment_correct_guesses,
questions_asked(QCount),
write('Мне потребовалось '), write(QCount), write(' вопросов.'), nl,
ask_play_again.
% Обработка неправильной догадки
handle_wrong_guess(Animal) :-
write('Я ошибся с '), write(Animal), write('.'), nl,
write('Какое животное вы загадали? '),
read(CorrectAnimal),
increment_wrong_guesses,
learn_from_mistake(CorrectAnimal, Animal),
ask_play_again.
% Обучение на ошибках
learn_from_mistake(CorrectAnimal, WrongGuess) :-
( object(CorrectAnimal) ->
write('Понятно, это был '), write(CorrectAnimal), write('.'), nl,
analyze_mistake(CorrectAnimal, WrongGuess)
; write('Спасибо! Я запомню животное '), write(CorrectAnimal), write('.'), nl,
write('К сожалению, его пока нет в моей базе данных.'), nl
).
% Анализ ошибки
analyze_mistake(Correct, Wrong) :-
write('Анализирую различия между '), write(Correct),
write(' и '), write(Wrong), write('...'), nl,
find_distinguishing_characteristics(Correct, Wrong),
write('Теперь я буду умнее!'), nl.
find_distinguishing_characteristics(Animal1, Animal2) :-
findall(Question-Value1-Value2,
(characteristic(Animal1, Question, Value1),
characteristic(Animal2, Question, Value2),
Value1 \= Value2),
Differences),
( Differences = [] ->
write('Эти животные имеют одинаковые характеристики в моей базе.'), nl
; write('Ключевые различия:'), nl,
show_differences(Differences)
).
show_differences([]).
show_differences([Question-Value1-Value2|Rest]) :-
question(Question, Text),
write(' '), write(Text), write(' -> '),
write(Value1), write(' vs '), write(Value2), nl,
show_differences(Rest).
% Обучение на неудачах
learn_from_failure(Mystery) :-
write('Буду помнить о '), write(Mystery), write('.'), nl,
write('Добавлю это животное в список для изучения.'), nl.
% Предложить сыграть еще раз
ask_play_again :-
nl,
write('Хотите сыграть еще раз? (yes/no): '),
read(Response),
( Response = yes ->
write('Отлично! Новая игра!'), nl, nl,
main_game_loop
; Response = no ->
write('Спасибо за игру! Было весело!'), nl,
show_session_stats
; write('Пожалуйста, ответьте yes или no.'), nl,
ask_play_again
).
% ===============================================
% СТАТИСТИКА И АНАЛИТИКА
% ===============================================
% Увеличить счетчик заданных вопросов
increment_questions_asked :-
retract(questions_asked(Count)),
NewCount is Count + 1,
assert(questions_asked(NewCount)).
% Увеличить счетчик правильных догадок
increment_correct_guesses :-
retract(session_stats(Correct, Wrong, Total)),
NewCorrect is Correct + 1,
NewTotal is Total + 1,
assert(session_stats(NewCorrect, Wrong, NewTotal)).
% Увеличить счетчик неправильных догадок
increment_wrong_guesses :-
retract(session_stats(Correct, Wrong, Total)),
NewWrong is Wrong + 1,
NewTotal is Total + 1,
assert(session_stats(Correct, NewWrong, NewTotal)).
% Показать статистику сессии
show_session_stats :-
session_stats(Correct, Wrong, Total),
write('========================================'), nl,
write(' СТАТИСТИКА СЕССИИ'), nl,
write('========================================'), nl,
write('Всего игр: '), write(Total), nl,
write('Правильных догадок: '), write(Correct), nl,
write('Неправильных догадок: '), write(Wrong), nl,
( Total > 0 ->
SuccessRate is (Correct * 100) // Total,
write('Процент успеха: '), write(SuccessRate), write('%'), nl
; write('Процент успеха: 0%'), nl
),
write('========================================'), nl.
% Информация об акинаторе
akinator_info :-
findall(Obj, object(Obj), Objects),
findall(Q, question(Q, _), Questions),
length(Objects, ObjCount),
length(Questions, QCount),
write('=== ИНФОРМАЦИЯ ОБ АКИНАТОРЕ ==='), nl,
write('Объектов в базе: '), write(ObjCount), nl,
write('Вопросов в базе: '), write(QCount), nl,
MaxDistinguishable is 2^QCount,
write('Максимум различимых объектов: '), write(MaxDistinguishable), nl,
( ObjCount =< MaxDistinguishable ->
write('✓ База данных сбалансирована'), nl
; write('⚠ Возможны проблемы с различением'), nl
),
nl,
write('КАТЕГОРИИ ЖИВОТНЫХ:'), nl,
show_animal_categories,
nl.
% Показать категории животных
show_animal_categories :-
count_by_category(is_domestic, 'Домашние/дикие'),
count_by_category(is_mammal, 'Млекопитающие/остальные'),
count_by_category(can_fly, 'Летающие/наземные'),
count_by_category(is_predator, 'Хищники/травоядные'),
count_by_category(is_large, 'Крупные/мелкие').
count_by_category(Category, Description) :-
findall(_, characteristic(_, Category, yes), YesList),
findall(_, characteristic(_, Category, no), NoList),
length(YesList, YesCount),
length(NoList, NoCount),
write(' '), write(Description), write(': '),
write(YesCount), write('/'), write(NoCount), nl.
% Статистика акинатора
akinator_statistics :-
write('=== РАСШИРЕННАЯ СТАТИСТИКА ==='), nl,
% Анализ уникальности
analyze_uniqueness,
nl,
% Анализ сложности вопросов
analyze_question_difficulty,
nl,
% Рекомендации
provide_recommendations.
% Анализ уникальности объектов
analyze_uniqueness :-
findall(Obj, object(Obj), Objects),
findall(Obj, is_unique_object(Obj), UniqueObjects),
length(Objects, Total),
length(UniqueObjects, Unique),
Duplicate is Total - Unique,
write('АНАЛИЗ УНИКАЛЬНОСТИ:'), nl,
write(' Всего объектов: '), write(Total), nl,
write(' Уникальных: '), write(Unique), nl,
write(' Дубликатов: '), write(Duplicate), nl,
( Duplicate = 0 ->
write(' ✓ Все объекты различимы'), nl
; Efficiency is (Unique * 100) // Total,
write(' Эффективность различения: '), write(Efficiency), write('%'), nl
).
% Проверка уникальности объекта
is_unique_object(Object) :-
\+ (object(OtherObject),
OtherObject \= Object,
same_characteristics(Object, OtherObject)).
% Проверка одинаковых характеристик
same_characteristics(Obj1, Obj2) :-
\+ (question(Question, _),
characteristic(Obj1, Question, Value1),
characteristic(Obj2, Question, Value2),
Value1 \= Value2).
% Анализ сложности вопросов
analyze_question_difficulty :-
write('АНАЛИЗ СЛОЖНОСТИ ВОПРОСОВ:'), nl,
findall(Q, question(Q, _), Questions),
forall(member(Question, Questions), analyze_single_question_difficulty(Question)).
analyze_single_question_difficulty(Question) :-
question(Question, Text),
findall(_, characteristic(_, Question, yes), YesList),
findall(_, characteristic(_, Question, no), NoList),
length(YesList, YesCount),
length(NoList, NoCount),
Total is YesCount + NoCount,
( Total > 0 ->
Balance is abs(YesCount - NoCount),
BalancePercent is (Balance * 100) // Total,
write(' '), write(Question), write(': '),
( BalancePercent < 20 ->
write('сбалансированный ('), write(BalancePercent), write('%)')
; BalancePercent < 40 ->
write('умеренный ('), write(BalancePercent), write('%)')
; write('несбалансированный ('), write(BalancePercent), write('%)')
), nl
; write(' '), write(Question), write(': нет данных'), nl
).
% Рекомендации по улучшению
provide_recommendations :-
write('РЕКОМЕНДАЦИИ:'), nl,
% Проверка дубликатов
findall(Obj, \+ is_unique_object(Obj), Duplicates),
( Duplicates = [] ->
write(' ✓ Дубликаты не найдены'), nl
; write(' ⚠ Найдены дубликаты, рекомендуется добавить вопросы'), nl
),
% Проверка покрытия
findall(Q, question(Q, _), Questions),
findall(Obj, object(Obj), Objects),
length(Questions, QCount),
length(Objects, ObjCount),
MaxCoverage is 2^QCount,
( ObjCount =< MaxCoverage ->
write(' ✓ Покрытие вопросов достаточное'), nl
; RecommendedQuestions is ceiling(log(ObjCount)/log(2)),
write(' ⚠ Рекомендуется минимум '), write(RecommendedQuestions),
write(' вопросов для '), write(ObjCount), write(' объектов'), nl
).
% ===============================================
% ДЕМОНСТРАЦИОННЫЕ ФУНКЦИИ
% ===============================================
% Демонстрация работы акинатора
demo_akinator :-
write('=== ДЕМОНСТРАЦИЯ АКИНАТОРА ==='), nl, nl,
write('1. ИНФОРМАЦИЯ О БАЗЕ ДАННЫХ'), nl,
write('============================'), nl,
akinator_info,
nl,
write('2. ТЕСТИРОВАНИЕ ЛОГИКИ'), nl,
write('======================'), nl,
test_akinator_logic,
nl,
write('3. АНАЛИЗ ЭФФЕКТИВНОСТИ'), nl,
write('========================'), nl,
akinator_statistics,
nl,
write('4. ИНСТРУКЦИИ ПО ИСПОЛЬЗОВАНИЮ'), nl,
write('==============================='), nl,
show_usage_instructions,
nl.
% Тестирование логики акинатора
test_akinator_logic :-
write('Тестирование поиска кандидатов:'), nl,
% Тест 1: домашний хищник
retractall(answer(_, _)),
assert(answer(is_domestic, yes)),
assert(answer(is_predator, yes)),
get_current_candidates(Candidates1),
write('Домашние хищники: '), write_list(Candidates1), nl,
% Тест 2: крупное летающее
retractall(answer(_, _)),
assert(answer(is_large, yes)),
assert(answer(can_fly, yes)),
get_current_candidates(Candidates2),
write('Крупные летающие: '), write_list(Candidates2), nl,
% Тест 3: полосатое животное
retractall(answer(_, _)),
assert(answer(has_stripes, yes)),
get_current_candidates(Candidates3),
write('Полосатые животные: '), write_list(Candidates3), nl,
retractall(answer(_, _)).
% Показать инструкции по использованию
show_usage_instructions :-
write('КАК ИСПОЛЬЗОВАТЬ АКИНАТОР:'), nl, nl,
write('1. ЗАПУСК ИГРЫ:'), nl,
write(' ?- start_akinator.'), nl,
write(' Следуйте инструкциям на экране'), nl, nl,
write('2. ОТВЕТЫ НА ВОПРОСЫ:'), nl,
write(' yes - да'), nl,
write(' no - нет'), nl,
write(' quit - выход из игры'), nl, nl,
write('3. ДЕМОНСТРАЦИОННЫЕ КОМАНДЫ:'), nl,
write(' ?- demo_akinator. % Полная демонстрация'), nl,
write(' ?- akinator_info. % Информация о базе'), nl,
write(' ?- akinator_statistics. % Статистика'), nl,
write(' ?- test_akinator_logic. % Тестирование логики'), nl, nl,
write('4. MAKEFILE КОМАНДЫ:'), nl,
write(' make run % Показать информацию об акинаторе'), nl,
write(' make interactive % Запустить интерактивную сессию'), nl,
write(' make demo % Запустить демонстрацию'), nl,
write(' make test % Запустить тесты'), nl, nl.
% Вспомогательная функция для вывода списка
write_list([]).
write_list([Item]) :- write(Item).
write_list([Item|Rest]) :-
write(Item), write(', '), write_list(Rest).
% ===============================================
% СЛУЖЕБНЫЕ ПРЕДИКАТЫ
% ===============================================
% Очистка состояния
reset_akinator :-
retractall(answer(_, _)),
retractall(questions_asked(_)),
retractall(session_stats(_, _, _)),
write('Состояние акинатора сброшено.'), nl.
% Экспорт статистики сессии
export_session_stats(Filename) :-
tell(Filename),
write('% Статистика сессии акинатора'), nl,
write('% Экспортировано: '), get_time(Time), write(Time), nl, nl,
session_stats(Correct, Wrong, Total),
write('session_correct_guesses('), write(Correct), write(').'), nl,
write('session_wrong_guesses('), write(Wrong), write(').'), nl,
write('session_total_games('), write(Total), write(').'), nl,
told,
write('Статистика экспортирована в '), write(Filename), nl.
% Получить случайное животное для тестирования
random_animal(Animal) :-
findall(Obj, object(Obj), Objects),
length(Objects, Len),
random(0, Len, Index),
nth0(Index, Objects, Animal).
% Симуляция игры для тестирования
simulate_game(Animal) :-
write('Симуляция игры для животного: '), write(Animal), nl,
retractall(answer(_, _)),
% Устанавливаем все характеристики животного
forall(characteristic(Animal, Question, Answer),
assert(answer(Question, Answer))),
% Проверяем, сможет ли акинатор угадать
get_current_candidates([Animal]),
write('✓ Акинатор успешно определил '), write(Animal), nl.
simulate_game(Animal) :-
write('✗ Акинатор не смог однозначно определить '), write(Animal), nl.