Можно оптимизировать тем, что вывод вынести в конец кода.
Сначала расчитать математику (определить на сколько попал и т.д.), а потом сделать вывод.
В общем случае что имеем.
Есть удар.
1. Расчитываем повреждение.
2. Расчитываем жизнь противника с учетом повреждения.
3. Проверяем "смерть" врага.
4. Выводим полученную информацию.
Что-то типа:
Код:
procedure TMainForm.Click(Sender: TObject);
const
KickMsg = 'Вы ударили врага на %d.';
KillMsg = #13#10'Вы уничтожили врага.';
var
Msg : String;
Kick : Integer;
Damage : Integer;
EnemyHeal : Integer;
begin
// Расчет
Kick := Random(100); // Сила удара
If (Kick > 50) And (Random > 0.5)
Then Damage := Kick * 2 // Крит. удар (х2)
Else Damage := Kick; // Обычный удар (х1)
EnemyHeal := EnemyHeal - Damage;
// Вывод
Msg := Format(KickMsg,[Damage]);
If EnemyHeal <= 0 Then Msg := Msg + KillMsg;
ShowMessage(Msg);
// Статистика
statistic.Lines.Add(Msg);
label1.Caption := Msg;
end;
Здесь, конечно, немного упрощен алгоритм расчета. Но смысл понятен.
Лучше структурируйте код, что бы потом самому легче было читать.
тогда и компилятор и выполнение тормозить не будут.