Сценарий обучающей игры для дошкольников и первоклашек.
          2015г. (C) Евгений Котов http://projectveka.ru
Данная программа работает только совместно с программой распознавания речи "PERPETUUM M"
версии не ниже 4.01


###:Main
//------------------   общие константы   --------------------------
ДлинаЗаписи=20; //длина одной записи со сведениями о рисунке
Ширина=350; //для размещения рисунков на экране
Высота=270; //для размещения рисунков на экране
ЦветФона='$7CFC00';
ВидовПредметов=4;
ТекстМеню[0]='Случайный выбор';
ТекстМеню[1]='Сложение';
ТекстМеню[2]='Вычитание';
ТекстМеню[3]='Сравнительное вычитание';
ТекстМеню[4]='Прямой счет';
ТекстМеню[5]='Обратный счет';
ТекстМеню[6]='Больше или меньше';
ТекстМеню[7]='Соседи числа';
ТекстМеню[8]='Состав числа';
ТекстМеню[9]='Выход';
ТекстЗаголовкаОкна='Подготовка к школе: учимся считать';
ВремяПомехи=0.7; //с этой величиной неплохо отбрасывает помеху из колонок, но на грани потери ответа пользователя, если тот торопится


//------------------   расширение словаря   ---------------------
СтандартныйНаборЧисел='0,1,2,3,4,5,6,7,8,9,10';

DicAdd('на1#на один~наадин,наатин,надин,натин');
DicAdd('на2#на два~адва,нава,надва,надван,натва');
DicAdd('на3#на три~атри,нари,натари,натли,натри');
DicAdd('на4#на четыре~начетыри,очитыри');
DicAdd('на5#на пять~напять');
DicAdd('на6#на шесть~ашэсть,нашэс,нашэсть');
DicAdd('на7#на семь~асемь,васемь,насе,насемь');
DicAdd('на8#на восемь~авосим,навосим');
DicAdd('на9#на девять~адевить,надевить,надеить,надить');
ДополнительныйНаборЧисел='на1,на2,на3,на4,на5,на6,на7,на8,на9';

DicAdd('выбрать~вобрать,вубратин,выбатин,выбать,выбратциму,вырать,убракцин,убратини,вабрациный,вуратини,вуратцэм,виратциний');

DicAdd('случайный выбор~слочалывода,случалы,случаныводар,сучанывубар,сучаный');
DicAdd('сложение~сажыний,слажынин,служинни,снужыни');
DicAdd('вычитание~вычидани,вычитани,учитании,лочитарни');
DicAdd('сравнительное вычитание~савнитинаяничитани,санитинае,санитинаичитани,сравнитинавычитани,сранитина');
DicAdd('прямой счет~пимольшот,пимошот,примольшот,принощёт,прильщё');
DicAdd('обратный счет~абратнишот,абратыльшут,обратыщёт,фабрадныщут');
DicAdd('больше или меньше~большименьшы,большылименьшэ');
DicAdd('соседи числа~сасадишисла,саседчисла,сасивичислай,сасичисла,сесивичиства,сесикчислай,сисивичиса,сысикчисна,шыситьичиспо,асенчифна,сасенчиса');
DicAdd('состав числа~сасачисла,састачисла,систалчифа,тестачиску,тестачислай,шасталчиснай,тастатсысла');
ДополнительныйНаборСловМеню='случайный выбор,сложение,вычитание,сравнительное вычитание,'&
  'прямой счет,обратный счет,больше или меньше,соседи числа,состав числа';

ДопКоманды='выход,выбрать,восемь,десять'; //слова "восемь" и "десять" здесь уменьшают вероятность ложного срабатывания "выход" при их произнесении

//------------------   общие функции   --------------------------
function ВнестиВСписок(); //запоминаем имена надписей, чтобы потом их стереть
begin
  НомерНадписи=НомерНадписи+1;
  ИмяНадписи='Lab'&НомерНадписи;
  Список=Список&ИмяНадписи&' ';
  ВнестиВСписок='Name='&ИмяНадписи&';';
end;

function УкрашениеМеню();
begin
  ПараметрыПредмета='Picture=' & AppDir & 'Digits\airball' & (Sys.Random(7)+1) & '.jpg;Parent=PerpForm;AutoSize=1';
  Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета);
end;

function Меню();
begin
  if (Ответ<>'выбрать') and not Старт then Меню=0 else
  begin
    while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить возможные надписи с экрана
    ClearScr(ЦветФона);
    Список=''; НомерНадписи=0; //необходимо перед использованием функции ВнестиВСписок()
    ШирОк=Form.PerpForm.Prop(,'Width'); //узнаём ширину окна
    Текст='ГОЛОСОВОЕ МЕНЮ';
    Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top=5;Left=0;Parent=PerpForm;Font=Arial/20//B;Alignment=C;AutoSize=0;Width='&ШирОк&';Caption='+Текст);
    Текст='Назовите нужную тему или её номер';
    Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top=35;Left=0;Parent=PerpForm;Font=Arial/12;Alignment=C;AutoSize=0;Width='&ШирОк&';Caption='+Текст);
    ЛевКрай=Round((ШирОк-280)/2);
    Номер=0;
    while Номер<10 do
    begin
      Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top='&(60+Номер*25)&';Left='&ЛевКрай&';Parent=PerpForm;Font=Arial/16;Width='&ШирОк&';Caption='&Номер&'. '&ТекстМеню[Номер]);
      Номер=Номер+1;
    end;
    Правила='Советы. Программа слушает ответ после того, как закончит произносить вопрос.
 Поэтому не нужно торопиться с ответом, иначе программа его не услышит.
 Дополнительные команды ("выход", "выбрать тему" или просто - "выбрать")
 можно произносить, не дожидаясь окончания вопроса,
 но громко звучащие условия задачи могут создавать помехи.
 При этом возможно ложное срабатывание команд, либо отсутствие реакции на них.
 В этом случае рекомендуется понизить громкость колонок или использовать наушники.
 Во время движения рисунков дополнительные команды могут не восприниматься вовсе или восприниматься с задержкой.
 Желательно использовать внешний микрофон, разместив его возле щеки.';
    Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top=350;Left=5;Parent=PerpForm;Font=Arial/8;WordWrap=1;AutoSize=0;Width='&(ШирОк-15)&';Height=84;Caption='&Правила);

    //украсим меню шариками
    Выс=2; Поз=90; УкрашениеМеню();
    Выс=70; Поз=15; УкрашениеМеню();
    Выс=200; Поз=65; УкрашениеМеню();
    Выс=2; Поз=ШирОк-70-90; УкрашениеМеню();
    Выс=70; Поз=ШирОк-70-15; УкрашениеМеню();
    Выс=200; Поз=ШирОк-70-65; УкрашениеМеню();
    Sys.PM();

    if Старт then
    begin
      Say('привет','давай поиграем в цифры');
      ВремяОжидания=15;
      Текст='При отсутствии команды через 15 секунд автоматически включится "случайный выбор"';
      Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top=320;Left=5;Parent=PerpForm;Font=Arial/12/FF0000/b;Caption='+Текст);
    end else ВремяОжидания=1000000;
    DicSet(СтандартныйНаборЧисел, ДополнительныйНаборСловМеню&',выход');
    КомандаПолучена=0;
    while not КомандаПолучена do
    begin
      Команда=MicInput();
      while (Команда='') and (ВремяОжидания>0) do
      begin
        Delay(0.25);
        Команда=MicInput();
        ВремяОжидания=ВремяОжидания-0.25;
      end;
      if Команда='' then Break; //время истекло
      Номер=0;
      while Номер<10 do
      begin
        if (Команда=Номер) or (Команда=Str.LowerCase(ТекстМеню[Номер])) then
        begin
          ЗадачиОдногоВида=Номер;
          КомандаПолучена=1;
          Break;
        end;
        Номер=Номер+1;
      end;
    end;

    while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить строки меню с экрана
    Меню=1;
  end;
end;

function ПрерывающийОтвет();
begin
  if Меню() or (Ответ='выход') then ПрерывающийОтвет=1 else ПрерывающийОтвет=0;
  if Ответ='выход' then ПродолжатьИгру=0;
end;

function Прервано();
begin
  Прервано=0;
  Sys.PM();
  Ответ=MicInput();
  while Ответ<>'' do
  begin
    if not Прервано then Прервано=ПрерывающийОтвет();
    Ответ=MicInput();
  end;
end;

function Предметов();
begin
  if Штук=1 then Предметов=Предмет[1] else
    if Str.IsPresent(Штук,'2 3 4') then Предметов=Предмет[234] else Предметов=Предмет['много'];
end;

function ПолучитьСвойстваПредмета();
begin
  if КодПредмета=0 then
  begin
    Предмет[1]='карандаш'; Предмет[234]='карандаша'; Предмет['много']='карандашей';
    Предметы='карандаши';
    ФайлКартинки='pen';
    Расцветок=7;
    ВысотаКартинки=130;
  end else

  if КодПредмета=1 then
  begin
    Предмет[1]='шарик'; Предмет[234]='шарика'; Предмет['много']='шариков';
    Предметы='шарики';
    ФайлКартинки='airball';
    Расцветок=7;
    ВысотаКартинки=130;
  end else

  if КодПредмета=2 then
  begin
    Предмет[1]='мячик'; Предмет[234]='мячика'; Предмет['много']='мячиков';
    Предметы='мячики';
    ФайлКартинки='ball';
    Расцветок=1;
    ВысотаКартинки=68;
  end else

  if КодПредмета=3 then
  begin
    Предмет[1]='кораблик'; Предмет[234]='кораблика'; Предмет['много']='корабликов';
    Предметы='кораблики';
    ФайлКартинки='boat1';
    Расцветок=1;
    ВысотаКартинки=99;
  end;
end;

function ПараметрыПредмета();
begin
  if КодВидаЗадачи=8 then //особый режим для задач на состав числа
    if Справа then КодРасцветки=3 else КодРасцветки=2 else
    if Расцветок=1 then КодРасцветки='' else КодРасцветки=Sys.Random(Расцветок)+1;
  ПараметрыПредмета='Picture=' & AppDir & 'Digits\' & ФайлКартинки &
      КодРасцветки & '.jpg;Parent=PerpForm;AutoSize=1';
end;

function ПоказатьПредметы();
begin
  Имя='';
  ПорядковыйНомер=0;
  ИменаИКоординатыРисунков='';
  Группа1=Штук;
  Группа2=0;
  if Группа1=0 then Exit;
  X2=0;
  if Справа then X2=Ширина;
  if Группа1>3 then
  begin
    Группа2=round(Группа1/2);
    Группа1=Группа1-Группа2;
  end;
  if Группа2=0 then Выс=round(Высота/4) else Выс=5;
  Шаг=round(Ширина/Группа1);
  X=5;
  while Группа1>0 do
  begin
    Поз=X+X2;
    if КодВидаЗадачи=2 then //если неодбходим учет рисунков
    begin
      ПорядковыйНомер = ПорядковыйНомер + 1;
      Имя = 'Name=Pict' & ПорядковыйНомер & ';';
      ИменаИКоординатыРисунков = ИменаИКоординатыРисунков & Str.SetLen.Left('Pict' & ПорядковыйНомер & ' ' & Выс & ' ' & Поз, ДлинаЗаписи);
    end;
    Form.PerpForm.Create('TImage', Имя & 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета());
    X=X+Шаг;
    Группа1=Группа1-1;
  end;
  if Группа2>0 then
  begin
    Шаг=round(Ширина/Группа2);
    X=5;
    Выс=round(Высота/2);
    while Группа2>0 do
    begin
      Поз=X+X2;
      if КодВидаЗадачи=2 then //если неодбходим учет рисунков
      begin
        ПорядковыйНомер = ПорядковыйНомер + 1;
        Имя = 'Name=Pict' & ПорядковыйНомер & ';';
        ИменаИКоординатыРисунков = ИменаИКоординатыРисунков & Str.SetLen.Left('Pict' & ПорядковыйНомер & ' ' & Выс & ' ' & Поз, ДлинаЗаписи);
      end;
      Form.PerpForm.Create('TImage', Имя & 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета());
      X=X+Шаг;
      Группа2=Группа2-1;
    end;
  end;
  Sys.PM();
end;

//перед вызовом функции ПоказатьПредметыВОдинРяд() необходимо установить
//значения переменных Штук и Ряд (соответственно количество и номер ряда - 1 или 2),
//а также предварительно должна быть вызвана функция ПолучитьСвойстваПредмета()
//для нужного кода предмета
function ПоказатьПредметыВОдинРяд();
begin
  Группа1=Штук;
  if Группа1=0 then Exit;
  if Ряд=1 then Выс=5 else Выс=round(Высота/2);
  Шаг=round(Ширина/5);
  Поз=5;
  while Группа1>0 do
  begin
    Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета());
    Поз=Поз+Шаг;
    Группа1=Группа1-1;
  end;
end;

//функция ВычитаемыеПредметы() выбирает рисунки предметов, подлежащих вычитанию
//используются данные переменной ИменаИКоординатыРисунков
//результат сохраняется в переменной ВычитаемыеПредметы
//в переменной Вычитаемое должно храниться вычитаемое кол-во
function ВычитаемыеПредметы();
begin
  ВычитаемыеПредметы='';
  Счетчик=Вычитаемое;
  ОставшиесяРисунки=ИменаИКоординатыРисунков;
  while Счетчик>0 do
  begin
    //выбор рисунка
    if Str.IsPresent(КодПредмета,'1 3')  then //по критерию
    begin
      ИндексВыбранного=-1;
      Критерий=0;
      Индекс=0;
      ОбходОставшихся=ОставшиесяРисунки;
      while ОбходОставшихся <> '' do
      begin
        Ост= Str.Item('ОбходОставшихся', ДлинаЗаписи);
        Имя= Str.Item('Ост');
        Выс= Str.Item('Ост');
        Поз= Str.Item('Ост');
        Кр= Высота-Выс + Поз; //преимущество у правых верхних
        if Кр > Критерий then {Критерий=Кр; ИндексВыбранного=Индекс;};
        Индекс=Индекс+1;
      end;
    end else //случайный выбор
    begin
      КолвоОставшихся = Str.GetLen(ОставшиесяРисунки) / ДлинаЗаписи;
      ИндексВыбранного = Sys.Random(КолвоОставшихся);
    end;
    //перенос данных рисунка в вычитаемые
    ВычитаемыеПредметы= ВычитаемыеПредметы & Str.Copy(ОставшиесяРисунки, ИндексВыбранного*ДлинаЗаписи, ДлинаЗаписи);
    ОставшиесяРисунки= Str.Delete(ОставшиесяРисунки, ИндексВыбранного*ДлинаЗаписи, ДлинаЗаписи);
    Счетчик=Счетчик-1;
  end;
end;

//получение ответа (учтена возможность остаточной помехи из колонок после звучания задачи)
function ОтветОбработан();
begin
  ОтветОбработан=0;
  Delay(0.5); //ответ, принятый до этого момента, должен попасть в первую попытку
  Попытка=1;
  Ответ=MicInput();
  if Str.Pos('на',Ответ)=1 then Ответ=Str.Delete(Ответ,1,2); //для сравнительного вычитания "на сколько"
  while not Str.IsPresent(Ответ, ПравильныйОтвет&' выход выбрать') and (Попытка<5) do
  begin
    if Попытка>1 then
    begin
      if Sys.Random(2)=0 then Say('не понял') else {Say('повтори'); if Прервано() then exit; Say('пожалуйста');};
      if Прервано() then exit;
      Delay(ВремяПомехи); //данные за это время не используем (они могут содержать помеху из колонок)
      if Прервано() then exit;
    end;
    Попытка=Попытка+1;
    Ответ='';
    while Ответ='' do {Delay(0.25); Ответ=MicInput();}; //дожидаемся любого слова
    if Str.Pos('на',Ответ)=1 then Ответ=Str.Delete(Ответ,1,2); //для сравнительного вычитания "на сколько"
    if Попытка>2 then if Str.IsPresent(Ответ,'0 1 2 3 4 5 6 7 8 9 10') then Break; //если ответ числовой, здесь разрешается выход даже если он неверен
  end;
  if ПрерывающийОтвет() then Exit;
  ОтветОбработан=1;
end;

function ПодведениеИтоговПослеОтвета();
begin
  ПодведениеИтоговПослеОтвета=0;
  DicSet(, ДопКоманды);
  Штук=ПравильныйОтвет;
  if Ответ=ПравильныйОтвет then
  begin
    Похвала=Sys.Random(3);
    if Похвала=0 then Say('молодец') else
      if Похвала=1 then
        {Say('верно');  if Прервано() then exit; Say(ПравильныйОтвет,Предметов());} else
        {Say('правильно');  if Прервано() then exit; Say(ПравильныйОтвет,Предметов());};
      if Прервано() then exit;
  end else
  begin
    if Str.IsPresent(Ответ,'0 1 2 3 4 5 6 7 8 9 10') then
    begin
      Say('нет',-Ответ);  if Прервано() then exit;
      Delay(1);  if Прервано() then exit;
    end;
    Say('правильный','ответ');  if Прервано() then exit;
    Say(ПравильныйОтвет,Предметов());  if Прервано() then exit;
  end;
  ПодведениеИтоговПослеОтвета=1;
end;

function ПаузаИВосторг();
begin
  Delay(1);
  if Прервано() then exit;
  Восторг=Sys.Random(4);
  if Восторг=0 then Say('мне понравилось');
  if Восторг=1 then Say('здорово');
  if Прервано() then exit;
  Say('давай еще');
  if Прервано() then exit;
end;


//********************************************************************************
//***************                 ЗАДАЧИ НА СЛОЖЕНИЕ                     **************************
//********************************************************************************

function ЗадачиНаСложение();
begin
  DicSet(, ДопКоманды);

  КодПредмета=Sys.Random(ВидовПредметов);
  ПолучитьСвойстваПредмета();

  Сумма=Sys.Random(10)+1;
  Уменя=Sys.Random(Сумма+1);
  Утебя=Сумма-Уменя;

  //постановка задачи
  ClearScr(ЦветФона);
  Штук=Уменя;
  Справа=0;
  ПоказатьПредметы();
  Inscription(Уменя);
  Say('у меня');  if Прервано() then exit;
  Say(Штук, 'w:0.1', Предметов());  if Прервано() then exit;
  Delay(0.5);
  if Прервано() then exit;
  Штук=Утебя;
  Справа=1;
  ПоказатьПредметы();
  if Уменя=Утебя then
    {Say('а у тебя','тоже');  if Прервано() then exit;} else
    {Say('а у тебя');  if Прервано() then exit;};
  Say(Штук, 'w:0.1', Предметов());  if Прервано() then exit;
  Inscription(Уменя+'+'+Утебя);
  Delay(1);
  if Прервано() then exit;
  Say('сколько','у нас');  if Прервано() then exit;
  Say('всего',Предмет['много']);  if Прервано() then exit;
  Inscription(Уменя+'+'+Утебя+'=?');
  ПравильныйОтвет=Сумма;

  //получение ответа
  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  if not ОтветОбработан() then exit;

  //подведение итогов
  if not ПодведениеИтоговПослеОтвета() then exit;
  Inscription(Уменя+'+'+Утебя+'='+Сумма);

  ПаузаИВосторг();
end;


//********************************************************************************
//***************                 ЗАДАЧИ НА ВЫЧИТАНИЕ                    **************************
//********************************************************************************

function Исчезли();
begin
  if КодПредмета=0 then {if Штук=1 then Исчезли='сломался' else Исчезли='сломались';} else
  if КодПредмета=1 then {if Штук=1 then Исчезли='улетел' else Исчезли='улетели';} else
  if КодПредмета=2 then {if Штук=1 then Исчезли='укатился' else Исчезли='укатились';} else
  if КодПредмета=3 then {if Штук=1 then Исчезли='уплыл' else Исчезли='уплыли';};
end;

function УбратьВычитаемыеПредметы();
begin
  if Str.IsPresent(КодПредмета,'0 2') then //для карандашей и мячиков
  begin
    if КодПредмета=0 then ПустаяКартинка='Pen0.jpg' else ПустаяКартинка='ball0.jpg';
    ВП=ВычитаемыеПредметы;
    while ВП <> '' do
    begin
      Предм= Str.Item('ВП', ДлинаЗаписи);
      Имя= Str.Item('Предм');
      Выс= Str.Item('Предм');
      Поз= Str.Item('Предм');
      Form.PerpForm.Free(Имя); //стираем картинку, а затем выводим пустой контур
      Form.PerpForm.Create('TImage', 'Name=' & Имя & ';Top=' & Выс & ';Left=' & Поз & ';' & 'Picture=' & AppDir & 'Digits\' & ПустаяКартинка & ';Parent=PerpForm;AutoSize=1');
    end;
    Delay(0.7);
  end else
  if КодПредмета=1 then //для шариков
  begin
    УшлиЗаЭкран=0;
    while not УшлиЗаЭкран do
    begin
      УшлиЗаЭкран=1;
      ВП=ВычитаемыеПредметы;
      while ВП<>'' do
      begin
        Предм= Str.Item('ВП', ДлинаЗаписи);
        Имя= Str.Item('Предм');
        Выс= Form.PerpForm.Prop(Имя,'Top')-2;
        if Выс>-130 then {Form.PerpForm.Prop(Имя,'Top',Выс); УшлиЗаЭкран=0;}; //смещаем вверх
      end;
      Sys.PM();
      Delay(0.03);
    end;
    if Вычитаемое=0 then Delay(0.7);
  end else
  if КодПредмета=3 then //для корабликов
  begin
    ШирОк=Form.PerpForm.Prop(,'Width'); //узнаём ширину окна
    УшлиЗаЭкран=0;
    while not УшлиЗаЭкран do
    begin
      УшлиЗаЭкран=1;
      ВП=ВычитаемыеПредметы;
      while ВП<>'' do
      begin
        Предм= Str.Item('ВП', ДлинаЗаписи);
        Имя= Str.Item('Предм');
        Поз= Form.PerpForm.Prop(Имя,'Left')+3;
        if Поз<ШирОк then {Form.PerpForm.Prop(Имя,'Left',Поз); УшлиЗаЭкран=0;}; //смещаем вправо
      end;
      Sys.PM();
      Delay(0.03);
    end;
    if Вычитаемое=0 then Delay(0.7);
  end;
end;

function ЗадачиНаВычитание();
begin
  DicSet(, ДопКоманды);

  КодПредмета=Sys.Random(ВидовПредметов);
  ПолучитьСвойстваПредмета();

  Было=Sys.Random(10)+1;
  Вычитаемое=Sys.Random(Было+1);
  Стало=Было-Вычитаемое;

  //постановка задачи
  ClearScr(ЦветФона);
  Штук=Было;
  Справа=0;
  ПоказатьПредметы();
  Inscription(Было);
  if Было=1 then СловоБыло='был' else СловоБыло='было';
  Say('у меня',СловоБыло);  if Прервано() then exit;
  Say(Было,Предметов());  if Прервано() then exit;
  Delay(0.6);
  if Прервано() then exit;
  Штук=Вычитаемое;
  Say('а потом',Вычитаемое);  if Прервано() then exit;
  Say(Предметов(),Исчезли());  if Прервано() then exit;
  Inscription(Было & '-' & Вычитаемое);
  ВычитаемыеПредметы(); //готовим список вычитаемых предметов
  УбратьВычитаемыеПредметы(); //производим действия на экране
  if Прервано() then exit;
  Say('сколько','у меня');  if Прервано() then exit;
  Say('осталось',Предмет['много']);  if Прервано() then exit;
  Inscription(Было & '-' & Вычитаемое & '=?');
  ПравильныйОтвет=Стало;

  //получение ответа
  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  if not ОтветОбработан() then exit;

  //подведение итогов
  if not ПодведениеИтоговПослеОтвета() then exit;
  Inscription(Было & '-' & Вычитаемое & '=' & Стало);

  ПаузаИВосторг();
end;

//********************************************************************************
//***************                 ЗАДАЧИ НА СРАВНИТЕЛЬНОЕ ВЫЧИТАНИЕ                    *************
//********************************************************************************

function ЗадачиНаСравнительноеВычитание();
begin
  DicSet(, ДопКоманды);
  КодПредмета1=Sys.Random(ВидовПредметов); //придумываем два неодинаковых вида предметов
  КодПредмета2=Sys.Random(ВидовПредметов);
  if КодПредмета1=КодПредмета2 then {КодПредмета2=КодПредмета2+1; if КодПредмета2=ВидовПредметов then КодПредмета2=0;};
  Штук1=Sys.Random(10)+1; //придумываем количество предметов
  Штук2=Sys.Random(10)+1;
  if Штук1=Штук2 then {Штук2=Штук2-1; if Штук2=0 then Штук2=10;};
  Относительность=Sys.Random(2)+1; //относительно какого предмета формулируем условие задачи
  if Штук1>Штук2 then {Большее=Штук1; Меньшее=Штук2;} else {Большее=Штук2; Меньшее=Штук1;};
  if Относительность=1 then
    {if Штук2>Штук1 then БМ='больше' else БМ='меньше';} else
    {if Штук1>Штук2 then БМ='больше' else БМ='меньше';}; 

  //формулировка задачи
  ClearScr(ЦветФона);
  Штук=Штук1;
  Ряд=1;
  КодПредмета=КодПредмета1;
  ПолучитьСвойстваПредмета();
  ПоказатьПредметыВОдинРяд();
  Inscription(Штук);
  Say('у нас');  if Прервано() then exit;
  Say(Штук,Предметов());  if Прервано() then exit;
  if Относительность=1 then Основное=Предмет['много'] else Проверяемое=Предмет['много'];
  Delay(0.6);
  if Прервано() then exit;
  Штук=Штук2;
  Ряд=2;
  КодПредмета=КодПредмета2;
  ПолучитьСвойстваПредмета();
  Say('а еще','у нас');  if Прервано() then exit;
  Say(Штук,Предметов());  if Прервано() then exit;
  ПоказатьПредметыВОдинРяд();
  Inscription(Большее & '-' & Меньшее);
  if Относительность=2 then Основное=Предмет['много'] else Проверяемое=Предмет['много'];
  Delay(1);
  if Прервано() then exit;
  Say('на сколько');  if Прервано() then exit;
  Say('у нас');  if Прервано() then exit;
  Say(Проверяемое);  if Прервано() then exit;
  Say(БМ,'чем');  if Прервано() then exit;
  Say(Основное);  if Прервано() then exit;
  Inscription(Большее & '-' & Меньшее & '=?');
  ПравильныйОтвет= Большее - Меньшее;

  //получение ответа
  DicSet(СтандартныйНаборЧисел&','&ДополнительныйНаборЧисел, 'выход,выбрать');
  if not ОтветОбработан() then exit;

  //подведение итогов
  DicSet(, ДопКоманды);
  if Ответ=ПравильныйОтвет then
  begin
    Похвала=Sys.Random(3);
    if Похвала=0 then Say('молодец') else
    begin
      if Похвала=1 then Say('верно') else Say('правильно');  if Прервано() then exit;
      Say(ПравильныйОтвет);
    end;
    if Прервано() then exit;
  end else
  begin
    if Str.IsPresent(Ответ,'0 1 2 3 4 5 6 7 8 9 10') then
    begin
      Say('нет',-Ответ);  if Прервано() then exit;
      Delay(1);  if Прервано() then exit;
    end;
    Say('правильный','ответ');  if Прервано() then exit;
    Say(ПравильныйОтвет);  if Прервано() then exit;
  end;
  Inscription(Большее & '-' & Меньшее & '=' & ПравильныйОтвет);

  ПаузаИВосторг();
end;

//********************************************************************************
//**************                          БОЛЬШЕ ИЛИ МЕНЬШЕ                        *********************
//********************************************************************************

function ЗадачиНаБольшеИлиМеньше();
begin
  DicSet(, ДопКоманды);
  КодПредмета1=Sys.Random(ВидовПредметов); //придумываем два неодинаковых вида предметов
  КодПредмета2=Sys.Random(ВидовПредметов);
  if КодПредмета1=КодПредмета2 then {КодПредмета2=КодПредмета2+1; if КодПредмета2=ВидовПредметов then КодПредмета2=0;};
  Штук1=Sys.Random(10)+1; //придумываем количество предметов
  Штук2=Sys.Random(10)+1;
  if Штук1=Штук2 then {Штук2=Штук2-1; if Штук2=0 then Штук2=10;};

  //формулировка задачи
  ClearScr(ЦветФона);
  КодПредмета=КодПредмета1;
  ПолучитьСвойстваПредмета();
  Штук=Штук1;
  Справа=0;
  ПоказатьПредметы();
  Inscription(Штук1);
  Say('у нас');  if Прервано() then exit;
  Say(Штук,Предметов());  if Прервано() then exit;
  Первых=Предмет['много'];
  Delay(0.6);
  if Прервано() then exit;
  Штук=Штук2;
  Справа=1;
  КодПредмета=КодПредмета2;
  ПолучитьСвойстваПредмета();
  Say('а еще','у нас');  if Прервано() then exit;
  Say(Штук,Предметов());  if Прервано() then exit;
  ПоказатьПредметы();
  Inscription(Штук1 & '     ' & Штук2);
  Вторых=Предмет['много'];
  Delay(1);
  if Прервано() then exit;
  Say('скажи');  if Прервано() then exit;
  Say('пожалуйста');  if Прервано() then exit;
  Say('у нас',Первых);  if Прервано() then exit;
  Say('больше или меньше');  if Прервано() then exit;
  Say('чем',Вторых);  if Прервано() then exit;
  Inscription(Штук1 & '  ?  ' & Штук2);
  if Штук1>Штук2 then ПравильныйОтвет= 'больше' else ПравильныйОтвет= 'меньше';

  //получение ответа (учтена возможность остаточной помехи из колонок)
  DicSet('8,10', 'больше,меньше,выход,выбрать'); //8 и 10 при их отсутствии могут быть приняты как "выход" (есть некоторое сходство)
  Delay(0.5);
  Попытка=1;
  Ответ=MicInput();
  while not Str.IsPresent(Ответ, ПравильныйОтвет&' выход выбрать') and (Попытка<5) do
  begin
    if Попытка>1 then
    begin
      if Sys.Random(2)=0 then Say('не понял') else {Say('повтори'); if Прервано() then exit; Say('пожалуйста');};
      if Прервано() then exit;
      Delay(ВремяПомехи); //данные за это время не используем (они могут содержать помеху из колонок)
      if Прервано() then exit;
    end;
    Попытка=Попытка+1;
    Ответ='';
    while Ответ='' do {Delay(0.25); Ответ=MicInput();}; //дожидаемся любого слова
  end;
  if ПрерывающийОтвет() then Exit;

  if Штук1>Штук2 then Inscription(Штук1 & '  >  ' & Штук2) else Inscription(Штук1 & '  <  ' & Штук2);

  //подведение итогов
  DicSet(, ДопКоманды);
  if Ответ=ПравильныйОтвет then
  begin
    Похвала=Sys.Random(3);
    if Похвала=0 then Say('молодец') else
    begin
      if Похвала=1 then Say('верно') else Say('правильно');  if Прервано() then exit;
      Say('w:0.5',Первых);  if Прервано() then exit;
      Say(ПравильныйОтвет,'чем');  if Прервано() then exit;
      Say(Вторых);
    end;
    if Прервано() then exit;
  end else
  begin
    if Str.IsPresent(Ответ, 'больше меньше') then {Say('нет','w:0.5');  if Прервано() then exit;};
    Say('правильный');  if Прервано() then exit;
    Say('ответ');  if Прервано() then exit;
    Say(Первых);  if Прервано() then exit;
    Say(ПравильныйОтвет,'чем');  if Прервано() then exit;
    Say(Вторых);  if Прервано() then exit;
  end;

  ПаузаИВосторг();
end;

//********************************************************************************
//**********************            ПРЯМОЙ СЧЕТ              *********************************
//********************************************************************************

function ЗадачиНаПрямойСчет();
begin
  DicSet(, ДопКоманды);
  КодПредмета=Sys.Random(ВидовПредметов); //что будем считать

  //реализация задачи
  ClearScr(ЦветФона);
  ПолучитьСвойстваПредмета();
  Say('давай посчитаем');  if Прервано() then exit;
  Say(Предметы,'w:0.5');  if Прервано() then exit;
  Say('повторяй за мной');  if Прервано() then exit;

  Список=''; НомерНадписи=0; //необходимо перед использованием функции ВнестиВСписок()
  Выс=round(Высота/3)-25; Шаг=round(Ширина/5); Поз=5; //для размещения картинок
  ВысНомер=Выс+ВысотаКартинки+10; //высота для числовых надписей
  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  ПредыдущийПропущен=0;
  Пропусков=0;
  Нуже=0;
  Помогай=0;
  Номер=1;
  while Номер<=10 do
  begin
    Inscription(Номер);
    Имя = 'Name=Pict' & Номер & ';';
    Form.PerpForm.Create('TImage', Имя & 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета());
    Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top='&ВысНомер&';Left='&(Поз+20)&';Parent=PerpForm;Font=Arial/30;Width='&Шаг&';Caption='&Номер);
    Сказано=0;
    if (Пропусков>=2) and ПредыдущийПропущен then
      if Sys.Random(2)=1 then
      begin //подбадривание
        if Нуже<1 then
          if Sys.Random(2)=1 then {Say('ну же','w:0.5'); Нуже=Нуже+1; Сказано=1;};
        if (Помогай<2) and not Сказано then
          if Sys.Random(2)=1 then {Say('помогай','w:0.5'); Помогай=Помогай+1;};
      end;
    if Прервано() then exit;
    Say(Номер);
    if Прервано() then exit;
    Попытка=3;
    while Попытка>0 do
    begin
      Delay(ВремяПомехи);
      Ответ=MicInput(); //этот ответ игнорируем (он может содержать помеху из колонок)
      ВремяОжидания=5;
      Ответ='';
      while (Ответ='') and (ВремяОжидания>0) do
      begin
        Delay(0.25);
        Ответ=MicInput();
        ВремяОжидания=ВремяОжидания-0.25;
      end;
      Попытка=Попытка-1;
      if Str.IsPresent(Ответ,Номер&' выход выбрать')  or (Ответ='') then Break else
          if Попытка>0 then {Say(Номер); if Прервано() then exit;};
    end;
    if ПрерывающийОтвет() then Exit;
    if Ответ=Номер then //перекрашиваем номер, иначе - считаем пропуски
      Form.PerpForm.Prop('Lab'&Номер,'Font','Arial/30/FF0000/b') else
      Пропусков=Пропусков+1;
    ПредыдущийПропущен = Ответ<>Номер;
    Sys.PM();
    Поз=Поз+Шаг;
    Номер=Номер+1;
  end;

  Say('а теперь');  if Прервано() then exit;
  Say('попробуй');  if Прервано() then exit;
  Say('без моей помощи');  if Прервано() then exit;
  Список2=Список;
  while Список2<>'' do Form.PerpForm.Prop(Str.Item('Список2'),'Font','Arial/30/000000/'); //возвращаем обычный шрифт
  Номер=1;
  while Номер<=10 do
  begin
    Inscription(Номер);
    Form.PerpForm.Prop('Lab'&Номер,'Font','Arial/30/0000FF/b'); //выделяем следующий номер
    ВремяОжидания=5;
    Ответ=MicInput();
    if ПрерывающийОтвет() then Exit;
    while (Ответ<>Номер) and (ВремяОжидания>0) do
    begin
      Delay(0.25);
      Ответ=MicInput();
      if ПрерывающийОтвет() then Exit;
      ВремяОжидания=ВремяОжидания-0.25;
    end;
    Form.PerpForm.Prop('Lab'&Номер,'Font','Arial/30/000000/'); //снимаем выделение номера
    if Ответ=Номер then
    begin
      Form.PerpForm.Prop('Lab'&Номер, 'Font', 'Arial/30/FF0000/b'); //перекрашиваем номер
      Form.PerpForm.Prop('Pict'&Номер, 'Top', Выс-30); //приподнимаем фигуру
    end;
    Номер=Номер+1;
  end;
  DicSet(, ДопКоманды);
  ПаузаИВосторг();

  while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить надписи с экрана
end;

//********************************************************************************
//**********************            ОБРАТНЫЙ СЧЕТ              *******************************
//********************************************************************************

function ЗадачиНаОбратныйСчет();
begin
  DicSet(, ДопКоманды);
  КодПредмета=Sys.Random(ВидовПредметов); //что будем считать

  //реализация задачи
  ClearScr(ЦветФона);
  ПолучитьСвойстваПредмета();
  Выс=round(Высота/3)-25; Шаг=round(Ширина/5); Поз=5; //для размещения картинок
  Номер=10;
  while Номер>=1 do
  begin
    Имя = 'Name=Pict' & Номер & ';';
    Form.PerpForm.Create('TImage', Имя & 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета());
    Поз=Поз+Шаг;
    Номер=Номер-1;
  end;
  Sys.PM();
  Say('давай посчитаем');  if Прервано() then exit;
  Say(Предметы);  if Прервано() then exit;
  Say('в обратном порядке','w:0.5');  if Прервано() then exit;
  Say('повторяй за мной');  if Прервано() then exit;
  Список=''; НомерНадписи=0; //необходимо перед использованием функции ВнестиВСписок()
  Поз=25;
  ВысНомер=Выс+ВысотаКартинки+10; //высота для числовых надписей
  Номер=10;
  while Номер>=1 do
  begin
    Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top='&ВысНомер&';Left='&Поз&';Parent=PerpForm;Font=Arial/30;Width='&Шаг&';Caption='&Номер);
    Поз=Поз+Шаг;
    Номер=Номер-1;
  end;
  if Прервано() then exit;

  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  ПредыдущийПропущен=0;
  Пропусков=0;
  Нуже=0;
  Помогай=0;
  Номер=10;
  while Номер>=1 do
  begin
    Inscription(Номер);
    Form.PerpForm.Prop('Lab'&(11-Номер),'Font','Arial/30/0000FF/b'); //выделяем следующий номер
    Сказано=0;
    if (Пропусков>=2) and ПредыдущийПропущен then
      if Sys.Random(2)=1 then
      begin //подбадривание
        if Нуже<1 then
          if Sys.Random(2)=1 then {Say('ну же','w:0.5'); Нуже=Нуже+1; Сказано=1;};
        if (Помогай<2) and not Сказано then
          if Sys.Random(2)=1 then {Say('помогай','w:0.5'); Помогай=Помогай+1;};
      end;
    if Прервано() then exit;
    Say(Номер);
    if Прервано() then exit;
    Попытка=3;
    while Попытка>0 do
    begin
      Delay(ВремяПомехи);
      Ответ=MicInput(); //этот ответ игнорируем (он может содержать помеху из колонок)
      ВремяОжидания=5;
      Ответ='';
      while (Ответ='') and (ВремяОжидания>0) do
      begin
        Delay(0.25);
        Ответ=MicInput();
        ВремяОжидания=ВремяОжидания-0.25;
      end;
      Попытка=Попытка-1;
      if Str.IsPresent(Ответ,Номер&' выход выбрать')  or (Ответ='') then Break else
          if Попытка>0 then {Say(Номер); if Прервано() then exit;};
    end;
    if ПрерывающийОтвет() then Exit;
    if Ответ=Номер then //перекрашиваем номер, иначе - считаем пропуски
    begin
      Form.PerpForm.Prop('Lab'&(11-Номер),'Font','Arial/30/FF0000/b');
      ПредыдущийПропущен=0;
    end else
    begin
      ПредыдущийПропущен=1;
      Пропусков=Пропусков+1;
      Form.PerpForm.Prop('Lab'&(11-Номер),'Font','Arial/30/000000/'); //снимаем выделение номера
    end;
    Form.PerpForm.Prop('Pict' & Номер, 'Visible', 0); //прячем посчитанные картинки
    Sys.PM();
    Номер=Номер-1;
  end;

  Say('а теперь');  if Прервано() then exit;
  Say('попробуй');  if Прервано() then exit;
  Say('без моей помощи');  if Прервано() then exit;
  Список2=Список;
  while Список2<>'' do Form.PerpForm.Prop(Str.Item('Список2'),'Font','Arial/30/000000/'); //возвращаем обычный шрифт
  Номер=10;
  while Номер>=1 do
  begin
    Form.PerpForm.Prop('Pict' & Номер, 'Visible', 1);
    Номер=Номер-1;
  end;
  Номер=10;
  while Номер>=1 do
  begin
    Inscription(Номер);
    Form.PerpForm.Prop('Lab'&(11-Номер),'Font','Arial/30/0000FF/b'); //выделяем следующий номер
    ВремяОжидания=5;
    Ответ=MicInput();
    if ПрерывающийОтвет() then Exit;
    while (Ответ<>Номер) and (ВремяОжидания>0) do
    begin
      Delay(0.25);
      Ответ=MicInput();
      if ПрерывающийОтвет() then Exit;
      ВремяОжидания=ВремяОжидания-0.25;
    end;
    Form.PerpForm.Prop('Lab'&(11-Номер),'Font','Arial/30/000000/'); //снимаем выделение следующего номера
    if Ответ=Номер then Form.PerpForm.Prop('Lab'&(11-Номер), 'Font', 'Arial/30/FF0000/b'); //перекрашиваем номер
    Form.PerpForm.Prop('Pict' & Номер, 'Visible', 0); //прячем посчитанные картинки
    Номер=Номер-1;
  end;
  DicSet(, ДопКоманды);
  ПаузаИВосторг();

  while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить надписи с экрана
end;

//********************************************************************************
//**********************            СОСЕДИ ЧИСЛА              ********************************
//********************************************************************************

function ПерестатьМучитьПользователя();
begin
  DicSet(, ДопКоманды);
  Say('правильный', 'ответ');  if Прервано() then exit;
  Say('у числа');  if Прервано() then exit;
  Say(ЧислоОтПрограммы);  if Прервано() then exit;
  Say('есть');  if Прервано() then exit;
  Say('два соседних');  if Прервано() then exit;
  Say('числа');  if Прервано() then exit;
  Say('это числа');  if Прервано() then exit;
  Say(ЧислоОтПрограммы-1);  if Прервано() then exit;
  Say('и', 'w:0.1', ЧислоОтПрограммы+1);  if Прервано() then exit;
  Form.PerpForm.Prop('Lab'&(ЧислоОтПрограммы-1), 'Font', 'Arial/36/0076E1/b'); //перекрашиваем число слева
  Form.PerpForm.Prop('Lab'&(ЧислоОтПрограммы+1), 'Font', 'Arial/36/0076E1/b'); //перекрашиваем число справа
  ПаузаИВосторг();
  while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить надписи с экрана
end;

function ЗадачиНаСоседиЧисла();
begin
  DicSet(, ДопКоманды);
  ClearScr(ЦветФона);
  Список=''; НомерНадписи=0; //необходимо перед использованием функции ВнестиВСписок()
  Выс=round(Высота/2); Шаг=round(Ширина/5); Поз=5;
  Номер=1;
  while Номер<=10 do
  begin
    if Str.IsPresent(Номер, '2 3 4 5 6 7 8 9') then Шрифт='Arial/30/FF0000/b' else Шрифт='Arial/30';
    Form.PerpForm.Create('TLabel',ВнестиВСписок()&'Top='&Выс&';Left='&(Поз+20)&';Parent=PerpForm;Font='&Шрифт&';Width='&Шаг&';Caption='&Номер);
    Поз=Поз+Шаг;
    Номер=Номер+1;
  end;
  Sys.PM();
  Say('назови','w:0.1');  if Прервано() then exit;
  Say('пожалуйста','w:0.1');  if Прервано() then exit;
  Say('любое','число');  if Прервано() then exit;
  Say('от 2 до 9');  if Прервано() then exit;

  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  КопилкаОшибок=0;
  while 1 do
  begin
    Delay(ВремяПомехи);
    Ответ=MicInput();
    if ПрерывающийОтвет() then Exit;
    if Str.IsPresent(Ответ,'2 3 4 5 6 7 8 9') then Break;
    Ответ='';
    while Ответ='' do {Delay(0.25); Ответ=MicInput();}; //дожидаемся любого слова
    if ПрерывающийОтвет() then Exit;
    if Str.IsPresent(Ответ,'2 3 4 5 6 7 8 9') then Break;
    if КопилкаОшибок>0 then Break;
    Say('извини');  if Прервано() then exit;
    Say('но мне');  if Прервано() then exit;
    Say('требуется');  if Прервано() then exit;
    Say('число');  if Прервано() then exit;
    Say('от 2 до 9');  if Прервано() then exit;
    КопилкаОшибок=КопилкаОшибок+1;
  end;
  if Str.IsPresent(Ответ,'2 3 4 5 6 7 8 9') then ЧислоОтПользователя=Ответ else
  begin
    ЧислоОтПользователя=Sys.Random(8)+2;
    Say('пусть', 'например');  if Прервано() then exit;
    Say('это будет', 'число');  if Прервано() then exit;
    Say('w:0.2', ЧислоОтПользователя, 'w:0.5');  if Прервано() then exit;
  end;

  //выделяем выбранное число
  Номер=2;
  while Номер<=9 do
  begin
    if Номер=ЧислоОтПользователя then Шрифт='Arial/36/FF0000/b' else Шрифт='Arial/30/0/';
    Form.PerpForm.Prop('Lab'&Номер, 'Font', Шрифт); //перекрашиваем номер
    Номер=Номер+1;
  end;
  Sys.PM();

  DicSet(, ДопКоманды);
  Say('у числа');  if Прервано() then exit;
  Say(ЧислоОтПользователя);  if Прервано() then exit;
  Say('есть');  if Прервано() then exit;
  Say('два соседних');  if Прервано() then exit;
  Say('числа');  if Прервано() then exit;
  Say('это числа');  if Прервано() then exit;
  Say(ЧислоОтПользователя-1);  if Прервано() then exit;
  Say('и', 'w:0.1', ЧислоОтПользователя+1);  if Прервано() then exit;
  Form.PerpForm.Prop('Lab'&(ЧислоОтПользователя-1), 'Font', 'Arial/36/0076E1/b'); //перекрашиваем число слева
  Form.PerpForm.Prop('Lab'&(ЧислоОтПользователя+1), 'Font', 'Arial/36/0076E1/b'); //перекрашиваем число справа
  Delay(1);
  if Прервано() then exit;
  Say('а теперь');  if Прервано() then exit;
  Say('я придумаю');  if Прервано() then exit;
  Say('число');  if Прервано() then exit;
  ЧислоОтПрограммы=Sys.Random(8)+2;
  if ЧислоОтПрограммы=ЧислоОтПользователя then //числа не должны совпадать
  begin
    ЧислоОтПрограммы=ЧислоОтПрограммы+2;
    if ЧислоОтПрограммы>9 then ЧислоОтПрограммы=ЧислоОтПрограммы-8;
  end;

  Номер=1;
  while Номер<=10 do {Form.PerpForm.Prop('Lab'&Номер, 'Font', 'Arial/30/0/'); Номер=Номер+1;}; //снимаем все выделения
  Delay(0.5);
  if Прервано() then exit;
  Say('мое число', 'w:0.5');  if Прервано() then exit;
  Say(ЧислоОтПрограммы);  if Прервано() then exit;
  Form.PerpForm.Prop('Lab'&ЧислоОтПрограммы, 'Font', 'Arial/36/FF0000/b'); //выделяем выбранное число
  Sys.PM();
  Say('назови','w:0.1');  if Прервано() then exit;
  Say('пожалуйста','w:0.1');  if Прервано() then exit;
  Say('любое');  if Прервано() then exit;
  Say('соседнее');  if Прервано() then exit;
  Say('число');  if Прервано() then exit;
  Say('для числа', ЧислоОтПрограммы);  if Прервано() then exit;

  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  КопилкаОшибок=0;
  while 1 do
  begin
    Delay(ВремяПомехи);
    Ответ=MicInput();
    if ПрерывающийОтвет() then Exit;
    if (Ответ=ЧислоОтПрограммы-1) or (Ответ=ЧислоОтПрограммы+1) then Break;
    Ответ='';
    while Ответ='' do {Delay(0.25); Ответ=MicInput();}; //дожидаемся любого слова
    if ПрерывающийОтвет() then Exit;
    if (Ответ=ЧислоОтПрограммы-1) or (Ответ=ЧислоОтПрограммы+1) then Break;
    if КопилкаОшибок>=2 then {ПерестатьМучитьПользователя(); Exit;};
    КопилкаОшибок=КопилкаОшибок+1;
    if Str.IsPresent(Ответ,'0 1 2 3 4 5 6 7 8 9 10') then
    begin
      Say('нет', -Ответ);  if Прервано() then exit;
      Say('попробуй');  if Прервано() then exit;
      Say('еще раз');  if Прервано() then exit;
    end else
    begin
      if Sys.Random(2)=0 then Say('не понял') else {Say('повтори'); if Прервано() then exit; Say('пожалуйста');};
      if Прервано() then exit;
    end;
  end;

  DicSet(, ДопКоманды);
  ПервыйСосед=Ответ;
  Form.PerpForm.Prop('Lab'&ПервыйСосед, 'Font', 'Arial/36/0076E1/b'); //перекрашиваем число
  Похвала=Sys.Random(3);
  if Похвала=0 then Say('молодец') else
  begin
    if Похвала=1 then Say('верно','w:0.5') else Say('правильно','w:0.5');  if Прервано() then exit;
    Say(ПервыйСосед);
  end;
  if Прервано() then exit;
  Delay(0.5);
  Say('а теперь');  if Прервано() then exit;
  Say('назови', 'другое');  if Прервано() then exit;
  Say('соседнее');  if Прервано() then exit;
  Say('число');  if Прервано() then exit;
  Say('для числа', ЧислоОтПрограммы);  if Прервано() then exit;

  if ПервыйСосед=ЧислоОтПрограммы-1 then ВторойСосед=ЧислоОтПрограммы+1 else ВторойСосед=ЧислоОтПрограммы-1;
  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  КопилкаОшибок=0;
  while 1 do
  begin
    Delay(ВремяПомехи);
    Ответ=MicInput();
    if ПрерывающийОтвет() then Exit;
    if Ответ=ВторойСосед then Break;
    Ответ='';
    while Ответ='' do {Delay(0.25); Ответ=MicInput();}; //дожидаемся любого слова
    if ПрерывающийОтвет() then Exit;
    if Ответ=ВторойСосед then Break;
    if КопилкаОшибок>=2 then {ПерестатьМучитьПользователя(); Exit;};
    КопилкаОшибок=КопилкаОшибок+1;
    if Ответ=ПервыйСосед then
    begin
      Say('назови');  if Прервано() then exit;
      Say('пожалуйста');  if Прервано() then exit;
      Say('другое');  if Прервано() then exit;
      Say('соседнее');  if Прервано() then exit;
      Say('число');  if Прервано() then exit;
      Say('для числа', ЧислоОтПрограммы);  if Прервано() then exit;
    end else
      if Str.IsPresent(Ответ,'0 1 2 3 4 5 6 7 8 9 10') then
      begin
        Say('нет', -Ответ);  if Прервано() then exit;
        Say('попробуй');  if Прервано() then exit;
        Say('еще раз');  if Прервано() then exit;
      end else
      begin
        if Sys.Random(2)=0 then Say('не понял') else {Say('повтори'); if Прервано() then exit; Say('пожалуйста');};
        if Прервано() then exit;
      end;
  end;

  DicSet(, ДопКоманды);
  Form.PerpForm.Prop('Lab'&ВторойСосед, 'Font', 'Arial/36/0076E1/b'); //перекрашиваем число
  Похвала=Sys.Random(3);
  if Похвала=0 then Say('молодец') else
  begin
    if Похвала=1 then Say('верно','w:0.5') else Say('правильно','w:0.5');  if Прервано() then exit;
    Say(ВторойСосед);
  end;
  if Прервано() then exit;
  ПаузаИВосторг();

  while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить надписи с экрана
end;

//********************************************************************************
//**********************            СОСТАВ ЧИСЛА              ********************************
//********************************************************************************

function ЗадачиНаСоставЧисла();
begin
  DicSet(, ДопКоманды);

  КодПредмета=Sys.Random(2); //берем только карандаши и шарики
  ПолучитьСвойстваПредмета();

  if Sys.Random(3)=0 then
    Сумма=Sys.Random(9)+2 else //от 2 до 10
    Сумма=Sys.Random(6)+5; //от 5 до 10
  Уменя=Sys.Random(Сумма-1)+1; //от 1 до Сумма-1
  НужноДобавить=Сумма-Уменя;

  //постановка задачи
  ClearScr(ЦветФона);
  Inscription(Сумма);
  Say('помоги мне');  if Прервано() then exit;
  Say('составить');  if Прервано() then exit;
  Say('число');  if Прервано() then exit;
  Say('w:0.2',Сумма,'w:1');  if Прервано() then exit;
  Штук=Уменя;
  Справа=0;
  ПоказатьПредметы();
  Inscription(Уменя & '+...=' & Сумма);
  Say('у меня');  if Прервано() then exit;
  Say('уже');  if Прервано() then exit;
  Say('есть');  if Прервано() then exit;
  Say(Уменя);  if Прервано() then exit;
  if Уменя=1 then НазваниеЦвета='синий' else НазваниеЦвета='синих';
  Say(НазваниеЦвета,Предметов(),'w:1');  if Прервано() then exit;
  Say('сколько','красных');  if Прервано() then exit;
  Say(Предмет['много']);  if Прервано() then exit;
  Штук=НужноДобавить;
  Справа=1;
  ПоказатьПредметы();
  Say('я должен');  if Прервано() then exit;
  Say('добавить');  if Прервано() then exit;
  Say('чтобы');  if Прервано() then exit;
  Say('всего', Предмет['много']);  if Прервано() then exit;
  Say('стало', Сумма);  if Прервано() then exit;
  ПравильныйОтвет=НужноДобавить;

  //получение ответа
  DicSet(СтандартныйНаборЧисел, 'выход,выбрать');
  if not ОтветОбработан() then exit;

  //подведение итогов
  if not ПодведениеИтоговПослеОтвета() then exit;
  Inscription(Уменя & '+' & НужноДобавить & '=' & Сумма);

  ПаузаИВосторг();
end;

//********************************************************************************
//**************                          НАЧАЛО ПРОГРАММЫ                    ************************
//********************************************************************************
Sys.PM();

ИмяСценария="Игра 'Юный математик' (подготовка к школе).pms";
ПутьИмяСценария=AppDir+ИмяСценария;
if not Sys.File.Exists(ПутьИмяСценария) then
begin
  ПутьИмяСценария=AppDir+'pms\'+ИмяСценария;
  if not Sys.File.Exists(ПутьИмяСценария) then ПутьИмяСценария="";
end;
Gv.Выход=0;
if ПутьИмяСценария="" then Message('Не найден файл ' & ИмяСценария) else
  Prg.StopEvent.Load(ПутьИмяСценария,'StopEvent');

ClearScr(ЦветФона);
Title(ТекстЗаголовкаОкна&'   (дополн. голосовые команды: "выход", "выбрать тему")');
SoundDir(AppDir & 'Digits');
//ModeSpeech(3);

Font.Name('Arial');
Font.Size(140);
Sys.Randomize();
ПродолжатьИгру=1;

MicStart(); //работаем в режиме постоянно включенного микрофона
Список=''; //список имен временных надписей на экране (сначала пуст)
ЗадачиОдногоВида=0;
Ответ='';
Старт=1;
Меню();
Старт=0;

//Главный цикл
while ПродолжатьИгру do
begin
  if ЗадачиОдногоВида>0 then КодВидаЗадачи=ЗадачиОдногоВида else
    КодВидаЗадачи=Sys.Random(8)+1; //случайный выбор вида задачи

  //очередная задача
  if КодВидаЗадачи=1 then ЗадачиНаСложение() else
  if КодВидаЗадачи=2 then ЗадачиНаВычитание() else
  if КодВидаЗадачи=3 then ЗадачиНаСравнительноеВычитание() else
  if КодВидаЗадачи=4 then ЗадачиНаПрямойСчет() else
  if КодВидаЗадачи=5 then ЗадачиНаОбратныйСчет() else
  if КодВидаЗадачи=6 then ЗадачиНаБольшеИлиМеньше() else
  if КодВидаЗадачи=7 then ЗадачиНаСоседиЧисла() else
  if КодВидаЗадачи=8 then ЗадачиНаСоставЧисла() else
    ПродолжатьИгру=0;
end;
MicStop(); //микрофон больше не требуется
Say('пока заходи еще');

//заключительное окно
if ПутьИмяСценария<>"" then
begin
  while Список<>'' do Form.PerpForm.Free(Str.Item('Список')); //удалить возможные оставшиеся надписи с экрана
  ClearScr(ЦветФона);
  Title(ТекстЗаголовкаОкна);
  ШирОк=Form.PerpForm.Prop(,'Width'); //узнаём ширину окна
  Текст='Если вам понравилась эта программа,';
  Form.PerpForm.Create('TLabel','Top=100;Left=0;Parent=PerpForm;Font=Arial/12//B;Alignment=C;AutoSize=0;Width='&ШирОк&';Caption='+Текст);
  Текст='поделитесь ссылкой на неё в социальных сетях и на форумах.';
  Form.PerpForm.Create('TLabel','Top=125;Left=0;Parent=PerpForm;Font=Arial/12//B;Alignment=C;AutoSize=0;Width='&ШирОк&';Caption='+Текст);
  Текст='Этим вы поможете дальнейшему развитию программы.';
  Form.PerpForm.Create('TLabel','Top=150;Left=0;Parent=PerpForm;Font=Arial/12//B;Alignment=C;AutoSize=0;Width='&ШирОк&';Caption='+Текст);
  Текст='Прямая ссылка на скачивание программы:';
  Form.PerpForm.Create('TLabel','Top=175;Left=0;Parent=PerpForm;Font=Arial/12//B;Alignment=C;AutoSize=0;Width='&ШирОк&';Caption='+Текст);
  Ссылка='http://projectveka.ru/YunijMatematik.rar';
  Form.PerpForm.Create('TEdit','Top=200;Left='&(Round(ШирОк/2)-240)&';Parent=PerpForm;ReadOnly=1;Font=Arial/12//B;Width=480;Text='+Ссылка);
  Form.PerpForm.Create('TButton','Name=ButStop;Top=370;Left='&(Round(ШирОк/2)-80)&';Width=160;Height=40;Parent=PerpForm;Caption=Закрыть;OnClick=StopEvent');
  Выс=70; Поз=15; УкрашениеМеню();
  Выс=70; Поз=ШирОк-70-15; УкрашениеМеню();
  ПараметрыПредмета='Picture=' & AppDir & 'Digits\ball.jpg;Parent=PerpForm;AutoSize=1';
  Выс=10;
  Поз=round(ШирОк/2)-135; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета);
  Поз=Поз+100; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета);
  Поз=Поз+100; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета);
  Выс=260;
  Поз=round(ШирОк/2)-35;
  ПараметрыПредмета='Picture=' & AppDir & 'Digits\boat1.jpg;Parent=PerpForm;AutoSize=1';
  Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ';' & ПараметрыПредмета);
  //добавим карандаши
  ПараметрыПредмета=';Parent=PerpForm;AutoSize=1;Picture=' & AppDir & 'Digits\Pen';
  Поз=Поз-170; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ПараметрыПредмета & (Sys.Random(7)+1) & '.jpg');
  Поз=Поз-70; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ПараметрыПредмета & (Sys.Random(7)+1) & '.jpg');
  Поз=Поз-70; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ПараметрыПредмета & (Sys.Random(7)+1) & '.jpg');
  Поз=round(ШирОк/2)-35;
  Поз=Поз+170; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ПараметрыПредмета & (Sys.Random(7)+1) & '.jpg');
  Поз=Поз+70; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ПараметрыПредмета & (Sys.Random(7)+1) & '.jpg');
  Поз=Поз+70; Form.PerpForm.Create('TImage', 'Top=' & Выс & ';Left=' & Поз & ПараметрыПредмета & (Sys.Random(7)+1) & '.jpg');

  while not Gv.Выход do Sys.HM();
end;
###

###:StopEvent
//нажатие кнопки "Закрыть"
Gv.Выход=1;
###
