Сборка случайного числа в пределах диапазона с использованием Easy 68K (68000) - PullRequest
2 голосов
/ 20 декабря 2011

Я создаю простую игру в блэкджек, используя симулятор Easy 68K, и мне нужно использовать случайное число для назначения карт.Мои карты должны быть в диапазоне от 2 до 11. Я, кажется, получаю одно и то же число каждый раз, и это не в пределах диапазона, который я ожидаю.Значение моей карты должно заканчиваться на D3, поэтому у меня есть следующий код случайного числа:

 CLR.L       D0
 CLR.L       D3
 MOVE.B      #8, D0         ;Access time
 TRAP        #15
 AND.L       #$5FFFFF,D1    ;prevent overflow in divu
 DIVU        #10, D1
 SWAP        D1
 ADDQ.W      #1, D1
 MOVE        D1, D3

, к которому я пришел, изменив код на этом сайте: https://notendur.hi.is/voe1/3.%20onn/Tolvuhogun/EASy68K/Examples/tutorial3.X68

IЯ надеюсь найти помощь в создании номера от 2 до 11. Я искал в Интернете в течение нескольких часов.Я знаю, что мне нужно получить доступ ко времени, используя Move.B # 8, D0, но кроме этого я не добился большого прогресса.Буду очень признателен за любую помощь!

Ответы [ 2 ]

5 голосов
/ 20 декабря 2011

Маска, используемая в AND.L («предотвращение переполнения в divu»), была хороша только для деления на 100 - вам нужно будет замаскировать 0x7FFFF для деления на 10.

Почему:

0xFFFFFFFF / #100 = 0x28f5c28 - too big for a single word!
0x5FFFFF   / #100 = 0xF5C2    - that fits

0x5FFFFF / #10  = 0x99999 - too big for a single word!
0x7FFFF  / #10  = 0xCCCC  - that fits

Кроме того, у вашего кода будет число от 1 до 10 (0-9 + 1). Если вы хотите от 2 до 11, вам нужно добавить 2, а не 1.


Вот более продвинутый генератор случайных чисел, заимствованный из исходного кода Mac OS QuickDraw. Обратите внимание, что вам может потребоваться несколько перевести синтаксис (он был написан более 25 лет назад!) И / или изменить способ загрузки и сохранения своего начального числа.

;--------------------------------------------------------------
;
;  FUNCTION Random: INTEGER;
;
;  returns a signed 16 bit number, and updates unsigned 32 bit randSeed.
;
;  recursion is randSeed := (randSeed * 16807) MOD 2147483647.
;
;  See paper by Linus Schrage, A More Portable Fortran Random Number Generator
;  ACM Trans Math Software Vol 5, No. 2, June 1979, Pages 132-138.
;
;  Clobbers D0-D2, A0
;
;
;  GET LO 16 BITS OF SEED AND FORM LO PRODUCT
;  xalo := A * LoWord(seed)
;
        MOVE.L  GRAFGLOBALS(A5),A0      ;POINT TO QuickDraw GLOBALS
        MOVE    #16807,D0               ;GET A = 7^5
        MOVE    D0,D2                   ;GET A = 7^5
        MULU    RANDSEED+2(A0),D0       ;CALC LO PRODUCT = XALO
;
;  FORM 31 HIGHEST BITS OF LO PRODUCT
;  fhi:=HiWord(seed) * ORD4(a) + HiWord(xalo);
;
        MOVE.L  D0,D1                   ;COPY xalo
        CLR.W   D1
        SWAP    D1                      ;GET HiWord(xalo) as a long
        MULU    RANDSEED(A0),D2         ;MULT BY HiWord(seed)
        ADD.L   D1,D2                   ;ADD LEFTLO = FHI
;
;  GET OVERFLOW PAST 31ST BIT OF FULL PRODUCT
;  k:=fhi DIV 32768;
;
        MOVE.L  D2,D1                   ;COPY FHI
        ADD.L   D1,D1                   ;CALC 2 TIMES FHI
        CLR.W   D1
        SWAP    D1                      ;CALC FHI SHIFTED RIGHT 15 FOR K
;
;  ASSEMBLE ALL THE PARTS AND PRE-SUBTRACT P
;  seed:=((BitAnd(XALO,$0000FFFF) - P) + BitAnd(fhi,$00007FFF) * b16) + K;
;
        AND.L   #$0000FFFF,D0           ;GET LO WORD XALO
        SUB.L   #$7FFFFFFF,D0           ;SUBTRACT P = 2^31-1
        AND.L   #$00007FFF,D2           ;BitAnd(fhi,$00007FFF)
        SWAP    D2                      ;TIMES 64K
        ADD.L   D1,D2                   ;PLUS K
        ADD.L   D2,D0                   ;CALC TOTAL
;
;  IF seed < 0 THEN seed:=seed+p;
;
        BPL.S   UPDATE
        ADD.L   #$7FFFFFFF,D0
UPDATE  MOVE.L  D0,RANDSEED(A0)         ;UPDATE SEED
        CMP.W   #$8000,D0               ;IS NUMBER -32768 ?
        BNE.S   NUMOK                   ;NO, CONTINUE
        CLR     D0                      ;YES, RETURN ZERO INSTEAD
NUMOK   MOVE.W  D0,4(SP)                ;RETURN LO WORD AS RESULT
        RTS
0 голосов
/ 13 января 2019

Вам нужно использовать правильную маску в зависимости от вашего интервала (минимального и максимального). Этот код решит все ваши проблемы, он принимает два аргумента: минимум в D5 и максимум в D6, он также использует D0, D7 и A1.

RAND_GEN
    SUB     D5,D6             ;You should give Min in D5 and Max in D6
    MOVE    D6,D7
    ADDI     #1,D6
    MULU    #$FFFF,D7
    LEA     SEED,A1
    MOVE.B  #8,d0
    TRAP    #15
    ADD    (A1),D1
    MULU  #$FFFF,D1
    EOR.L     #$F321F23A,D1
    MOVE    D1,(A1)
    AND.L   D7,D1    ;PREVENT OVERFLOW FOR (Max-Min)
    DIVU    D6,D1         ;time count / (Max-Min)
    SWAP    D1              ;swap upper and lower words of D1 to put remainder in low word
    ADD  D5,d1           ;D1.W contains number in the range of (Min,Max)
    RTS

* Put variables and constants here
SEED
    DC.W    1

SEED будет по умолчанию 1 при запуске программы и автоматически обновляется после каждого вызова RAND_GEN, вы также можете изменить его в любое время.

Проверено на EASY68K.

...