| |||
![]()
|
![]() ![]() |
![]()
Код Hamurabi_2 (начало см. http://vlkamov.livejournal.com/722060.h Переведенный на русскоперловый язык код игры стал существенно более прозрачным. Это позволило побороть почти все "макароны", остались две малосущественные, описывающие экстремальное увольнение. Вся программа разбита на последовательно исполняемые блоки с ясными функциями. Для красоты кода пришлось немножко изменить порядок исполнения блоков и привести его в соответствие естественному ходу вещей. В оригинальном коде первый годовой цикл отрабатывается без участия игрока, так что диалог начинается годового отчета. Я не поленился отчет перенести в конец, так что игрок отдает распоряжения с первого же года, а итоги года подводятся в его конце. Чума, голодомор и прирост населения вынесены в отдельный демографический блок. Интересно отметить, что в формуле прироста население стоит в знаменателе, что заставляет сомневаться в ориентации авторов. При сборке-разборке традиционно остались лишние детали: $C = 0; # ????????? Что делает эта вспомогательная переменная в операциях с землей и распределении зерна, понять так и не удалось. Итоговые критерии весьма специфические - площадь земли на душу населения и смертность от голода. Поэтому чума здорово улучшает показатели - чем больше вымерло, тем джефферснее. А если "не повезло" - количество едоков не сокращается по естественным причинам - такая же смертность низведет управляющего в "иваны". Чисто невидимая рука рынка. Игра сочинена в какие-то дремучие года, и уже тогда либеральная общественность пренебрегала состоянием общества в целом, выпячивая "витрину". Игрокам с детства внушали, что территорию можно сдать, население нехай уменьшается, лишь бы права отдельной личности были защищены. #!/usr/bin/perl #hamurabi_2.pl Начальные_условия(); foreach $ГОД (1..10){ Операции_с_землей(); Распределение_зерна(); Планирование(); Сельхоз_цикл(); Демограф_цикл(); Годовой_отчет(); } Итоги_десятилетия(); goto Выход; Уволить_за_наглость: print "\nХаммурапи: я не могу сделать то, что ты хочешь.\nЗаменю тебя другим управляющим !!!!!"; goto Выход; Досрочное_увольнение: print "Ты уморил голодом ", $УМЕРЛО_ОТ_ГОЛОДА, " человек за год !!!\n"; print "Из-за чрезвычайно плохого управления ты сейчас же уволен, \nвыброшен из резиденции и\n объявлен \"Предателем нации\" !!"; goto Выход; Выход: print "\nБиииииииииииип\nПока.\n\n"; exit; # ===================================== sub Начальные_условия{ $УМЕРЛО_ОТ_ГОЛОДА_10 = 0; # за 10 лет нарастающим итогом $СМЕРТНОСТЬ_ОТ_ГОЛОДА_10 = 0; $ГОД = 0; $НАСЕЛЕНИЕ = 100; $ПРИРОСТ_НАСЕЛЕНИЯ = 5; $Q = 1; $D = 0; $ПЛОЩАДЬ = 1000; $ЗЕРНО_В_АМБАРЕ = 2800; print "Хаммурапи: поручаю тебе управление поселением в течение 10 лет. На начало периода:\n"; print "население составляет ", $НАСЕЛЕНИЕ, " человек\n"; print "Город владеет ", $ПЛОЩАДЬ, " акрами плодородной земли.\n"; print "Запасы зерна составляют ", $ЗЕРНО_В_АМБАРЕ, " бушелей.\n"; } # ===================================== sub Операции_с_землей{ # операции с землей $ЦЕНА_ЗЕМЛИ = int (10*rand()) + 17; # 17..26 print "Земля торгуется по ", $ЦЕНА_ЗЕМЛИ, " бушелей за акр.\n"; Покупка_земли: print "Сколько акров ты намерен купить ? "; $Q = <STDIN>; goto Уволить_за_наглость if $Q<0; goto Продажа_земли if $Q==0; if ($ЦЕНА_ЗЕМЛИ*$Q > $ЗЕРНО_В_АМБАРЕ){ print "Хаммурапи: думай снова. У тебя только \n", $ЗЕРНО_В_АМБАРЕ, " бушелей зерна. Итак, \n"; goto Покупка_земли; } $ПЛОЩАДЬ = $ПЛОЩАДЬ + $Q; $ЗЕРНО_В_АМБАРЕ = $ЗЕРНО_В_АМБАРЕ - $ЦЕНА_ЗЕМЛИ*$Q; $C = 0; # ????????? goto Закончить_операции_с_землей; Продажа_земли: print "Сколько акров ты намерен продать ? "; $Q = <STDIN>; goto Уволить_за_наглость if $Q<0; goto Закончить_операции_с_землей if $Q==0; if ($Q > $ПЛОЩАДЬ) { print "Хаммурапи: думай снова. У тебя только \n", $ПЛОЩАДЬ, " акров земли. Итак, \n"; goto Продажа_земли; } $ПЛОЩАДЬ = $ПЛОЩАДЬ - $Q; $ЗЕРНО_В_АМБАРЕ = $ЗЕРНО_В_АМБАРЕ + $ЦЕНА_ЗЕМЛИ*$Q; $C = 0; # ????????? goto Закончить_операции_с_землей; Закончить_операции_с_землей: } # ===================================== sub Распределение_зерна{ print "\n"; Выделить_зерно: print "Сколько зерна пойдет на продовольствие ?"; $ПРОДОВОЛЬСТВЕННОЕ_ЗЕРНО=<STDIN>; goto Уволить_за_наглость if $ПРОДОВОЛЬСТВЕННОЕ_ЗЕРНО < 0; if ($ПРОДОВОЛЬСТВЕННОЕ_ЗЕРНО > $ЗЕРНО_В_АМБАРЕ){ print "Хаммурапи: думай снова. У тебя только \n", $ЗЕРНО_В_АМБАРЕ, " бушелей зерна. Итак, \n"; goto Выделить_зерно; } $ЗЕРНО_В_АМБАРЕ = $ЗЕРНО_В_АМБАРЕ - $ПРОДОВОЛЬСТВЕННОЕ_ЗЕРНО; $C = 1; # ????????? print "\n"; } # ===================================== sub Планирование{ Назначить_площадь_посевов: print "Сколько акров ты намерен засеять ?"; $ПЛОЩАДЬ_ПОСЕВОВ = <STDIN>; goto Уволить_за_наглость if $ПЛОЩАДЬ_ПОСЕВОВ < 0; if ($ПЛОЩАДЬ_ПОСЕВОВ > $ПЛОЩАДЬ ) { print "Хаммурапи: думай снова. У тебя только \n", $ПЛОЩАДЬ, " акров земли. Итак, \n"; goto Назначить_площадь_посевов; } # норма посева - 1 бушель на 2 акра if (int($ПЛОЩАДЬ_ПОСЕВОВ/2) > $ЗЕРНО_В_АМБАРЕ){ print "Хаммурапи: думай снова. У тебя только \n", $ЗЕРНО_В_АМБАРЕ, " бушелей зерна. Итак, \n"; goto Назначить_площадь_посевов; } # норма обслуживания - 10 акров на человека if ($ПЛОЩАДЬ_ПОСЕВОВ > 10*$НАСЕЛЕНИЕ) { print "Но у тебя только ", $НАСЕЛЕНИЕ, " человек чтобы обрабатывать поля. Итак, \n"; goto Назначить_площадь_посевов; } } # ===================================== sub Сельхоз_цикл{ # норма посева - 1 бушель на 2 акра $ЗЕРНО_В_АМБАРЕ = $ЗЕРНО_В_АМБАРЕ - int($ПЛОЩАДЬ_ПОСЕВОВ/2); # вегетационный период $Y = int(rand()*5) + 1; # урожайность 1..5 бушелей с акра, в среднем 3 # сбор урожая и засыпка зерна на хранение $УРОЖАЙ = $ПЛОЩАДЬ_ПОСЕВОВ*$Y; #потери урожая 2 года из пяти $C = int(rand()*5) + 1; # 1..5 if (int($C/2) != $C/2){ # если нечетное $С потерь нет $СЪЕДЕНО_КРЫСАМИ = 0; } else { $СЪЕДЕНО_КРЫСАМИ = int($ЗЕРНО_В_АМБАРЕ/$C); # в среднем 3/20 остатка } $ЗЕРНО_В_АМБАРЕ = $ЗЕРНО_В_АМБАРЕ - $СЪЕДЕНО_КРЫСАМИ + $УРОЖАЙ; } # ===================================== sub Демограф_цикл{ # странно - обратно пропорционально населению $C = int(rand()*5) + 1; # 1..5 $ПРИРОСТ_НАСЕЛЕНИЯ = int($C*(20*$ПЛОЩАДЬ + $ЗЕРНО_В_АМБАРЕ)/$НАСЕЛЕНИЕ/100 + 1); # пропитание 20 бушелей в год на человека $ОБЕСПЕЧЕНО_ПИЩЕЙ = int($ПРОДОВОЛЬСТВЕННОЕ_ЗЕРНО / 20); if ($ОБЕСПЕЧЕНО_ПИЩЕЙ < $НАСЕЛЕНИЕ){ $УМЕРЛО_ОТ_ГОЛОДА = $НАСЕЛЕНИЕ - $ОБЕСПЕЧЕНО_ПИЩЕЙ; } else { $УМЕРЛО_ОТ_ГОЛОДА = 0; } goto Досрочное_увольнение if $УМЕРЛО_ОТ_ГОЛОДА > 0.45*$НАСЕЛЕНИЕ; $СМЕРТНОСТЬ_ОТ_ГОЛОДА_10 = (($ГОД - 1)*$СМЕРТНОСТЬ_ОТ_ГОЛОДА_10 + $УМЕРЛО_ОТ_ГОЛОДА*100/$НАСЕЛЕНИЕ)/$ГОД; $НАСЕЛЕНИЕ = $ОБЕСПЕЧЕНО_ПИЩЕЙ; $УМЕРЛО_ОТ_ГОЛОДА_10 = $УМЕРЛО_ОТ_ГОЛОДА_10 + $УМЕРЛО_ОТ_ГОЛОДА; $НАСЕЛЕНИЕ = $НАСЕЛЕНИЕ + $ПРИРОСТ_НАСЕЛЕНИЯ; # 15% вероятность чумы $ЧУМА = ''; if (rand() < 0.15){ $НАСЕЛЕНИЕ = int ($НАСЕЛЕНИЕ / 2); $ЧУМА = "Ужасная чума ! Половина народу умерло.\n"; } } # ===================================== sub Годовой_отчет{ print "\n\nХаммурапи: прошу отчитаться.\n"; print "В ", $ГОД, " году \n", $УМЕРЛО_ОТ_ГОЛОДА, " человек умерло от голода.\n"; print "Прирост населения составил ", $ПРИРОСТ_НАСЕЛЕНИЯ," человек.\n"; print $ЧУМА; print "Сейчас население составляет ", $НАСЕЛЕНИЕ, " человек\n"; print "Город владеет ", $ПЛОЩАДЬ, " акрами.\n"; print "Собрано зерна ", $Y, " бушелей с акра.\n"; print "Крысы съели ", $СЪЕДЕНО_КРЫСАМИ, " бушелей.\n"; print "Запасы зерна составляют ", $ЗЕРНО_В_АМБАРЕ, " бушелей.\n"; } # ===================================== sub Итоги_десятилетия{ $L = $ПЛОЩАДЬ / $НАСЕЛЕНИЕ; $C = sprintf "%6.2f", $СМЕРТНОСТЬ_ОТ_ГОЛОДА_10; print "За время вашего 10 летнего пребывания на посту в среднем ", $C , " процентов\n"; print "населения ежегодно умирали от голода, в общей сложности ", $УМЕРЛО_ОТ_ГОЛОДА_10, " человек.\n"; print "Вы начали с 10 акров на человека, а закончили \n", $L; " акрами на человека.\n\n"; goto ЧУДОВИЩНЫЙ_РЕЗУЛЬТАТ if $СМЕРТНОСТЬ_ОТ_ГОЛОДА_10 > 33; goto ЧУДОВИЩНЫЙ_РЕЗУЛЬТАТ if $L < 7; goto ПЛОХОЙ_РЕЗУЛЬТАТ if $СМЕРТНОСТЬ_ОТ_ГОЛОДА_10 > 10; goto ПЛОХОЙ_РЕЗУЛЬТАТ if $L < 9; goto СРЕДНИЙ_РЕЗУЛЬТАТ if $СМЕРТНОСТЬ_ОТ_ГОЛОДА_10 > 3; goto СРЕДНИЙ_РЕЗУЛЬТАТ if $L < 10; #если площадь на человека >= 10 и смертность от голода <= 3% goto ФАНТАСТИЧЕСКИЙ_РЕЗУЛЬТАТ; ФАНТАСТИЧЕСКИЙ_РЕЗУЛЬТАТ: print "Фантастический результат !!! Шарлемань, Дизраели и \nДжефферсон вместе не смогли бы сделать лучше ! \n"; goto ДО_СВИДАНИЯ; ЧУДОВИЩНЫЙ_РЕЗУЛЬТАТ: print "Из-за чрезвычайно плохого управления ты объявлен \"Предателем нации\" !!"; goto ДО_СВИДАНИЯ; ПЛОХОЙ_РЕЗУЛЬТАТ: print "Ваша тяжелая рука припахивает Нероном и Иваном IV. \nВыжившие люди считают вас плохим правителем и ужасно ненавидят ваши потроха ! \n"; goto ДО_СВИДАНИЯ; СРЕДНИЙ_РЕЗУЛЬТАТ: print "Ваши достижения могли бы быть лучше, но \nдела не совсем плохи. \n"; print int($НАСЕЛЕНИЕ*0.8*rand()), " человек хотели бы видеть вас убитым, но это обычная проблема для нас.\n"; goto ДО_СВИДАНИЯ; ДО_СВИДАНИЯ: } # ===================================== exit; Update Если ваш интерпретатор Perl не поддерживает русскоперловый язык, то конвертировать имена в латиницу можно с помощью вот этой программки: http://vlkamov.narod.ru/rupl.zip Сгрузите и распакуйте. Скопируйте код, находящийся под катом в файл hamurabi.rupl и команда perl rupl2pl.pl hamurabi.rupl > tmp.pl ; perl tmp.pl сразу конвертирует в латиницу и запускает исполнение. |
||||||||||||||
![]() |
![]() |