Започнах да пиша за моя производствен метод за играта C64, върху която работя, и това някак се превърна в това как да се справя със скучните части от работата по хоби проект.

Пол Колар наскоро писа за своя опит с разработването на Luftrauserz и засегна рисковете от такива скучни части тук: http://www.rgcd.co.uk/2018/01/after-action-review-overview-of-making. html. За да спестя описанието на производствения си метод, вместо това ще започна да пиша за скучните части.

Само за да си припомня каква е играта (вдъхновена от M.U.L.E.), ето малко видео, което направих заедно с музиката на Stein:

Точно сега съм в средата на една наистина скучна функция и я направих приоритет, защото трябва да реши проблем с настройката на играта. Това не е очевиден проблем, но искам да го разбера правилно.

За щастие това е вид проблем, който не изисква много нов код и наистина е по-скоро проблем на хартия. Вместо да изпадам в състояние на ума за кодиране, просто ще напиша това, докато разбера математиката.

Играта се състои от шестоъгълна решетка, където всеки играч избира една земна клетка на ход. След това всеки играч може да закупи дроиди и да ги оборудва, за да генерира предмети като руда, използвана за изграждане на още дроиди, или енергияза управление на дроиди или храна да оцелееш.

Съпоставянето на типа земя (гора, планини, равнинии т.н.) с вида на производството на предмета е ключовата стратегия на играта. За всеки тип земя има диапазон от брой артикули, произведени на ход

За да работи тази работа с възможно най-малко памет на 8-битов процесор без фантастични функции като вградено умножение, внедряването е доста спартанско.

Броят на произведените елементи на клетка на ход не е много критичен във времето, така че има доста обработка, за да се спести памет. В паметта има множество мрежи, всяко оформление на мрежата се нарича карта. Тази система използва картата на типа земя, картата на дроидите (какъв елемент се произвежда във всяка клетка) и карта на стойността. Картата на стойността е по същество произволно семе, което се коригира в зависимост от вида на елемента, който се произвежда в клетката.

Играчите могат да използват част от хода си, за да помолят земската служба да оцени земна клетка, преди да решат какво да произведат върху нея, за да вземат по-добро решение, с цената на известно време за този ход.

Ето пример за това какво може да произведе даден тип земя, всеки слот е широк 16 проби. За този тип земя, равнините, най-добрият избор би бил енергията, но това не е непременно най-доходният вид артикул за този тип земя. Обърнете внимание, че настройката изобщо не се извършва и тези стойности ще се променят.

За да завършим това, броят на артикулите, произведени в клетка за определен тип артикул, зависи от типа земя. Типът земя има известен диапазон от броя на артикулите, които могат да бъдат произведени за всеки тип артикул. Въз основа на семената в картата на стойността се определя фиксирано количество артикули и всеки ход ще се произвежда този брой артикули.

И тук възниква проблемът ми с дизайна на играта. Ето илюстрация за това как шансът за производствения капацитет работи в момента: (опростено, за да се покаже една проба на слот, а не 16)

В този пример имам само една проба за всеки слот, но на практика използвам 16 за всеки слот и измествам резултата надолу, за да добавя малко повече контрол към проектните данни.

Проблемът ми е, че с това, което имам в момента, има равен шанс да получа 6 предмета, както и да получа 1, 2, 3 или 4. Това прави отбелязването на 6 твърде често, което просто не е особено специално. Ако това беше истинско нещо, вероятно дори щеше да е нещо като камбановидна крива.

Така че това, което търся, е основно обърната статистика, имам представа какво трябва да представлява малък набор от проби и искам да разбера как да генерирам този набор от проби.

Ето какво мисля, че бих искал да видя, на следващата снимка всеки квадрат е с равна вероятност:

Така че нека се опитаме да разбием това.

Между слотове 3 до 6 шансът намалява, така че има 4 стъпки (3, 4, 5 и 6). Слотове 1 и 2 са със същия шанс като 3, така че и двата са с по 4 шанса.

Общият брой проби е: 4 + 4 + 4 + 3 + 2 + 1 = 18. Генерирането на произволна извадка под 18 прави тривиално преброяването на кутии от първия слот, за да се намери разпределеният слот.

За всеки производствен случай (тип земя, тип артикул) трябва да добавя колко слота са шанс за нарастване и колко са с равен шанс.

Броят на пробите, обхванати от наклонения участък, е 1 + 2 +… + N, където N е броят на слотовете, които се увеличават. Това се оказва N *(N+1) / 2, което е доста лесно изчисление. Броят на стойностите за всеки от линейно разпределените слотове е N, тъй като е същият като най-ниския наклонен слот.

Само за да назовем броя на пробите в частите за линейно и наклонено разпределение: Sr = N * (N + 1 ) / 2 и Sl = N * L, където L е броят на линейните слотове.

Това довежда общия брой избори до Общо = Sl + Sr. Следващата стъпка е да преобразувате семето от картата на стойността в проба между 0 и Общо. Това ще изисква допълнително мислене, тъй като всички битове са значими (най-високият слот има само една проба, присвоена към него).

И така, как да преминете ефективно на 6502 от интегрираната проба обратно към слота, който представлява? С ефективно деление на процесора и квадратни корени това може да се направи доста лесно чрез разделяне на диапазона между линейно разпределените слотове и наклонените слотове. В моя случай все още мога да започна, като разделя стойностите на две групи: По-малко от броя на наклонените стойности =› проверете наклона, в противен случай извадете броя на наклонените стойности и разделете на N.

И така, как да намеря слота от проба в участъка с наклонена стена?

Мисля, че вместо да се опитваме да приложим квадратичната формула, броят на слотовете, през които трябва да се премине един по един, е достатъчно малък, за да бъде по-бързо

1: Оставащ = Sr, или N * (N+1)/2 отгоре, C = N
2: Оставащ= Оставащ - C
3: ако Резултат › Оставащ, тогава слотът е C стъпки от последното.
4: C = C-1
5: Отидете на 2, докато C ›= 0

Така че, за да стигнете до кода, първо генерирайте проба в диапазона от 0 до Total, ако пробата е по-малка от Sr, проверете пробата спрямо рампата и ако е по-голяма, извадете Sr от пробата и разделете на N.

С обхвата на слот има значително повече потенциални проби за преминаване и вероятността ще изглежда по-скоро така:

Ето малко код, който преминава през всяка стъпка от рампата, за да видите коя стъпка представлява пробата, акумулаторът трябва да бъде 0 за първата стъпка и N-1 за последната, или N, ако пробата е извън обхвата. Все още не съм тествал кода, тъй като това е упражнение на хартия, така че може да е грешен.

Така че дори ако този цикъл трябва да премине през, да речем, 64 стъпки в дълга рампа, това все още е приемливо. Всяка итерация, при която дадена проба не е в диапазона, е 29 цикъла, а последната итерация е 22 цикъла. Освен това цикълът започва с по-големите диапазони, така че е N пъти по-вероятно пробата да е в първия слот, отколкото в последния слот. Играта просто показва картата, докато това се случва.

Така че основната причина това да е скучно е, че това е нещо, което първоначално изглежда тривиално, което се оказва, че изисква много повече код, който не прави нищо очевидно на екрана. Решението почти само ще улесни изпипването на играта, но няма да направи очевидна разлика при игра. Освен това статистиките са склонни да правят забавните неща по-малко забавни.

Мисля, че е важно проблемите да се разглеждат възможно най-скоро, ако има някакъв шанс да възникне друг проблем. Колкото повече скучни неразрешени проблеми съществуват по всяко време в един хоби проект, толкова по-голям е шансът да се откажа от проекта. Не виждам това да се случва с тази игра, изобщо не ми се струва, че е завършена!

В крайна сметка разпределението на броя произведени елементи вероятно може да бъде настроено добре с линейно разпределение и никой няма да забележи, но щях да знам, че можеше да е по-добре.

Надявам се, че сте прекарали наистина скучно време, докато четете това, както аз го писах ;) Само за да запълня останалото пространство на екрана, ето една скорошна функция, върху която работих: