WarCraft 3: Тип integer

Тип integer
» Раздел: Триггеры и объекты

Предисловие - для кого эта статья

Статья носит скорее более теоретический характер, хотя и дает достаточно пищи для размышлений о том, как код можно сделать намного проще и качественней. Предполагается что читатель достаточно хорошо знает JASS.

Теория

Тип integer в Jass это long signed int (в C) или попросту DWORD, это значит что он имеет 32 бита: 31 бит что бы обозначить само число и один знаковый бит. В JASS коде он может быть представлен в 8 (восьмеричная или octimal), 10 (десятеричная или decimal, самая привычная для большинства людей), 16 (шестнадцатеричная или hexadecimal) и 256(ASCII) нотации (системе счисления).
Чем одна система отличается от другой? (если Вы знакомы с этими понятиями можете пропустить этот абзац) В десятеричной системе переход в следующий разряд происходит когда число достигает 10 (9+1=10). Точно также и в других системах счисления: в восьмеричной системе 7+1=10 (причем 10 в ней реально равно 8 в десятеричной системе). В шестнадцатеричной системе что бы обозначить цифры (не путайте число и цифру, цифра - обозначение числа, поэтому разные цифры - в разных нотациях могут указывать на одно число), так вот, что бы обозначить в шестнадцатеричной системе цифру больше 9 мы будем использовать первые буквы английского алфавита: A=10, B=11, ... F=15. С 256 системой счисления дело обстоит также, ниже я выложу таблицу символов и значений (взято из WEU документации):
Хорошо, теперь вернемся к JASS. Что бы написать цифру в восьмеричной системе счисления мы должны приставить к ней 0
local integer i=012 // 10 в десятеричной си
Цифры без префиксов считаются десятичными, hex обозначается через 0x
local integer i=0x0f // 15 в десятеричной си
256 цифры указываются обрамленными в апострофы
local integer i='A' // 65 в десятеричной си
Если Вы хотите перевести цифру в другую си - используйте WinCalc (есть такая программа в меню "пуск") переставленный в инженерный вид. Перевод числа из ASCII делается тоже достаточно просто: переведите каждый чар (ну т.е. символ) в hex, и вы получите 16ричное число. К примеру: 'A0a1', 'A' = 0x41, '0' = 0x30, 'a' = 0x61, '1' = 0x31, 'A0a1' равно 0x41306131 или 1093689649.
Помните, что большинство равкодов (кроме lightning, ubersplat) в JASS обычные integer, поэтому с ними возможны любые математические действия, что и будет описано дальше.
В JASS невозможно указать integer в двоичной (binary) системе счисления, но она очень важна для понимания всего материала. Как Вы могли догадаться, в ней переход в следующий разряд происходит при достижение 2: 1bin+1bin == 10bin (2dec). Теперь вернемся к нашему 32 битному integer
0x 7       a       9      8      0      1       f      0
     0111 1010 1001 1000 0000 0001 1111 0000
Один разряд в двоичной системе называется бит, восемь разрядов или двух разрядное шестнадцатеричное число - байт.
Напомню, что первый бит числа - знаковый бит, и он определяет будет ли оно положительным (0) или отрицательным (1). Положительные числа идут от 0x00000000 (0dec) до 0x7fffffff (2147483647dec), отрицательные от 0xffffffff (-1dec) до 0x80000000 (-2147483648dec). Что бы изменить знак числа надо инвертировать (где было 1 написать 0, где был 0 написать один) все биты числа и потом к нему прибавить 1.
  // в примере я использую однобайтовое число что бы было легче понять

  0000 0001 // +1dec
  1111 1110 // inv
  1111 1111 // -1dec
Теперь, хоть в JASS и нету побитовых операций над числами, можно имитировать их с помощью умножения и деления
   1000 1000 // *10bin  (<<)
1 0001 0000 // /100bin (>>)
   0000 0100
Биты, которые не помещаются в результате будут считаться потерянными. Также с помощью нескольких сдвигов мы сможем получить любые биты числа, имитировав тем самым логические побитовые операции, к примеру на нужно узнать значение 3 и 4 бита
  0110 **11**01 // *1000
  0**11**0 1000 // /100000
  0000 00**11**
Отлично! Но у нас могут возникнуть некоторые проблемы с знаковым битом при таких операциях
  0111 1100 // *1000
  1110 0000 // 1110 0000bin = -20dec

  1110 0000 // но мы можем изменить знаковый бит
 +1000 0000
  _____ _____
1 0110 0000
Так что мы смело можем прибавить 0x80000000, но есть еще более простой способ использовать бит "сепавратор", который всегда будет равен 0, и если он займет место знакового то результат все равно будет верным
  0vv! vvvv

  v - наши данные
  ! - бит сепаратор
Остается добавить, что деление или умножение на 10bin, 100bin, 1000bin это сдвиг влево или вправо на 1, 2, 3 бита (2^1 == 2 dec == 10 bin; 2^2 == 4 dec == 100 bin; 2^3 == 8 dec == 1000 bin; 2^n == сдвиг на n бит).
Хорошо, теперь попробуем применить это все на практике.

Практика

Тут я выложу несколько простых задач, в решение которых стоит применить полученные знания.

Золото за убийство

Мы должны добавить владельцу убившего юнита золота в зависимости от какой либо характеристики (к примеру у юнита есть способность или предмет +50% золота от крипов). На карте есть много всяких крипов, и от каждого должно даваться случайное количество золота, но пересчитанное по какой либо формуле. Функция, создающая texttag и добавляющая золота у нас есть, в нее просто надо сообщить его количество. Также сделайте два варианта, в первом 1 <=minGold <=maxGold <=80000000, во втором 1 <=minGold <=MaxGold <=75.

Добавление предмета

На карте существует ~60 типов различных героев. Когда какой либо герой достигнет 50 уровня надо создать уникальный для это типа героя артефакт возле него.

Данные юнита

Необходимо сохранить для каждого юнита в игре сколько героев и крипов он убил, и на какой стороне он сражается (к примеру свет и тьма). Предположительно юнит не может убить больше 2000 других юнитов, не может убить больше чем 500 героев, и он либо темный, либо светлый. Возможное количество таких юнитов, которым надо сопоставить эти данные неограниченно. Также добавлю условие что нельзя использовать глобальные переменные, массивы или кешь.

Просмотров: 25 567

MartyrOfSorrow #1 - 9 лет назад 0
неплохо...с предметами особенно, интересно это может относится к обычным предметам?Видел в картах на какойто их сторон полоса с отрезками земли на которых различные предметы а на других нет...очевидно оно както выбирает ячейку и каким то образом дает предмет героям/ю.
ScorpioT1000 #2 - 9 лет назад 0
Наконец ты соединил поток мыслей в что-то целое)
BioAleks #3 - 8 лет назад 0
Маладец аффтор
Gam_Over #4 - 8 лет назад 2
о! полезная статья, теперь про integer стало намного больше понятного и в тоже время еще осталось непонятного :) но со временем разберемся
JamesBlack #5 - 7 лет назад 2
Плохо одно - многие так и не поймут, как можно применять инты для хранения стольразной информации
2 комментария удалено