Game Duenix for Amiga computers
What follows is the source code for the Duenix game by Dan Polansky for Amiga line of computer originally developed in 1994-1998 in the AMOS BASIC language. One of the purposes is to act as an example of use of that language for those who want to learn the language or get an idea of its syntactic face and its facilities; no other such example currently exists in Wikiversity. The syntax is reminiscent of Visual Basic.
The source code package below should be complete now: it consists of the main AMOS file and three Motorola 68000 assembly source code files for the portions for which AMOS was too slow. However, the full game can be compiled and run only with the use of all supporting files, including image, sound and music module files.
Among the assembly files, the most interesting one is the one for Duenix strategy for computer-driven players/worms. One can use it to train understanding of the assembly. Since it merely complements the main AMOS program, it is reasonably short and therefore suitable for learning. One can start learning by picking only some of the supporting routines and trying to understand them. The assembly source code ends with a quick 68000 assembly guide to serve as a quick reference.
The game was inspired by (but has more features than) Amiga Game Wikipedia: Achtung, die Kurve!, whose full title seems to be "Dune 3 – Achtung! Die Kurve"[1]. Dune 3 was inspired by game Cervii[2] ("Worms"). The name Duenix is based on the name Dune.
Duenix.AMOS
[edit | edit source]Set Buffer 20
Erase All
Set Sprite Buffer 256
Trap Screen Close 0
VERSION$="$VER: Duenix 1.2 (17.10.98)"
YEAR$="1994-1998"
RELEASE$="Release 1.2"
MEMORY_REQUIREMENT=800000-170000
If Prg State=-1 : Break Off : PATH$=Dir$ : Else : If Exist("ram:editamos.lock") : Kill "ram:editamos.lock" : Edit : End If
PATH$="Work:Programming/Duenix/Dx/"
End If
Dim _NOT(1)
Dim X#(6),Y#(6),SMER(6),NEW_X#(6),NEW_Y#(6),NEW_SMER(6),NEW_PLAYER(6),SCORE(6),SELECTED(6),SEMIALIVE(6),SPACE_COUNTER(6),LINE_COUNTER(6),SPEED(6),SPEED_PERCENT#(6),TURNING(6),LIVES(6),_TOP_LIVES(6),AUCH_COUNTER(6),AUCH_PROTECTION(6)
Dim _PLAYER_RECORD(5),_FREE_VALUE(6),LIVING_PLAYER(6),COMPUTER_STRATEGY(6),CYBORG(6),PLAN_BANK(2),_NEXT_SOUND_FX_CHANNEL(8),WRITE_KOI82IMAGE($),WRITE_KOI82HOOK($),ZOMBIE(6),LINE_LENGTH_(6),SPACE_LENGTH_(6),ALIVE(6)
Dim BOUND_THIS_ROUND(6),BOUND_COUNTER(6),REDRAW_PLAYER(6),ACCEPT_KEYSTROKE(6),_KEYSTROKE_COUNTER(6),SPEED_SOURCE#($F),WIND_FACTOR#(6),UPP($),SPP($),TEAM_MATE_THRU(6),TEAM_MATE(6),DEMOSTORE_PLAYSTATE(6),PL_RGB(6),_PLAYER_PROPRIETY(2,3)
Dim STAYED_ALIVE_BONUS(6),_PLAYER_TYPE(6),_PLAYER_TYPE_IMAGE(3),STANDARD_PLAN_PAL$(5),GS_GAME_NAME$(20,1),_PUTPIX_QUEUE_X(12-1),_PUTPIX_QUEUE_Y(12-1),_PUTPIX_QUEUE_COLOUR(12-1)
Dim NO_IMAGE(2),YES_IMAGE(2),RED_BOX_IMAGE(2),_BOB_PLAYER_IMAGE(1,1),_SPRITE_NUMBER(6),_SPRITE_IMAGE(6),_PLAYER_GREY_COLOUR(6),PL_DEF_COLOR(6),P_COLOR(6),PL_DEF_COLOR_LIGHT(6),PL_DEF_COLOR_DARK(6),OS_LC_BOX(14),OS_RC_BOX(14)
Dim OS_LEFT_COLUMN_TEXT$(14,1),OS_RIGHT_COLUMN_TEXT$(14,1),MAIN_OPTION_TEXT$(4),SELECTING_UPPER_TEXT$(5),SELECTING_LOWER_TEXT$(5),RR_COLUMN_TEXT$(2),CREATE_USER_GS_EXPLANATION$(13),_NOT_ALL_FILES$(2),GAMEPLAN_EXPLANATION$(2),GAMEPLAN_KEY_TEXT$(2)
MAIN
Procedure SET_CONSTANTS
_TRUE=1 : _FALSE=0 : _NOT(_TRUE)=_FALSE : _NOT(_FALSE)=_TRUE : _T=1 : _F=0
_ERROR_BADPATH=250
EN$=Chr$($D)+Chr$($A)
CZ_SEND$="Ahoj.\ Tato hra je Freeware. PŇesto, pokud se ti lÉbÉ,\pĹknĹ prosÉm, poÓli 10 KĂ na adresu:\"
EN_SEND$="Hello.\ This game is Freeware, but if you like the game,\pretty please, send twice the price of post stamp to:"
EN_VALUE$="Note that even one dollar is a big piece of money \for me."
RECORDNAME$="Duenix_GameRecord"
CONFIG_LENGTH=$80
DEMO_TIMER_LIMIT=50*18
DEMO_PRESS_SPACE_LIMIT=50*3
'Pul minuty
V=26-1
Inc V : PRECOUNTED_SIN__BANK=V
Inc V : PRECOUNTED_ATAN__BANK=V
Inc V : DEF_GAMESET__BANK=V
Inc V : USER_GAMESET__BANK=V
CONFIG_TEMPORARY__BANK=31
LIFE_MOTION_MUSIC__BANK=15
WINNER_MUSIC__BANK=16
For I=0 To 2 : PLAN_BANK(I)=8+I : Next I
V=0-1
Inc V : BOUND_SOUND=V
Inc V : TELEPORT_SOUND=V
Inc V : DEATH_SOUND=V
Inc V : ARROW_SOUND=V
Inc V : PRESS_SPACE_SOUND=V
Inc V : AUCH_SOUND=V
Inc V : BODY_CHANGE_SOUND=V
V=14-1
Inc V : DUENIX_TITLE_IMAGE=V
Inc V : DUENIX_ANIM_IMAGE=V
Inc V : MOUSE_ON_LINE_IMAGE=V
Inc V : _JOY_ON_LINE_IMAGE=V
Restore CONSTANTS
' .----------------.
' | Box System |
' `----------------'
Read BS_LEFT_TOP,BS_MIDDLE_TOP,BS_RIGHT_TOP
Read BS_LEFT_MIDDLE,BS_MIDDLE_MIDDLE,BS_RIGHT_MIDDLE
Read BS_LEFT_BOTTOM,BS_MIDDLE_BOTTOM,BS_RIGHT_BOTTOM
For I=0 To 3 : Read _PLAYER_TYPE_IMAGE(I) : Next I
For PROP=0 To 2
For TYPE=0 To 3
Read _PLAYER_PROPRIETY(PROP,TYPE)
Next TYPE
Next PROP
For I=0 To 5
Read STANDARD_PLAN_PAL$(I)
Next I
For I=0 To 2 : Read NO_IMAGE(I),YES_IMAGE(I),RED_BOX_IMAGE(I) : Next
Read LATERAL_LEFT,LATERAL_RIGHT
Read HORIZONTAL_WOOD_IMAGE,CORNER_WOOD_IMAGE
Read VERTICAL_WOOD_IMAGE,NOSCROLL_CORNER_IMAGE
Read SCORE_PANEL_BACKGROUND_IMAGE
Read _BOB_PLAYER_IMAGE(0,0),_BOB_PLAYER_IMAGE(1,0)
Read _BOB_PLAYER_IMAGE(0,1),_BOB_PLAYER_IMAGE(1,1)
Read LIFE_BOX_IMAGE,PRESS_SPACE_IMAGE
Read _FREE_FOR_MANIPULATION_IMAGE
For I=1 To 14 : OS_LC_BOX(I)=Rnd(2) : OS_RC_BOX(I)=Rnd(2) : Next
For I=1 To 6 : Read _SPRITE_NUMBER(I) : Next
For I=1 To 6 : Read _SPRITE_IMAGE(I) : Next
For I=1 To 6 : Read _PLAYER_GREY_COLOUR(I) : Next
For I=1 To 6 : Read PL_DEF_COLOR(I) : Next
For I=1 To 6 : Read PL_DEF_COLOR_LIGHT(I) : Next
For I=1 To 6 : Read PL_DEF_COLOR_DARK(I) : Next
_ADDRESS$=""
For I=1 To 59
Read A : A=127-(A and $7F)
_ADDRESS$=_ADDRESS$+Chr$(A)
Next
For I=1 To 8
Read _NEXT_SOUND_FX_CHANNEL(I)
Next I
' ############################################
' ############################################
' ############################################
CONSTANTS:
Data 23,24,25,26,27,28,29,30,31
Data 12,13,32,47
Data 0,-1,-1,-1,0,0,-1,0,0,0,0,-1
Data "000100200310410520620730830930A30B30C30D30E30F30"
Data "000010110120220230330340440450550560660670770880"
Data "000100200301401511612712812913A23B23C24D24E34F35"
Data "00000110210320420530640740850950A60B60C70D80E80F"
Data "000100200410510720820A30B30B41A53A64975876887888"
Data "000010020130140250360470770870980996AA9BBACCBDDC"
Data 20,21,22,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67
Data 0,1,4,6,2,3
Data 1,2,3,4,1,2
Data $555,$666,$444,$555,$444,$555
Data $BB9,$D4,$F6E,$FD0,$98F,$DC
Data $BB9,$D4,$F6E,$FD0,$98F,$DC
Data $997,$B2,$D4C,$DB0,$76D,$BA
Data 15547871,851935,717919,14521183,15184699,15895454,4796305,14405910,1778714,1785619
Data 3568095,16049967,16590608,8523667,9276702,6056593,1776908,14231444,1650054,16523762
Data 8584949,5226207,1411039,12670559,2261855,5154089,11158032,5056525,6662934,11519244
Data 666900,1713424,13908489,6241310,9845471,10016972,8328520,1943410,12217717,13195487
Data 15031647,8158431,7539679,14262205,3611437,1997745,9762352,9414386,338933,16412511
Data 3954015,4265823,6466015,11781321,7741645,5544140,790367,10503503,12815311
Data 2,8,0,1,0,0,0,4
End Proc
Procedure SET_TEXT_CONSTANTS
On Error Proc HANDLE_ERROR
_NOT_ALL_FILES$(0)="You miss Texts file!"
_NOT_ALL_FILES$(1)="... not to talk about the other files."
_NOT_ALL_FILES$(2)="Try to get complete version of Duenix."
Set Input 10,-1
Open In 1,LOCALE_PATH$+"Texts"
Line Input #1,_LOADING$
For I=0 To 5 : Line Input #1,SELECTING_UPPER_TEXT$(I) : Next
For I=0 To 5 : Line Input #1,SELECTING_LOWER_TEXT$(I) : Next
Line Input #1,PAGE_ONE$,MAIN_OPTION_LOADING_AND_SAVING$
Line Input #1,MAIN_OPTION_E_TEXT$,MAIN_OPTION_G_TEXT$,MAIN_OPTION_R_TEXT$,MAIN_OPTION_U_TEXT$
Line Input #1,CONFIGURATION$
For I=0 To 3 : Line Input #1,MAIN_OPTION_TEXT$(I) : Next
Line Input #1,_PRESS_SPACE_OR_ESCAPE$,ESCAPE_ACCEPT$
Line Input #1,PAGE_TWO$,GAME_SETTINGS$
For PAGE=0 To 1
For I=1 To 14 : Line Input #1,OS_LEFT_COLUMN_TEXT$(I,PAGE) : Next
For I=1 To 14 : Line Input #1,OS_RIGHT_COLUMN_TEXT$(I,PAGE) : Next
Next PAGE
Line Input #1,PAGE_THREE$,GAMEPLAN$,THIS_IS_DEFPLAN$
Line Input #1,THIS_IS_STANDARD_GAMEPLAN_NUMBER$
Line Input #1,HERE_MAY_BE_YOUR_PLAN$,HERE_IS_YOUR_PLAN$,GAMEPLAN_L_TEXT$
Line Input #1,ENTER_NAME_OFF_IFF_TO_LOAD$
For I=0 To 2 : Line Input #1,GAMEPLAN_KEY_TEXT$(I) : Next
For I=0 To 2 : Line Input #1,GAMEPLAN_EXPLANATION$(I) : Next
Line Input #1,PAGE_FOUR$,RECORD_AND_REPLAY$,RECORD_AND_REPLAY_SPACE$
For I=0 To 2 : Line Input #1,RR_COLUMN_TEXT$(I) : Next
For I=0 To 13 : Line Input #1,CREATE_USER_GS_EXPLANATION$(I) : Next
Line Input #1,PAGE_FIVE$,CREATING_USER_GAMESET$,CREATE_USER_GAMESET$
Line Input #1,SORRY$
Line Input #1,_MINIMUM_OF_DIRECTIONS$,_MAXIMUM_OF_DIRECTIONS$
Line Input #1,INSERT_VOLUME$
For I=0 To 2 : Line Input #1,_NOT_ALL_FILES$(I) : Next
Line Input #1,_NOT_FONT$
Line Input #1,OPERATION_ABORTED$,DUENIX_CONFIG_ISNT_CONFIG$,DEF_CONFIG_LOADED$
Line Input #1,CANT_FIND_DEF_CONFIG1$,CANT_FIND_DEF_CONFIG2$
Line Input #1,CONFIG_SAVED_AS_DEF1$,CONFIG_SAVED_AS_DEF2$,ENTER_CONFIGNAME$
Line Input #1,THIS_FILE_ISNT_CONFIG$,CONFIG_LOADED$,FILE_DOESNT_EXIST$
Line Input #1,ENTER_NAME_OF_CONFIG_TO_SAVE$,CONFIG_SAVED$,CONFIG_NOT_SAVED$
Line Input #1,THIS_FILE_ALREADY_EXISTS$,WANT_TO_OVERWRITE$
Line Input #1,_ORIGINAL_CONFIG_LOADED$,ENTER_NAME_OF_CONFIG_LIST_FILE$
Line Input #1,NONE_OF_FILES_WAS_CONFIG1$,NONE_OF_FILES_WAS_CONFIG2$,YOUR_NEW_GAMESET_IS_SAVED$
Line Input #1,MORE_THAN_20_FILES1$,MORE_THAN_20_FILES2$,NAME_OF_EMPTY_GAME_IN_GAMESET$
Line Input #1,YOU_HAVENT_RECORDED1$,YOU_HAVENT_RECORDED2$,YOU_HAVENT_RECORDED3$
Line Input #1,YOU_HAVENT_SAVED_GAME1$,YOU_HAVENT_SAVED_GAME2$,YOU_HAVENT_SAVED_GAME3$
Line Input #1,_MAXIMUM_OF_WATER_ANGLE$
Line Input #1,PRESS_U_TO_SELECT_USER_GAME$,SELECT_GAME$
Line Input #1,SELECT_GAME_FROM_USERSET$,NO_GAMERECORD_SAVED$
Line Input #1,THE_WINNER$,THE_LOSER1$,THE_LOSER2$,THE_LOSERS$
Close 1
End Proc
Procedure SET_SCANCODE_CONSTANTS
Restore _SCANCODE_DATA
Read A_SCANCODE,B_SCANCODE,C_SCANCODE,D_SCANCODE,E_SCANCODE,F_SCANCODE
Read G_SCANCODE,H_SCANCODE,I_SCANCODE,J_SCANCODE,K_SCANCODE,L_SCANCODE
Read M_SCANCODE,N_SCANCODE,O_SCANCODE,P_SCANCODE,Q_SCANCODE,R_SCANCODE
Read S_SCANCODE,T_SCANCODE,U_SCANCODE,V_SCANCODE,W_SCANCODE,X_SCANCODE
Read Y_SCANCODE,Z_SCANCODE
Read ESC_SCANCODE,ENTER_SCANCODE,SPACE_SCANCODE
_SCANCODE_DATA:
Data 32,53,51,34,18,35,36,37,23,38,39,40,55,54,24,25,16,19,33,20,22,52,17,50,21,49,69,68,64
End Proc
Procedure COMMENTS__NOT_REALLY_PROC
'UPP = UserPlanPalette ;; SPP = StandardPlanPalette
'========== Banky ===========
' 1 .. Sprite Classic
' 2 .. Icon Font
' 3 .. Music Duning
' 4 .. Icon Digits
' 5 .. Samples Classic
' 7 .. Work Config
' 8 .. Pic Default Plan
' 9 .. Pic Standard Plan
' 10 .. Pic Own Plan
' 12 .. Pic Beau Frame
' 15 .. Track Life Motion
' 16 .. Track Winner music
' 20 .. Ass PutPix
' 21 .. Pic SQLogo ONLY WHEN LOADING
' 22 .. Track SQSound ONLY WHEN LOADING
' 23 .. Sprite FlagAnimation
' 24 .. Ass RecordAndReplay
' 25 .. Ass Strategy & sin+cos picking
' 26 .. Work Precounted sin, sixe 250*4=1000
' 27 .. Work Precounted arctan, angle in smeru units
' 28 .. Work DEF_GAMESET
' 29 .. Work USER_GAMESET
' 30 .. Work GameRecordBank
' 31 .. Work Help Config Bank
'========= Game Record ======
' 0 .. (24) SMERU
' 24 .. (24) XPositions
' 48 .. (24) YPositions
' 72 .. (6) Player on/off
' 78 .. Playing Config - Dark GamePlan & Turbo
' $AE .. This might be record, but it isnt nice size
' $B0 .. Game configuration
' $130 .. Own Record
'========= Options ==========
' Smeru=pocet moznych smeru
' angle_constant#..z toho pocitana konstanta
' line_length..delka cary nez prijde mezera (vcetne predchozi mezery)
' space_length..delka mezery
' speedjump#..procentualni skok rychlosti na kopcich
' rate..rychlost..50-150
' ratemode..0-nezrychlovat rate, 1-zrychlit z 1 na 0 (rate musi byt 2)
' user_rate_length..pocet kol, kdy nezrychlime
' space_kill..1-v mezere se zabiji,0-nezabiji
' bouncing..0-neodrazi,1-odrazi (od okraje)
' central_box..0-neni,1-je central_boxalni box
' central_box_size..radius
' teleporting..vyjizdeni na druhe strane
' _music_on-hudba
' boldline 1-tlusta,0-tenka
'
' plan..0-default,1-standard,2-own
'
'=========== Config =================
' Bank 7
' Offsets:
' 0-flags
' 1-ratemode
' 2-_music_on
' 4-space_kill
' 8-bouncing
' 10-center
' 20-teleporting
' 40-boldline
' 80-turbo (turbolimit)
'
' 1-Directions
' 2-Speedjump
' 3-Spacelen
' 5-line_length
' 7-Speeding lenght
' 9-Cbox radius
' A-Speed
' B-flags2
' 1-watering
' 2-always_turning
' 3-grey gameplan
' C-Water_limit
'
' D-1F free for future
'
End Proc
Procedure DUENIX_REQUEST
If Not Exist(PATH$)
Screen Open 3,320,8,2,Lowres
Flash Off : Curs Off : Hide On
Screen Display 3,,170,320,8
Paper 0 : Pen 1
Palette 0,0
Cls 0
Locate 0,0
Centre INSERT_VOLUME$+PATH$
Fade 2,0,$FF0
Wait 30
Repeat
Until Exist(PATH$)
Fade 2,0,0
Wait 30
Screen Close 3
End If
End Proc
Procedure HANDLE_ERROR
E=Errn
Screen Open 3,640,256,2,Hires : Curs Off
Cls 0 : Paper 0 : Pen 1 : Locate 0,10
If E=_ERROR_BADPATH
Centre "Bad path." : Print : Print
Centre "I guess you have run me from CLI." : Print
Centre "In that case you must run me from directory" : Print
Centre "where I am located." : Print : Print
Centre "You may of course run me from WorkBench." : Print
Else If E=81
Centre _NOT_ALL_FILES$(0) : Print : Print
Centre _NOT_ALL_FILES$(1) : Print : Print
Centre _NOT_ALL_FILES$(2)
Else
Centre "An error has occured:" : Print : Print
Centre Err$(E) : Print : Print
Centre "Sorry."
End If
Fade 1,0,$F5A : Wait Key : Fade 1,0,0 : Wait 10
Erase All : End
End Proc
Procedure WRITE_INITDATA
Restore WRITEDATA
For I=0 To $40-1
Read WRITE_KOI82IMAGE(I)
Next I
For I=0 To $40-1
Read WRITE_KOI82HOOK(I)
Next I
WRITEDATA:
Data 0,97,0,99,100,101,114,0,0,105,117,108,108,0,110,111
Data 111,97,114,115,116,117,0,101,0,121,122,0,0,0,0,0
Data 0,65,0,67,68,69,82,0,0,73,85,76,76,0,78,79
Data 79,65,82,83,84,85,0,69,0,89,90,0,0,0,0,0
Data 0,$61,0,$62,$82,$62,$62,0,0,$61,$63,$81,$83,0,$62,$61
Data $62,$62,$62,$62,$82,$61,0,$61,0,$61,$62,0,0,0,0,0
Data 0,$81,0,$82,$82,$82,$82,0,0,$81,$83,$81,$83,0,$82,$81
Data $82,$82,$82,$82,$82,$81,0,$81,0,$81,$82,0,0,0,0,0
End Proc
Procedure WRITEXY[PRINX,PRINY,PRIN$]
If PRINX>-1 : SFX=PRINX
Else If PRINX=-2 : SFX=160-3*Len(PRIN$) : Rem center
Else If PRINX=-3 : SFX=320-6*Len(PRIN$) : End If : Rem right align
If PRINY>-1 : SFY=PRINY : End If
SFDEL=Len(PRIN$)
If SFDEL=0 : Pop Proc : End If
For SFI=1 To SFDEL
SFCH=Asc(Mid$(PRIN$,SFI,1))
If(SFCH=10) or(SFCH=92) : Rem 92="\"
SFY=SFY+9 : SFX=0
Else
If(SFCH>$C0)
Paste Icon SFX,SFY,WRITE_KOI82IMAGE(SFCH-$C0)-32+1
HOOKNPOSITION=WRITE_KOI82HOOK(SFCH-$C0)
Paste Icon SFX,SFY-(HOOKNPOSITION/$10),(HOOKNPOSITION and $F)+$5B
Else
Paste Icon SFX,SFY,Max(0,SFCH-32)+1
End If
If(SFCH=Asc("l")) : Add SFX,4
Else : Add SFX,6 : End If
If SFX>312 : SFX=0 : SFY=SFY+9 : End If
End If
Next SFI
End Proc
Procedure HELP
Open In 1,LOCALE_PATH$+"Help"
SFY=0
Repeat
Unpack PLAN_BANK(0)
P0=Phybase(0) : P1=Phybase(1) : P2=Phybase(2) : P3=Phybase(3)
Copy P1,P1+10240-1 To P0
Copy P2,P2+10240-1 To P1
Copy P3,P3+10240-1 To P2
Fill P3 To P3+10240-1,0
Palette $0,$101,$201,$301,$402,$502,$602,$702,,,,,,,,,,,,,,,,,$831,$A52,$B62,$C73,$D83,$E94,$F94,$FA5
Repeat
Line Input #1,A$
WRITEXY[0,-1,A$+"\"]
Until Eof(1) or SFY>(256-10)
Clear Key
Repeat
A$=Lower$(Inkey$)
ESC=Key State(ESC_SCANCODE)
Until(A$<>"") or ESC
FAST_FADE_OUT
Cls 0 : SFY=0
Until Eof(1) or ESC
Close 1
End Proc
Procedure INIT_PUTPIX_STRATEGY_SIN_ATAN
Screen 1
For I=0 To 4
Loke BITPLAN_BASE+I*4,Phybase(I)
Next I
Loke VA_PQ_X,Varptr(_PUTPIX_QUEUE_X(0))
Loke VA_PQ_Y,Varptr(_PUTPIX_QUEUE_Y(0))
Loke VA_PQ_COL,Varptr(_PUTPIX_QUEUE_COLOUR(0))
Loke VA_PQ_TOP,Varptr(_PUTPIX_QUEUE_TOP)
Loke VA_BITPLAN4,Phybase(4)
Loke VA_SIN_TABLE,Start(26)
Loke VA_DIRECTIONS,SMERU
Loke VA_DIRSTEP0,SMERU*0.08
Loke VA_DIRSTEP1,SMERU*0.16
Loke VA_DIRSTEP2,SMERU*0.26
Loke VA_DIRSTEP3,SMERU*0.32
Loke VA_DIRSTEP4,SMERU*0.38
Loke VA_ATAN_TABLE,Start(27)
Loke VA_XHASH,Varptr(X#(1))
Loke VA_YHASH,Varptr(Y#(1))
Loke VA_PLAYERSDIR,Varptr(SMER(1))
Loke VA_PLAYERALIVE,Varptr(SEMIALIVE(1))
Loke VA_PLAYERSCHOICE,0
Doke VA_PLAYERSCHOICE+4,0
Poke VA_TURN,0
' Poke VA_BIGSCREEN,BIG_SCREEN
Poke VA_BIGSCREEN,Sgn(_SCREEN_SIZE)
ANGLE_CONSTANT#=2*Pi#/SMERU : Rem Userdirs=smeru/4 by the way
' ________________________________
' | |
' | Sin |
' |________________________________|
For I=0 To USER_DIRECTIONS
LOCAL#=Sin(ANGLE_CONSTANT#*I)
Loke Start(26)+4*I,Leek(Varptr(LOCAL#))
Next I
' ________________________________
' | |
' | Atan |
' |________________________________|
For I=0 To 256
I#=I
LOC#=I#/256
AN=Atan(LOC#)/ANGLE_CONSTANT#
Poke Start(27)+I,AN
Next I
End Proc
' ________________________________________
' | \
' | Begin actions, configuration n dialogs \
' |__________________________________________\
Procedure _GET_IMAGES
On Error Proc HANDLE_ERROR
' ________________________________
' | |
' | GET FLAG ANIMATION |
' |________________________________|
Screen Open 2,320,256,16,Lowres
Screen To Front 1
Load Iff PATH$+"Flag"
For J=0 To 2
For I=0 To 3
Get Sprite J*4+I+1,I*32,J*24 To(I+1)*32,(J+1)*24
Next I
Next J
Bank Swap 1,23
' ________________________________
' | |
' | GET HEAD SPRITES |
' |________________________________|
' Sprites 1,2,5,6 are 4 col, 1,2 are small while 5,6 are big
' Sprites 3,4,7,8 are 16 col, 3,4 are small while 7,8 are big
Ink 3 : Bar 0,0 To 1,1 : Get Sprite 7,0,0 To 2,2 : Get Sprite 3,0,0 To 1,1
Ink 4 : Bar 0,0 To 1,1 : Get Sprite 8,0,0 To 2,2 : Get Sprite 4,0,0 To 1,1
Screen Close 2
Screen Open 2,320,256,4,Lowres
Screen To Front 1
Load Iff PATH$+"Lateral"
Get Sprite LATERAL_LEFT,0,0 To 5,218
Get Sprite LATERAL_RIGHT,5,0 To 5+5,218
Ink 1 : Bar 0,0 To 1,1 : Get Sprite 5,0,0 To 2,2 : Get Sprite 1,0,0 To 1,1
Ink 2 : Bar 0,0 To 1,1 : Get Sprite 6,0,0 To 2,2 : Get Sprite 2,0,0 To 1,1
' ________________________________
' | |
' | 32 colour images |
' |________________________________|
Screen Open 2,320,256,32,Lowres
Flash Off : Curs Off : Hide On
Screen To Front 1
Ink $13 : Bar 0,0 To 1,1 : Get Sprite _BOB_PLAYER_IMAGE(0,1),0,0 To 2,2
Get Sprite _BOB_PLAYER_IMAGE(0,0),0,0 To 1,1
Ink $14 : Bar 0,0 To 1,1 : Get Sprite _BOB_PLAYER_IMAGE(1,1),0,0 To 2,2
Get Sprite _BOB_PLAYER_IMAGE(1,0),0,0 To 1,1
' =========================================
' = 12 X =
' = 13 cervik =
' = 20,21 Yellow fajfky =
' = 22 box =
' = 32 computer =
' = 47 cyborg =
' =========================================
Load Iff PATH$+"Graphics"
Get Sprite 12,160,0 To 160+40,20
Get Sprite 13,160,20 To 160+40,20+20
Get Sprite DUENIX_TITLE_IMAGE,0,154 To 205,154+26+3
Get Sprite DUENIX_ANIM_IMAGE,0,200 To 0+48,200+32
Get Sprite 16,0,22+36+2 To 153,22+36+18
Get Sprite 17,0,22+36+18 To 153,22+36+18+18
Get Sprite MOUSE_ON_LINE_IMAGE,0,99 To 50,125
Get Sprite _JOY_ON_LINE_IMAGE,50,99 To 100,125
For I=0 To 2
Get Sprite NO_IMAGE(I),35*I,0 To 35*I+35,17
Get Sprite YES_IMAGE(I),35*I,17 To 35*I+35,2*17
Get Sprite RED_BOX_IMAGE(I),35*I,2*17 To 35*I+35,3*17
Next I
Get Sprite 32,160,40 To 160+40,40+20
Get Sprite 47,160,60 To 160+40,60+20
Get Sprite SCORE_PANEL_BACKGROUND_IMAGE,0,55 To 40,55+40
Get Sprite HORIZONTAL_WOOD_IMAGE,0,256-4 To 160,256
Get Sprite CORNER_WOOD_IMAGE,160,256-4 To 160+9,256
Get Sprite VERTICAL_WOOD_IMAGE,320-4,0 To 320,256-30-2*4
Get Sprite NOSCROLL_CORNER_IMAGE,160+10,256-4 To 160+10+4,256
' ___________________________
' | |
' | .--------------. |
' | Box | 23 | 24 | 25 | |
' | Systems |----+----+----| |
' | | 26 | 27 | 28 | |
' | |----+----+----| |
' | | 29 | 30 | 31 | |
' | `--------------' |
' |___________________________|
Get Sprite 23,0,127 To 0+16,127+8
Get Sprite 24,0+16,127 To 0+16+16,127+8
Get Sprite 25,0+16+16,127 To 0+16+16+16,127+8
Get Sprite 26,0,127+8 To 0+16,127+8+8
Get Sprite 27,0+16,127+8 To 0+16+16,127+8+8
Get Sprite 28,0+16+16,127+8 To 0+16+16+16,127+8+8
Get Sprite 29,0,127+8+8 To 0+16,127+8+8+8
Get Sprite 30,0+16,127+8+8 To 0+16+16,127+8+8+8
Get Sprite 31,0+16+16,127+8+8 To 0+16+16+16,127+8+8+8
' ________________________________
' | |
' | logo anim 33-46 |
' |________________________________|
BASE=Phybase(4)
Fill BASE To BASE+10239,0
For I=1 To 14
Get Sprite 32+I,(I-1)*20,182 To I*20-1,182+18
Next I
' ________________________________
' | |
' | Press space |
' |________________________________|
Load Iff LOCALE_PATH$+"PressSpace"
Get Sprite PRESS_SPACE_IMAGE,0,0 To 53,33
Screen 1
End Proc
Procedure _GET_ICONS_FROM_SCOREIMAGES
Screen Open 2,320,256,16,Lowres
Screen To Front 1
Load Iff PATH$+"scorepanel"
Get Icon 1,0,0 To 320,30
Get Icon 2,0,30 To 320,30+30
For I=0 To 10+6-1
Get Icon 3+I,20*I,83 To 20*(I+1),83+24
Next I
Get Icon 19,0,108 To 0+55,108+30
Get Icon 20,55,108 To 55+10,108+4
Make Icon Mask
Screen Close 2
End Proc
Procedure _PROC_SHOW_SQ_LOGO
DUENIX_REQUEST
Load PATH$+"SQLogo",21
Track Load PATH$+"SQSound",22
Screen Open 2,320,256,64,EHB
Flash Off : Curs Off : Hide On
Unpack 21
Fade 3,$0,$741,$270,$255,$E80,$424,$550,$565,$4A0,$290,$5C0,$5F5,$C20,$A10,$A60,$954,$E30,$F40,$878,$B90,$AA5,$BC0,$AF5,$EA0,$FC1,$FF1,$FF5,$AA9,$ADA,$C98,$FFA,$FFE
Track Play 22
PAUSED=_FALSE
Timer=0 : Repeat
If Key State(P_SCANCODE)
PAUSED=_TRUE
End If
Until Timer>50*6
Track Stop
If PAUSED
Clear Key : Wait Key
End If
Fade 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Wait 50
Screen Close 2
Erase 22 : Erase 21
End Proc
Procedure SEND_MONEY
Screen Open 2,320,256,32,Lowres
Flash Off : Curs Off : Hide On
Cls 0
WRITEXY[0,9*2,CZ_SEND$+"\\"+_ADDRESS$+"\"]
WRITEXY[0,130,EN_SEND$+"\"+_ADDRESS$+"\ Czech Republic\\"+EN_VALUE$]
Ink $12,0 : Set Font FONT_NUMBER
Text 10*10,128-4-4,RELEASE$
BASE=Phybase(4) : Fill BASE+5120 To BASE+10239,0
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$A07,$B18,$C29,$D3A,$E49,$F59,$F69,$F78,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$223,$334,$557,$779,$99A,$AAB,$CCC,$DDD
Clear Key
Repeat
PRESS$=Inkey$ : PRESS$=Lower$(PRESS$)
Until PRESS$<>""
_SHOW_SQ_LOGO= Not(Scancode=ESC_SCANCODE)
Fade 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Wait 15
Screen Close 2
End Proc
Procedure _ASK_FOR_LANGUAGE
Screen Open 2,320,256,32,Lowres
Flash Off : Curs Off : Hide On
Cls 0
WRITEXY[0,9*2,"Zvol si prosÉm jazyk:\\ C: ăeÓtina\ E: AngliĂtina\"]
WRITEXY[-1,130,"Select the language please:\\ C: Czech\ E: English\"]
BASE=Phybase(4)
Fill BASE+5120 To BASE+10239,0
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$A07,$B18,$C29,$D3A,$E49,$F59,$F69,$F78,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$223,$334,$557,$779,$99A,$AAB,$CCC,$DDD
Clear Key
Repeat
PRESS$=Inkey$ : PRESS$=Lower$(PRESS$)
Until PRESS$="c" or PRESS$="e"
If PRESS$="c"
LOCALE_PATH$=PATH$+"czech_files/"
Else
LOCALE_PATH$=PATH$+"english_files/"
End If
Fade 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Wait 15
Screen Close 2
End Proc
Procedure BEGIN_LOADING
On Error Proc HANDLE_ERROR
If Not Exist(PATH$+"Duenix.info")
Error _ERROR_BADPATH
End If
LOCALE_PATH$=""
If Exist(PATH$+"Language")
Open In 1,PATH$+"Language"
Line Input #1,LANGUAGE$
Close 1
LOCALE_PATH$=PATH$+LANGUAGE$+"_files/"
If Not Exist(LOCALE_PATH$)
LOCALE_PATH$=""
End If
End If
If _COMPILED or _LOAD_DUENIX_FONT
' ________________________________
' | |
' | Load textfont |
' |________________________________|
Exec "Makedir T:tempfonts"
Exec "Copy Fonts:Duenix.font T:tempfonts"
Exec "Assign ofonts: fonts:"
Exec "Assign fonts: T:tempfonts"
Get Fonts
Exec "Assign fonts: ofonts:"
Exec "Assign ofonts:"
Exec "Delete T:tempfonts"
FONT_NUMBER=0
Repeat
Inc FONT_NUMBER
CURRENTFONT$=Lower$(Left$(Font$(FONT_NUMBER),11))
Until CURRENTFONT$="" or CURRENTFONT$="duenix.font"
If CURRENTFONT$=""
If LOCALE_PATH$=""
LOCALE_PATH$=PATH$+"english_files/"
End If
SET_TEXT_CONSTANTS
Screen Open 3,640,256,2,Hires : Curs Off
Cls 0 : Paper 0 : Pen 1 : Locate 0,10
Centre _NOT_FONT$ : Print : Print : Centre _NOT_ALL_FILES$(1)
Print : Print : Centre _NOT_ALL_FILES$(2)
Fade 1,0,$F5A : Wait Key : Fade 1,0,0 : Wait 14
Screen Close 3 : Erase All : End
Else
Set Font FONT_NUMBER
End If
End If
_TRUE=Asc(Mid$(_ADDRESS$,36,1))-50
_FALSE=Len(_ADDRESS$)-59
DUENIX_REQUEST
_GET_ICONS_FROM_SCOREIMAGES
Bank Swap 4,2
Load PATH$+"Font",2 : Make Icon Mask
If _COMPILED
SEND_MONEY
If _SHOW_SQ_LOGO
If LOCALE_PATH$=""
_ASK_FOR_LANGUAGE
End If
_PROC_SHOW_SQ_LOGO
End If
If LOCALE_PATH$=""
LOCALE_PATH$=PATH$+"czech_files/"
End If
Else
LOCALE_PATH$=PATH$+"czech_files/"
End If
' ________________________________
' | |
' | The Rest |
' |________________________________|
SET_TEXT_CONSTANTS
If _COMPILED
Cls 0
WRITEXY[-2,124,_LOADING$]
SELECTING_FADE_UP
End If
DUENIX_REQUEST
Pload PATH$+"PutPixel",20
Pload PATH$+"RecordAndReplay",24
Pload PATH$+"Strategy",25
Reserve As Work PRECOUNTED_SIN__BANK,1004
Reserve As Work PRECOUNTED_ATAN__BANK,$101
' __________________________________
' | |
' | Setting CatchPoints of Assembler |
' |__________________________________|
A20=Start(20)
BITPLAN_BASE=A20 : Add A20,$20
VA_PQ_X=A20 : Add A20,4
VA_PQ_Y=A20 : Add A20,4
VA_PQ_COL=A20 : Add A20,4
VA_PQ_TOP=A20 : Add A20,4
VA_PUTPIX_TYPE=A20 : Add A20,4
PA_DRAW_PIXEL_QUEUE=A20 : Add A20,4
PA_SMALL_PIX=A20 : Add A20,4
PA_BIG_PIX=A20 : Add A20,4
PA_SMALL_PIX_BIGSCREEN=A20 : Add A20,4
PA_BIG_PIX_BIGSCREEN=A20 : Add A20,4
VA_PLAYER_RECORD=Start(24)
VA_GAME_RECORD=Start(24)+4
VA_GAME_RECORD_POINTER=Start(24)+8
PA_SAVE_POSITION=Start(24)+$C
PA_LOAD_POSITION=Start(24)+$10
A25=Start(25)
VA_BITPLAN4=A25 : Add A25,4
VA_SIN_TABLE=A25 : Add A25,4
VA_ATAN_TABLE=A25 : Add A25,4
VA_DIRECTIONS=A25 : Add A25,4
VA_DIRSTEP0=A25 : Add A25,4
VA_DIRSTEP1=A25 : Add A25,4
VA_DIRSTEP2=A25 : Add A25,4
VA_DIRSTEP3=A25 : Add A25,4
VA_DIRSTEP4=A25 : Add A25,4
VA_ROTATION=A25 : Add A25,4
VA_DIRECTION=A25 : Add A25,4
VA_XAMOSREAL=A25 : Add A25,4
VA_YAMOSREAL=A25 : Add A25,4
VA_PLAYER=A25 : Add A25,4
VA_XHASH=A25 : Add A25,4
VA_YHASH=A25 : Add A25,4
VA_PLAYERSDIR=A25 : Add A25,4
VA_PLAYERALIVE=A25 : Add A25,4
VA_PLAYERSCHOICE=A25 : Add A25,6
VA_TURN=A25 : Add A25,1
VA_BIGSCREEN=A25 : Add A25,1
PA_STRATEGY=A25 : Add A25,4
PA_COUNTSINANDCOS=A25 : Add A25,4
PA_COUNTTESTANDSPEEDPOINTS_1PIX=A25 : Add A25,4
PA_COUNTTESTANDSPEEDPOINTS_2PIX=A25 : Add A25,4
' ________________________________
' | |
' | Continue |
' |________________________________|
Track Load PATH$+"LifeMotion",LIFE_MOTION_MUSIC__BANK
_GET_IMAGES
If _COMPILED
For I=1 To 6
A$=PATH$+"Plan"+(Str$(I)-" ")
If Not Exist(A$) : Error 81 : End If : Rem NOT ALL FILES
Next I
End If
Load PATH$+"PlanDef",PLAN_BANK(0)
Load PATH$+"Plan1",PLAN_BANK(1)
DUENIX_REQUEST
_LOAD_CONFIGURATION[3] : Rem AT STARTUP
Load PATH$+"Default_Gameset",DEF_GAMESET__BANK
BASE=Start(DEF_GAMESET__BANK)
For I=0 To 19
OFFSET=Deek(BASE+2*I)
If OFFSET=0
GS_GAME_NAME$(I,0)="Level"+Str$(I-10+1)
Else
GS_GAME_NAME$(I,0)=Peek$(BASE+OFFSET,16)
End If
Next I
If Exist(PATH$+"User_Gameset")
Load PATH$+"User_Gameset",USER_GAMESET__BANK
BASE=Start(USER_GAMESET__BANK)
For I=0 To 19
OFFSET=Deek(BASE+2*I)
If OFFSET=0
GS_GAME_NAME$(I,1)="Empty"
Else
GS_GAME_NAME$(I,1)=Peek$(BASE+OFFSET,16)
End If
Next I
End If
' _________________________________________
' | |
' | Not neccessary, only when enough memory |
' |_________________________________________|
If(Chip Free>28000+128000)
Load PATH$+"Samples",5
ENABLED_SOUND=True
Else
If Not Exist(PATH$+"Samples") : Error 81 : End If : Rem NOT ALL FILES
ENABLED_SOUND=False
End If
If Chip Free>19000+128000
GAME_MUSIC_IN_CHIP_RAM=True
Load PATH$+"Duming",3
Else
GAME_MUSIC_IN_CHIP_RAM=False
End If
If Chip Free>30000+128000
GAME_MUSIC_IN_CHIP_RAM=True
Track Load PATH$+"WinnerMusic",WINNER_MUSIC__BANK
Else
If Not Exist(PATH$+"WinnerMusic") : Error 81 : End If : Rem _NOT_ALL_FILES
GAME_MUSIC_IN_CHIP_RAM=False
End If
RECORDING_ALLOWED=False
If(Chip Free+Fast Free)>10000+128000
Reserve As Work 30,10000
RECORDING_ALLOWED=True
Loke VA_PLAYER_RECORD,Varptr(_PLAYER_RECORD(0))
Loke VA_GAME_RECORD_POINTER,0
RECORD_BASE=Start(30)
RECORD_MOVEMENTS_START=RECORD_BASE+$130
Loke VA_GAME_RECORD,RECORD_MOVEMENTS_START
GAME_RECORD_EMPTY=True
End If
If _COMPILED
Fade 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Wait 30
Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
End If
If _COMPILED or _LOAD_DUENIX_FONT
Screen 2
Set Font FONT_NUMBER
Screen 1
End If
' ________________________________
' | |
' | Now change the plan |
' |________________________________|
SET_PLAN_USING_CONFIG[True]
Track Loop Of
If _MUSIC_ON
Track Play LIFE_MOTION_MUSIC__BANK
End If
End Proc
Procedure SET_PLAN_USING_CONFIG[LONG_TERMED]
If PLAN=1
Trap Load PATH$+"Plan"+Str$(GAMEPLAN)-" ",PLAN_BANK(1)
End If
If PLAN=1
SET_SPP
End If
If LONG_TERMED or PLAN=2
If OWN_PLAN_PATH$<>""
OWN_PLAN_LOAD[OWN_PLAN_PATH$,False]
Else
If(LONG_TERMED=False) and(Length(PLAN_BANK(2))>0)
Erase PLAN_BANK(2)
End If
For I=0 To $F
UPP(I)=0
Next I
End If
End If
End Proc
Procedure _DECONFIG[BASE,FROM_SET]
SHORT_CONFIG=-Peek(BASE)
USER_DIRECTIONS=Peek(BASE+1)
SMERU=USER_DIRECTIONS*4
ANGLE_CONSTANT#=2*Pi#/SMERU
SMERU_QUARTER=USER_DIRECTIONS
SMERU_HALVE=USER_DIRECTIONS*2
SPEEDJUMP=Peek(BASE+2)
SPACE_LENGTH=Deek(BASE+3)
_DRAWING_LINE_LENGTH=Deek(BASE+5)
LINE_LENGTH=SPACE_LENGTH+_DRAWING_LINE_LENGTH+20
USER_RATE_LENGTH=Deek(BASE+7)
CENTRAL_BOX_SIZE=Peek(BASE+9)
FINAL_RATE=Peek(BASE+$A)
FLAGS=Peek(BASE+$B)
WATERING=FLAGS and $1
ALWAYS_TURNING=FLAGS and $2 : Ror.b 1,ALWAYS_TURNING
USER_SOUND_FX=FLAGS and $4 : Ror.b 2,USER_SOUND_FX
COMPUDEATH=FLAGS and $8 : Ror.b 3,COMPUDEATH
TEAM_GAME=FLAGS and $10 : Ror.b 4,TEAM_GAME
TEAM_GAME=-TEAM_GAME
LONG_GAME=FLAGS and $20 : Ror.b 5,LONG_GAME
COMPUTURBO=FLAGS and $40 : Ror.b 6,COMPUTURBO
SURPRISING_START=FLAGS and $80 : Ror.b 7,SURPRISING_START
WATER_LIMIT=Peek(BASE+$C)
WATER_LIMIT#=WATER_LIMIT*Pi#/180
' LIVES_TOP=Peek(BASE+$D)
PLAN=Peek(BASE+$E)
GAMEPLAN=Peek(BASE+$F)
FLAGS=Peek(BASE+$10)
RATEMODE=FLAGS and 1
_MUSIC_ON=FLAGS and 2 : Ror.b 1,_MUSIC_ON
SPACE_KILL=FLAGS and 4 : Ror.b 2,SPACE_KILL
BOUNCING=FLAGS and 8 : Ror.b 3,BOUNCING
CENTRAL_BOX=FLAGS and $10 : Ror.b 4,CENTRAL_BOX
TELEPORTING=FLAGS and $20 : Ror.b 5,TELEPORTING
BOLDLINE=FLAGS and $40 : Ror.b 6,BOLDLINE
TURBO=(FLAGS and $80) : Ror.b 7,TURBO
FLAGS=Peek(BASE+$11)
WIND=FLAGS and 1
BODY_CHANGE=FLAGS and 2 : Ror.b 1,BODY_CHANGE
ZOMBIES=FLAGS and 4 : Ror.b 2,ZOMBIES
WIND_STRENGTH=Peek(BASE+$12)
_SCREEN_SIZE=Peek(BASE+$13)
BODY_CHANGE_PERCENT=Peek(BASE+$14)
SET_APPROPRIATE_DRAWPIXEL_PROC
If Not FROM_SET
PATH_S_LEN=Peek(BASE+$20)
If PATH_S_LEN<$60
OWN_PLAN_PATH$=Peek$(BASE+$21,PATH_S_LEN)
Else
_LOAD_CONFIGURATION[0] : Rem BUILTIN
End If
End If
' ________________________________
' | |
' | Is It Configuration ?! |
' |________________________________|
FCONFIG=0 : Rem False configuration bool
FCONFIG=FCONFIG or(PLAN>2) or(GAMEPLAN<1) or(GAMEPLAN>6) or(WATERING+TELEPORTING+BOUNCING>1)
FCONFIG=FCONFIG or(SPEEDJUMP>95) or(USER_RATE_LENGTH>999) or(CENTRAL_BOX_SIZE>80) or(CENTRAL_BOX_SIZE<10)
FCONFIG=FCONFIG or(FINAL_RATE>100) or(_SCREEN_SIZE>2)
FCONFIG=FCONFIG or(USER_DIRECTIONS<5) or(USER_DIRECTIONS>250) or(SPACE_LENGTH>999) or(_DRAWING_LINE_LENGTH>999)
If FCONFIG
_LOAD_CONFIGURATION[0] : Rem BUILTIN
End If
End Proc
Procedure CONFIG[BASE,FROM_SET]
OWN_PLAN_PATH$=Left$(OWN_PLAN_PATH$,$5F)
Poke BASE,-SHORT_CONFIG
Poke BASE+1,USER_DIRECTIONS
Poke BASE+2,SPEEDJUMP
Doke BASE+3,SPACE_LENGTH
Doke BASE+5,_DRAWING_LINE_LENGTH
Doke BASE+7,USER_RATE_LENGTH
Poke BASE+9,CENTRAL_BOX_SIZE
Poke BASE+$A,FINAL_RATE
FLAGS=WATERING
Add FLAGS,2*ALWAYS_TURNING
Add FLAGS,4*USER_SOUND_FX
Add FLAGS,8*COMPUDEATH
Add FLAGS,-$10*TEAM_GAME
Add FLAGS,$20*LONG_GAME
Add FLAGS,$40*COMPUTURBO
Add FLAGS,$80*SURPRISING_START
Poke BASE+$B,FLAGS
Poke BASE+$C,WATER_LIMIT
Poke BASE+$D,LIVES_TOP
Poke BASE+$E,PLAN
Poke BASE+$F,GAMEPLAN
FLAGS=RATEMODE
Add FLAGS,2*_MUSIC_ON
Add FLAGS,4*SPACE_KILL
Add FLAGS,8*BOUNCING
Add FLAGS,$10*CENTRAL_BOX
Add FLAGS,$20*TELEPORTING
Add FLAGS,$40*BOLDLINE
Add FLAGS,$80*TURBO
Poke BASE+$10,FLAGS
FLAGS=WIND
Add FLAGS,2*BODY_CHANGE
Add FLAGS,4*ZOMBIES
Poke BASE+$11,FLAGS
Poke BASE+$12,WIND_STRENGTH
Poke BASE+$13,_SCREEN_SIZE
Poke BASE+$14,BODY_CHANGE_PERCENT
If Not FROM_SET
Poke BASE+$20,Len(OWN_PLAN_PATH$)
Poke$ BASE+$21,OWN_PLAN_PATH$
End If
End Proc
Procedure _LOAD_CONFIGURATION[WHAT]
If(WHAT=0) or(WHAT=3) : Rem 3 means at StartUp
' ________________________________
' | |
' | Builtin |
' |________________________________|
USER_DIRECTIONS=18
SMERU=USER_DIRECTIONS*4 : ANGLE_CONSTANT#=2*Pi#/SMERU
SMERU_QUARTER=USER_DIRECTIONS : SMERU_HALVE=USER_DIRECTIONS*2
_DRAWING_LINE_LENGTH=100
SPACE_LENGTH=10 : LINE_LENGTH=SPACE_LENGTH+_DRAWING_LINE_LENGTH+20
SPEEDJUMP=60
RATE=100
RATEMODE=1
USER_RATE_LENGTH=500
FINAL_RATE=100
SPACE_KILL=1
BOUNCING=0
TELEPORTING=0
_MUSIC_ON=1
BOLDLINE=1 : SET_APPROPRIATE_DRAWPIXEL_PROC
PLAN=0
CENTRAL_BOX=0
CENTRAL_BOX_SIZE=50
XBOTTOM=145-CENTRAL_BOX_SIZE : XTOP=146+CENTRAL_BOX_SIZE
YBOTTOM=127-CENTRAL_BOX_SIZE : YTOP=128+CENTRAL_BOX_SIZE
TURBOLIMIT=0
WATERING=1
WATER_LIMIT=75 : WATER_LIMIT#=WATER_LIMIT*Pi#/180
ALWAYS_TURNING=0
SURPRISING_START=1
BODY_CHANGE=1
BODY_CHANGE_PERCENT=80
COMPUDEATH=1
ZOMBIES=0
PLAN=0
GAMEPLAN=1
End If
If WHAT=3
' ________________________________
' | |
' | At startup |
' |________________________________|
Trap If Exist(PATH$+"Config")
Trap Load PATH$+"Config",7
If Length(7)>=$80
_DECONFIG[Start(7),False]
End If
End If
Else If WHAT=1
' ________________________________
' | |
' | Default |
' |________________________________|
DUENIX_REQUEST
If Exist(PATH$+"Config")
Trap Load PATH$+"Config",7
If Not((Length(7)=$80))
HALFWAITING_DIALOG[DUENIX_CONFIG_ISNT_CONFIG$,OPERATION_ABORTED$,""]
Else
_DECONFIG[Start(7),False]
HALFWAITING_DIALOG["",DEF_CONFIG_LOADED$,""]
End If
Else
HALFWAITING_DIALOG[CANT_FIND_DEF_CONFIG1$,CANT_FIND_DEF_CONFIG2$,""]
End If
Else If WHAT=2
' ________________________________
' | |
' | Other |
' |________________________________|
Screen 1
Show On
Change Mouse 1
Trap A$=Fsel$(PATH$+"","",ENTER_CONFIGNAME$)
Hide On
If Exist(A$)
Trap Load A$,7
If(Length(7)<>$80)
HALFWAITING_DIALOG[THIS_FILE_ISNT_CONFIG$,OPERATION_ABORTED$,""]
Else
_DECONFIG[Start(7),False]
HALFWAITING_DIALOG["",CONFIG_LOADED$,""]
End If
Else
HALFWAITING_DIALOG["",FILE_DOESNT_EXIST$,""]
End If
End If
Erase 7
End Proc
Procedure _SAVE_CONFIGURATION[WHAT]
If WHAT=0
' ________________________________
' | |
' | Default |
' |________________________________|
CONFIG_LENGTH=$80
Reserve As Work 7,CONFIG_LENGTH
CONFIG[Start(7),False]
DUENIX_REQUEST
Trap Save PATH$+"Config",7
HALFWAITING_DIALOG[CONFIG_SAVED_AS_DEF1$,CONFIG_SAVED_AS_DEF2$,""]
Else
' ________________________________
' | |
' | Other |
' |________________________________|
CONFIG_LENGTH=$80
Reserve As Work 7,CONFIG_LENGTH
CONFIG[Start(7),False]
Screen 1
Show On
Change Mouse 1
A$=Fsel$(PATH$+"","",ENTER_NAME_OF_CONFIG_TO_SAVE$)
Hide On
If Exist(A$)
_DIALOGBEG
B$=THIS_FILE_ALREADY_EXISTS$ : Text 160-4*Len(B$),14*8+6,B$
B$=WANT_TO_OVERWRITE$ : Text 160-4*Len(B$),15*8+6,B$
Repeat
B$=Lower$(Inkey$)
Until(B$="y") or(B$="n")
_DIALOGEND
If B$="y"
Trap Save A$,7
HALFWAITING_DIALOG["",CONFIG_SAVED$,""]
Else
HALFWAITING_DIALOG["",CONFIG_NOT_SAVED$,""]
End If
Else
Trap Save A$,7
If A$="" : HALFWAITING_DIALOG["",CONFIG_NOT_SAVED$,""]
Else : HALFWAITING_DIALOG["",CONFIG_SAVED$,""] : End If
End If
End If
Erase 7
End Proc
Procedure _DIALOGBEG
Screen 1 : Get Block 1,0,104,320,50
Screen 2 : Put Block 1,0,0 : Rem STORE UNDERDIALOG
Paste Bob 0+32,104,BS_LEFT_TOP
For I=1 To 14 : Paste Bob I*16+32,104,BS_MIDDLE_TOP : Next I
Paste Bob 320-16-32,104,BS_RIGHT_TOP
For J=1 To 3
J_OFFSET=8*J
Paste Bob 0+32,104+8*J,BS_LEFT_MIDDLE
For I=1 To 14 : Paste Bob I*16+32,104+J_OFFSET,BS_MIDDLE_MIDDLE : Next I
Paste Bob 320-16-32,104+8*J,BS_RIGHT_MIDDLE
Next J
Paste Bob 0+32,104+8*4,BS_LEFT_BOTTOM
For I=1 To 14 : Paste Bob I*16+32,104+8*4,BS_MIDDLE_BOTTOM : Next I
Paste Bob 320-16-32,104+8*4,BS_RIGHT_BOTTOM
Get Block 1,0,104,320,50,1 : Screen 1
Put Block 1,0,104
Del Block 1
Ink $11,$15
End Proc
Procedure _DIALOGEND
Screen 2 : Get Block 1,0,0,320,50 : Screen 1
Wait Vbl : Put Block 1,0,104
Del Block 1
End Proc
Procedure HALFWAITING_DIALOG[HW_T1$,HW_T2$,HW_T3$]
_DIALOGBEG
Text 160-4*Len(HW_T1$),14*8+6,HW_T1$
Text 160-4*Len(HW_T2$),15*8+6,HW_T2$
Text 160-4*Len(HW_T3$),16*8+6,HW_T3$
Wait 5 : Clear Key : Timer=0
Repeat
A$=Inkey$
Until A$<>"" or Timer>50*6
Clear Key
_DIALOGEND
Wait 10 : Clear Key
End Proc
' ______________________________________
' | \
' | Options \
' |________________________________________\
Procedure MAKE_OPTIONS_BACKGROUND[PAGE_NUMBER$,PAGE_NAME$]
Screen 1
Cls 0
Unpack PLAN_BANK(0)
Screen 2
Cls 0
Paste Bob 35,1,DUENIX_TITLE_IMAGE
WRITEXY[5,12,PAGE_NUMBER$]
WRITEXY[316-6*Len(PAGE_NAME$),12,PAGE_NAME$]
End Proc
Procedure BOOL_OPTION[BO_SIGN,BO_I,BO_COLUMN]
If BO_SIGN=0 Then IMAGE=NO_IMAGE(OS_LC_BOX(BO_I)) Else IMAGE=YES_IMAGE(OS_LC_BOX(BO_I))
Paste Bob 152*BO_COLUMN+116+6,8*(2*BO_I+1)-4,IMAGE
End Proc
Procedure NUMBER_OPTION[NO_NUMBER,NO_NUMBER_SIZE,NO_HIGHLITE,NO_I,NO_COLUMN]
Ink $13,$15
If NO_HIGHLITE=_FALSE : Ink $16 : End If
A$=Str$(NO_NUMBER)-" " : A$=String$("0",NO_NUMBER_SIZE-Len(A$))+A$
Text 152*NO_COLUMN+8*(19-NO_NUMBER_SIZE),8*(NO_I*2+1)+6,A$
End Proc
Procedure DEPENDENT_OPTION[DEO_SIGN,DEO_NUMBER,DEO_NUMBER_SIZE,DEO_YPOS,DEO_COLUMN]
If DEO_SIGN=0 Then IMAGE=NO_IMAGE(OS_LC_BOX(DEO_YPOS)) Else IMAGE=YES_IMAGE(OS_LC_BOX(DEO_YPOS))
Paste Bob 152*DEO_COLUMN+116+6,8*(2*DEO_YPOS+1)-4,IMAGE
Ink $13,$15
If DEO_SIGN=_FALSE : Ink $16 : End If
A$=Str$(DEO_NUMBER)-" " : A$=String$("0",DEO_NUMBER_SIZE-Len(A$))+A$
Text 152*DEO_COLUMN+8*(19-DEO_NUMBER_SIZE),8*(DEO_YPOS*2+1+2)+6,A$
End Proc
Procedure _GET_3NUMBER[G3X,G3Y]
Clear Key : Wait 5
G3NUMBER=0
G3C=100
For I=0 To 2
Ink $0,$13
Text 8*(G3X+I),8*G3Y+6," "
Ink $13,$15
Repeat
A$=Inkey$
A=Asc(A$)
Until(A>47) and(A<58)
Text 8*(G3X+I),8*G3Y+6,A$-" "
Add G3NUMBER,G3C*(A-48)
G3C=G3C/10
Next I
End Proc[G3NUMBER]
Procedure OPTIONS_MAIN
If _NOT(E_THRU or G_THRU or R_THRU)
OPTIONS_MAIN_RESTORE_SCREEN
End If
ESC_QUITED=False
Clear Key
Repeat
If Key State(L_SCANCODE)
_LOAD_CONFIGURATION[1] : Rem DEFAULT
End If
If Key State(S_SCANCODE)
_SAVE_CONFIGURATION[0] : Rem DEFAULT
End If
If Key State(Z_SCANCODE)
_LOAD_CONFIGURATION[2] : Rem OTHER
End If
If Key State(X_SCANCODE)
_SAVE_CONFIGURATION[1] : Rem OTHER
End If
If Key State(E_SCANCODE) or E_THRU
If Not E_THRU
FAST_FADE_OUT
End If
E_THRU=False
OPTIONS_GAMESETTINGS
If Not ESC_QUITED
OPTIONS_GAMESETTINGS2
If Not ESC_QUITED
OPTIONS_MAIN_RESTORE_SCREEN
End If
End If
End If
If Key State(G_SCANCODE) or G_THRU
If Not G_THRU
FAST_FADE_OUT
End If
G_THRU=False
OPTIONS_GAMEPLAN
If Not ESC_QUITED
OPTIONS_MAIN_RESTORE_SCREEN
End If
End If
If Key State(R_SCANCODE) or R_THRU
If Not R_THRU
FAST_FADE_OUT
End If
R_THRU=False
OPTIONS_RECORD_AND_REPLAY
If Not ESC_QUITED
OPTIONS_MAIN_RESTORE_SCREEN
End If
End If
If Key State(U_SCANCODE)
FAST_FADE_OUT
OPTIONS_USER_GAMESET
If Not ESC_QUITED
OPTIONS_MAIN_RESTORE_SCREEN
End If
End If
Until Key State(SPACE_SCANCODE) or Key State(ESC_SCANCODE) or ESC_QUITED
If Not ESC_QUITED
If FAST_INTERFACE
Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Else
Fade 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Wait 15
End If
End If
End Proc
Procedure OPTIONS_MAIN_FADEUP
If FAST_INTERFACE
Wait Vbl
Palette $0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$81D,$A1D,$C2E,$E1E,$F0F,$F2F,$F4F,$F6F
Wait 1
Else
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$81D,$A1D,$C2E,$E1E,$F0F,$F2F,$F4F,$F6F
Wait 15
End If
End Proc
Procedure OPTIONS_MAIN_RESTORE_SCREEN
MAKE_OPTIONS_BACKGROUND[PAGE_ONE$,MAIN_OPTION_LOADING_AND_SAVING$]
WRITEXY[-2,8*17-16,CONFIGURATION$]
For I=6 To 9
WRITEXY[-2,(I+3)*12+7*8-16,MAIN_OPTION_TEXT$(I-6)]
Next I
WRITEXY[-2,6*8,MAIN_OPTION_E_TEXT$]
WRITEXY[-2,6*8+12,MAIN_OPTION_G_TEXT$]
WRITEXY[-2,6*8+24,MAIN_OPTION_R_TEXT$]
WRITEXY[-2,6*8+36,MAIN_OPTION_U_TEXT$]
WRITEXY[-2,27*8,_PRESS_SPACE_OR_ESCAPE$]
WRITEXY[-2,29*8,ESCAPE_ACCEPT$]
LET_IT_SHOW
Screen 1
OPTIONS_MAIN_FADEUP
End Proc
Procedure OPTIONS_USER_GAMESET
' ________________________________
' | |
' | Print |
' |________________________________|
MAKE_OPTIONS_BACKGROUND[PAGE_FIVE$,CREATING_USER_GAMESET$]
WRITEXY[-2,32,CREATE_USER_GAMESET$]
SFX=0 : COORDY=50
For I=0 To 13
WRITEXY[0,COORDY,CREATE_USER_GS_EXPLANATION$(I)]
Add COORDY,9
Next
WRITEXY[-2,29*8,RECORD_AND_REPLAY_SPACE$]
LET_IT_SHOW
Screen 1
If FAST_INTERFACE
Wait Vbl
Palette $0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$664,$775,$887,$998,$AAA,$BBB,$CCC,$DDD
Wait 1
Else
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$664,$775,$887,$998,$AAA,$BBB,$CCC,$DDD
Wait 15
End If
' ________________________________
' | |
' | Key control |
' |________________________________|
ESC_QUITED=False
Clear Key
Repeat
If Key State(C_SCANCODE)
Screen 1
Show On
Change Mouse 1
Trap A$=Fsel$("","",ENTER_NAME_OF_CONFIG_LIST_FILE$)
Hide On
If Not Exist(A$)
HALFWAITING_DIALOG["",FILE_DOESNT_EXIST$,""]
Else
CREATE_GAMESET[USER_GAMESET__BANK,A$]
CONFIGS=Param
If CONFIGS=0
HALFWAITING_DIALOG[NONE_OF_FILES_WAS_CONFIG1$,"",NONE_OF_FILES_WAS_CONFIG2$]
Else If CONFIGS>20
Trap Save PATH$+"User_gameset",USER_GAMESET__BANK
HALFWAITING_DIALOG[YOUR_NEW_GAMESET_IS_SAVED$,MORE_THAN_20_FILES1$,MORE_THAN_20_FILES2$]
Else
Trap Save PATH$+"User_gameset",USER_GAMESET__BANK
HALFWAITING_DIALOG["",YOUR_NEW_GAMESET_IS_SAVED$,""]
End If
End If
If Length(USER_GAMESET__BANK)>0
BASE=Start(USER_GAMESET__BANK)
For I=0 To 19
OFFSET=Deek(BASE+2*I)
If OFFSET=0
GS_GAME_NAME$(I,1)=NAME_OF_EMPTY_GAME_IN_GAMESET$
Else
GS_GAME_NAME$(I,1)=Peek$(BASE+OFFSET,16)
End If
Next I
End If
End If
ESC_QUITED=Key State(ESC_SCANCODE)
Until Key State(SPACE_SCANCODE) or ESC_QUITED
FAST_FADE_OUT
End Proc
Procedure OPTIONS_RECORD_AND_REPLAY
' ________________________________
' | |
' | Print |
' |________________________________|
MAKE_OPTIONS_BACKGROUND[PAGE_FOUR$,RECORD_AND_REPLAY$]
For I=0 To 2 : WRITEXY[5,(I+1)*16+8,RR_COLUMN_TEXT$(I)] : Next
WRITEXY[-2,29*8,RECORD_AND_REPLAY_SPACE$]
For I=1 To 3
Paste Bob 122,16*I+4,RED_BOX_IMAGE(OS_LC_BOX(I))
Next I
BOOL_OPTION[USER_RECORDING,1,0]
BOOL_OPTION[USER_REPLAYING,2,0]
BOOL_OPTION[REPLAY_ALL_SAVED_ON,3,0]
LET_IT_SHOW
Screen 1
If FAST_INTERFACE
Wait Vbl
Palette $0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$81D,$A1D,$C2E,$E1E,$F0F,$F2F,$F4F,$F6F
Wait 1
Else
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$111,$81D,$A1D,$C2E,$E1E,$F0F,$F2F,$F4F,$F6F
Wait 15
End If
' ________________________________
' | |
' | Key control |
' |________________________________|
ESC_QUITED=_FALSE : Clear Key
Repeat
If Key State(R_SCANCODE)
USER_RECORDING= Not USER_RECORDING
Wait Vbl
BOOL_OPTION[USER_RECORDING,1,0]
If USER_REPLAYING
USER_REPLAYING=False
BOOL_OPTION[USER_REPLAYING,2,0]
Else If REPLAY_ALL_SAVED_ON
REPLAY_ALL_SAVED_ON=False
BOOL_OPTION[REPLAY_ALL_SAVED_ON,3,0]
End If
Clear Key : Wait 10
End If
If Key State(P_SCANCODE)
Wait Vbl
If Not USER_REPLAYING
If GAME_RECORD_EMPTY
HALFWAITING_DIALOG[YOU_HAVENT_RECORDED1$,YOU_HAVENT_RECORDED2$,YOU_HAVENT_RECORDED3$]
Else
USER_REPLAYING=True
BOOL_OPTION[USER_REPLAYING,2,0]
If USER_RECORDING
USER_RECORDING=False
BOOL_OPTION[USER_RECORDING,1,0]
Else If REPLAY_ALL_SAVED_ON
REPLAY_ALL_SAVED_ON=False
BOOL_OPTION[REPLAY_ALL_SAVED_ON,3,0]
End If
End If
Else
USER_REPLAYING=False
BOOL_OPTION[USER_REPLAYING,2,0]
End If
Clear Key : Wait 10
End If
If Key State(A_SCANCODE)
If Not REPLAY_ALL_SAVED_ON
_EXISTS_INDEX=True
If Exist("Duenrecord:")
GAME_SAVING_PATH$="DuenRecord:"
Else
If Not Exist("ram:DuenRecord/")
_EXISTS_INDEX=False
End If
GAME_SAVING_PATH$="ram:DuenRecord/"
End If
If _EXISTS_INDEX
INDEX=0
_EXISTS_INDEX=False
Repeat
INDEX$=Str$(INDEX)-" " : INDEX$=String$("0",2-Len(INDEX$))+INDEX$
If Exist(GAME_SAVING_PATH$+RECORDNAME$+INDEX$)
_EXISTS_INDEX=True
End If
Inc INDEX
Until _EXISTS_INDEX or(INDEX=100)
Dec INDEX
End If
If _EXISTS_INDEX
REPLAY_ALL_SAVED_ON= Not REPLAY_ALL_SAVED_ON
Wait Vbl
BOOL_OPTION[REPLAY_ALL_SAVED_ON,3,0]
If USER_RECORDING
USER_RECORDING=False
BOOL_OPTION[USER_RECORDING,1,0]
Else If USER_REPLAYING
USER_REPLAYING=False
BOOL_OPTION[USER_REPLAYING,2,0]
End If
Else
HALFWAITING_DIALOG[YOU_HAVENT_SAVED_GAME1$,YOU_HAVENT_SAVED_GAME2$,YOU_HAVENT_SAVED_GAME3$]
End If
Else
REPLAY_ALL_SAVED_ON= Not REPLAY_ALL_SAVED_ON
Wait Vbl
BOOL_OPTION[REPLAY_ALL_SAVED_ON,3,0]
End If
Clear Key : Wait 10
End If
ESC_QUITED=Key State(ESC_SCANCODE)
Until Key State(SPACE_SCANCODE) or ESC_QUITED
FAST_FADE_OUT
End Proc
Procedure OPTIONS_GAMESETTINGS
' ________________________________
' | |
' | Print |
' |________________________________|
MAKE_OPTIONS_BACKGROUND[PAGE_TWO$,GAME_SETTINGS$]
For I=1 To 14
WRITEXY[8,I*16+8,OS_LEFT_COLUMN_TEXT$(I,0)]
Paste Bob 116+6,16*I+4,RED_BOX_IMAGE(OS_LC_BOX(I))
WRITEXY[8*21,I*16+8,OS_RIGHT_COLUMN_TEXT$(I,0)]
Paste Bob 152+116+6,16*I+4,RED_BOX_IMAGE(OS_RC_BOX(I))
Next
Wait Vbl
NUMBER_OPTION[USER_DIRECTIONS,3,_TRUE,1,0]
NUMBER_OPTION[SPEEDJUMP,2,_TRUE,2,0]
NUMBER_OPTION[SPACE_LENGTH,3,_TRUE,3,0]
NUMBER_OPTION[_DRAWING_LINE_LENGTH,3,_TRUE,4,0]
DEPENDENT_OPTION[RATEMODE,USER_RATE_LENGTH,3,5,0]
NUMBER_OPTION[FINAL_RATE,3,_TRUE,7,0]
BOOL_OPTION[SPACE_KILL,8,0]
BOOL_OPTION[BOUNCING,9,0]
BOOL_OPTION[TELEPORTING,10,0]
DEPENDENT_OPTION[WATERING,WATER_LIMIT,3,11,0]
BOOL_OPTION[_MUSIC_ON,13,0]
BOOL_OPTION[USER_SOUND_FX,14,0]
BOOL_OPTION[TURBO,1,1]
BOOL_OPTION[COMPUTURBO,2,1]
DEPENDENT_OPTION[CENTRAL_BOX,CENTRAL_BOX_SIZE,3,3,1]
BOOL_OPTION[ALWAYS_TURNING,5,1]
BOOL_OPTION[1-BOLDLINE,6,1]
DEPENDENT_OPTION[BODY_CHANGE,BODY_CHANGE_PERCENT,2,7,1]
BOOL_OPTION[TEAM_GAME,9,1]
BOOL_OPTION[LONG_GAME,10,1]
BOOL_OPTION[SURPRISING_START,11,1]
DEPENDENT_OPTION[WIND,WIND_STRENGTH,2,12,1]
NUMBER_OPTION[_SCREEN_SIZE+1,1,_TRUE,14,1]
LET_IT_SHOW
Screen 1
OPTIONS_GAMESETTINGS_FADE_UP
' ________________________________
' | |
' | Key control |
' |________________________________|
ESC_QUITED=_FALSE : Clear Key
Repeat
If Key State(1)
_GET_3NUMBER[16,3] : USER_DIRECTIONS=Param
If USER_DIRECTIONS<5
USER_DIRECTIONS=5
HALFWAITING_DIALOG[_MINIMUM_OF_DIRECTIONS$,SORRY$,""]
Else If USER_DIRECTIONS>250
USER_DIRECTIONS=250
HALFWAITING_DIALOG[_MAXIMUM_OF_DIRECTIONS$,SORRY$,""]
End If
SMERU=USER_DIRECTIONS*4
ANGLE_CONSTANT#=2*Pi#/SMERU
SMERU_QUARTER=USER_DIRECTIONS
SMERU_HALVE=USER_DIRECTIONS*2
NUMBER_OPTION[USER_DIRECTIONS,3,_TRUE,1,0]
Wait 10
Else If Key State(2)
Add SPEEDJUMP,5,0 To 95
NUMBER_OPTION[SPEEDJUMP,2,_TRUE,2,0]
Wait 10
Else If Key State(3)
_GET_3NUMBER[16,7] : SPACE_LENGTH=Param
LINE_LENGTH=SPACE_LENGTH+_DRAWING_LINE_LENGTH+20
Wait 10
Else If Key State(4)
_GET_3NUMBER[16,9] : _DRAWING_LINE_LENGTH=Param
LINE_LENGTH=SPACE_LENGTH+_DRAWING_LINE_LENGTH+20
Wait 10
Else If Key State(5)
RATEMODE=1-RATEMODE
DEPENDENT_OPTION[RATEMODE,USER_RATE_LENGTH,3,5,0]
Wait 10
Else If Key State(6) and(RATEMODE=1)
_GET_3NUMBER[16,13] : USER_RATE_LENGTH=Param
Wait 10
Else If Key State(7)
Add FINAL_RATE,5,50 To 100
NUMBER_OPTION[FINAL_RATE,3,_TRUE,7,0]
Wait 10
Else If Key State(8)
SPACE_KILL=1-SPACE_KILL
BOOL_OPTION[SPACE_KILL,8,0]
Wait 10
Else If Key State(9)
BOUNCING=1-BOUNCING
If BOUNCING
TELEPORTING=0
WATERING=0
BOOL_OPTION[TELEPORTING,10,0]
DEPENDENT_OPTION[WATERING,WATER_LIMIT,3,11,0]
End If
BOOL_OPTION[BOUNCING,9,0]
Wait 10
Else If Key State(O_SCANCODE)
TELEPORTING=1-TELEPORTING
If TELEPORTING
BOUNCING=0
WATERING=0
BOOL_OPTION[BOUNCING,9,0]
DEPENDENT_OPTION[WATERING,WATER_LIMIT,3,11,0]
End If
BOOL_OPTION[TELEPORTING,10,0]
Wait 10
Else If Key State(P_SCANCODE)
'~~~ Change of watering 0/1) ~~~
WATERING=WATERING xor 1
If WATERING=1
BOUNCING=0
TELEPORTING=0
BOOL_OPTION[BOUNCING,9,0]
BOOL_OPTION[TELEPORTING,10,0]
End If
DEPENDENT_OPTION[WATERING,WATER_LIMIT,3,11,0]
Wait 10
Else If Key State(Q_SCANCODE) and(WATERING=1)
_GET_3NUMBER[16,25]
WATER_LIMIT=Param
If WATER_LIMIT>=90
WATER_LIMIT=89
DEPENDENT_OPTION[WATERING,WATER_LIMIT,3,11,0]
HALFWAITING_DIALOG[_MAXIMUM_OF_WATER_ANGLE$,SORRY$,""]
End If
WATER_LIMIT#=WATER_LIMIT*Pi#/180
Clear Key
Wait 5
Else If Key State(R_SCANCODE)
_MUSIC_ON=_NOT(_MUSIC_ON)
If _MUSIC_ON : Track Play LIFE_MOTION_MUSIC__BANK
Else : Track Stop : End If
BOOL_OPTION[_MUSIC_ON,13,0]
Wait 10
Else If Key State(S_SCANCODE)
USER_SOUND_FX=_NOT(USER_SOUND_FX)
BOOL_OPTION[USER_SOUND_FX,14,0]
Wait 10
Else If Key State(A_SCANCODE)
TURBO=_NOT(TURBO)
If TURBO : COMPUTURBO=_FALSE : End If
BOOL_OPTION[TURBO,1,1]
BOOL_OPTION[COMPUTURBO,2,1]
Wait 10
Else If Key State(B_SCANCODE)
COMPUTURBO=_NOT(COMPUTURBO)
If COMPUTURBO : TURBO=_FALSE : End If
BOOL_OPTION[TURBO,1,1]
BOOL_OPTION[COMPUTURBO,2,1]
Wait 10
Else If Key State(C_SCANCODE)
CENTRAL_BOX=_NOT(CENTRAL_BOX)
DEPENDENT_OPTION[CENTRAL_BOX,CENTRAL_BOX_SIZE,3,3,1]
Wait 10
Else If Key State(D_SCANCODE) and CENTRAL_BOX
Add CENTRAL_BOX_SIZE,5,10 To 80
DEPENDENT_OPTION[CENTRAL_BOX,CENTRAL_BOX_SIZE,3,3,1]
Wait 10
Else If Key State(E_SCANCODE)
ALWAYS_TURNING=_NOT(ALWAYS_TURNING)
BOOL_OPTION[ALWAYS_TURNING,5,1]
Wait 10
Else If Key State(F_SCANCODE)
BOLDLINE=_NOT(BOLDLINE)
SET_APPROPRIATE_DRAWPIXEL_PROC
BOOL_OPTION[_NOT(BOLDLINE),6,1]
Wait 10
Else If Key State(G_SCANCODE)
BODY_CHANGE=1-BODY_CHANGE
DEPENDENT_OPTION[BODY_CHANGE,BODY_CHANGE_PERCENT,3,7,1]
Wait 10
Else If Key State(H_SCANCODE) and BODY_CHANGE
Add BODY_CHANGE_PERCENT,20,20 To 120
DEPENDENT_OPTION[BODY_CHANGE,BODY_CHANGE_PERCENT,3,7,1]
Wait 5
Else If Key State(I_SCANCODE)
TEAM_GAME= Not TEAM_GAME
BOOL_OPTION[TEAM_GAME,9,1]
Wait 10
Else If Key State(J_SCANCODE)
LONG_GAME=1-LONG_GAME
BOOL_OPTION[LONG_GAME,10,1]
Wait 10
Else If Key State(K_SCANCODE)
SURPRISING_START=_NOT(SURPRISING_START)
BOOL_OPTION[SURPRISING_START,11,1]
Wait 10
Else If Key State(L_SCANCODE)
WIND=_NOT(WIND)
DEPENDENT_OPTION[WIND,WIND_STRENGTH,2,12,1]
Wait 10
Else If Key State(M_SCANCODE)
Add WIND_STRENGTH,1,1 To 10
DEPENDENT_OPTION[WIND,WIND_STRENGTH,2,12,1]
Wait 10
Else If Key State(N_SCANCODE)
Add _SCREEN_SIZE,1,0 To 2
SET_APPROPRIATE_DRAWPIXEL_PROC
NUMBER_OPTION[_SCREEN_SIZE+1,1,_TRUE,14,1]
Wait 10
End If
ESC_QUITED=Key State(ESC_SCANCODE)
Until Key State(SPACE_SCANCODE) or ESC_QUITED
FAST_FADE_OUT
End Proc
Procedure OPTIONS_GAMESETTINGS2
' ________________________________
' | |
' | Print |
' |________________________________|
MAKE_OPTIONS_BACKGROUND[PAGE_TWO$,GAME_SETTINGS$]
For I=1 To 1
WRITEXY[8,I*16+8,OS_LEFT_COLUMN_TEXT$(I,1)]
Paste Bob 116+6,16*I+4,RED_BOX_IMAGE(OS_LC_BOX(I))
WRITEXY[8*21,I*16+8,OS_RIGHT_COLUMN_TEXT$(I,1)]
Paste Bob 152+116+6,16*I+4,RED_BOX_IMAGE(OS_RC_BOX(I))
Next
BOOL_OPTION[COMPUDEATH,1,0]
BOOL_OPTION[ZOMBIES,1,1]
LET_IT_SHOW
Screen 1
OPTIONS_GAMESETTINGS_FADE_UP
' ________________________________
' | |
' | Key control |
' |________________________________|
ESC_QUITED=_FALSE : Clear Key
Repeat
If Key State(1)
COMPUDEATH=1-COMPUDEATH
BOOL_OPTION[COMPUDEATH,1,0]
Wait 10
End If
If Key State(A_SCANCODE)
ZOMBIES=1-ZOMBIES
BOOL_OPTION[ZOMBIES,1,1]
Wait 10
End If
ESC_QUITED=Key State(ESC_SCANCODE)
Until Key State(SPACE_SCANCODE) or ESC_QUITED
FAST_FADE_OUT
End Proc
Procedure OPTIONS_GAMESETTINGS_FADE_UP
If FAST_INTERFACE
Palette $0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$122,$177,$196,$2A7,$1B6,$B5,$2C4,$4D3,$6E2
Else
' Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$122,$177,$196,$2A7,$1B6,$B5,$2C4,$4D3,$6E2
Fade 1,$10,$10,$121,$121,$232,$232,$343,$343,$454,$454,$565,$565,$676,$676,$787,$787,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$122,$177,$196,$2A7,$1B6,$B5,$2C4,$4D3,$6E2
' PALETTE VER 1.1 Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,$F80,$EA0,$DC0,$CE0,$F01,$F20,$F50,$122,$177,$196,$2A7,$1B6,$B5,$2C4,$4D3,$6E2
Wait 15
End If
End Proc
Procedure OPTIONS_GAMEPLAN
OPTIONS_GAMEPLAN_RESTORE_SCREEN
ESC_QUITED=False
Clear Key
Repeat
If Key State(D_SCANCODE) and(PLAN>0)
PLAN=0
FAST_FADE_OUT
OPTIONS_GAMEPLAN_RESTORE_SCREEN
Else If Key State(Y_SCANCODE) and(PLAN<2)
PLAN=2
FAST_FADE_OUT
OPTIONS_GAMEPLAN_RESTORE_SCREEN
Else If Key State(L_SCANCODE) and(PLAN=2)
Screen 1
Show On
Change Mouse 1
Trap A$=Fsel$("","",ENTER_NAME_OFF_IFF_TO_LOAD$)
Hide On
OWN_PLAN_LOAD[A$,True]
End If
For I=1 To 6
If Key State(I) and((GAMEPLAN<>I) or(PLAN<>1))
GAMEPLAN=I
SET_SPP
PLAN=1
DUENIX_REQUEST
Trap Load PATH$+"Plan"+Str$(GAMEPLAN)-" ",PLAN_BANK(1)
FAST_FADE_OUT
OPTIONS_GAMEPLAN_RESTORE_SCREEN
End If
Next
ESC_QUITED=Key State(ESC_SCANCODE)
Until Key State(SPACE_SCANCODE) or ESC_QUITED
FAST_FADE_OUT
End Proc
Procedure OPTIONS_GAMEPLAN_RESTORE_SCREEN
Screen 1
If Length(PLAN_BANK(PLAN))>0
Unpack PLAN_BANK(PLAN)
Else
Cls 0
End If
Screen 2
Cls 0
Paste Bob 35,0,DUENIX_TITLE_IMAGE
WRITEXY[5,12,PAGE_THREE$]
WRITEXY[316-6*Len(GAMEPLAN$),12,GAMEPLAN$]
Pen $14
If PLAN=1
WRITEXY[8,4*8,THIS_IS_STANDARD_GAMEPLAN_NUMBER$+Str$(GAMEPLAN)]
Else If PLAN=2
If Length(PLAN_BANK(2))=0
A$=HERE_MAY_BE_YOUR_PLAN$
Else
A$=HERE_IS_YOUR_PLAN$
End If
WRITEXY[8,4*8,A$+"\"]
WRITEXY[1*8,11*8,GAMEPLAN_L_TEXT$+"\"]
Add SFY,20
For I=0 To 2 : WRITEXY[-1,-1,GAMEPLAN_EXPLANATION$(I)+"\"] : Next
Else
WRITEXY[8,4*8,THIS_IS_DEFPLAN$]
End If
SFY=180
For I=0 To 2 : WRITEXY[10,-1,GAMEPLAN_KEY_TEXT$(I)+"\"] : Next
WRITEXY[-2,29*8,RECORD_AND_REPLAY_SPACE$]
LET_IT_SHOW
Screen 1
Wait Vbl
If FAST_INTERFACE
If PLAN=0
Palette $0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,0,$E7D,$DD,$D42,$88F,$953,$F0F,$0,$D15,$E26,$E37,$F48,$F59,$F6A,$F7B,$F8C
Else If PLAN=2
Palette 0,UPP(1),UPP(2),UPP(3),UPP(4),UPP(5),UPP(6),UPP(7),UPP(8),UPP(9),UPP(10),UPP(11),UPP(12),UPP(13),UPP(14),UPP(15),0,$E7D,$DD,$D42,$88F,$953,$F0F,$0,$D15,$E26,$E37,$F48,$F59,$F6A,$F7B,$F8C
Else
Palette 0,SPP(1),SPP(2),SPP(3),SPP(4),SPP(5),SPP(6),SPP(7),SPP(8),SPP(9),SPP(10),SPP(11),SPP(12),SPP(13),SPP(14),SPP(15),0,$E7D,$DD,$D42,$88F,$953,$F0F,$0,$D15,$E26,$E37,$F48,$F59,$F6A,$F7B,$F8C
End If
Clear Key : Wait 1
Else
If PLAN=0
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,0,$E7D,$DD,$D42,$88F,$953,$F0F,$0,$D15,$E26,$E37,$F48,$F59,$F6A,$F7B,$F8C
Else If PLAN=2
Fade 1,UPP(0),UPP(1),UPP(2),UPP(3),UPP(4),UPP(5),UPP(6),UPP(7),UPP(8),UPP(9),UPP(10),UPP(11),UPP(12),UPP(13),UPP(14),UPP(15),0,$E7D,$DD,$D42,$88F,$953,$F0F,$0,$D15,$E26,$E37,$F48,$F59,$F6A,$F7B,$F8C
Else If DARK_GAMEPLAN=0
Fade 1,0,SPP(1),SPP(2),SPP(3),SPP(4),SPP(5),SPP(6),SPP(7),SPP(8),SPP(9),SPP(10),SPP(11),SPP(12),SPP(13),SPP(14),SPP(15),0,$E7D,$DD,$D42,$88F,$953,$F0F,$0,$D15,$E26,$E37,$F48,$F59,$F6A,$F7B,$F8C
End If
Wait 15
End If
End Proc
Procedure OWN_PLAN_LOAD[FILE$,OP_INTERACTIVE]
Screen 2
Trap Load Iff FILE$
If Errtrap=0
BASE=Phybase(4)
Fill BASE To BASE+10239,0
For I=0 To $F
UPP(I)=Colour(I)
Next I
Screen 1
If OP_INTERACTIVE
FAST_FADE_OUT
End If
Screen Copy 2 To 1
Pack 1 To PLAN_BANK(2)
If OP_INTERACTIVE
OPTIONS_GAMEPLAN_RESTORE_SCREEN
End If
OWN_PLAN_PATH$=FILE$
Else
OWN_PLAN_PATH$=""
End If
End Proc
' ______________________________________
' | \
' | Selecting and Gameset work \
' |________________________________________\
Procedure SELECTING_FADE_UP
' Fade 1,$0,$0,$110,$110,$221,$221,$332,$332,$443,$443,$554,$554,$665,$665,$776,$776,0,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6),$0,$811,$931,$A41,$B51,$C61,$D81,$EA1,$FC2
' Fade 1,$0,$0,$110,$110,$221,$221,$332,$332,$443,$443,$554,$554,$665,$665,$776,$776,0,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6),$0,$822,$942,$A52,$B62,$C72,$D92,$EB2,$FD3
Fade 1,$0,$110,$221,$332,$443,$554,$665,$776,$822,$942,$A52,$B62,$C72,$D92,$EB2,$FD3,$0,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6),$0,$832,$942,$A43,$B53,$C54,$D64,$E75,$F76
'PALETTE Ver 1.1 Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778,0,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6),$0,$915,$A26,$B37,$C48,$D59,$E6A,$F7B,$F8C
' Fade 1,$0,$1,$2,$3,$112,$114,$116,$118,$333,$335,$337,$339,$555,$558,$55C,$55F,0,$BB9,$D4,$F6E,$FD0,$98F,$DC,$0,$915,$A26,$B37,$C48,$D59,$E6A,$F7B,$F8C
Wait 15
End Proc
Procedure SELECTING_PRINT[CLEAR_SCREEN_1]
If CLEAR_SCREEN_1
Screen 2
Sprite Off
Screen 1
Unpack PLAN_BANK(0)
P0=Phybase(0) : P1=Phybase(1) : P2=Phybase(2) : P3=Phybase(3)
Copy P1,P1+10240-1 To P0
Copy P2,P2+10240-1 To P1
Copy P3,P3+10240-1 To P2
Fill P3 To P3+10240-1,0
End If
Screen 2
Cls 0 : Paper 0 : Pen $18
Paste Bob 35,1+3,DUENIX_TITLE_IMAGE
Paste Bob 255,1,DUENIX_ANIM_IMAGE
' Wait Vbl
' ________________________________
' | |
' | Print Fajfky and Lives |
' |________________________________|
For _PLAYER=1 To 6
Ink $10+_PLAYER,0
Bar 33*8-6,3*8*_PLAYER+10 To 33*8+25,24*_PLAYER+16+10
Paste Bob 33*8-8,24*_PLAYER+10,_PLAYER_TYPE_IMAGE(_PLAYER_TYPE(_PLAYER))
If _TOP_LIVES(_PLAYER)>0
Ink $10+_PLAYER,1
Text 33*8+42,24*_PLAYER+22,Str$(_TOP_LIVES(_PLAYER))-" "
End If
Next _PLAYER
If CLEAR_SCREEN_1=0
Screen 1 : Put Block 1 : Screen 2
End If
' ________________________________
' | |
' | Print Player Texts |
' |________________________________|
For I=1 To 6
A$=SELECTING_UPPER_TEXT$(I-1)
Ink $17 : Text 1,8*(3*I+2)+6,A$
Get Sprite _FREE_FOR_MANIPULATION_IMAGE,1,8*(3*I+2) To 8*Len(A$),8*(3*I+2)+8
Screen 1
Paste Bob 1,8*(3*I+2)+1,_FREE_FOR_MANIPULATION_IMAGE
Paste Bob 2,8*(3*I+2),_FREE_FOR_MANIPULATION_IMAGE
Paste Bob 1,8*(3*I+2)-1,_FREE_FOR_MANIPULATION_IMAGE
Paste Bob 0,8*(3*I+2),_FREE_FOR_MANIPULATION_IMAGE
Paste Bob 1,8*(3*I+2)+5,_FREE_FOR_MANIPULATION_IMAGE
Paste Bob 1,8*(3*I+2)+6,_FREE_FOR_MANIPULATION_IMAGE
Screen 2
Ink $17
If I=5
Box 245,24*5+20+3 To 250,24*5+20+3
Box 198-2*8,24*5+20+3 To 200,24*5+20+3
Else If I=3
Box 245,24*3+20+3 To 250,24*3+20+3
Box Len(A$)*8+6,24*3+20+3 To 220,24*3+20+3
Else
Box Len(A$)*8+6,24*I+20+3 To 250,24*I+20+3
End If
Ink $10+I
If I=5
Draw 245,24*5+20 To 250,24*5+20
Draw 198-2*8,24*5+20 To 200,24*5+20
Else If I=3
Draw 245,24*3+20 To 250,24*3+20
Draw Len(A$)*8+6,24*3+20 To 220,24*3+20
Else
Draw Len(A$)*8+6,24*I+20 To 250,24*I+20
End If
Text 1,8*(3*I+2)+6,A$
Next
' ________________________________
' | |
' | Draw Mouse & Joy |
' |________________________________|
Paste Bob 200,130,MOUSE_ON_LINE_IMAGE
Paste Bob 200,82,_JOY_ON_LINE_IMAGE
' ________________________________
' | |
' | Other Texts |
' |________________________________|
LET_IT_SHOW
If CLEAR_SCREEN_1
Screen 1
WRITEXY[-2,178,SELECTING_LOWER_TEXT$(0)]
WRITEXY[-2,188,SELECTING_LOWER_TEXT$(1)]
WRITEXY[-2,198,SELECTING_LOWER_TEXT$(2)]
WRITEXY[-2,208,SELECTING_LOWER_TEXT$(3)]
WRITEXY[-2,228,SELECTING_LOWER_TEXT$(4)]
WRITEXY[-2,247,SELECTING_LOWER_TEXT$(5)+YEAR$]
End If
Screen 2
End Proc
Procedure SELECTING
SELECTING_RESTORE_SCREEN
For _PLAYER=1 To 6
ACCEPT_KEYSTROKE(_PLAYER)=_TRUE
_KEYSTROKE_COUNTER(_PLAYER)=0
Next _PLAYER
LAST_CHANGED_PLAYER=6
Repeat
' ________________________________
' | |
' | Test player keys |
' |________________________________|
REDRAW_ANY_PLAYER=_FALSE
For _PLAYER=1 To 6
REDRAW_PLAYER(_PLAYER)=_FALSE
If ACCEPT_KEYSTROKE(_PLAYER)
On _PLAYER Goto LTL1,LTL2,LTL3,LTL4,LTL5,LTL6
LTL1: RIGHT_PUSHED=Key State(66)
LEFT_PUSHED=Key State(0) : Goto LTL_END
LTL2: RIGHT_PUSHED=((Key Shift and $40)>0)
LEFT_PUSHED=((Key Shift and $10)>0) : Goto LTL_END
LTL3: RIGHT_PUSHED=Key State(54) or Jright(1)
LEFT_PUSHED=Key State(53) or Jleft(1) : Goto LTL_END
LTL4: RIGHT_PUSHED=((Key Shift and $20)>0)
LEFT_PUSHED=((Key Shift and $80)>0) : Goto LTL_END
LTL5: RIGHT_PUSHED=Key State(95) or((Mouse Key and 2)=2)
LEFT_PUSHED=Key State(70) or((Mouse Key and 1)=1) : Goto LTL_END
LTL6: RIGHT_PUSHED=Key State(63)
LEFT_PUSHED=Key State(47)
LTL_END:
If LEFT_PUSHED or RIGHT_PUSHED
_KEYSTROKE_COUNTER(_PLAYER)=10
ACCEPT_KEYSTROKE(_PLAYER)=_FALSE
REDRAW_PLAYER(_PLAYER)=_TRUE
REDRAW_ANY_PLAYER=_TRUE
Add _PLAYER_TYPE(_PLAYER),1,0 To 3
SELECTED(_PLAYER)=(_PLAYER_TYPE(_PLAYER)>0)
If SELECTED(_PLAYER)=0
_TOP_LIVES(_PLAYER)=0
End If
End If
Else
Dec _KEYSTROKE_COUNTER(_PLAYER)
If(_KEYSTROKE_COUNTER(_PLAYER)=0)
ACCEPT_KEYSTROKE(_PLAYER)=_TRUE
End If
End If
Next _PLAYER
_COUNT_SELECTED
' ________________________________
' | |
' | Test lives keys |
' |________________________________|
If(HRAJOU>0)
If Key State(10)
Repeat
Add LAST_CHANGED_PLAYER,1,1 To 6
Until SELECTED(LAST_CHANGED_PLAYER)
Timer=0
_TOP_LIVES(LAST_CHANGED_PLAYER)=0
REDRAW_PLAYER(LAST_CHANGED_PLAYER)=_TRUE
REDRAW_ANY_PLAYER=_TRUE
Wait 7
End If
For KEY=1 To 7
If Key State(KEY)
Repeat
Add LAST_CHANGED_PLAYER,1,1 To 6
Until SELECTED(LAST_CHANGED_PLAYER)
Timer=0
_TOP_LIVES(LAST_CHANGED_PLAYER)=KEY
REDRAW_PLAYER(LAST_CHANGED_PLAYER)=_TRUE
REDRAW_ANY_PLAYER=_TRUE
Wait 7
End If
Next KEY
End If
' ________________________________
' | |
' | Redraw selected players n lives|
' |________________________________|
If REDRAW_ANY_PLAYER
Timer=0
Screen 2
For _PLAYER=1 To 6
If REDRAW_PLAYER(_PLAYER)
Ink $10+_PLAYER,0
Bar 33*8-6,3*8*_PLAYER+10 To 33*8+25,24*_PLAYER+16+10
Paste Bob 33*8-8,24*_PLAYER+10,_PLAYER_TYPE_IMAGE(_PLAYER_TYPE(_PLAYER))
T=_TOP_LIVES(_PLAYER)
T$=" "
If T>0 : T$=Str$(T)-" " : End If
Ink $10+_PLAYER,1
Text 33*8+42,24*_PLAYER+22,T$
End If
Next _PLAYER
Get Block 1,16*16,0,320-16*16,256,1
Screen 1
Wait Vbl
Put Block 1
Del Block 1
Else
Wait Vbl
End If
Clear Key
' ________________________________
' | |
' | Test screen keys |
' |________________________________|
If Key State(H_SCANCODE)
FAST_FADE_OUT
Amal Off : Sprite Off
HELP
SELECTING_RESTORE_SCREEN
Else If Key State(L_SCANCODE)
_PLAYER_COLOURS_SET=1-_PLAYER_COLOURS_SET
If _PLAYER_COLOURS_SET=0
For I=1 To 6 : PL_DEF_COLOR(I)=PL_DEF_COLOR_LIGHT(I) : Next
Else
For I=1 To 6 : PL_DEF_COLOR(I)=PL_DEF_COLOR_DARK(I) : Next
End If
Fade 1,,,,,,,,,,,,,,,,,,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6)
Wait 10
Else If Key State(O_SCANCODE)
FAST_FADE_OUT
Amal Off : Sprite Off
OPTIONS_MAIN
SELECTING_RESTORE_SCREEN
Else If Key State(E_SCANCODE)
FAST_FADE_OUT : E_THRU=_TRUE
Amal Off : Sprite Off
OPTIONS_MAIN
SELECTING_RESTORE_SCREEN
Else If Key State(G_SCANCODE)
FAST_FADE_OUT : G_THRU=_TRUE
Amal Off : Sprite Off
OPTIONS_MAIN
SELECTING_RESTORE_SCREEN
Else If Key State(R_SCANCODE)
FAST_FADE_OUT : R_THRU=_TRUE
Amal Off : Sprite Off
OPTIONS_MAIN
SELECTING_RESTORE_SCREEN
Else If Key State(S_SCANCODE)
SELECT_GAME : Timer=0
Else If Key State(U_SCANCODE)
If Length(USER_GAMESET__BANK)>0
U_THRU=_TRUE
SELECT_GAME : Timer=0
End If
Else If Key State(Q_SCANCODE)
Fade 3 : Wait 50 : Track Stop : Erase All
Screen Close 2 : Screen Close 1
If Prg State=-1
End
Else
Edit
End If
End If
DEMO_ON=(Timer>DEMO_TIMER_LIMIT)
Until Key State(SPACE_SCANCODE) and(((HRAJOU>1) and(TEAM_GAME=False)) or HRAJOU=4 or HRAJOU=6 or REPLAY_ALL_SAVED_ON) or DEMO_ON or _ONE_PLAYER_GAME
_ONE_PLAYER_GAME=False
Fade 1
Wait 15
If DEMO_ON
DEMO_ENVIRONMENT[0] : Rem Store envi before demo and set demo envi
End If
If Not(DEMO_ON or REPLAY_ALL_SAVED_ON)
REALIZE_PLAYER_TYPE
End If
SET_TEAMMATES
If Not DEMO_ON
Track Stop
End If
Amal Off
Sprite Off
Paper 0
Cls 0
End Proc
Procedure SELECTING_RESTORE_SCREEN
Sprite Off
SELECTING_PRINT[True]
Screen 1
Sprite Off : Wait Vbl : Wait 1
'#### My Last Attempt ####
For I=0 To 7
Sprite I,0,0,0
Next I
Sprite 0,260+X Hard(0)-24-4+30+2+2,5+4+42,33
' _ANIM_FLAG$="Anim 0,(33,6)(34,6)(35,6)(36,6)(37,6)(38,6)(39,6)(40,6)(41,6)(42,6)(43,6)(44,6)(45,6)(46,6)"
_ANIM_FLAG$="Anim 0,(33,6)(34,6)(35,5)(36,4)(37,3)(38,3)(39,4)(40,5)(41,6)(42,6)(43,6)(44,6)(45,6)(46,6)(33,4)(34,1)(35,1)(36,1)(37,1)(38,1)(39,1)(40,1)(41,1)(42,1)(43,2)(44,3)(45,4)(46,5)"
Amal 0,_ANIM_FLAG$
Amal On
SELECTING_FADE_UP
Timer=0 : DEMO_ON=False
End Proc
Procedure SET_TEAMMATES
Dim TM(3)
If Not TEAM_GAME
For I=1 To 6
TEAM_MATE(I)=I
Next I
Else
If HRAJOU=6
TEAM_MATE_THRU(1)=$12
TEAM_MATE_THRU(2)=0
TEAM_MATE_THRU(3)=$14
TEAM_MATE_THRU(4)=0
TEAM_MATE_THRU(5)=$16
TEAM_MATE_THRU(6)=0
TEAM_MATE(1)=2
TEAM_MATE(2)=1
TEAM_MATE(3)=4
TEAM_MATE(4)=3
TEAM_MATE(5)=6
TEAM_MATE(6)=5
Else
TM_INDEX=0
For I=1 To 6
If SELECTED(I)
TM(TM_INDEX)=I
Inc TM_INDEX
End If
Next I
TEAM_MATE_THRU(TM(0))=$10+TM(1)
TEAM_MATE_THRU(TM(1))=0
TEAM_MATE_THRU(TM(2))=$10+TM(3)
TEAM_MATE_THRU(TM(3))=0
TEAM_MATE(TM(0))=TM(1)
TEAM_MATE(TM(1))=TM(0)
TEAM_MATE(TM(2))=TM(3)
TEAM_MATE(TM(3))=TM(2)
End If
End If
End Proc
Procedure _DO_SELECTION_SCREEN[GS_TYPE]
U_GOES_TO_USERBANK=(GS_TYPE=0) and(Length(USER_GAMESET__BANK)>0)
For I=0 To 9
WRITEXY[20-4,20+51-10+I*9,Str$(I)+" "+GS_GAME_NAME$(I,GS_TYPE)]
Next I
For I=0 To 9
WRITEXY[20-2+120,20+51-10+I*9,Chr$(I+65)+" "+GS_GAME_NAME$(I+10,GS_TYPE)]
Next I
If U_GOES_TO_USERBANK
WRITEXY[45,156,PRESS_U_TO_SELECT_USER_GAME$]
End If
' ________________________________
' | |
' | Draw Box |
' |________________________________|
_W_=10 : _E_=250 : _N_=36 : _S_=170
Ink $10
Box _W_+3,_N_+3 To _E_+3,_S_+3
Box _W_+2,_N_+2 To _E_+2,_S_+2
Ink $19 : Box _W_+1,_N_+1 To _E_+1,_S_+1
Ink $1E : Box _W_,_N_ To _E_,_S_
Ink $10
Box _W_-1,_N_-1 To _E_+2,_S_+2
Box _W_+2,_N_+2 To _E_-1,_S_-1
Get Block 1,0,32,320-32-32,140 : Screen 1
Put Block 1 : Del Block 1
' .-----------------------------------------.
' | Now wait for what key is pressed |
' `-----------------------------------------'
Clear Key : _DO_RECONFIGURING=True : OK=0
Repeat
A$=Upper$(Inkey$)
If(Scancode=ESC_SCANCODE) or(U_GOES_TO_USERBANK and(A$="U"))
OK=True
_DO_RECONFIGURING=False
Else If A$<>""
IND=Asc(A$)
If(IND>48-1) and(IND<48+10)
Add IND,-48 : OK=True
Else If(IND>65-1) and(IND<65+10)
Add IND,-55 : OK=True
End If
OK=OK and((GS_TYPE=0) or(Left$(GS_GAME_NAME$(Min(IND,19),GS_TYPE),5)<>NAME_OF_EMPTY_GAME_IN_GAMESET$))
End If
Until OK
' .-----------------------------------------.
' | Now do the reconfiguring |
' `-----------------------------------------'
If _DO_RECONFIGURING
_ONE_PLAYER_GAME=((GS_TYPE=0) and(IND>=10))
If _ONE_PLAYER_GAME
_LOAD_CONFIGURATION[0] : Rem BUILTIN CONFIGURATION
_PLAYER_TYPE(1)=2
_PLAYER_TYPE(2)=2
_PLAYER_TYPE(3)=0
_PLAYER_TYPE(4)=1
_PLAYER_TYPE(5)=0
_PLAYER_TYPE(6)=0
For _PLAYER=1 To 6
SELECTED(_PLAYER)=(_PLAYER_TYPE(_PLAYER)>0)
_TOP_LIVES(_PLAYER)=0
Next
Add IND,-10
_TOP_LIVES(1)=IND
If IND>7 : _TOP_LIVES(1)=IND-2
Else If IND>5 : _TOP_LIVES(1)=IND-1 : End If
_TOP_LIVES(2)=IND
If IND>8 : _TOP_LIVES(2)=IND-2
Else If IND>6 : _TOP_LIVES(2)=IND-1 : End If
Else
If GS_TYPE=0
BASE=Start(DEF_GAMESET__BANK)
Else
BASE=Start(USER_GAMESET__BANK)
End If
C_BASE=BASE+Deek(BASE+2*IND)+$10
_DECONFIG[C_BASE,True]
If PLAN=2
P_LEN=Peek(C_BASE+$20)
OWN_PLAN_PATH$=Peek$(C_BASE+$21,P_LEN)
End If
If PLAN>0
SET_PLAN_USING_CONFIG[False]
End If
End If
End If
End Proc
Procedure SELECT_GAME
Screen 1 : Get Block 1,0,32,320-32-32,140
If _NOT(U_THRU)
Screen 2
Unpack PLAN_BANK(0)
P0=Phybase(0) : P1=Phybase(1) : P2=Phybase(2) : P3=Phybase(3)
Copy P1,P1+10240-1 To P0
Copy P2,P2+10240-1 To P1
Copy P3,P3+10240-1 To P2
Fill P3 To P3+10240-1,0
WRITEXY[45+7*5+20,51-10,SELECT_GAME$]
_DO_SELECTION_SCREEN[0]
End If
If(A$="U") or U_THRU
Screen 2
Unpack PLAN_BANK(0)
P0=Phybase(0) : P1=Phybase(1) : P2=Phybase(2) : P3=Phybase(3)
Copy P1,P1+10240-1 To P0
Copy P2,P2+10240-1 To P1
Copy P3,P3+10240-1 To P2
Fill P3 To P3+10240-1,0
WRITEXY[45+7*5+20-7*8,51-10,SELECT_GAME_FROM_USERSET$]
_DO_SELECTION_SCREEN[1]
U_THRU=False
End If
If(_ONE_PLAYER_GAME=0)
Screen 2 : Unpack PLAN_BANK(0)
P0=Phybase(0) : P1=Phybase(1) : P2=Phybase(2) : P3=Phybase(3)
Copy P1,P1+10240-1 To P0
Copy P2,P2+10240-1 To P1
Copy P3,P3+10240-1 To P2
Fill P3 To P3+10240-1,0
Get Block 1,0,32,320-32-32,140
SELECTING_PRINT[False]
Screen 1
End If
End Proc
Procedure CREATE_GAMESET[GS__BANK,CONFIG_LIST_NAME$]
' ________________________________
' | |
' | Count length to open |
' |________________________________|
EXTRACT_PATH[CONFIG_LIST_NAME$] : GAMESET_PATH$=Param$
NUMBER_OF_CONFIGS=0
Open In 1,CONFIG_LIST_NAME$
GAMESET_LENGTH=0
While Not Eof(1) or(NUMBER_OF_CONFIGS>=20)
Input #1,F_NAME$ : F_NAME$=GAMESET_PATH$+F_NAME$
If Exist(F_NAME$)
Open In 2,F_NAME$
Add GAMESET_LENGTH,Lof(2)+$10-20
Inc NUMBER_OF_CONFIGS
Close 2
End If
Wend
Close 1
Add GAMESET_LENGTH,20*2
' ________________________________
' | |
' | Push configs to set |
' |________________________________|
If NUMBER_OF_CONFIGS>0
Reserve As Work GS__BANK,GAMESET_LENGTH
CONFIG_NUMBER=0
Open In 1,CONFIG_LIST_NAME$
GS_BASE=Start(GS__BANK)
GS_POS=GS_BASE+20*2
For I=GS_BASE To GS_BASE+20*2-1
Poke I,0
Next I
While Not Eof(1) or(CONFIG_NUMBER>=20)
Input #1,F_NAME$ : C_NAME$=F_NAME$ : F_NAME$=GAMESET_PATH$+F_NAME$
If Exist(F_NAME$)
Erase CONFIG_TEMPORARY__BANK
Load F_NAME$,CONFIG_TEMPORARY__BANK
Doke GS_BASE+2*CONFIG_NUMBER,GS_POS-GS_BASE
C_NAME$=Left$(C_NAME$,$10)
C_NAME$=C_NAME$+Space$($10-Len(C_NAME$))
Poke$ GS_POS,C_NAME$ : Add GS_POS,16
BASE=Start(CONFIG_TEMPORARY__BANK)
TEMP_PLAN=Peek(BASE)+$E
Copy BASE,BASE+$20-1 To GS_POS : Add GS_POS,$20
If TEMP_PLAN=2
P_LEN=Peek(BASE+$20)
Copy BASE+$20,BASE+$20+P_LEN+1-1 To GS_POS : Add GS_POS,P_LEN+1
End If
Inc CONFIG_NUMBER
End If
Wend
Close 1
End If
End Proc[NUMBER_OF_CONFIGS]
' ______________________________________
' | \
' | @ Rest \
' |________________________________________\
Procedure _DO_SOUND[ST]
' ST means sound type
If SOUND_FX
If ST=BOUND_SOUND
Sam Play SOUND_FX_CHANNEL,2,7500+200*Rnd(5)
Else If ST=TELEPORT_SOUND
Sam Play SOUND_FX_CHANNEL,3,16000
Else If ST=DEATH_SOUND
Sam Play SOUND_FX_CHANNEL,1,12000
Else If ST=ARROW_SOUND
Sam Play SOUND_FX_CHANNEL,3,10000
Else If ST=PRESS_SPACE_SOUND
Else If ST=AUCH_SOUND
Sam Play SOUND_FX_CHANNEL,4,6000+500*Rnd(5)
Else If ST=BODY_CHANGE_SOUND
Sam Play SOUND_FX_CHANNEL,5,7000
End If
If GAME_MUSIC_PLAYING=0
SOUND_FX_CHANNEL=_NEXT_SOUND_FX_CHANNEL(SOUND_FX_CHANNEL)
End If
End If
End Proc
Procedure SET_SPP
P$=STANDARD_PLAN_PAL$(GAMEPLAN-1)
For I=0 To $F
C$="$"+Left$(P$,3) : P$=Mid$(P$,4,Len(P$)-3)
SPP(I)=Val(C$)
Next I
End Proc
Procedure FAST_FADE_OUT
If FAST_INTERFACE
Wait Vbl
Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Clear Key
Wait 1
Else
Fade 1
Wait 13
Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Wait Vbl : Wait 1
End If
End Proc
Procedure LET_IT_SHOW
Get Block 1,0,0,320,256,1
Screen 1
Put Block 1
Del Block 1
Screen 2
End Proc
Procedure _COUNT_SELECTED
HRAJOU=0
NUMBER_OF_LIVING_HUMANS=0
For _PLAYER=1 To 6
If SELECTED(_PLAYER)
Inc HRAJOU
If Not COMPUTER_STRATEGY(_PLAYER)
Inc NUMBER_OF_LIVING_HUMANS
End If
End If
Next _PLAYER
ZIJOU=HRAJOU
End Proc
Procedure SET_APPROPRIATE_DRAWPIXEL_PROC
_SPRITE_INDEX_BASE=4*BOLDLINE
' Poke VA_PUTPIX_TYPE,4*(Abs(BIG_SCREEN)*2+Abs(BOLDLINE))
Poke VA_PUTPIX_TYPE,4*(Sgn(_SCREEN_SIZE)*2+Abs(BOLDLINE))
If BOLDLINE=0
If _SCREEN_SIZE>0
PA_CURRENT_PIX=PA_SMALL_PIX_BIGSCREEN
Else
PA_CURRENT_PIX=PA_SMALL_PIX
End If
PA_COUNTTESTANDSPEEDPOINTS=PA_COUNTTESTANDSPEEDPOINTS_1PIX
Else
If _SCREEN_SIZE>0
PA_CURRENT_PIX=PA_BIG_PIX_BIGSCREEN
Else
PA_CURRENT_PIX=PA_BIG_PIX
End If
PA_COUNTTESTANDSPEEDPOINTS=PA_COUNTTESTANDSPEEDPOINTS_2PIX
End If
End Proc
Procedure REALIZE_PLAYER_TYPE
For _PLAYER=1 To 6
SELECTED(_PLAYER)=_PLAYER_PROPRIETY(0,_PLAYER_TYPE(_PLAYER))
COMPUTER_STRATEGY(_PLAYER)=_PLAYER_PROPRIETY(1,_PLAYER_TYPE(_PLAYER))
CYBORG(_PLAYER)=_PLAYER_PROPRIETY(2,_PLAYER_TYPE(_PLAYER))
Next _PLAYER
End Proc
Procedure _UPDATE_SCORE
If TEAM_GAME
For I=1 To 6
If ALIVE(I) and(I<>TEAM_MATE(_PLAYER))
Add SCORE(I),STAYED_ALIVE_BONUS(I)
Add SCORE(TEAM_MATE(I)),STAYED_ALIVE_BONUS(I)
If SCORE(I)>GR
GR=SCORE(I)
GRP=I
End If
End If
Next I
Else
For I=1 To 6
If ALIVE(I)
Add SCORE(I),STAYED_ALIVE_BONUS(I)
If SCORE(I)>GR
GR=SCORE(I)
GRP=I
End If
End If
Next I
End If
End Proc
Procedure MAKE_SCOREPANEL
Screen 4 : Cls 0
Paste Icon 0,0,1
Paste Icon 320,0,2
For _PLAYER=1 To 6
If SELECTED(_PLAYER)
Paste Icon 60*(_PLAYER-1)+25,0,19
End If
Next _PLAYER
' _____________________
' | |
' | Draw Init Lives |
' |_____________________|
If LIVES_ON
For _PLAYER=1 To 6
If SELECTED(_PLAYER) and(_TOP_LIVES(_PLAYER)>0)
For I=1 To _TOP_LIVES(_PLAYER)
Paste Icon 28+21+25+6+60*(_PLAYER-1)-2,2+(I-1)*4-1,20
Ink 9+_PLAYER
Bar 28+21+25+6+60*(_PLAYER-1),2+(I-1)*4 To 4+28+21+25+6+60*(_PLAYER-1),2+(I-1)*4+1
Next I
End If
Next _PLAYER
End If
Screen Copy 4 To 3
End Proc
Procedure _DRAW_SCORE
If Not(REPLAY_ALL_SAVED_ON) and 0
Screen 4
For I=1 To 6
If SEMIALIVE(I) or SEMIALIVE(TEAM_MATE(I))
If SCORE(I)>=10
Paste Icon 25+6+60*(I-1),3,12+I
Paste Icon 25+6+60*(I-1),3,SCORE(I)/10+3
End If
Paste Icon 25+6+60*(I-1)+21,3,12+I
Paste Icon 25+6+60*(I-1)+21,3,SCORE(I) mod 10+3
End If
Next I
Screen 1
End If
Screen Copy 4 To 3
End Proc
Procedure _DRAW_SMALL_WOOD_FRAME
Paste Bob 0,0,HORIZONTAL_WOOD_IMAGE+$4000
Paste Bob 160,0,HORIZONTAL_WOOD_IMAGE+$4000
Paste Bob 0,0,NOSCROLL_CORNER_IMAGE
Paste Bob 320-16,0,NOSCROLL_CORNER_IMAGE+$8000
Paste Bob 0,256-30-4-2,HORIZONTAL_WOOD_IMAGE
Paste Bob 160,256-30-4-2,HORIZONTAL_WOOD_IMAGE
Paste Bob 0,256-30-4-2,NOSCROLL_CORNER_IMAGE+$4000
Paste Bob 320-16,256-30-4-2,NOSCROLL_CORNER_IMAGE+$8000+$4000
Paste Bob 0,4,VERTICAL_WOOD_IMAGE
Paste Bob 320-16,4,VERTICAL_WOOD_IMAGE+$8000
End Proc
Procedure _DRAW_WINNER_WOOD_FRAME[DS_HEIGHT]
Paste Bob 0,0,HORIZONTAL_WOOD_IMAGE+$4000
Paste Bob 160,0,HORIZONTAL_WOOD_IMAGE+$4000
Paste Bob 0,0,NOSCROLL_CORNER_IMAGE
Paste Bob 320-16,0,NOSCROLL_CORNER_IMAGE+$8000
Paste Bob 0,DS_HEIGHT-4,HORIZONTAL_WOOD_IMAGE
Paste Bob 160,DS_HEIGHT-4,HORIZONTAL_WOOD_IMAGE
Paste Bob 0,4,VERTICAL_WOOD_IMAGE
Paste Bob 320-16,4,VERTICAL_WOOD_IMAGE+$8000
Paste Bob 0,DS_HEIGHT-4,NOSCROLL_CORNER_IMAGE+$4000
Paste Bob 320-16,DS_HEIGHT-4,NOSCROLL_CORNER_IMAGE+$8000+$4000
End Proc
Procedure EDGES_FOR_BOUNCING
If(X_WORK#<_LEFT_LIMIT) or(X_WORK#>_RIGHT_LIMIT)
SMER(_PLAYER)=SMERU-SMER(_PLAYER)
_DO_SOUND[BOUND_SOUND]
RECALCULATE_ANGLE=True
BOUND_THIS_ROUND(_PLAYER)=True
BOUND_COUNTER(_PLAYER)=3
End If
If(Y_WORK#<_UP_LIMIT) or(Y_WORK#>_DOWN_LIMIT)
SMER(_PLAYER)=SMERU/2-SMER(_PLAYER)
If SMER(_PLAYER)<0
Add SMER(_PLAYER),SMERU
End If
_DO_SOUND[BOUND_SOUND]
RECALCULATE_ANGLE=True
BOUND_THIS_ROUND(_PLAYER)=True
BOUND_COUNTER(_PLAYER)=3
End If
If CENTRAL_BOX=1
If(((X_WORK=XBOTTOM) or(X_WORK=XTOP)) and(Y_WORK>=YBOTTOM) and(Y_WORK<=YTOP))
SMER(_PLAYER)=SMERU-SMER(_PLAYER)
_DO_SOUND[BOUND_SOUND]
RECALCULATE_ANGLE=True
BOUND_THIS_ROUND(_PLAYER)=True
BOUND_COUNTER(_PLAYER)=3
End If
If(((Y_WORK=YBOTTOM) or(Y_WORK=YTOP)) and(X_WORK>=XBOTTOM) and(X_WORK<=XTOP))
SMER(_PLAYER)=SMERU/2-SMER(_PLAYER)
If SMER(_PLAYER)<0
Add SMER(_PLAYER),SMERU
End If
_DO_SOUND[BOUND_SOUND]
RECALCULATE_ANGLE=True
BOUND_THIS_ROUND(_PLAYER)=True
BOUND_COUNTER(_PLAYER)=3
End If
End If
End Proc
Procedure EDGES_STANDARD
If(X_WORK#<_LEFT_LIMIT) or(X_WORK#>_RIGHT_LIMIT) or(Y_WORK#<_UP_LIMIT) or(Y_WORK#>_DOWN_LIMIT)
_PLAYER_KILLED
End If
If CENTRAL_BOX=1
If((X_WORK=XBOTTOM) and(Y_WORK>YBOTTOM) and(Y_WORK<YTOP)) or((X_WORK=XTOP) and(Y_WORK>YBOTTOM) and(Y_WORK<YTOP))
_PLAYER_KILLED
End If
If((Y_WORK=YBOTTOM) and(X_WORK>XBOTTOM) and(X_WORK<XTOP)) or((Y_WORK=YTOP) and(X_WORK>XBOTTOM) and(X_WORK<XTOP))
_PLAYER_KILLED
End If
End If
End Proc
Procedure EDGES_FOR_TELEPORTING
If X_WORK#<_LEFT_LIMIT
X#(_PLAYER)=_RIGHT_LIMIT
If(Point(_RIGHT_LIMIT-0.5,Y#(_PLAYER))>$10) or(Point(_RIGHT_LIMIT-1.5,Y#(_PLAYER))>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
Else If X_WORK#>_RIGHT_LIMIT
X#(_PLAYER)=_LEFT_LIMIT
If(Point(_LEFT_LIMIT,Y#(_PLAYER))>$10) or(Point(_LEFT_LIMIT+1,Y#(_PLAYER))>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
End If
If Y_WORK#<_UP_LIMIT
Y#(_PLAYER)=_DOWN_LIMIT
If(Point(X#(_PLAYER),_DOWN_LIMIT-0.5)>$10) or(Point(X#(_PLAYER),_DOWN_LIMIT-1.5)>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
Else If Y_WORK#>_DOWN_LIMIT
Y#(_PLAYER)=_UP_LIMIT
If(Point(X#(_PLAYER),_UP_LIMIT)>$10) or(Point(X#(_PLAYER),_UP_LIMIT+1)>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
End If
If CENTRAL_BOX=1
If(X_WORK=XBOTTOM) and(Y_WORK>YBOTTOM) and(Y_WORK<YTOP)
X#(_PLAYER)=XTOP+1
If(Point(XTOP+1,Y#(_PLAYER))>$10) or(Point(XTOP+1+1,Y#(_PLAYER))>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
Else If(X_WORK=XTOP) and(Y_WORK>YBOTTOM) and(Y_WORK<YTOP)
X#(_PLAYER)=XBOTTOM
If(Point(XBOTTOM-0.5,Y#(_PLAYER))>$10) or(Point(XBOTTOM-1.5,Y#(_PLAYER))>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
End If
If(Y_WORK=YBOTTOM) and(X_WORK>XBOTTOM) and(X_WORK<XTOP)
Y#(_PLAYER)=YTOP+1
If(Point(X#(_PLAYER),YTOP+1)>$10) or(Point(X#(_PLAYER),YTOP+1+1)>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
End If
If(Y_WORK=YTOP) and(X_WORK>XBOTTOM) and(X_WORK<XTOP)
Y#(_PLAYER)=YBOTTOM
If(Point(X#(_PLAYER),YBOTTOM-0.5)>$10) or(Point(X#(_PLAYER),YBOTTOM-1.5)>$10)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
_DO_SOUND[TELEPORT_SOUND]
RECALCULATE_COORDINATES=True
End If
End If
End Proc
Procedure EDGES_FOR_WATERING
CAST_TYPE=0
If(X_WORK#<_LEFT_LIMIT) or(X_WORK#>_RIGHT_LIMIT)
CAST_TYPE=1
End If
If(Y_WORK#<_UP_LIMIT) or(Y_WORK#>_DOWN_LIMIT)
CAST_TYPE=2
Goto EW_FOUND
End If
If CENTRAL_BOX=1
If(((X_WORK=XBOTTOM) or(X_WORK=XTOP)) and(Y_WORK>=YBOTTOM) and(Y_WORK<=YTOP))
CAST_TYPE=1
End If
If(((Y_WORK=YBOTTOM) or(Y_WORK=YTOP)) and(X_WORK>=XBOTTOM) and(X_WORK<=XTOP))
CAST_TYPE=2
End If
End If
'~~~~~~ Uz vime kde prekroceno ~~~~~~
EW_FOUND:
If CAST_TYPE>0
ANGLE_MAKER=SMER(_PLAYER) mod SMERU_HALVE
'~~~~~~ Special transformation ~~~~~~
_REVERSE_CAST=(ANGLE_MAKER<SMERU_QUARTER)
If CAST_TYPE=1
_REVERSE_CAST= Not _REVERSE_CAST
End If
ANGLE_MAKER=ANGLE_MAKER mod SMERU_QUARTER
If _REVERSE_CAST
ANGLE_MAKER=SMERU_QUARTER-ANGLE_MAKER
End If
If ANGLE_MAKER*ANGLE_CONSTANT#<WATER_LIMIT#
EDGES_FOR_BOUNCING
Else
EDGES_FOR_TELEPORTING
End If
End If
End Proc
Procedure _PLAYER_KILLED
_PUTPIX_QUEUE_X(_PUTPIX_QUEUE_TOP)=X#(_PLAYER)
_PUTPIX_QUEUE_Y(_PUTPIX_QUEUE_TOP)=Y#(_PLAYER)
_PUTPIX_QUEUE_COLOUR(_PUTPIX_QUEUE_TOP)=$10+_PLAYER
Inc _PUTPIX_QUEUE_TOP
If ZOMBIES
If ZOMBIE(_PLAYER)
Inc LINE_LENGTH_(_PLAYER)
Inc SPACE_LENGTH_(_PLAYER)
SPACE_COUNTER(_PLAYER)=SPACE_LENGTH_(_PLAYER)
Else
_DO_SOUND[DEATH_SOUND]
ALIVE(_PLAYER)=_FALSE
ZOMBIE(_PLAYER)=_TRUE
Dec ZIJOU
_UPDATE_SCORE
_DRAW_SCORE
LINE_LENGTH_(_PLAYER)=1
SPACE_LENGTH_(_PLAYER)=15
LINE_COUNTER(_PLAYER)=LINE_LENGTH_(_PLAYER)+20-SPACE_LENGTH_(_PLAYER)+30
SPACE_COUNTER(_PLAYER)=SPACE_LENGTH_(_PLAYER)
End If
Else
_DO_SOUND[DEATH_SOUND]
SEMIALIVE(_PLAYER)=_FALSE
ALIVE(_PLAYER)=_FALSE
Dec ZIJOU
Dec NUMBER_OF_SEMIALIVES
If GO_FOR_COMPUTURBO
If(COMPUTER_STRATEGY(_PLAYER)=False)
Dec NUMBER_OF_LIVING_HUMANS
If NUMBER_OF_LIVING_HUMANS=0
GO_FOR_COMPUTURBO=_FALSE
DIE_COMPUTERS=COMPUDEATH
TURBOLIMIT=-1
End If
End If
End If
NS=_SPRITE_NUMBER(_PLAYER)
If(_SCREEN_SIZE=0) or(NS<4)
Sprite Off _SPRITE_NUMBER(_PLAYER)
Else
Bob Off _PLAYER-2
End If
_UPDATE_SCORE
_DRAW_SCORE
End If
End Proc
Procedure _PLAYER_KILLED__TESTED_ON_LIVES
If LIVES_ON and(LIVES(_PLAYER)>0)
_DO_SOUND[AUCH_SOUND]
Screen 3
Ink 0
Bar 28+21+25+6+60*(_PLAYER-1),2+(LIVES(_PLAYER)-1)*4 To 4+28+21+25+6+60*(_PLAYER-1),2+(LIVES(_PLAYER)-1)*4+1
Screen 4
Ink 0
Bar 28+21+25+6+60*(_PLAYER-1),2+(LIVES(_PLAYER)-1)*4 To 4+28+21+25+6+60*(_PLAYER-1),2+(LIVES(_PLAYER)-1)*4+1
Screen 1
' Dreg(0)=278 : Dreg(1)=LIVES(_PLAYER)*3-1+(_PLAYER-1)*43 : Dreg(2)=0
' Call(PA_BIG_PIX)
Dec LIVES(_PLAYER)
AUCH_PROTECTION(_PLAYER)=True
AUCH_COUNTER(_PLAYER)=30
LINE_COUNTER(_PLAYER)=LINE_LENGTH_(_PLAYER)+20-SPACE_LENGTH_(_PLAYER)+30
SPACE_COUNTER(_PLAYER)=30
Else
_PLAYER_KILLED
End If
End Proc
Procedure GAME
If ESC
Goto _FADE_OUT
End If
If GAME_MUSIC_PLAYING
Volume 0
For I=0 To 40 Step 5 : Volume I : Wait Vbl : Next I
Else
Volume 40
End If
Make Mask
If J_REPLAYING_OR_J_RECORDING
Loke VA_GAME_RECORD_POINTER,0
End If
'<<<<<<<<<<<<<<<< Main Loop >>>>>>>>>>>>>>>>
CYCLES=0
Repeat
Timer=0
If JUST_REPLAYING
Call(PA_LOAD_POSITION)
End If
_PUTPIX_QUEUE_TOP=0
For _PLAYER=1 To 6
If SEMIALIVE(_PLAYER)
' ---------------- Care About Spaces ---------------
Dec LINE_COUNTER(_PLAYER)
If LINE_COUNTER(_PLAYER)=0
If J_REPLAYING_OR_J_RECORDING or ZOMBIE(_PLAYER)
LINE_COUNTER(_PLAYER)=LINE_LENGTH_(_PLAYER)+20
Else
LINE_COUNTER(_PLAYER)=LINE_LENGTH_(_PLAYER)+Rnd(40)-20
End If
SPACE_COUNTER(_PLAYER)=SPACE_LENGTH_(_PLAYER)
End If
If AUCH_PROTECTION(_PLAYER)
Dec AUCH_COUNTER(_PLAYER)
If AUCH_COUNTER(_PLAYER)=0
AUCH_PROTECTION(_PLAYER)=False
GAME_SLOWED=_FALSE
End If
End If
' ---------------- Compute New position -------------
If WIND
TIMES_CONSTANT#=SPEED_PERCENT#(_PLAYER)*RATE#*WIND_FACTOR#(_PLAYER)
Else
TIMES_CONSTANT#=SPEED_PERCENT#(_PLAYER)*RATE#
End If
' ________________
' | |
' | count sin+cos |
' |________________|
Dreg(0)=SMER(_PLAYER)
Call(PA_COUNTSINANDCOS)
Loke Varptr(_SIN_ANGLE#),Dreg(0)
Loke Varptr(_COS_ANGLE#),Dreg(2)
_SIN_KRAT_TIMES_CONSTANT#=_SIN_ANGLE#*TIMES_CONSTANT#
_COS_KRAT_TIMES_CONSTANT#=_COS_ANGLE#*TIMES_CONSTANT#
X_WORK#=X#(_PLAYER)+_SIN_KRAT_TIMES_CONSTANT#
Y_WORK#=Y#(_PLAYER)+_COS_KRAT_TIMES_CONSTANT#
X_WORK=X_WORK#
Y_WORK=Y_WORK#
RECALCULATE_ANGLE=False
RECALCULATE_COORDINATES=False
If BOUNCING
EDGES_FOR_BOUNCING
Else If TELEPORTING
EDGES_FOR_TELEPORTING
Else If WATERING
EDGES_FOR_WATERING
Else
EDGES_STANDARD
End If
If BOUND_THIS_ROUND(_PLAYER)
Dec BOUND_COUNTER(_PLAYER)
If BOUND_COUNTER(_PLAYER)=0
BOUND_THIS_ROUND(_PLAYER)=False
End If
End If
' ________________________________
' | |
' | Count test and speed points |
' |________________________________|
Dreg(0)=SMER(_PLAYER)
Areg(1)=Leek(Varptr(X#(_PLAYER)))
Areg(2)=Leek(Varptr(Y#(_PLAYER)))
Call(PA_COUNTTESTANDSPEEDPOINTS)
Loke Varptr(X_TESTPOINT),Dreg(0)
Loke Varptr(Y_TESTPOINT),Dreg(1)
Loke Varptr(X_SPEEDPOINT),Areg(1)
Loke Varptr(Y_SPEEDPOINT),Areg(2)
' ________________________________
' | |
' | Ted uloz do x#,y# novou posici |
' |________________________________|
If RECALCULATE_ANGLE
Dreg(0)=SMER(_PLAYER)
Call(PA_COUNTSINANDCOS)
Loke Varptr(_SIN_ANGLE#),Dreg(0)
Loke Varptr(_COS_ANGLE#),Dreg(2)
X#(_PLAYER)=X#(_PLAYER)+_SIN_ANGLE#*TIMES_CONSTANT#
Y#(_PLAYER)=Y#(_PLAYER)+_COS_ANGLE#*TIMES_CONSTANT#
Else If RECALCULATE_COORDINATES
X#(_PLAYER)=X#(_PLAYER)+_SIN_KRAT_TIMES_CONSTANT#
Y#(_PLAYER)=Y#(_PLAYER)+_COS_KRAT_TIMES_CONSTANT#
Else
X#(_PLAYER)=X_WORK#
Y#(_PLAYER)=Y_WORK#
End If
' .-------------------------------------------------------.
' | What's under head? |
' `-------------------------------------------------------'
TEST_POINT=Point(X_TESTPOINT,Y_TESTPOINT)
SPEED_POINT=Point(X_SPEEDPOINT,Y_SPEEDPOINT)
If TEST_POINT>$10
If BOUND_THIS_ROUND(_PLAYER)
If(TEST_POINT<>($10+_PLAYER)) and(TEST_POINT<$18) and(SPACE_COUNTER(_PLAYER)<(SPACE_LENGTH+10)*SPACE_KILL) and(AUCH_PROTECTION(_PLAYER)=_FALSE)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
Else If TEAM_GAME
If(TEST_POINT<$18) and(SPACE_COUNTER(_PLAYER)<(SPACE_LENGTH+10)*SPACE_KILL) and(AUCH_PROTECTION(_PLAYER)=False) and((TEST_POINT=TEAM_MATE_THRU(_PLAYER))=False)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
Else
If(TEST_POINT<$18) and(SPACE_COUNTER(_PLAYER)<(SPACE_LENGTH+10)*SPACE_KILL) and(AUCH_PROTECTION(_PLAYER)=False)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
End If
End If
If DIE_COMPUTERS and COMPUTER_STRATEGY(_PLAYER)
_PLAYER_KILLED__TESTED_ON_LIVES
End If
If SPEED_POINT<$10
SPEED_PERCENT#(_PLAYER)=SPEED_SOURCE#(SPEED_POINT)
End If
If Not SEMIALIVE(_PLAYER)
Goto DEAD
End If
' .-------------------------------------------------------.
' | Umisti sprita |
' `-------------------------------------------------------'
NS=_SPRITE_NUMBER(_PLAYER)
If _SCREEN_SIZE>0
If NS<4
NI=_SPRITE_IMAGE(_PLAYER)
_SPRITE_Y=Y#(_PLAYER)+42-_VIEWED_AREA_Y
If _SPRITE_Y>(256-36+42-2)
Sprite Off NS
Else
Sprite NS,X#(_PLAYER)+X Hard(0)-_VIEWED_AREA_X,_SPRITE_Y,NI+_SPRITE_INDEX_BASE
End If
Else
Bob _PLAYER-2,X#(_PLAYER),Y#(_PLAYER),
End If
Else
Sprite NS,X#(_PLAYER)+X Hard(0),Y#(_PLAYER)+42,
End If
Dec SPACE_COUNTER(_PLAYER)
If(SPACE_COUNTER(_PLAYER)<0)
_PUTPIX_QUEUE_X(_PUTPIX_QUEUE_TOP)=X#(_PLAYER)
_PUTPIX_QUEUE_Y(_PUTPIX_QUEUE_TOP)=Y#(_PLAYER)
_PUTPIX_QUEUE_COLOUR(_PUTPIX_QUEUE_TOP)=$10+_PLAYER
Inc _PUTPIX_QUEUE_TOP
End If
' .-------------------------------------------------------.
' | Player or Computer input |
' `-------------------------------------------------------'
If JUST_REPLAYING
LEFT_PUSHED=(_PLAYER_RECORD(_PLAYER-1)=1)
RIGHT_PUSHED=(_PLAYER_RECORD(_PLAYER-1)=2)
Else If CYBORG(_PLAYER)
Clear Key
On _PLAYER Goto C1,C2,C3,C4,C5,C6
C1: RIGHT_PUSHED=Key State(66)
LEFT_PUSHED=Key State(0) : Goto C_END
C2: RIGHT_PUSHED=(Key Shift and $40)
LEFT_PUSHED=(Key Shift and $10) : Goto C_END
C3: RIGHT_PUSHED=Key State(54) or Jright(1)
LEFT_PUSHED=Key State(53) or Jleft(1) : Goto C_END
C4: RIGHT_PUSHED=(Key Shift and $20)
LEFT_PUSHED=(Key Shift and $80) : Goto C_END
C5: RIGHT_PUSHED=Key State(95) or(Mouse Key and 2)
LEFT_PUSHED=Key State(70) or(Mouse Key and 1) : Goto C_END
C6: RIGHT_PUSHED=Key State(63)
LEFT_PUSHED=Key State(47)
C_END:
If Not(RIGHT_PUSHED or LEFT_PUSHED)
PRUMER_CHANGE#=(1+TIMES_CONSTANT#)/2
Loke VA_DIRECTION,SMER(_PLAYER)
Loke VA_XAMOSREAL,Leek(Varptr(X#(_PLAYER)))
Loke VA_YAMOSREAL,Leek(Varptr(Y#(_PLAYER)))
Loke VA_ROTATION,(SMERU_QUARTER*PRUMER_CHANGE#+2)
Loke VA_PLAYER,(_PLAYER-1)
Call(PA_STRATEGY)
LEFT_PUSHED=(Dreg(7)=1)
RIGHT_PUSHED=(Dreg(7)=2)
End If
Else If COMPUTER_STRATEGY(_PLAYER)
PRUMER_CHANGE#=(1+TIMES_CONSTANT#)/2
Loke VA_DIRECTION,SMER(_PLAYER)
Loke VA_XAMOSREAL,Leek(Varptr(X#(_PLAYER)))
Loke VA_YAMOSREAL,Leek(Varptr(Y#(_PLAYER)))
Loke VA_ROTATION,(SMERU_QUARTER*PRUMER_CHANGE#+2)
Loke VA_PLAYER,(_PLAYER-1)
Call(PA_STRATEGY)
LEFT_PUSHED=(Dreg(7)=1)
RIGHT_PUSHED=(Dreg(7)=2)
Else
Clear Key
On _PLAYER Goto L1,L2,L3,L4,L5,L6
L1: RIGHT_PUSHED=Key State(66)
LEFT_PUSHED=Key State(0) : Goto L_END
L2: RIGHT_PUSHED=(Key Shift and $40)
LEFT_PUSHED=(Key Shift and $10) : Goto L_END
L3: RIGHT_PUSHED=Key State(54) or Jright(1)
LEFT_PUSHED=Key State(53) or Jleft(1) : Goto L_END
L4: RIGHT_PUSHED=(Key Shift and $20)
LEFT_PUSHED=(Key Shift and $80) : Goto L_END
L5: RIGHT_PUSHED=Key State(95) or(Mouse Key and 2)
LEFT_PUSHED=Key State(70) or(Mouse Key and 1) : Goto L_END
L6: RIGHT_PUSHED=Key State(63)
LEFT_PUSHED=Key State(47)
L_END:
End If
'!!!!!!!!!!!! Future FIRE !!!!!!!!
If(LEFT_PUSHED and RIGHT_PUSHED)
LEFT_PUSHED=False
RIGHT_PUSHED=False
End If
_PLAYER_MOVE=0
If ALWAYS_TURNING=1
If LEFT_PUSHED
TURNING(_PLAYER)=1
End If
If RIGHT_PUSHED
TURNING(_PLAYER)=2
End If
If TURNING(_PLAYER)=1
Add SMER(_PLAYER),1,0 To SMERU-1
End If
If TURNING(_PLAYER)=2
Add SMER(_PLAYER),-1,0 To SMERU-1
End If
If JUST_RECORDING
_PLAYER_MOVE=TURNING(_PLAYER)
End If
Else
If LEFT_PUSHED
Add SMER(_PLAYER),1,0 To SMERU-1
_PLAYER_MOVE=1
End If
If RIGHT_PUSHED
Add SMER(_PLAYER),-1,0 To SMERU-1
_PLAYER_MOVE=2
End If
End If
' .-------------------------------------------------------.
' | Change directions according to wind |
' `-------------------------------------------------------'
If WIND
TEMP_ANGLE=SMER(_PLAYER)-WIND_ANGLE
If TEMP_ANGLE<0
Add TEMP_ANGLE,SMERU
End If
Dreg(0)=TEMP_ANGLE : Call(PA_COUNTSINANDCOS)
Loke Varptr(_SIN_ANGLE#),Dreg(0)
Loke Varptr(_COS_ANGLE#),Dreg(2)
SIGN=Sgn(_SIN_ANGLE#) : _SIN_ANGLE#=Abs(_SIN_ANGLE#)
A=Rnd(999)
If A<Int(WIND_STRENGTH#*_SIN_ANGLE#*1000.0)
Add SMER(_PLAYER),SIGN,0 To SMERU-1
End If
WIND_FACTOR#(_PLAYER)=Sqr(1.0-WIND_STRENGTH#*_COS_ANGLE#)
End If
If JUST_RECORDING
_PLAYER_RECORD(_PLAYER-1)=_PLAYER_MOVE
End If
DEAD:
End If
Next _PLAYER
If _BOBS_USED
Bob Clear
Call(PA_DRAW_PIXEL_QUEUE)
Bob Draw
Else
Call(PA_DRAW_PIXEL_QUEUE)
End If
If GAME_SLOWED
Repeat : Until Timer>2
Else
Repeat : Until Timer>TURBOLIMIT
End If
If JUST_RECORDING
Call(PA_SAVE_POSITION)
End If
' ________________________________
' | |
' | Viewed area possition |
' |________________________________|
If _SCREEN_SIZE>0
X_SUM=0 : Y_SUM=0 : SUM_NUM=0
For I=1 To 6
If SEMIALIVE(I) and(_PLAYER_TYPE(I)=1)
X_SUM=X_SUM+Int(X#(I))
Y_SUM=Y_SUM+Int(Y#(I))
Inc SUM_NUM
End If
Next I
If SUM_NUM=0
For I=1 To 6
If SEMIALIVE(I)
X_SUM=X_SUM+Int(X#(I))
Y_SUM=Y_SUM+Int(Y#(I))
Inc SUM_NUM
End If
Next I
End If
If SUM_NUM>0
X_SUM=(X_SUM/SUM_NUM)-160
Y_SUM=(Y_SUM/SUM_NUM)-110
End If
D_X0=X_SUM-_VIEWED_AREA_X
D_Y0=Y_SUM-_VIEWED_AREA_Y
X_SUM=Max(X_SUM,0)
Y_SUM=Max(Y_SUM,0)
X_SUM=Min(X_SUM,X_SCROLL_LIMIT)
Y_SUM=Min(Y_SUM,Y_SCROLL_LIMIT)
D_X=X_SUM-_VIEWED_AREA_X
D_Y=Y_SUM-_VIEWED_AREA_Y
If _NOT(_DO_X_SCROLL) and(Abs(D_X0)>20)
_DO_X_SCROLL=_TRUE
End If
If _NOT(_DO_Y_SCROLL) and(Abs(D_Y0)>20)
_DO_Y_SCROLL=_TRUE
End If
If _DO_X_SCROLL
If(Abs(D_X)>0)
_VIEWED_AREA_X=_VIEWED_AREA_X+Sgn(D_X)
Else
_DO_X_SCROLL=_FALSE
End If
End If
If _DO_Y_SCROLL
If(Abs(D_Y)>0)
_VIEWED_AREA_Y=_VIEWED_AREA_Y+Sgn(D_Y)
Else
_DO_Y_SCROLL=_FALSE
End If
End If
Screen Offset 1,_VIEWED_AREA_X,_VIEWED_AREA_Y
End If
' ________________________________
' | |
' | Care about rate |
' |________________________________|
If STILL_SPEEDING_UP
RATE#=RATE#+RATEJUMP#
_MUSIC_TEMPO#=_MUSIC_TEMPO#+_MUSIC_TEMPO_JUMP#
Tempo _MUSIC_TEMPO#
If RATE#>=FINAL_RATE#
STILL_SPEEDING_UP=False
End If
End If
' ________________________________
' | |
' | Body Change |
' |________________________________|
If BODY_CHANGE and(ZIJOU>1)
Dec BODY_CHANGE_COUNTER
If BODY_CHANGE_COUNTER<0
BODY_CHANGE_COUNTER=(_EXPECTED_GAME_LENGTH*BODY_CHANGE_PERCENT)/200+Rnd((_EXPECTED_GAME_LENGTH*BODY_CHANGE_PERCENT)/100)
BODY_CHANGE_COUNTER=Max(BODY_CHANGE_COUNTER,100)
_DO_SOUND[BODY_CHANGE_SOUND]
GAME_SLOWED=_TRUE
' ------- make list of living players ----------
LIVING_PLAYER=1
_PLAYER=1
While LIVING_PLAYER<=ZIJOU
If ALIVE(_PLAYER)
LIVING_PLAYER(LIVING_PLAYER)=_PLAYER
Inc LIVING_PLAYER
End If
Inc _PLAYER
Wend
' ---------- Permute living players ----------
Repeat
CORRECT=_TRUE
For _PLAYER=1 To ZIJOU
_FREE_VALUE(_PLAYER)=_TRUE
Next
_PLAYER=1
While(_PLAYER<=ZIJOU) and CORRECT
P=(Rnd(ZIJOU-1) mod(ZIJOU-_PLAYER+1))+1
I=0
Repeat
Inc I
If _FREE_VALUE(I) : Dec P : End If
Until P=0
_FREE_VALUE(I)=_FALSE
NEW_PLAYER(_PLAYER)=I
CORRECT=CORRECT and(I<>_PLAYER)
Inc _PLAYER
Wend
Until CORRECT
' ---------- swap x,y,smer ----------
For LIVING_PLAYER=1 To ZIJOU
_PLAYER=LIVING_PLAYER(LIVING_PLAYER)
NEW_PLAYER=LIVING_PLAYER(NEW_PLAYER(LIVING_PLAYER))
AUCH_PROTECTION(_PLAYER)=True
AUCH_COUNTER(_PLAYER)=50
LINE_COUNTER(_PLAYER)=LINE_LENGTH+20
NEW_X#(_PLAYER)=X#(NEW_PLAYER)
NEW_Y#(_PLAYER)=Y#(NEW_PLAYER)
NEW_SMER(_PLAYER)=SMER(NEW_PLAYER)
Next
For _PLAYER=1 To 6
If ALIVE(_PLAYER)
X#(_PLAYER)=NEW_X#(_PLAYER)
Y#(_PLAYER)=NEW_Y#(_PLAYER)
SMER(_PLAYER)=NEW_SMER(_PLAYER)
End If
Next _PLAYER
End If
End If
If WIND_TURNING
If Rnd(999)<2
Add WIND_ANGLE,1,0 To SMERU-1
End If
End If
ESC=ESC or Key State(ESC_SCANCODE)
Inc CYCLES
Poke VA_TURN,Peek(VA_TURN) xor 1
Until(ZIJOU<2) or ESC
' ________________________________
' | |
' | All players are dead |
' |________________________________|
For _PLAYER=1 To 6
If ZOMBIE(_PLAYER)
NS=_SPRITE_NUMBER(_PLAYER)
If(_SCREEN_SIZE=0) or(NS<4)
Sprite Off _SPRITE_NUMBER(_PLAYER)
Else
Bob Off _PLAYER-2
End If
End If
Next _PLAYER
WIN=_FALSE
If GR>=_TOPSCORE
WIN=_TRUE
For I=1 To 6
If TEAM_GAME
WIN=WIN and((I=GRP) or(I=TEAM_MATE(GRP)) or(SCORE(I)<>GR))
Else
WIN=WIN and((I=GRP) or(SCORE(I)<>GR))
End If
Next I
End If
If GAME_MUSIC_PLAYING
For I=40 To 0 Step -1 : Mvolume I : Wait Vbl : Next I
Mvolume 0
End If
If WIN and JUST_RECORDING
GAME_RECORD_EMPTY=_FALSE
End If
_ANIM_FLAG_AND_PRESS_SPACE_PRINT
Inc GAMES_PLAYED
_FADE_OUT:
GAME_FADE_OUT
Sprite Off
Bob Off
End Proc
Procedure _ANIM_FLAG_AND_PRESS_SPACE_PRINT
If(ESC or WIN)=0
'------------------ Is Anyone Alive ? ---------------------
SURVIVAL_PLAYER=0
For I=1 To 6
If ALIVE(I)
SURVIVAL_PLAYER=I
End If
Next I
If(SURVIVAL_PLAYER>0) and(_SCREEN_SIZE>0)
For I=1 To 6
NS=_SPRITE_NUMBER(I)
If(I<>SURVIVAL_PLAYER) and(NS<4)
Sprite Off NS
End If
Next I
X_SUM=X#(SURVIVAL_PLAYER)-160
Y_SUM=Y#(SURVIVAL_PLAYER)-110
X_SUM=Max(X_SUM,0)
Y_SUM=Max(Y_SUM,0)
X_SUM=Min(X_SUM,X_SCROLL_LIMIT)
Y_SUM=Min(Y_SUM,Y_SCROLL_LIMIT)
X_SUM=X_SUM and $FFFE
Y_SUM=Y_SUM and $FFFE
_VIEWED_AREA_X=_VIEWED_AREA_X and $FFFE
_VIEWED_AREA_Y=_VIEWED_AREA_Y and $FFFE
Repeat
_VIEWED_AREA_X=_VIEWED_AREA_X+2*Sgn(X_SUM-_VIEWED_AREA_X)
_VIEWED_AREA_Y=_VIEWED_AREA_Y+2*Sgn(Y_SUM-_VIEWED_AREA_Y)
NS=_SPRITE_NUMBER(SURVIVAL_PLAYER)
NI=_SPRITE_IMAGE(SURVIVAL_PLAYER)
_SPRITE_Y=Y#(SURVIVAL_PLAYER)+42-_VIEWED_AREA_Y
Sprite NS,X#(SURVIVAL_PLAYER)+X Hard(0)-_VIEWED_AREA_X,_SPRITE_Y,NI+_SPRITE_INDEX_BASE
Screen Offset 1,_VIEWED_AREA_X,_VIEWED_AREA_Y
Wait Vbl
Until(_VIEWED_AREA_X=X_SUM) and(_VIEWED_AREA_Y=Y_SUM)
End If
If JUST_RECORDING
GAME_RECORD_EMPTY=_FALSE
IS_GAME_SAVING
Else
ALLOW_GAME_SAVING=_FALSE
End If
Paste Bob 160-50/2+_VIEWED_AREA_X,160-30/2+_VIEWED_AREA_Y,PRESS_SPACE_IMAGE
If SURVIVAL_PLAYER>0
If _SCREEN_SIZE=0
Sprite Off
End If
Bank Swap 1,23
SURVIVAL_COLOUR=Colour($10+SURVIVAL_PLAYER)
For I=1 To 6 : PL_RGB(I)=_PLAYER_GREY_COLOUR(I) : Next I
PL_RGB(SURVIVAL_PLAYER)=SURVIVAL_COLOUR
Fade 1,,,,,,,,,,,,,,,,,,PL_RGB(1),PL_RGB(2),PL_RGB(3),PL_RGB(4),PL_RGB(5),PL_RGB(6)
Wait 12
Y_FLAG=Int(Y#(SURVIVAL_PLAYER))
Colour $17,Colour($10+SURVIVAL_PLAYER)
Sprite 0,X#(SURVIVAL_PLAYER)+X Hard(0)-15-_VIEWED_AREA_X,Y_FLAG+42-22+BOLDLINE-_VIEWED_AREA_Y,1
If _SCREEN_SIZE>0
Screen 5
Get Palette 1
Screen 1
End If
_ANIM_FLAG$="Anim 0,(1,2)(2,2)(3,2)(4,2)(5,2)(6,2)(12,2)(11,2)(10,2)(9,2)(8,2)(7,2)"
Amal 0,_ANIM_FLAG$
Amal On
If Y_FLAG<14
For Y_CURR=Y_FLAG To 30
Sprite 0,X#(SURVIVAL_PLAYER)+X Hard(0)-15-_VIEWED_AREA_X,Y_CURR+42-22+BOLDLINE_VIEWED_AREA_Y,
Wait Vbl
Next Y_CURR
End If
End If
Timer=0
If DEMO_ON
Repeat
Until Timer>DEMO_PRESS_SPACE_LIMIT
Else
If _ONLY_COMPUTERS_IN_GAME
PRESS_SPACE_LIMIT=50*4
Else
PRESS_SPACE_LIMIT=999999999
End If
Clear Key
Repeat
ESC_PRESSED=Key State(ESC_SCANCODE)
SPACE_PRESSED=Key State(SPACE_SCANCODE)
R_PRESSED=Key State(R_SCANCODE) and JUST_RECORDING
S_PRESSED=Key State(S_SCANCODE) and ALLOW_GAME_SAVING
Until ESC_PRESSED or SPACE_PRESSED or R_PRESSED or S_PRESSED or(Timer>PRESS_SPACE_LIMIT)
ESC=ESC_PRESSED
If R_PRESSED
JUST_RECORDING=_FALSE
End If
If S_PRESSED
Trap Save GAME_SAVING_PATH$+RECORDNAME$+INDEX$,30
End If
End If
If SURVIVAL_PLAYER>0
Amal Off
Sprite Off
Bank Swap 1,23
End If
_DO_SOUND[PRESS_SPACE_SOUND]
Wait Vbl
End If
End Proc
Procedure INITIALIZE_GAME
' ________________________________
' | |
' | Load gamerecord |
' |________________________________|
If REPLAY_ALL_SAVED_ON
Trap Load GAME_SAVING_PATH$+RECORDNAME$+INDEX$,30
End If
If JUST_REPLAYING or JUST_RECORDING
RECORD_BASE=Start(30)
RECORD_MOVEMENTS_START=RECORD_BASE+$130
Loke VA_GAME_RECORD,RECORD_MOVEMENTS_START
If JUST_REPLAYING
_DECONFIG[RECORD_BASE+$B0,False]
SET_PLAN_USING_CONFIG[False]
Else If JUST_RECORDING
CONFIG[RECORD_BASE+$B0,False]
End If
End If
' ________________________________
' | |
' | Some neccessities |
' |________________________________|
SOUND_FX=USER_SOUND_FX and ENABLED_SOUND
SOUND_FX_CHANNEL=1
If JUST_REPLAYING
For I=1 To 6
SELECTED(I)=-Peek(RECORD_BASE+72+I-1)
Next I
_COUNT_SELECTED
End If
If GAMES_PLAYED>0
_EXPECTED_GAME_LENGTH=(_EXPECTED_GAME_LENGTH*GAMES_PLAYED+CYCLES)/(GAMES_PLAYED+1)
End If
BODY_CHANGE_COUNTER=(_EXPECTED_GAME_LENGTH*BODY_CHANGE_PERCENT)/200+Rnd((_EXPECTED_GAME_LENGTH*BODY_CHANGE_PERCENT)/100)
BODY_CHANGE_COUNTER=Max(BODY_CHANGE_COUNTER,100)
GAME_SLOWED=_FALSE
DIE_COMPUTERS=_FALSE
If(Prg State=-1)
_TOPSCORE=(HRAJOU-1)*5
If LONG_GAME
_TOPSCORE=_TOPSCORE*2
End If
Else
_TOPSCORE=(HRAJOU-1)*DEBUGGING_LIFELIMIT_COEFICIENT
End If
' .---------------------.
' | Draw Background |
' `---------------------'
If _SCREEN_SIZE>0
Screen 2
If Length(PLAN_BANK(PLAN))>0 : Unpack PLAN_BANK(PLAN)
Else : Cls 0 : End If
Screen Copy 2,0,0,320,256 To 1,0,0
Screen Copy 2,0,0,320,256 To 1,320,256
Screen Copy 2,0,0,320,256 To 1,320,0
Screen Copy 2,0,0,320,256 To 1,0,256
Else
Screen 1
If Length(PLAN_BANK(PLAN))>0 : Unpack PLAN_BANK(PLAN)
Else : Cls 0 : End If
Ink 0 : Bar 0,256-30-3 To 320-1,256-1
End If
' .----------------.
' | Set bordes |
' `----------------'
If _SCREEN_SIZE=2
XBOTTOM=640/2-2*CENTRAL_BOX_SIZE
XTOP=640/2+2*CENTRAL_BOX_SIZE
YBOTTOM=(512-30)/2-2*CENTRAL_BOX_SIZE
YTOP=(512-30)/2+2*CENTRAL_BOX_SIZE
_LEFT_LIMIT=4+3+1
_UP_LIMIT=4+3
_RIGHT_LIMIT=320*2-5-3-1
_DOWN_LIMIT=256*2-5-3
X_SCROLL_LIMIT=640-320
Y_SCROLL_LIMIT=512-256+31
Else If _SCREEN_SIZE=1
XBOTTOM=480/2-2*CENTRAL_BOX_SIZE
XTOP=480/2+2*CENTRAL_BOX_SIZE
YBOTTOM=(384-30)/2-2*CENTRAL_BOX_SIZE
YTOP=(384-30)/2+2*CENTRAL_BOX_SIZE
_LEFT_LIMIT=4+3+1
_UP_LIMIT=4+3
_RIGHT_LIMIT=320*1.5-5-3-1
_DOWN_LIMIT=256*1.5-5-3
X_SCROLL_LIMIT=480-320
Y_SCROLL_LIMIT=384-256+31
Else
XBOTTOM=320/2-CENTRAL_BOX_SIZE
XTOP=320/2+CENTRAL_BOX_SIZE
YBOTTOM=(256-30)/2-CENTRAL_BOX_SIZE
YTOP=(256-30)/2+CENTRAL_BOX_SIZE
_LEFT_LIMIT=4
_UP_LIMIT=4
_RIGHT_LIMIT=320-5
_DOWN_LIMIT=256-30-5-2
End If
If BOLDLINE=0
Inc _RIGHT_LIMIT
Inc _DOWN_LIMIT
Inc XBOTTOM
Inc YBOTTOM
End If
_VIEWED_AREA_X=0
_VIEWED_AREA_Y=0
_DO_X_SCROLL=_FALSE
_DO_Y_SCROLL=_FALSE
Screen Offset 1,_VIEWED_AREA_X,_VIEWED_AREA_Y
Sprite Off
' .-----------------------------------.
' | Precount SpeedSource# |
' `-----------------------------------'
TEMP#=SPEEDJUMP : SPEEDJUMP#=0.01*TEMP#/15
For UNDER_HEAD=0 To $F
SPEED=UNDER_HEAD
SPEED_SOURCE#(UNDER_HEAD)=1-SPEED*SPEEDJUMP#
Next UNDER_HEAD
' .-----------------------------------.
' | Set begin positions of players |
' `-----------------------------------'
BEGIN_Y_MAX=256-36-10
LIVES_ON=_FALSE
For _PLAYER=1 To 6
If SELECTED(_PLAYER)
NC=_TRUE : Rem New Coordinates
While NC
If JUST_REPLAYING
SMER(_PLAYER)=Leek(RECORD_BASE+4*(_PLAYER-1))
If SMER(_PLAYER)>=SMERU
SMER(_PLAYER)=SMERU-1
End If
ANGLE#=ANGLE_CONSTANT#*SMER(_PLAYER)
X#(_PLAYER)=Leek(RECORD_BASE+24+4*(_PLAYER-1))
Y#(_PLAYER)=Leek(RECORD_BASE+48+4*(_PLAYER-1))
Else
SMER(_PLAYER)=Rnd(SMERU)
RADIUS=Rnd(160)+40
ANGLE#=ANGLE_CONSTANT#*SMER(_PLAYER)
X#(_PLAYER)=145-Sin(ANGLE#)*RADIUS
Y#(_PLAYER)=127-Cos(ANGLE#)*RADIUS
X#(_PLAYER)=Int(X#(_PLAYER))
Y#(_PLAYER)=Int(Y#(_PLAYER))
End If
NC=_FALSE
NC=NC or(X#(_PLAYER)<10) or(X#(_PLAYER)>270) or(Y#(_PLAYER)<10) or(Y#(_PLAYER)>BEGIN_Y_MAX)
NC=NC or((X#(_PLAYER)>XBOTTOM-10) and(X#(_PLAYER)<XTOP+10)) or((Y#(_PLAYER)>YBOTTOM-10) and(Y#(_PLAYER)<YTOP+10))
If _PLAYER>1
For I=1 To _PLAYER-1
If SELECTED(I)
NC=NC or(Abs(X#(I)-X#(_PLAYER))<15) and(Abs(Y#(I)-Y#(_PLAYER))<15)
End If
Next I
End If
Wend
If JUST_RECORDING
Loke RECORD_BASE+4*(_PLAYER-1),SMER(_PLAYER)
Loke RECORD_BASE+24+4*(_PLAYER-1),Int(X#(_PLAYER))
Loke RECORD_BASE+48+4*(_PLAYER-1),Int(Y#(_PLAYER))
End If
If JUST_RECORDING or JUST_REPLAYING
LINE_COUNTER(_PLAYER)=LINE_LENGTH+6
Else
LINE_COUNTER(_PLAYER)=LINE_LENGTH+Rnd(12)-6
End If
SPACE_COUNTER(_PLAYER)=-1
SPEED_PERCENT#(_PLAYER)=1
TURNING(_PLAYER)=0
AUCH_PROTECTION(_PLAYER)=False
LIVES(_PLAYER)=_TOP_LIVES(_PLAYER)
LIVES_ON=LIVES_ON or(_TOP_LIVES(_PLAYER)>0)
_PLAYER_RECORD((_PLAYER-1))=0
BOUND_THIS_ROUND(_PLAYER)=False
WIND_FACTOR#(_PLAYER)=1.0
STAYED_ALIVE_BONUS(_PLAYER)=1
ZOMBIE(_PLAYER)=_FALSE
LINE_LENGTH_(_PLAYER)=LINE_LENGTH
SPACE_LENGTH_(_PLAYER)=SPACE_LENGTH
End If
SEMIALIVE(_PLAYER)=SELECTED(_PLAYER)
ALIVE(_PLAYER)=SELECTED(_PLAYER)
Next _PLAYER
' .----------------------------------.
' | Draw bordes, scores and lives |
' `----------------------------------'
INITIALIZE_GAME____DRAW_BORDERS
MAKE_SCOREPANEL
_DRAW_SCORE
' ________________________________
' | |
' | Set Colours |
' |________________________________|
If SURPRISING_START
P_COLOR(1)=Rnd(5)+1
For _PLAYER=2 To 6
C=Rnd(5)+1
Repeat
CORRECT=_TRUE
Add C,1,1 To 6
For I=1 To _PLAYER-1
If P_COLOR(I)=C : CORRECT=_FALSE : End If
Next I
Until CORRECT
P_COLOR(_PLAYER)=C
Next _PLAYER
For _PLAYER=1 To 6
P_COLOR(_PLAYER)=PL_DEF_COLOR(P_COLOR(_PLAYER))
Next _PLAYER
Else
For _PLAYER=1 To 6
P_COLOR(_PLAYER)=PL_DEF_COLOR(_PLAYER)
Next _PLAYER
End If
If _SCREEN_SIZE>0
Sprite 4,0+X Hard(0),4+42,LATERAL_LEFT
Sprite 5,320-5+X Hard(0),4+42,LATERAL_RIGHT
End If
Sprite Off 6
Sprite Off 7
' ______________________________________
' | |
' | Let all players know their positions |
' |______________________________________|
Screen 1
GAME_FADE_UP
INIT_PUTPIX_STRATEGY_SIN_ATAN
ESC=False
If SURPRISING_START
Else
_ANIM_FLAG$="Anim 1,(1,3)(2,2)(3,3)(4,2)(5,3)(6,2)(12,3)(11,2)(10,3)(9,2)(8,3)(7,2)(1,3)(2,2)(3,3)"
Bank Swap 1,23
For I=1 To 6
If SELECTED(I) and(ESC=False)
Volume 1,40
_DO_SOUND[ARROW_SOUND]
Colour $17,Colour($10+I)
If _SCREEN_SIZE>0
Screen 5
Get Palette 1
Screen 1
End If
Sprite 0,X#(I)+X Hard(0)-15,Y#(I)+42-22+BOLDLINE,1
Amal 0,_ANIM_FLAG$
Amal On
Wait 2
While Chanan(0) and(ESC=False)
If Key State(ESC_SCANCODE)
ESC=True
End If
Wend
Dreg(0)=X#(I) : Dreg(1)=Y#(I) : Dreg(2)=$10+I
Call(PA_CURRENT_PIX)
Sprite Off 0
Wait Vbl
End If
If ESC
Exit
End If
Next I
Amal Off
For I=0 To 3
Sprite Off I
Next I
Bank Swap 1,23
End If
' ______________________________________
' | |
' | Set begin possitions of sprites |
' |______________________________________|
For I=1 To 6
If SELECTED(I)
NS=_SPRITE_NUMBER(I)
If(_SCREEN_SIZE=0) or(NS<4)
NI=_SPRITE_IMAGE(I)
Sprite NS,X#(I)+X Hard(0),Y#(I)+42,NI+_SPRITE_INDEX_BASE
Else
Bob I-2,X#(I),Y#(I),_BOB_PLAYER_IMAGE(I-3,Abs(BOLDLINE))
_BOBS_USED=_TRUE : Bob Update Off
End If
End If
Next I
INITIALIZE_GAME____SET_RATE_VARIABLES
J_REPLAYING_OR_J_RECORDING=JUST_REPLAYING or JUST_RECORDING
TURBOLIMIT=0
GO_FOR_COMPUTURBO=_FALSE
If TURBO
TURBOLIMIT=-1
Else If(_ONLY_COMPUTERS_IN_GAME=_FALSE)
GO_FOR_COMPUTURBO=COMPUTURBO or COMPUDEATH
End If
If WIND
WIND_ANGLE=Rnd(SMERU-1)
WIND_STRENGTH#=WIND_STRENGTH
WIND_STRENGTH#=WIND_STRENGTH#*0.08
End If
SEMIALIVE(0)=False
Clear Key
' Paper 0 : Pen $12 : Locate 1,1 : Print BODY_CHANGE_COUNTER;" ";_EXPECTED_GAME_LENGTH;" ";BODY_CHANGE_PERCENT
End Proc
Procedure INITIALIZE_GAME____DRAW_BORDERS
Screen 1
If _SCREEN_SIZE=2
Ink 0 : Box 5,4 To 640-6,512-5
Ink $D : Box 6,5 To 640-7,512-6
Ink $10 : Box 7,6 To 640-8,512-7
Ink 0 : Box 8,7 To 640-9,512-8
Else If _SCREEN_SIZE=1
Ink 0 : Box 5,4 To 480-6,384-5
Ink $D : Box 6,5 To 480-7,384-6
Ink $10 : Box 7,6 To 480-8,384-7
Ink 0 : Box 8,7 To 480-9,384-8
Else
_DRAW_SMALL_WOOD_FRAME
Ink 0 : Box 4,4 To 320-5,256-32-5
End If
If CENTRAL_BOX=1
Ink 0 : Bar XBOTTOM,YBOTTOM To XTOP+1,YTOP+1
If _SCREEN_SIZE>0
Ink $10 : Box XBOTTOM+1,YBOTTOM+1 To XTOP+1-1,YTOP+1-1
Ink $D : Box XBOTTOM+2,YBOTTOM+2 To XTOP+1-2,YTOP+1-2
Else
Get Bob 100,0,10 To 5,10+YTOP-YBOTTOM
Paste Bob XTOP-3,YBOTTOM+1,100
Paste Bob XBOTTOM-(16-5),YBOTTOM+1,100+$8000
Get Bob 100,XBOTTOM+3,0 To XTOP-3,5
Paste Bob XBOTTOM+4,YTOP-3,100
Paste Bob XBOTTOM+4,YBOTTOM,100+$4000 : Del Bob 100
End If
End If
End Proc
Procedure INITIALIZE_GAME____SET_RATE_VARIABLES
If RATEMODE=1
RATE_LENGTH#=USER_RATE_LENGTH*2
STILL_SPEEDING_UP=True
RATE#=0.5
RATEJUMP#=0.01*(FINAL_RATE-50)/RATE_LENGTH#
FINAL_RATE#=FINAL_RATE/100.0
_MUSIC_TEMPO#=7+50/7.0
_MUSIC_TEMPO_JUMP#=(FINAL_RATE-50)/RATE_LENGTH#/7.0
Else
STILL_SPEEDING_UP=False
RATE#=FINAL_RATE*0.01
_MUSIC_TEMPO#=7+FINAL_RATE/7.0
End If
If GAME_MUSIC_PLAYING
Tempo _MUSIC_TEMPO#
End If
End Proc
Procedure INITIALIZE_GAMESET
For I=1 To 6 : SCORE(I)=0 : Next I
GR=0 : GRP=1 : WIN=False
GAME_MUSIC_PLAYING=((_MUSIC_ON=1) and(DEMO_ON=False))
JUST_REPLAYING=USER_REPLAYING or REPLAY_ALL_SAVED_ON
JUST_RECORDING=USER_RECORDING
If USER_RECORDING
For I=1 To 6
Poke(RECORD_BASE+72+I-1),-SELECTED(I)
Next I
Else If USER_REPLAYING
If Length(31)=0
Reserve As Work 31,CONFIG_LENGTH
End If
CONFIG[Start(31),False]
End If
If REPLAY_ALL_SAVED_ON
INDEX=0 : _EXISTS_INDEX=False
Repeat
INDEX$=Str$(INDEX)-" " : INDEX$=String$("0",2-Len(INDEX$))+INDEX$
_EXISTS_INDEX=_EXISTS_INDEX or Exist(GAME_SAVING_PATH$+RECORDNAME$+INDEX$)
Inc INDEX
Until _EXISTS_INDEX or(INDEX=100)
Dec INDEX
If _EXISTS_INDEX
If Length(31)=0
Reserve As Work 31,CONFIG_LENGTH
End If
CONFIG[Start(31),False]
End If
End If
_ONLY_COMPUTERS_IN_GAME=_TRUE
For _PLAYER=1 To 6
If(_PLAYER_TYPE(_PLAYER)=1) or(_PLAYER_TYPE(_PLAYER)=3)
_ONLY_COMPUTERS_IN_GAME=_FALSE : End If
Next
If _SCREEN_SIZE>0
Screen 2 : Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Screen Close 1
Screen Open 1,640,512,32,Lowres
Flash Off : Curs Off : Hide On
Screen Display 1,128,42,320,256-30
Screen Offset 1,0,0
Set Font FONT_NUMBER
End If
GAMES_PLAYED=0
_EXPECTED_GAME_LENGTH=(1000+250*HRAJOU)*(2^_SCREEN_SIZE)
End Proc
Procedure INITIALIZE_GAMESET____MIDDLE_PART
If GAME_MUSIC_PLAYING
Volume 0 : Music 1
End If
Screen Open 4,640,30,16,Hires
Flash Off : Curs Off : Hide On
Screen Hide 4
Screen Open 3,640,30,16,Hires
Flash Off : Curs Off : Hide On
Screen Display 3,128,42+300,640,30
If _SCREEN_SIZE>0
Screen Open 5,320,8,32,Lowres
Flash Off : Curs Off : Hide On
Screen Display 5,128,42,320,4
Paste Bob 0,0,HORIZONTAL_WOOD_IMAGE
Paste Bob 160,0,HORIZONTAL_WOOD_IMAGE
Paste Bob 0,0,CORNER_WOOD_IMAGE
Paste Bob 320-16,0,CORNER_WOOD_IMAGE+$8000
Ink 0 : Draw 5,0 To 5,4 : Draw 320-6,0 To 320-6,4
Screen Open 6,320,8,32,Lowres
Flash Off : Curs Off : Hide On
Screen Display 6,128,42+256-30-5,320,4
Paste Bob 0,0,HORIZONTAL_WOOD_IMAGE+$4000
Paste Bob 160,0,HORIZONTAL_WOOD_IMAGE+$4000
Paste Bob 0,0,CORNER_WOOD_IMAGE
Paste Bob 320-16,0,CORNER_WOOD_IMAGE+$8000
Ink 0 : Draw 5,0 To 5,4 : Draw 320-6,0 To 320-6,4
End If
End Proc
Procedure ICON_AND_MUSIC_CARE_BEFORE_GAMESET
'~~~ Care about music ~~~
If GAME_MUSIC_PLAYING
If Not GAME_MUSIC_IN_CHIP_RAM
Erase 15
DUENIX_REQUEST
If Exist(PATH$+"Duming")
Load PATH$+"Duming",3
Else
End
End If
End If
End If
'~~~ Pred gamesou swapni icony~~~
Bank Swap 2,4
End Proc
Procedure ICON_AND_MUSIC_CARE_AFTER_GAMESET
'~~~ Vrat icony, sycaku ~~~
Bank Swap 2,4
'~~~ Vrat muziku, sycaku ~~~
If GAME_MUSIC_PLAYING
Volume 0 : Music Off
If Not GAME_MUSIC_IN_CHIP_RAM
Erase 3
DUENIX_REQUEST
If Exist(PATH$+"LifeMotion")
Load PATH$+"LifeMotion",15
Else
Erase All : End
End If
End If
End If
If(DEMO_ON=False) and(_MUSIC_ON=1)
Track Play 15
End If
End Proc
Procedure GAME_FADE_UP
If PLAN=0
Fade 1,$0,$1,$2,$3,$4,$15,$115,$116,$227,$228,$339,$33A,$459,$669,$779,$778
Else If PLAN=2
Fade 1,0,UPP(1),UPP(2),UPP(3),UPP(4),UPP(5),UPP(6),UPP(7),UPP(8),UPP(9),UPP(10),UPP(11),UPP(12),UPP(13),UPP(14),UPP(15)
Else
Fade 1,0,SPP(1),SPP(2),SPP(3),SPP(4),SPP(5),SPP(6),SPP(7),SPP(8),SPP(9),SPP(10),SPP(11),SPP(12),SPP(13),SPP(14),SPP(15)
End If
Wait 14
Fade 1,,,,,,,,,,,,,,,,,,,,,,,,,$810,$A30,$B40,$C50,$D60,$E70,$F71,$F63
If _SCREEN_SIZE>0
Screen 5
Palette ,,,,,,,,,,,,,,,,Colour($A),P_COLOR(1),P_COLOR(2),P_COLOR(3),P_COLOR(4),P_COLOR(5),P_COLOR(6),$EEE,$810,$A30,$B40,$C50,$D60,$E70,$F71,$F63
Screen 6
Palette ,,,,,,,,,,,,,,,,Colour($A),P_COLOR(1),P_COLOR(2),P_COLOR(3),P_COLOR(4),P_COLOR(5),P_COLOR(6),$EEE,$810,$A30,$B40,$C50,$D60,$E70,$F71,$F63
Screen 1
End If
Wait 14
Fade 1,,,,,,,,,,,,,,,,,Colour($A),P_COLOR(1),P_COLOR(2),P_COLOR(3),P_COLOR(4),P_COLOR(5),P_COLOR(6),$EEE
'$EEE,$DDD,$1F1,$F6E,$FF0,$5AF,$EE,$EEE
ROLL_SCORE_IN
End Proc
Procedure GAME_FADE_OUT
Fade 1,,,,,,,,,,,,,,,,,0,0,0,0,0,0,0,0,0
Wait 14
Fade 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,,,,,,0,0,0,0,0,0,0,0
If _SCREEN_SIZE>0
Screen 5
Palette ,,,,,,,,,,,,,,,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Screen 6
Palette ,,,,,,,,,,,,,,,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Screen 1
End If
' Wait 14
For I=256-30 To 300 Step 5
Screen Display 3,128,42+I,640,30
Wait Vbl
Next I
End Proc
Procedure ROLL_SCORE_IN
Screen 3
PAL=Rnd(4)
If PAL=1
Palette $0,$200,$410,$620,$930,$B40,$D50,$F60,$430,$540,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6)
Else If PAL=2
Palette $0,$200,$500,$710,$A20,$C30,$E40,$F50,$430,$540,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6)
Else If PAL=3
Palette $0,$112,$222,$332,$442,$552,$662,$772,$530,$740,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6)
Else If PAL=4
Palette $0,$110,$230,$440,$750,$960,$B70,$D80,$31,$42,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6)
Else
Palette $0,$11,$32,$143,$453,$663,$873,$A83,$33,$44,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6)
End If
Screen 1
Wait Vbl
For I=300 To 256-20 Step -5
Screen Display 3,128,42+I,640,30
Wait Vbl
Next I
For I=256-20 To 256-25 Step -5
Screen Display 3,128,42+I,640,30
Wait Vbl
Next I
End Proc
Procedure WINNERS_AND_LOSERS
'toto je nutne, aby winnerprint vytiskl vsechny selectedy
For I=1 To 6 : SEMIALIVE(I)=SELECTED(I) : Next I
MAKE_SCOREPANEL
_DRAW_SCORE
WINNER=GRP : Rem winner already known
LOSER=GRP : Rem zatim!
' ________________________________
' | |
' | Find all losers |
' |________________________________|
For I=1 To 6
If SELECTED(I) and(SCORE(I)<SCORE(LOSER))
LOSER=I
End If
Next I
' == Co kdyby jich bylo vic ! ==
LOWEST_SCORE=SCORE(LOSER)
NUMBER_OF_LOSERS=0
For I=1 To 6
If(SCORE(I)=LOWEST_SCORE) and SELECTED(I)
Inc NUMBER_OF_LOSERS
End If
Next I
' ________________________________
' | |
' | Music'n Backgorund |
' |________________________________|
Music Stop
If _MUSIC_ON : Track Play WINNER_MUSIC__BANK : End If
Screen 2
If Length(PLAN_BANK(PLAN))>0 : Unpack PLAN_BANK(PLAN)
Else : Cls 0 : End If
Screen 2 : Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Screen Close 1
Screen Open 1,320,60,32,Lowres
Flash Off : Curs Off : Hide On
Screen Copy 2,0,0,320,60 To 1,0,0
Sprite Off
Screen Display 1,128,42,320,60
_DRAW_WINNER_WOOD_FRAME[60]
Screen Open 7,320,160,32,Lowres
Flash Off : Curs Off : Hide On
Screen Display 7,128,42+60+3,320,160
Screen Copy 2,0,63,320,63+160 To 7,0,0
_DRAW_WINNER_WOOD_FRAME[160]
Screen 2
' ________________________________
' | |
' | Write all texts |
' |________________________________|
HLASKA$=THE_WINNER$
Cls 0 : Ink $10+WINNER,0 : Text(40-Len(HLASKA$))*4,40-10,HLASKA$
If NUMBER_OF_LOSERS=1
Randomize Timer
If Rnd(1)=0
HLASKA$=THE_LOSER1$
Else
HLASKA$=THE_LOSER2$
End If
Ink $10+LOSER,0 : Text(40-Len(HLASKA$))*4,90,HLASKA$
Else
HLASKA$=THE_LOSERS$
CURRENT_LOSER=0
For I=1 To 6
If(SCORE(I)=LOWEST_SCORE) and SELECTED(I)
Ink $10+I,0 : Text(40-Len(HLASKA$))*4,CURRENT_LOSER*20+90,HLASKA$
Inc CURRENT_LOSER
End If
Next I
End If
' ________________________________
' | |
' | Fade Up and wait for any key |
' |________________________________|
Get Block 1,0,0,320,80,1
Screen 1 : Put Block 1 : Del Block 1
Screen 2 : Get Block 1,0,63,320,160,1
Screen 7 : Put Block 1,0,0 : Del Block 1
Screen 1
Fade 1,$0,$101,$201,$311,$412,$512,$623,$723,$824,$935,$A35,$B36,$C46,$D47,$E47,$F48,$F17,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6),$EEE,$810,$A30,$B40,$C50,$D60,$E70,$F71,$F63
ROLL_SCORE_IN
Screen 7
Fade 1,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F,$F17,PL_DEF_COLOR(1),PL_DEF_COLOR(2),PL_DEF_COLOR(3),PL_DEF_COLOR(4),PL_DEF_COLOR(5),PL_DEF_COLOR(6),$EEE,$10,$111,$222,$333,$444,$555,$666,$777
_ANIM_FLAG$="Anim 0,(1,3)(2,2)(3,3)(4,2)(5,3)(6,2)(12,3)(11,2)(10,3)(9,2)(8,3)(7,2)"
Bank Swap 1,23
Colour $17,Colour($10+GRP)
Sprite 0,40+X Hard(0),42+23-5,1
Sprite 4,320-40-20+X Hard(0),42+23-5,1
Amal 0,_ANIM_FLAG$
Amal 4,_ANIM_FLAG$
Amal On
Wait 10 : Clear Key : Timer=0
Repeat : A$=Inkey$ : Until(A$<>"") or(Timer>50*(60+4))
Amal Off : Sprite Off
Bank Swap 1,23
GAME_FADE_OUT
Screen 1
Fade 1
Wait 14
Screen Close 7
Track Stop
End Proc
Procedure IS_GAME_SAVING
If Exist("Duenrecord:")
Edit
GAME_SAVING_PATH$="DuenRecord:"
Else
If Not Exist("ram:DuenRecord/")
Mkdir "ram:DuenRecord"
End If
GAME_SAVING_PATH$="ram:DuenRecord/"
End If
INDEX=0
_FREE_INDEX=False
Repeat
INDEX$=Str$(INDEX)-" " : INDEX$=String$("0",2-Len(INDEX$))+INDEX$
If Not Exist(GAME_SAVING_PATH$+RECORDNAME$+INDEX$)
_FREE_INDEX=True
End If
Inc INDEX
Until _FREE_INDEX or(INDEX=100)
If((PATH$="ram:DuenRecord") and(Chip Free+Fast Free<20000)) or(_FREE_INDEX=False)
ALLOW_GAME_SAVING=False
Else
ALLOW_GAME_SAVING=True
End If
End Proc
Procedure DEMO_ENVIRONMENT[ACTION]
If ACTION=0
' ________________________________
' | |
' | Store before demo |
' |________________________________|
DEMOSTORE_PLAN=PLAN
DEMOSTORE_USER_RECORDING=USER_RECORDING
DEMOSTORE_USER_REPLAYING=USER_REPLAYING
DEMOSTORE_REPLAY_ALL_SAVED_ON=REPLAY_ALL_SAVED_ON
DEMOSTORE_TEAM_GAME=TEAM_GAME
DEMOSTORE_ENABLED_SOUND=ENABLED_SOUND
' ________________________________
' | |
' | Set environment |
' |________________________________|
For I=1 To 6
SELECTED(I)=0
COMPUTER_STRATEGY(I)=0
CYBORG(I)=0
Next I
SELECTED(2)=-1
COMPUTER_STRATEGY(2)=-1
SELECTED(4)=-1
COMPUTER_STRATEGY(4)=-1
PLAN=0
USER_RECORDING=False
USER_REPLAYING=False
REPLAY_ALL_SAVED_ON=False
TEAM_GAME=False
ENABLED_SOUND=False
Else If ACTION=1
' ________________________________
' | |
' | Restore after demo |
' |________________________________|
PLAN=DEMOSTORE_PLAN
USER_RECORDING=DEMOSTORE_USER_RECORDING
USER_REPLAYING=DEMOSTORE_USER_REPLAYING
REPLAY_ALL_SAVED_ON=DEMOSTORE_REPLAY_ALL_SAVED_ON
TEAM_GAME=DEMOSTORE_TEAM_GAME
ENABLED_SOUND=DEMOSTORE_ENABLED_SOUND
End If
End Proc
Procedure _GLOBAL_INITIALIZATION
If(Chip Free+Fast Free)<MEMORY_REQUIREMENT
Screen Open 3,640,256,2,Hires : Curs Off
Cls 0 : Paper 0 : Pen 1 : Locate 0,10
Centre "Low memory." : Print : Print
Centre "Don't be surprised, if Duenix suddenly quits."
Fade 1,0,$F5A : Wait Key : Fade 1,0,0 : Wait 10
Screen Close 3
End If
Set Input $A,-1 : Led Off
_COMPILED=(Prg State=-1)
DEBUGGING_LIFELIMIT_COEFICIENT=2
_LOAD_DUENIX_FONT=_TRUE
Default Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Screen Open 1,320,256,32,Lowres
Flash Off : Curs Off : Hide On
SET_CONSTANTS
SET_SCANCODE_CONSTANTS
WRITE_INITDATA
BEGIN_LOADING
For _PLAYER=1 To 6
SELECTED(_PLAYER)=_FALSE
COMPUTER_STRATEGY(_PLAYER)=_FALSE
CYBORG(_PLAYER)=_FALSE
_PLAYER_TYPE(_PLAYER)=0
_TOP_LIVES(_PLAYER)=0
Next _PLAYER
DEMO_ON=_FALSE
U_THRU=_FALSE
'-----------------------------This is temporary----------------------
FAST_INTERFACE=False
WIND_TURNING=_FALSE
_PLAYER_COLOURS_SET=0
End Proc
Procedure MAIN
_GLOBAL_INITIALIZATION
Do
SELECTING
INITIALIZE_GAMESET
ICON_AND_MUSIC_CARE_BEFORE_GAMESET
If REPLAY_ALL_SAVED_ON and(_EXISTS_INDEX=False)
Bank Swap 2,4
WRITEXY[-2,100,NO_GAMERECORD_SAVED$]
Bank Swap 2,4
SELECTING_FADE_UP
Clear Key : Wait Key : FAST_FADE_OUT
Goto INDEX_FAULT
End If
INITIALIZE_GAMESET____MIDDLE_PART
Repeat
If REPLAY_ALL_SAVED_ON
JUST_REPLAYING=_TRUE
End If
_COUNT_SELECTED
INITIALIZE_GAME
GAME
If REPLAY_ALL_SAVED_ON
JUST_REPLAYING=_FALSE
_EXISTS_INDEX=False
Repeat
Inc INDEX
If INDEX<100
INDEX$=Str$(INDEX)-" " : INDEX$=String$("0",2-Len(INDEX$))+INDEX$
_EXISTS_INDEX=Exist(GAME_SAVING_PATH$+RECORDNAME$+INDEX$)
End If
Until _EXISTS_INDEX or(INDEX=100)
ESC=ESC or _EXISTS_INDEX
End If
Until WIN or ESC or JUST_REPLAYING or DEMO_ON
If(ESC or JUST_REPLAYING or DEMO_ON)=0
WINNERS_AND_LOSERS
End If
If _SCREEN_SIZE>0
Screen Close 3
End If
If REPLAY_ALL_SAVED_ON or USER_REPLAYING
_DECONFIG[Start(31),False]
End If
INDEX_FAULT:
Screen 2 : Palette 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Screen Close 1
Screen Open 1,320,256,32,Lowres
Flash Off : Curs Off : Hide On
Set Font FONT_NUMBER
ICON_AND_MUSIC_CARE_AFTER_GAMESET
If DEMO_ON
DEMO_ENVIRONMENT[1]
End If
REALIZE_PLAYER_TYPE
Loop
End Proc
Procedure EXTRACT_PATH[EX$]
' 58 je code of : 47 je code of /
EX_TOP=Len(EX$)
If EX_TOP>0
EX_POS=EX_TOP
OK=False
Repeat
EX_VAL=Asc(Mid$(EX$,EX_POS,1))
If(EX_VAL=47) or(EX_VAL=58)
OK=True
Else
EX$=Left$(EX$,Len(EX$)-1)
End If
Dec EX_POS
Until(EX_POS=0) or OK
End If
End Proc[EX$]
' ______________________________________
' | \
' | @ Globals \
' |________________________________________\
Global _TRUE,_FALSE,_NOT(),_T,_F,PATH$,_COMPILED,YEAR$,RELEASE$
Global _LOAD_DUENIX_FONT,CONSUMED_TIME,DEBUGGING_LIFELIMIT_COEFICIENT
Global X#(),Y#(),SMER(),NEW_X#(),NEW_Y#(),NEW_SMER()
Global _SPRITE_NUMBER(),_SPRITE_IMAGE()
Global TURNING(),COMPUTER_STRATEGY(),CYBORG(),ALIVE()
Global SCORE(),SELECTED(),SEMIALIVE(),SPACE_COUNTER(),LINE_COUNTER()
Global BOUND_THIS_ROUND(),BOUND_COUNTER(),REDRAW_PLAYER()
Global ACCEPT_KEYSTROKE(),_KEYSTROKE_COUNTER()
Global SPEED_SOURCE#()
Global UPP(),SPP()
Global TEAM_MATE_THRU(),TEAM_MATE()
Global GS_GAME_NAME$()
Global STAYED_ALIVE_BONUS(),_PLAYER_TYPE(),_PLAYER_PROPRIETY(),NEW_PLAYER()
Global _PLAYER_GREY_COLOUR(),PL_DEF_COLOR(),P_COLOR()
Global WIND_FACTOR#()
Global _BOB_PLAYER_IMAGE()
Global _PUTPIX_QUEUE_X(),_PUTPIX_QUEUE_Y(),_PUTPIX_QUEUE_COLOUR(),_PUTPIX_QUEUE_TOP
Global _PLAYER_RECORD(),PL_RGB(),_FREE_VALUE(),LIVING_PLAYER()
Global _NEXT_SOUND_FX_CHANNEL()
Global PL_DEF_COLOR_LIGHT(),PL_DEF_COLOR_DARK()
Global WRITE_KOI82IMAGE(),WRITE_KOI82HOOK(),ZOMBIE(),LINE_LENGTH_(),SPACE_LENGTH_()
Global RIGHT_PUSHED,LEFT_PUSHED,HELP
Global GR,GRP,_TOPSCORE,LONG_GAME
Global SMERU,ANGLE_CONSTANT#,SMERU_QUARTER,SMERU_HALVE
Global ZIJOU,HRAJOU,SPACE_LENGTH,LINE_LENGTH,_DRAWING_LINE_LENGTH
Global SPEED(),SPEED_PERCENT#(),SPEEDJUMP#,SPEEDJUMP
Global RATE,FINAL_RATE,RATEMODE,SPEEDING_UP_COUNTER,STILL_SPEEDING_UP,USER_RATE_LENGTH,RATEJUMP#
Global BODY_CHANGE,BODY_CHANGE_COUNTER,BODY_CHANGE_PERCENT,_EXPECTED_GAME_LENGTH
Global GAMES_PLAYED
Global ESC,WIN
Global GAMEPLANS,GAMEPLAN,PLAN
Global _PLAYER,ANGLE#
Global XBOTTOM,YBOTTOM,XTOP,YTOP
Global BASE,BASE1,BASE2
Global GAME_MUSIC_PLAYING,GAME_SLOWED,SOUND_FX_CHANNEL
Global _SCREEN_SIZE,_VIEWED_AREA_X,_VIEWED_AREA_Y
Global _DO_X_SCROLL,_DO_Y_SCROLL,X_SCROLL_LIMIT,Y_SCROLL_LIMIT
Global _MUSIC_TEMPO_JUMP#,_MUSIC_TEMPO#
Global RATE#,FINAL_RATE#
Global OWN_PLAN_PATH$
Global _RIGHT_LIMIT,_DOWN_LIMIT,_LEFT_LIMIT,_UP_LIMIT
Global X_WORK#,Y_WORK#,X_WORK,Y_WORK
Global SFX,SFY
Global ENABLED_MUSIC,ENABLED_SOUND
Global DEMO_ON,DEMO_TIMER_LIMIT
Global HLASKA$,PAUSED,LOCALE_PATH$,FONT_NUMBER,EN$
Global RECALCULATE_ANGLE,RECALCULATE_COORDINATES
Global LIVES_ON,LIVES(),_TOP_LIVES(),AUCH_COUNTER(),AUCH_PROTECTION(),LIVES_TOP
Global NUMBER_OF_LIVING_HUMANS
Global SHORT_CONFIG,CONFIG_LENGTH
Global CENTRAL_BOX,CENTRAL_BOX_SIZE
Global WATERING,WATER_LIMIT#,WATER_LIMIT
Global ALWAYS_TURNING,USER_DIRECTIONS
Global TURBOLIMIT,TELEPORTING,BOLDLINE
Global TURBO,COMPUTURBO,GO_FOR_COMPUTURBO
Global TEAM_GAME,SPACE_KILL,BOUNCING,_MUSIC_ON,SURPRISING_START
Global USER_SOUND_FX,SOUND_FX,COMPUDEATH,DIE_COMPUTERS,ZOMBIES
Global FAST_INTERFACE,_ONE_PLAYER_GAME
Global WIND,WIND_ANGLE,WIND_STRENGTH#,WIND_STRENGTH
Global GAME_MUSIC_IN_CHIP_RAM,MEMORY_REQUIREMENT
Global _SPRITE_INDEX_BASE
Global ESC_QUITED,_SHOW_SQ_LOGO
Global ALLOW_GAME_SAVING,GAME_SAVING_PATH$,INDEX$,INDEX
Global JUST_REPLAYING,JUST_RECORDING,J_REPLAYING_OR_J_RECORDING
Global RECORDING_ALLOWED
Global USER_RECORDING,GAME_RECORD_EMPTY
Global USER_REPLAYING,REPLAY_ALL_SAVED_ON
Global _PLAYER_COLOURS_SET,NUMBER_OF_SEMIALIVES
Global R_THRU,G_THRU,E_THRU,U_THRU
Global _SIN_ANGLE#,_COS_ANGLE#
Global _EXISTS_INDEX
Global X_TESTPOINT,Y_TESTPOINT
Global REDRAW_ANY_PLAYER,_ONLY_COMPUTERS_IN_GAME
Global _BOBS_USED,CYCLES
Global DEMOSTORE_PLAYSTATE()
Global DEMOSTORE_PLAN,DEMOSTORE_USER_RECORDING
Global DEMOSTORE_USER_REPLAYING,DEMOSTORE_REPLAY_ALL_SAVED_ON
Global DEMOSTORE_TEAM_GAME,DEMOSTORE_ENABLED_SOUND
' ______________________________________
' | |
' | Assembler CatchPoints Globals |
' |______________________________________|
Global BITPLAN_BASE,PA_CURRENT_PIX,PA_SMALL_PIX,PA_BIG_PIX,PA_SMALL_PIX_BIGSCREEN,PA_BIG_PIX_BIGSCREEN,VA_PQ_X,VA_PQ_Y,VA_PQ_COL,VA_PQ_TOP,VA_PUTPIX_TYPE,PA_DRAW_PIXEL_QUEUE
Global VA_PLAYER_RECORD,VA_GAME_RECORD,VA_GAME_RECORD_POINTER,PA_SAVE_POSITION,PA_LOAD_POSITION
Global VA_BITPLAN4,VA_SIN_TABLE,VA_ATAN_TABLE,VA_DIRECTIONS,VA_DIRECTION,VA_XAMOSREAL,VA_YAMOSREAL,PA_STRATEGY,PA_COUNTSINANDCOS,VA_ROTATION,VA_PLAYER,VA_XHASH,VA_YHASH,VA_PLAYERSDIR,VA_PLAYERALIVE
Global VA_DIRSTEP0,VA_DIRSTEP1,VA_DIRSTEP2,VA_DIRSTEP3,VA_DIRSTEP4,VA_PLAYERSCHOICE,VA_TURN,VA_BIGSCREEN,PA_TESTPROCEDURE,PA_COUNTTESTANDSPEEDPOINTS,PA_COUNTTESTANDSPEEDPOINTS_1PIX,PA_COUNTTESTANDSPEEDPOINTS_2PIX
Global PA_COUNTSPEEDPOINT,PA_COUNTSPEEDPOINT_1PIX,PA_COUNTSPEEDPOINT_2PIX,RECORD_BASE
Global PA_COUNTSINANDCOSFIXED
' _____________________________
' | |
' | "Constants" Definitions |
' |_____________________________|
Global _ERROR_BADPATH
Global BS_LEFT_TOP,BS_MIDDLE_TOP,BS_RIGHT_TOP,BS_LEFT_MIDDLE,BS_MIDDLE_MIDDLE,BS_RIGHT_MIDDLE,BS_LEFT_BOTTOM,BS_MIDDLE_BOTTOM,BS_RIGHT_BOTTOM
Global RECORDNAME$,DEMO_PRESS_SPACE_LIMIT,CONFIG_LENGTH
Global _PLAYER_TYPE_IMAGE(),STANDARD_PLAN_PAL$()
Global NO_IMAGE(),YES_IMAGE(),RED_BOX_IMAGE(),_FREE_FOR_MANIPULATION_IMAGE,SCORE_PANEL_BACKGROUND_IMAGE,HORIZONTAL_WOOD_IMAGE,CORNER_WOOD_IMAGE,VERTICAL_WOOD_IMAGE,NOSCROLL_CORNER_IMAGE,LIFE_BOX_IMAGE,PRESS_SPACE_IMAGE
Global DUENIX_TITLE_IMAGE,DUENIX_ANIM_IMAGE,MOUSE_ON_LINE_IMAGE,_JOY_ON_LINE_IMAGE
Global LATERAL_LEFT,LATERAL_RIGHT
Global _PLAYER_GREY_COLOUR()
Global OS_LC_BOX(),OS_RC_BOX()
Global EN$,CZ_SEND$,EN_SEND$,EN_VALUE$,_ADDRESS$
Global BOUND_SOUND,TELEPORT_SOUND,DEATH_SOUND,ARROW_SOUND,PRESS_SPACE_SOUND,AUCH_SOUND,BODY_CHANGE_SOUND
Global OS_LEFT_COLUMN_TEXT$(),OS_RIGHT_COLUMN_TEXT$(),MAIN_OPTION_TEXT$(),MAIN_OPTION_E_TEXT$,MAIN_OPTION_G_TEXT$,MAIN_OPTION_R_TEXT$,MAIN_OPTION_U_TEXT$,PAGE_ONE$,MAIN_OPTION_LOADING_AND_SAVING$
Global CONFIGURATION$,_PRESS_SPACE_OR_ESCAPE$,ESCAPE_ACCEPT$,SELECTING_UPPER_TEXT$(),SELECTING_LOWER_TEXT$(),PAGE_TWO$,GAME_SETTINGS$,GAME_SETTINGS_SPACE1$,GAME_SETTINGS_SPACE2$,PAGE_FOUR$,RECORD_AND_REPLAY$,RECORD_AND_REPLAY_SPACE$
Global RR_COLUMN_TEXT$(),CREATE_USER_GS_EXPLANATION$(),PAGE_FIVE$,CREATING_USER_GAMESET$,CREATE_USER_GAMESET$,SORRY$,_MINIMUM_OF_DIRECTIONS$,_MAXIMUM_OF_DIRECTIONS$,INSERT_VOLUME$,_NOT_ALL_FILES$(),_NOT_FONT$
Global OPERATION_ABORTED$,DUENIX_CONFIG_ISNT_CONFIG$,DEF_CONFIG_LOADED$,CANT_FIND_DEF_CONFIG1$,CANT_FIND_DEF_CONFIG2$,CONFIG_SAVED_AS_DEF1$,CONFIG_SAVED_AS_DEF2$,ENTER_CONFIGNAME$,THIS_FILE_ISNT_CONFIG$,CONFIG_LOADED$,FILE_DOESNT_EXIST$
Global ENTER_NAME_OF_CONFIG_TO_SAVE$,CONFIG_SAVED$,CONFIG_NOT_SAVED$,THIS_FILE_ALREADY_EXISTS$,WANT_TO_OVERWRITE$,_ORIGINAL_CONFIG_LOADED$,ENTER_NAME_OF_CONFIG_LIST_FILE$
Global NONE_OF_FILES_WAS_CONFIG1$,NONE_OF_FILES_WAS_CONFIG2$,YOUR_NEW_GAMESET_IS_SAVED$,MORE_THAN_20_FILES1$,MORE_THAN_20_FILES2$,NAME_OF_EMPTY_GAME_IN_GAMESET$,YOU_HAVENT_RECORDED1$,YOU_HAVENT_RECORDED2$,YOU_HAVENT_RECORDED3$
Global YOU_HAVENT_SAVED_GAME1$,YOU_HAVENT_SAVED_GAME2$,YOU_HAVENT_SAVED_GAME3$,_MAXIMUM_OF_WATER_ANGLE$,PAGE_THREE$,GAMEPLAN$,THIS_IS_STANDARD_GAMEPLAN_NUMBER$,HERE_MAY_BE_YOUR_PLAN$,HERE_IS_YOUR_PLAN$,GAMEPLAN_L_TEXT$
Global GAMEPLAN_EXPLANATION$(),THIS_IS_DEFPLAN$,GAMEPLAN_KEY_TEXT$(),ENTER_NAME_OFF_IFF_TO_LOAD$,PRESS_U_TO_SELECT_USER_GAME$,SELECT_GAME$,SELECT_GAME_FROM_USERSET$,NO_GAMERECORD_SAVED$,THE_WINNER$,THE_LOSER1$,THE_LOSER2$,THE_LOSERS$
Global _LOADING$
Global A_SCANCODE,B_SCANCODE,C_SCANCODE,D_SCANCODE,E_SCANCODE,F_SCANCODE,G_SCANCODE,H_SCANCODE,I_SCANCODE,J_SCANCODE,K_SCANCODE,L_SCANCODE,M_SCANCODE,N_SCANCODE,O_SCANCODE,P_SCANCODE,Q_SCANCODE,R_SCANCODE,S_SCANCODE,T_SCANCODE,U_SCANCODE,V_SCANCODE
Global W_SCANCODE,X_SCANCODE,Y_SCANCODE,Z_SCANCODE,ESC_SCANCODE,ENTER_SCANCODE,SPACE_SCANCODE
Global DEF_PLAN__BANK,STANDARD_PLAN__BANK,OWN_PLAN__BANK,PRECOUNTED_SIN__BANK,PRECOUNTED_ATAN__BANK,DEF_GAMESET__BANK,CONFIG_TEMPORARY__BANK,USER_GAMESET__BANK,LIFE_MOTION_MUSIC__BANK,WINNER_MUSIC__BANK
Global PLAN_BANK()
' ______________________________________
' | |
' | Silly variables |
' |______________________________________|
Global A$,TEMP,TEMP#,I,P
Duenix strategy.s
[edit | edit source];__________________________________________________________________________________________________
; Duenix Computer Strategy
;__________________________________________________________________________________________________
;
; This is Motorola 68000 assembly.
;
; The comments are in part original from years 1994-1998 and in part updated to make them more legible
; and comprehensive. Comments were added to make the code and logic easier to follow.
;
; The strategy is split between two turns/passes (probably for performance reasons); the choice to
; turn left, turn right or move straight on is made only at the end of the 2nd turn/pass. That is to say,
; the choice is made on every 2nd call from the AMOS code to the strategy.
;
; The core of the strategy is this: identify a set of directions to investigate: straight on, left 1, right 1
; left 2, right 2, etc. For each direction, determine how far one can go without hitting an obstacle,
; where an obstacle is the rectangle bounding the playground or a line drawn by another player.
; Then, turn left or right depending on whether the maximum length direction found is at the left
; or the right; or go straight on. The strategy starts at label DoStrategy.
;
; Additional logic covers the case where there are obstacles ahead rather close
; to the player, in which case letting large free space e.g. in left 4 or right 4 direction determine
; the decision would be a mistake. The case is given by the condition
; Len0 * 2 <= 6 and Len0 * 2 < LenL1 and Len0 * 2 < LenR1.
; To achieve its objective, it sets blocks of LenL* and LenR* to zero in dependence on certain
; conditions, thereby disabling the impact of these LenL* values on the final decision.
; This logic starts at label DS_ArrowCollisionLogic.
;
; Additional logic reckons with where other players are and it is to be reverse
; engineered and documented. It seems to be replacing the direction lengths.
; This logic starts at label OtherPlayersCare. It is called from turn/pass 1.
;
; A small number of comments seems questionable or incorrect. Finding out what the proper correction
; would be was decided (in 2024) to be not worth the effort. One can learn something from
; the code and comments as they are. A search for "issue" should find places marked as potentially
; problematic.
;
; At the end of this file, there is a quick 68000 asm guide.
;__________________________________________________________________________________________________
; Constants
LengthLimit = 100
ASizeLimit = 200 ;For handling of other players, the limit of the vector length ("a") above which
;the logic is not applied.
BitPlan4 dc.l 0 ;The address of bitplan 4, where bitplans are numbered from 0; obstacles have a bit there
SinTable dc.l 0 ;The table of precalculated sine values of directions
AtanTable dc.l 0 ;The table of precalculated atan
Directions dc.l 80 ;The direction count (into how many direction angles the 360 degrees are to be divided)
DirStep0 dc.l 10 ;The step size of a small bend, expressed as an int in the units given by the above direction count
DirStep1 dc.l 20
DirStep2 dc.l 30
DirStep3 dc.l 40
DirStep4 dc.l 50 ;The skips for different directions
Rotation dc.l 15 ;The rotation radius
Direction dc.l 60 ;The direction of motion, expressed as an integer in the units given by direction count
XAMOSReal dc.l $80000045 ;X coordinate in AMOS real
YAMOSReal dc.l $80000045 ;Y coordinate in AMOS real
Player dc.l 0
XHash dc.l $80000048 ;The address of an array of player x coordinate in AMOS real
YHash dc.l $80000048 ;The address of an array of player y coordinate in AMOS real
PlayersDir dc.l 46 ;The address of an array of directions of the players
PlayerOn dc.l 0 ;The address of the indicator whether the player is playing, of an array
PlayersChoice dc.b 0,0,0,0 ;The choice made by the players in the previous turn/pass
dc.b 0,0
Turn dc.b 0 ;Which turn/pass is occurring; for a player this is global
IsBigScreen dc.b 0 ;1=We have big screen
Bra DoStrategyDebug
; Bra DoStrategy
Bra CalculateSinAndCos
Bra CalcTestAndSpeedPoints_1Pixel
Bra CalcTestAndSpeedPoints_2Pixel
Bra CalculateSinAndCosFixed
;_____________________________
;
; Program Variables
;_____________________________
XFixed dc.l 0 ;Fixed X coord
YFixed dc.l 0 ;Fixed Y coord
XInt dc.l $80
YInt dc.l $80
; ________________________________________________________________________________________________
; |
; | Convert AMOSReal to Fixed
; |
; | in: d0 - AMOSReal input, assuming it is positive; negative numbers are malprocessed.
; | out: d0 - Fixed-point output: 16.16 signed, but during the conversion, we do not reckon with
; | numbers not fitting into it.
; | changed regs: d0, d1
; |
; | The logic:
; | sub.l #$40,d1 .. AMOS convention .. we get the position of the decimal point.
; | Now we want to shift the number by ($10-dec point position) to the right.
; | Hence Sub.l #$10,d1
; | Neg.l d1
; |________________________________________________________________________________________________
ConvertAMOSRealToFixed
Move.l d0,d1
And.l #$FF,d1
Sub.l #$50,d1
Neg.l d1 ; d1 := $50 - (d0 & $FF)
And.l #$FFFFFF00,d0 ; in d0, erase the information about the decimal point
Cmp.b #$20,d1
Ble CARTF_1 ; if d1 > 32: return 0
Moveq #$0,d0
Rts
CARTF_1
Lsr.l d1,d0 ; else: shift to the right to handle the decimal point
Rts
; ______________________________________________________________________________________________
; |
; | Test Length of Direction
; |
; | Determines the length to which the worm can go into the direction before it hits an obstacle,
; | e.g. a worm line. The obstacle is determined as a filled bit in bitplan 4. (In a bitplan, there
; | is a bit per pixel, so a byte covers 8 pixels. This means the worm line colors are in the range
; | of 16-31 of the color palette.) Depends on the sin values calculated from the AMOS program and
; | stored in SinTable; these values are in the AMOS real format and need to be converted
; | to fixed-point representation (the int part in the upper word, the after dec.point part
; | in the lower word).
; |
; | in: d0 = Direction (integer in units given by the number of directions)
; | out: d7 = Length
; | changed registers: d-all a0, a6
; |______________________________________________________________________________________________
TestLengthOfDirection
;____________________________
; Calculate Sin and Cos
;____________________________
Move.l Directions(pc),d6
Lsr.w #2,d6 ;d6 := direction count / 4 (DirCntQuarter)
Move.l d0,d7 ;d7 := direction
Divu.w d6,d7 ;d7 := direction / (direction count / 4)
;remainder is saved in the upper word or d7; d7.w has quadrant
Move.l d7,d1
Swap d1
Ext.l d1 ;d1 := remainder of direction / (direction count / 4)
Btst #0,d7
Beq TL_FinalDir
Sub.l d6,d1
Neg.l d1 ;dir = -(dir - direction count / 4)
TL_FinalDir
;Now d1 == DifDirection
Move.l d1,d5 ;Store DifDirection In (d5 is free yet)
Asl.l #2,d1 ;d1 := d1 * 4
Move.l SinTable(pc),a0
Move.l (a0,d1),d0
Bsr ConvertAMOSRealToFixed
;If required, multiply by -1
Btst #1,d7
Beq TL_SinCalculated ;If the quadrant is 2 or 3 => minus
Neg.l d0
TL_SinCalculated
Move.l d0,d3 ;d3 := WorkSin just calculated
Move.l d6,d2 ;d2 := DirCntQuarter
Sub.w d5,d2 ;d2 := DirCntQuarter-DifDirection
Asl.l #2,d2
Move.l SinTable(pc),a0
Move.l (a0,d2),d0
Bsr ConvertAMOSRealToFixed
Move.b d7,d2 ;d2 := quadrant
Add.b #1,d2
Btst #1,d2
Beq TL_CosCalculated
Neg.l d0
TL_CosCalculated
Move.l d0,d4 ;d4 := WorkCos just calculated
; Set start position
Move.l XFixed(pc),d5
Move.l YFixed(pc),d6
;____________________________
; Go straight
;____________________________
;a6: Bitplan4
;d3: worksin
;d4: workcos
;d5: XFixed
;d6: YFixed
;d7: length
;____________________________
; First two times forth
;____________________________
Move.l BitPlan4(pc),a6
Cmp.w #0,d7 ;Is quadrant 0?
Beq TL_QUAD_ZERO
Moveq #0,d7
Bra TL_TwoTimes
TL_QUAD_ZERO
Moveq #1,d7
TL_TwoTimes
Add.l d3,d5 ;XFixed := XFixed + worksin
Add.l d4,d6 ;YFixed := YFixed + workcos
DBra d7,TL_TwoTimes ;Decrement and branch unless the result is -1
Moveq #0,d7 ;Clear length
Move.b IsBigScreen(pc),d0
Bne TL_GoStraight_BS
TL_GoStraight
Addq #1,d7 ;line length := line length + 1
Add.l d3,d5 ;XFixed := XFixed + worksin
Move.l d5,d0 ;d0 := XFixed
Swap d0; ;d0 := X (the int part of XFixed, with the upper 16 bit dirty)
; No need to extend since in the following, we work with word.
Add.l d4,d6 ;YFixed := YFixed + workcos
Move.l d6,d1 ;d1 := YFixed
Swap d1
And.l #$FFFF,d1 ;d1 := Y (the int part of YFixed)
;d1 := Y * 40 (40 = screen x size / 8)
Asl.w #3,d1
Move.w d1,d2
Asl.w #2,d2
Add.w d2,d1
;d1 := d1 + X / 8
Move.w d0,d2
Lsr.w #3,d2
Add.w d2,d1
;d1 == the offset of the address from the beginning of BitPlan4
;d0 := (X bitand 7) xor 7 == the bit number in the byte
And.b #7,d0
Eor.b #7,d0
Btst.b d0,(a6,d1) ;test d0 bit from BitPlan4
Bne TL_Finished ;as long as zero, go on
Cmp.b #LengthLimit,d7
Bls TL_GoStraight
TL_Finished
Rts
; Go straight (for big screen)
TL_GoStraight_BS
Addq #1,d7 ;line length := line length + 1
Add.l d3,d5 ;XFixed := Xfixed + worksin
Move.l d5,d0 ;d0:=XFixed
Swap d0
; No need to extend since in the following, we work with word.
Add.l d4,d6 ;YFixed := Yfixed + workcons
Move.l d6,d1 ;d1:=YFixed
Swap d1
And.l #$FFFF,d1
;d1 := d1 * 80
Asl.w #4,d1
Move.w d1,d2
Asl.w #2,d2
Add.w d2,d1
;d1 := d1 + X / 8
Move.w d0,d2
Lsr.w #3,d2
Add.w d2,d1
;d1 == the offset of the address from the beginning of bitplan 4
;d0 := (X bitand 7) xor 7 == the bit number in the byte
And.b #7,d0 ;V D0 je pocet bitu
Eor.b #7,d0
Btst.b d0,(a6,d1.l) ;test d0 bit from bitplan 4
Bne TL_Finished_BS ;as long as zero, go on
Cmp.b #LengthLimit,d7
Bls TL_GoStraight_BS
TL_Finished_BS
Rts
; _____________________________________________________________________________
;| DoStrategy
;|
;| d5: Tested Direction.Variable
;|
;| Inputs: XAMOSReal(pc), YAMOSReal(pc), Directions(pc), Direction(pc),
;| Rotation(pc)
;|
;| output d7: 0: no action, 1: turn left, 2: turn right
;|_____________________________________________________________________________
DS_Len0 dc.l 18 ;length in the straight direction
DS_LenL1 dc.l 17 ;length in the left 1 direction
DS_LenR1 dc.l 23 ;length in the right 1 direction
DS_LenL2 dc.l 101 ;length in the left 2 direction
DS_LenR2 dc.l 200 ;length in the right 2 direction
DS_LenL3 dc.l 14 ;length in the left 3 direction
DS_LenR3 dc.l 13 ;length in the right 3 direction
DS_LenL4 dc.l 101 ;length in the left 4 direction
DS_LenR4 dc.l 200 ;length in the right 4 direction
DS_LenL5 dc.l 3 ;length in the left 5 direction
DS_LenR5 dc.l 8 ;length in the right 5 direction
DS_PrecalculatedLens
ds.l 6*8 ;For all players, obstacle-free lengths calculated in turn/pass 0, to be used in turn/pass 1.
;There is a room for 8 lengths per player, but only 5 lengths are stored.
DS_ArrowDecisionStore
dc.l 0,0 ;6 bytes of one of 0, 1, and 2, one per player
; a2: DirStore
; a3: Directions
; a4: Pointer to DS_Len Table
; a5: Dirs 1/6
DoStrategy
;-------------------------------------------------
; Convert XAMOSReal to XFixed and XInt
;-------------------------------------------------
Move.l XAMOSReal(pc),d0
Bsr ConvertAMOSRealToFixed
Lea.l XFixed(pc),a0
Move.l d0,(a0)
Swap d0
Ext.l d0
Lea.l XInt(pc),a0
Move.l d0,(a0)
;--------------------------------------------------
; Convert YAMOSReal to YFixed and YInt
;--------------------------------------------------
Move.l YAMOSReal(pc),d0
Bsr ConvertAMOSRealToFixed
Lea.l YFixed(pc),a0
Move.l d0,(a0)
Swap d0
Ext.l d0
Lea.l YInt(pc),a0
Move.l d0,(a0)
;------------------------
; Pick turn
;------------------------
Btst.b #0,Turn(pc)
Bne DS_Turn1
;--------------------
; TURN ZERO
;--------------------
DS_Turn0
;--------------------
; Fill variables
;--------------------
Lea.l DS_Len0(pc),a4
Move.l Directions(pc),a3
; ----------------------------------------------
; Calculate the length of the straight direction
; ----------------------------------------------
Move.l Direction(pc),d0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of the left 1 direction
; ----------------------------------------------
Move.l DirStep0(pc),a5
Move.l Direction(pc),d0
Add.l a5,d0
Cmp d0,a3
Bhi DS_OK0 ;d0 < a3
Sub.l a3,d0
DS_OK0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of the right 1 direction
; ----------------------------------------------
Move.l Direction(pc),d0
Cmp d0,a5
Bls DS_OK1 ;d0 >= a5
Add.l a3,d0
DS_OK1 Sub.l a5,d0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of the left 2 direction
; ----------------------------------------------
Move.l DirStep1(pc),a5
Move.l Direction(pc),d0
Add.l a5,d0
Cmp d0,a3
Bhi DS_OK2 ;d0 < a3
Sub.l a3,d0
DS_OK2
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of the right 2 direction
; ----------------------------------------------
Move.l Direction(pc),d0
Cmp d0,a5
Bls DS_OK3 ;d0 >= a5
Add.l a3,d0
DS_OK3 Sub.l a5,d0
Move.l d0,a2 ;Store
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ---------------------
; OtherPlayersCare
; ---------------------
Bsr OtherPlayersCare
;-----------------------------------------------
; Return the choice made in previous turn via d7
;-----------------------------------------------
Move.l Player(pc),d0
Lea.l PlayersChoice(pc),a0
Moveq #0,d7
Move.b (a0,d0),d7 ;d7 := PlayersChoice[Player]
;----------------------
; Store lengths
;----------------------
;DS_PrecalculatedLens[0, 1, ...] := DS_Len0, DS_LenL1, ...
Asl.w #5,d0 ;d0 := player no * 4 * 8
Moveq #5,d1 ;This could also be only 4.
Lea.l DS_PrecalculatedLens(pc),a0
Add.l d0,a0
Lea.l DS_Len0(pc),a1
DS_StoreLensLoop
Move.l (a1)+,(a0)+
Dbra d1,DS_StoreLensLoop
;----------------------
; Debugging
;----------------------
Move.l Player(pc),d0
Lea.l DS_ArrowDecisionStore(pc),a0
Move.b (a0,d0),d0 ;d0 := DS_ArrowDecisionStore[Player]
Moveq #1,d6
Tst.b d0
Bne DS_DebugSkip
Moveq #0,d6
DS_DebugSkip
Rts
;----------------------
; TURN ONE
;----------------------
DS_Turn1
;----------------------
; Load lengths
;----------------------
Move.l Player(pc),d0
Asl.w #5,d0 ;d0 := player*4*8
Moveq #5,d1 ; This could also be only 4.
Lea.l DS_PrecalculatedLens(pc),a0
Add.l d0,a0
Lea.l DS_Len0(pc),a1
DS_LoadLensLoop
Move.l (a0)+,(a1)+
Dbra d1,DS_LoadLensLoop
;--------------------
; Fill variables
;--------------------
Lea.l DS_LenL3(pc),a4
Move.l Directions(pc),a3
; ----------------------------------------------
; Calculate the length of the left 3 direction
; ----------------------------------------------
Move.l DirStep2(pc),a5
Move.l Direction(pc),d0
Add.l a5,d0
Cmp d0,a3
Bhi DS_1OK0 ;d0 < a3
Sub.l a3,d0
DS_1OK0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of right 3 direction
; ----------------------------------------------
Move.l Direction(pc),d0
Cmp d0,a5
Bls DS_1OK1 ;d0 >= a5
Add.l a3,d0
DS_1OK1 Sub.l a5,d0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of left 4 direction
; ----------------------------------------------
Move.l DirStep3(pc),a5
Move.l Direction(pc),d0
Add.l a5,d0
Cmp d0,a3
Bhi DS_1OK2 ;d0 < a3
Sub.l a3,d0
DS_1OK2
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of right 4 direction
; ----------------------------------------------
Move.l Direction(pc),d0
Cmp d0,a5
Bls DS_1OK3 ;d0 >= a5
Add.l a3,d0
DS_1OK3 Sub.l a5,d0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of left 5 direction
; ----------------------------------------------
Move.l DirStep4(pc),a5
Move.l Direction(pc),d0
Add.l a5,d0
Cmp d0,a3
Bhi DS_1OK4 ;d0 < a3
Sub.l a3,d0
DS_1OK4
Bsr TestLengthOfDirection
Move.l d7,(a4)+
; ----------------------------------------------
; Calculate the length of right 5 direction
; ----------------------------------------------
Move.l Direction(pc),d0
Cmp d0,a5
Bls DS_1OK5 ;d0 >= a5
Add.l a3,d0
DS_1OK5 Sub.l a5,d0
Bsr TestLengthOfDirection
Move.l d7,(a4)+
;------------------------------------------------------
; Rotation radius and arrow collision special logic
;------------------------------------------------------
; An "arrow" collision is the following condition:
; Len0 * 2 <= 6 and Len0 * 2 < LenL1 and Len0 * 2 < LenR1
; In words, the straight ahead len is small, and
; LenL1 and LenR1 are greater than twice the straight ahead len.
; On a new arrow collision, make the decision only
; based on LenL1 and LenR1 and not the other
; LenL* and LenR*.
; There is a certain stickiness to the decision from a previous turn/pass,
; as per the above jump to DS_WasArrowCollision.
;------------------------------------------------------
DS_ArrowCollisionLogic
Move.l #0,d6 ;DEBUG
Move.l Player(pc),d0
Lea.l DS_ArrowDecisionStore(pc),a0
Move.b (a0,d0),d0 ;d0 := DS_ArrowDecisionStore[Player]
Tst.b d0
Bne DS_WasArrowCollision
DS_WasntArrowCollision
;Set fractions of the radius of the rotation into d1, d2, d3, d4 and d5
Move.l Rotation(pc),d1 ;d1 := the radius of the rotation
; Move.l d1,d2
; Lsr.w #3,d2
; Sub.w d1,d2
; Neg.w d2 ;d2 := 7/8 * the radius
Move.l d1,d2
Lsr.w #2,d2
Move.l d2,d5 ;d5 := 1/4 * the radius
Sub.w d1,d2
Neg.w d2 ;d2 := 3/4 * the radius
Addq #2,d2
Move.l d1,d3
Lsr.w #1,d3 ;d3 := 1/2 * the radius
Addq #4,d3
Move.l d2,d4
Lsr.w #1,d4 ;d4 := 3/8 * the radius
; Check for arrow collision
Move.l DS_Len0(pc),d0
Lsr.w #1,d0
Cmp.l #6,d0
Bgt DS_NotNewArrowCollision ;if DS_Len0 * 2 > 6: branch to DS_NotNewArrowCollision
; Cmp.l d0,d4
; Bls DS_NotNewArrowCollision
Cmp.l DS_LenL1(pc),d0
Bge DS_NotNewArrowCollision ;if DS_Len0 * 2 >= DS_LenL1: branch to DS_NotNewArrowCollision
Cmp.l DS_LenR1(pc),d0
Blt DS_NewArrowCollision ;if DS_Len0 * 2 < DS_LenR1: branch to DS_NewArrowCollision
DS_NotNewArrowCollision
; If LenL* or LenR* are so small that turning left or right becomes too tight given the rotation radius,
; zero all directions at the same side with a higher index;
; then branch to DS_FindMax.
; Rationale: the FindMax logic takes plain maximum from L* and R*, and thus, free space in
; e.g. L4 overrides lack of free space in L1. The above zeroing makes sure that the tight
; conditions near to the ahead direction prevail in the decision.
DS_Left_Care
Cmp.l DS_LenL1(pc),d3
Bgt DS_L1_Collision ;if 1/2 * the radius > DS_LenL1: branch to DS_L1_Collision
Cmp.l DS_LenL2(pc),d2
Bgt DS_L2_Collision ;if 3/4 * the radius > DS_LenL2: branch to DS_L2_Collision
Cmp.l DS_LenL3(pc),d3
Bgt DS_L3_Collision; ;if 1/2 * the radius > DS_LenL3 (changed from d1, which is the radius)
DS_Right_Care
Cmp.l DS_LenR1(pc),d3
Bgt DS_R1_Collision ;if 1/2 * the radius > DS_LenR1: branch to DS_R1_Collision
Cmp.l DS_LenR2(pc),d2
Bgt DS_R2_Collision ;if 3/4 * the radius > DS_LenR2: branch to DS_R2_Collision
Cmp.l DS_LenR3(pc),d3
Bgt DS_R3_Collision ;if 1/2 * the radius > DS_LenR3 (changed from d1, which is the radius)
Bra DS_FindMax
DS_L1_Collision
Moveq #0,d0
Lea.l DS_LenL2(pc),a0
Move.l d0,(a0)+ ;DS_LenL2 := 0
Addq #4,a0
Move.l d0,(a0)+ ;DS_LenL3 := 0
Addq #4,a0
Move.l d0,(a0)+ ;DS_LenL4 := 0
Addq #4,a0
Move.l d0,(a0) ;DS_LenL5 := 0
Bra DS_Right_Care
DS_L2_Collision
Moveq #0,d0
Lea.l DS_LenL3(pc),a0
Move.l d0,(a0)+ ;DS_LenL3 := 0
Addq #4,a0
Move.l d0,(a0)+ ;DS_LenL4 := 0
Addq #4,a0
Move.l d0,(a0) ;DS_LenL5 := 0
Bra DS_Right_Care
DS_L3_Collision
Moveq #0,d0
Lea.l DS_LenL4(pc),a0
Move.l d0,(a0)+ ;DS_LenL4 := 0
Addq #4,a0
Move.l d0,(a0) ;DS_LenL5 := 0
Bra DS_Right_Care
DS_R1_Collision
Moveq #0,d0
Lea.l DS_LenR2(pc),a0
Move.l d0,(a0)+; ;DS_LenR2 := 0
Addq #4,a0
Move.l d0,(a0)+ ;DS_LenR3 := 0
Addq #4,a0
Move.l d0,(a0)+ ;DS_LenR4 := 0
Addq #4,a0
Move.l d0,(a0) ;DS_LenR5 := 0
Bra DS_FindMax
DS_R2_Collision
Moveq #0,d0
Lea.l DS_LenR3(pc),a0
Move.l d0,(a0)+ ;DS_LenR3 := 0
Addq #4,a0
Move.l d0,(a0)+ ;DS_LenR4 := 0
Addq #4,a0
Move.l d0,(a0) ;DS_LenR5 := 0
Bra DS_FindMax
DS_R3_Collision
Moveq #0,d0
Lea.l DS_LenR4(pc),a0
Move.l d0,(a0)+ ;DS_LenR4 := 0
Addq #4,a0
Move.l d0,(a0) ;DS_LenR5 := 0
Bra DS_FindMax
DS_WasArrowCollision ;There was an arrow collision in the previous frame.
;Preserve the previously made turn left or turn right decision driven by arrow collision
;unless quitting condition obtains
Move.l DS_Len0(pc),d1
Cmp.l DS_LenL1(pc),d1
Bge DS_QuitArrowCollision ;if DS_Len0 >= DS_LenL1: branch to DS_QuitArrowCollision
Cmp.l DS_LenR1(pc),d1
Bge DS_QuitArrowCollision ;if DS_Len0 >= DS_LenR1: branch to DS_QuitArrowCollision
Move.l d0,d7 ;d7 := DS_ArrowDecisionStore[Player]
Move.l #$1,d6 ;DEBUG
Bra DS_Store_Decision
DS_QuitArrowCollision
Move.l Player(pc),d0
Move.b #0,(a0,d0) ;DS_ArrowDecisionStore[Player] := 0
Bra DS_WasntArrowCollision
DS_NewArrowCollision
Moveq #1,d7 ;#1: turn left
Move.l DS_LenL1(pc),d0
Cmp.l DS_LenR1(pc),d0
Bge DS_NAC_DirInD7 ;if DS_LenL1 >= DS_LenR1: branch to DS_NAC_DirInD7
Moveq #2,d7 ;#2: turn right
DS_NAC_DirInD7
Move.l Player(pc),d0
Move.b d7,(a0,d0) ;DS_ArrowDecisionStore[Player] := d7
Move.l #$1,d6 ;DEBUG
Bra DS_Store_Decision
;------------------------------------------------------
; Find max direction length and max index of the length
;------------------------------------------------------
DS_FindMax
Lea.l DS_Len0(pc),a4
Moveq #$A,d0
Moveq #0,d1 ;lenMax: max value of length
Moveq #0,d2 ;lenMaxIdx: index of max length
DS_DecLoop
Move.l (a4)+,d3
Cmp.w d1,d3
Bls DS_NotHigher ;if DS_LenX <= lenMax: goto DS_NotHigher
Move.w d3,d1 ;lenMax := value
Move.b d0,d2 ;lenMaxIdx := index of the max value found
DS_NotHigher
DBra d0,DS_DecLoop
;------------------------------------------------------------------------
; Calculate decision number (0, 1, 2) and store it to PlayersChoice array
;------------------------------------------------------------------------
Cmp.b #$A,d2
Beq DS_STRAIGHT_ON_INDEX
; d7 := ((lenMaxIdx bitand 1) xor 1) + 1
And.b #1,d2
Eor.b #1,d2
Add.b #1,d2
Move.l d2,d7 ;Save to decision register, d7
DS_Store_Decision
Move.l Player(pc),d0
Lea.l PlayersChoice(pc),a0
Move.b d7,(a0,d0) ;PlayersChoice[Player] := decision (0: no action, 1: turn left, 2: turn right)
Rts
DS_STRAIGHT_ON_INDEX
Moveq #0,d7 ;Save to decision register
Bra DS_Store_Decision
; ___________________________________________________________________
;| Handle other players
;|___________________________________________________________________
;| Take into account a possible collision with a future trajectory
;| of other players and potentially change/reduce the calculated
;| lengths for how far one can go in different directions, thereby
;| affecting the decision to turn left or right or stay moving straight on.
;| The projected trajectory is a linear extension of the
;| current direction.
;|
;| The detail of the logic seems difficult to understand in retrospect (2024).
;| It involves the calculation of a certain vector, its size and a direction,
;| certain angles, certain other values based on these angles,
;| sin values of these values, a ratio of these sin values,
;| and a certain length times the ratio.
;|
;| Input: PlayerOn, PlayersDir, XHash, YHash, XInt
;| YInt, Direction
;| Affected: DS_Len0, DS_LenL1, DS_LenL2, DS_LenR1, DS_LenR2.
;|
;| Loop registers:
;| a1: plrNoTimesFour: other player no * 4 (an outer loop variable)
;| a2: ownPlrExamDirection: the examined own player direction,
;| initially the own player direction itself and then its modifications
;| a3: directionLoopVar: driving variable of the direction loop
;| Other register with invariant meaning:
;| a4: othPlrDirection: a player direction
;|
;| This procedure does not depend on any registers for input or output.
;|___________________________________________________________________
OP_PlayerX dc.l 0
OP_PlayerY dc.l 0
OP_A dc.l 0
OtherPlayersCare
Move.l #20,a1 ;for plrNoTimesFour from 5*4 to 0*4, step -4
OP_PlayersLoop_Start
Move.l PlayerOn(pc),a0
Tst.l (a0,a1)
Beq OP_PlayerFinished ;if PlayerOn[plrNoTimesFour] == 0, skip the player.
Move.l PlayersDir(pc),a0
Move.l (a0,a1),a4 ;othPlrDirection := PlayersDir[plrNoTimesFour]
;----------------------------------------------------------------
; Calculate dx and dy; and the vector quadrant
;----------------------------------------------------------------
; dx := abs(other player x int - the own player x int)
; dy := abs(other player y int - the own player y int)
; d2 := quadrant of the dx, dy vector before applying the abs
;----------------------------------------------------------------
Move.l YHash(pc),a0
Move.l (a0,a1),d0
Bsr ConvertAMOSRealToFixed
Swap d0
Move.w d0,d3 ;d3.w := Y#[plrNoTimesFour] converted to int
Move.l XHash(pc),a0
Move.l (a0,a1),d0
Bsr ConvertAMOSRealToFixed
Swap d0
Ext.l d0 ;d0 := int(X#[plrNoTimesFour])
Move.w d3,d1
Ext.l d1 ;d1 := int(Y#[plrNoTimesFour])
Sub.l XInt(pc),d0 ;d0 := int(X#[plrNoTimesFour]) - XInt
Sub.l YInt(pc),d1 ;d1 := int(Y#[plrNoTimesFour]) - YInt
Tst.l d0
Bmi OP_XMinus
Tst.l d1
Bmi OP_XPlus_YMinus
OP_XPlus_YPlus
Moveq #0,d2 ;quadrant is 0
Bra OP_Quadrant_Calculated
OP_XPlus_YMinus
Moveq #1,d2 ;quadrant is 1
Neg.l d1
Bra OP_Quadrant_Calculated
OP_XMinus
Tst.l d1
Bmi OP_XMinus_YMinus
OP_XMinus_YPlus
Moveq #3,d2 ;quadrant is 3
Neg.l d0
Bra OP_Quadrant_Calculated
OP_XMinus_YMinus
Neg.l d0
Neg.l d1
Moveq #2,d2 ;quadrant is 2
OP_Quadrant_Calculated
;--------------------------------------------
; If dx == 0 and dy == 0, finish the business.
Tst.w d1
Bne OP_DxDyNotZero
Tst.w d0
Beq OP_PlayerFinished
;----------------------------------------------------------------
; Calculate the direction of the dx, dy vector given the quadrant
;----------------------------------------------------------------
OP_DxDyNotZero
Move.l d1,d7 ;d7 := dy
Move.l d0,d6 ;d6 := dx
Cmp.w d1,d0
Bls OP_ReverseOK ;if dx <= dy: goto OP_ReverseOK
OP_ReverseDo
Asl.w #8,d1
Divu.w d0,d1 ;d1 == tan(alpha)*$100, which is d1 * $100/d0, which is dy * $100/dx
Ext.l d1
Move.l AtanTable(pc),a0
Moveq #0,d3
Move.b (a0,d1),d3 ;d3 := ATan(d1), in the directions units
Move.l Directions(pc),d4
Lsr.w #2,d4 ;d4 := DirectionsQuarter
Sub.w d3,d4 ;d4 := DirectionsQuarter - ATan(d1), in the directions units
Bra OP_Correct_Angle_Using_Quadrant
OP_ReverseOK ;d0 <=d1
Asl.w #8,d0
Divu.w d1,d0 ;d0 == tan(alpha)*$100, which is d0 * $100/d1, which is dx * $100/dy
Ext.l d0
Move.l AtanTable(pc),a0
Moveq #0,d4
Move.b (a0,d0),d4 ;d4 := ATan(d0) in the directions units
OP_Correct_Angle_Using_Quadrant
Move.l Directions(pc),d3
Lsr.w #1,d3 ;d3 := DirectionsHalf
Btst #0,d2 ;Is it 1 or 3 quadrant?
Beq OP_TestBit2 ;It isn't.
Sub.w d3,d4
Neg.w d4 ;d4 := DirectionsHalf - Direction
OP_TestBit2
Btst #1,d2 ;Is it 2 or 3 quadrant?
Beq OP_VectorDirectionCalculated
Add.w d3,d4 ;d4 := d4 + DirectionsHalf
;This pertains only to quadrant 3
Cmp.l Directions(pc),d4
Bne OP_VectorDirectionCalculated
Moveq #0,d4; ;if d4 == 2 * pi: d4 := 0
OP_VectorDirectionCalculated
;-----------------------------
; d4: direction of vector
; d6: dx
; d7: dy
;-----------------------------
; Calculate the size of vector
;-----------------------------
Bsr CalculateVectorSize
Move.l d6,d0 ;d0 := vector size of dy and dy
;---------------------------
; We need to preserve:
; d0: a (the vector size of dy and dy)
; d4: ownToOthrVectorDir: direction of vector
; Issue: it needs to be verified that the above is really a direction from own player
; to the other player rather than the other way around.
;---------------------------
Cmp.w #ASizeLimit,d0
Bhi OP_PlayerFinished ;if vector size > ASizeLimit: goto OP_PlayerFinished
Move.l #100,a6 ;DEBUG
;-----------------------------------
; A loop for own player directions
;-----------------------------------
;Direction will be in a2
;a3: loop variable 4->0 (init to 5, but the first taking into account is a decrement)
Move.l Direction(pc),a2 ;a2 := the own player direction (loop initialization)
Move.l #5,a3 ;directionLoopVar := straight ahead
OP_DirectionLoop_Start
;Let's check possibilities
Cmp.w a2,d4
Beq OP_LengthIsA ;if the own player direction == direction of vector: goto OP_LengthIsA
Move.l #$FFFF,d1 ;length := $FFFF
;------------------------------------------------------------------------------------
; Calculate alpha and beta
;------------------------------------------------------------------------------------
; alpha := direction of the vector - other player direction, normalized to positive value
; beta := direction of the vector - own player direction, normalized to positive value
; The normalization to positive value is adding 2 * pi if required.
; The alpha and beta angles are expressed in direction count units as integers.
; d7 := alpha; d6 := beta
;------------------------------------------------------------------------------------
Move.l a4,d3 ;d3 := othPlrDirection
Move.l d4,d7 ;d7 := direction of vector
Sub.l d3,d7 ;d7 := direction of vector - othPlrDirection
Bpl OP_AlphaCalculated
Add.l Directions(pc),d7
OP_AlphaCalculated ;d7 := alpha (direction of vector - othPlrDirection, norm. to positive value)
Move.l a2,d3 ;d3 := own player direction
Move.l d4,d6 ;d6 := direction of vector
Sub.l d3,d6
Bpl OP_BetaCalculated
Add.l Directions(pc),d6
OP_BetaCalculated ;d6 := beta (direction of vector - own player direction, norm. to positive value)
Move.l Directions(pc),d3
Lsr.w #1,d3 ;d3:= pi (=directions half)
;----------------------------------------------------------------
; Compare alpha and beta
; Issue: a description or a specification could be added here.
;----------------------------------------------------------------
; at time of entry: d7 == alpha; d6 == beta; d3 == pi
;----------------------------------------------------------------
Cmp.w d3,d7
Bls OP_AlphaNotGtThanPi ;if alpha <= pi: goto OP_AlphaNoGtThanPi
Cmp.w d3,d6
Bls OP_NoCollision ;if alpha > pi and beta <= pi: goto OP_NoCollision
; Holds true: alpha > pi and beta > pi
Asl.w #1,d3 ;d3 := 2 * pi
Sub.l d3,d7
Neg.l d7 ;d7 := -(alpha - 2 * pi) == 2 * pi - alpha
Sub.l d3,d6
Neg.l d6 ;d6 := -(beta - 2 * pi) == 2 * pi - beta
Lsr.w #1,d3 ;d3 := pi
Bra OP_MainAlphaBetaCase
OP_AlphaNotGtThanPi
Cmp.w d3,d6
Bhi OP_NoCollision ;if alpha <= pi and beta > pi: goto OP_NoCollision
OP_MainAlphaBetaCase
;----------------------------------------------------------------
; Handle main case
;----------------------------------------------------------------
; d6 and d7 are a) beta and alpha or b) 2 * pi - beta and 2 * pi - alpha.
; d7: alpha2; d6: beta2 (let us choose this notation).
; Issue: a description or specification could be added.
;----------------------------------------------------------------
Cmp.l d6,d7
Bls OP_NoCollision ;if alpha2 <= beta2: goto OP_NoCollision
Move.l d3,d5
Sub.l d7,d5 ;d5 := pi - alpha2
Cmp.l d5,d6
Bhi OP_NoCollision ;if pi + beta2 > alpha2: goto OP_NoCollision
; Issue: The above comment "if pi + beta2 > alpha2: goto OP_NoCollision" needs to be verified.
; Calculate to handle potential collision
; Issue: The above description needs to be verified.
Move.l #1000,a6 ;DEBUG
Sub.l d7,d6
Neg.l d6 ;d6 := alpha2 - beta2
Sub.l d3,d7
Neg.l d7 ;d7 := pi - alpha2
Move.l d3,d5 ;d5 := pi
Lsr.w #1,d3 ;d3 := pi/2
Cmp.w d3,d7
Bls OP_PiMinusAlphaCorrected
Sub.l d5,d7
Neg.l d7 ;if pi - alpha2 > pi/2: d7 := pi - d7
OP_PiMinusAlphaCorrected
Cmp.w d3,d6
Bls OP_AlphaMinusBetaCorrected
Sub.l d5,d6
Neg.l d6 ;if alpha2 - beta2 > pi/2: d6 := pi - d6
OP_AlphaMinusBetaCorrected
Move.l d0,d5 ;d5 := d0, which is a
;
Move.l SinTable(pc),a0
Asl.w #2,d6
Move.l (a0,d6),d0
Bsr ConvertAMOSRealToFixed
Move.l d0,d3 ;d3 := sin(d6)
Asl.w #2,d7
Move.l (a0,d7),d0
Bsr ConvertAMOSRealToFixed ;d0 := sin(d7)
;----------------------------------------------------------------
; Calculate d0/d3
; d0 and d3 are 16.16 fixed-point numbers
;
; Issue: The above comment seems incorrect since the code seems to do more than calculate d0/d3.
; This idea is supported by the label "OP_DividePlusTimes" containing "PlusTimes".
; The purpose of the initial swaps and rors is unclear.
;
; Issue: The meaning of the comment "This operation shifts d1,d2 as high as possible" is unclear.
;
; d1: position in out counter
; d6: result
;
; What are the conditions under which there is and is not the ror applied to d0 and d3:
; Ror is skipped iff d3.w == 0 and d0.w == 0.
;----------------------------------------------------------------
OP_DividePlusTimes
Swap d3
Swap d0
Cmp.w #0,d3
Beq OP_d1OK ;if d3.w == 0: goto OP_d1OK
OP_DoRor
Ror.l #1,d3
Ror.l #1,d0
Bra OP_RorFin
OP_d1OK
Cmp.w #0,d0
Bne OP_DoRor ;if d0.w != 0: goto OP_DoRor
OP_RorFin ;This operation shifts d1,d2 as high as possible
Swap d0
And.l #$FFFF,d1 ;This seems unnecessary given there is d1 := 31 later anyway.
Moveq #0,d6 ;Clear the result
Moveq #31,d1 ;Position := 31
OP_Divide_Loop_Start
;if d3 <= d0: d0 := d0 - d3; set bit d1 in d6(result)
Cmp.l d0,d3
Bhi OP_Divide_NotSub ;d3>d0
Sub.l d3,d0
Bset.l d1,d6
OP_Divide_NotSub
Lsr.l #1,d3 ;d3 := d3 / 2
Subq #1,d1 ;position counter -= 1
Tst.l d3
Bne OP_Divide_Loop_Start ;if d3 != 0: goto OP_Divide_Loop_Start
Asl.l #1,d6 ;d6 := d6 * 2
;----------------------------------------------------------------
; d6 is a 16.16 fixed-point number.
;----------------------------------------------------------------
; d1 := d6 * a, where a is in d5
; a is the dx, dy vector length, an integer
;----------------------------------------------------------------
Move.w d6,d0
Mulu.w d5,d0 ;d0 := ratio.w * a
Swap d6
Mulu.w d5,d6 ;d6 := ratio.uw * a
Moveq #0,d1
Move.w d6,d1
Swap d1 ;d1.uw := d6.w
Add.l d0,d1 ;d1 := d1 + d0; and thus, d1 := (ratio.uw * a) << 16 + ratio.w * a
Swap d1
And.l #$FFFF,d1 ;d1 := int(d1 as 16.16 fixed-point number)
;-------------------------------
; d1 == collDist
;-------------------------------
Move.l d5,d0 ;d0 := a
Bra OP_NoCollision
OP_LengthIsA
Move.l d0,d1 ;collDist := d0
;--------------------------------------------------------------------------
; Use the calculated distance to collision (in d1) to limit DS_LenL* or DS_LenR*
; as applicable for the currently evaluated direction.
; Then, finish the direction loop by changing a2, which is ownPlrExamDirection.
; Issue: The part "calculated distance to collision" needs to be verified.
;--------------------------------------------------------------------------
; d1 == collDist: the distance to a potential collision with the other player,
; possibly an approximation or heuristic
;--------------------------------------------------------------------------
; Issue: The label "OP_NoCollision" below seems misleading;
; it seems once can arrive at the label even when there was a collision.
OP_NoCollision
Subq #1,a3 ;directionLoopVar -= 1
Cmp.w #4,a3
Beq OP_Straight_Lim ;if directionLoopVar == 4: goto straight
Cmp.w #3,a3
Beq OP_L0_Lim ;if directionLoopVar == 3: goto left 0
Cmp.w #2,a3
Beq OP_R0_Lim ;if directionLoopVar == 2: goto right 0
Cmp.w #1,a3
Beq OP_L1_Lim ;if directionLoopVar == 1: goto left 1
Bra OP_R1_Lim ;goto right 1
;------------------------------------------------------
; Limit straight and advance to next direction
;------------------------------------------------------
OP_Straight_Lim
; Cmp.w #$FFFF,d1
; Beq OP_PlayerFinished
Lea.l DS_Len0(pc),a0
Cmp.l (a0),d1
Bhi OP_Straight_NoCol
Move.l d1,(a0) ;if collDist <= DS_Len0: DS_Len0 := collDist
OP_Straight_NoCol
Add.l DirStep0(pc),a2 ;ownPlrExamDirection += DirStep0
Move.l Directions(pc),d1
Cmp d1,a2
Bls OP_OK0
Sub.l d1,a2 ;if ownPlrExamDirection > Directions: ownPlrExamDirection -= Directions
OP_OK0
Bra OP_DirectionLoop_Start
;--------------------------------------------
; Limit left 1 and advance to next direction
;--------------------------------------------
OP_L0_Lim
Lea.l DS_LenL1(pc),a0
Cmp.l (a0),d1
Bhi OP_L0_NoCol
Move.l d1,(a0) ;if collDist <= DS_LenL1: DS_LenL1 := collDist
OP_L0_NoCol
Move.l Direction(pc),a2
Move.l DirStep0(pc),d1 ;ownPlrExamDirection := Direction
Cmp a2,d1
Bls OP_OK1
Add.l Directions(pc),a2 ;if ownPlrExamDirection > DirStep0: ownPlrExamDirection += Directions
OP_OK1
Sub.l d1,a2 ;ownPlrExamDirection -= DirStep0
Bra OP_DirectionLoop_Start
;--------------------------------------------
; Limit right 1 and advance to next direction
;--------------------------------------------
OP_R0_Lim
Lea.l DS_LenR1(pc),a0
Cmp.l (a0),d1
Bhi OP_R0_NoCol
Move.l d1,(a0) ;if collDist <= DS_LenR1: DS_LenR1 := collDist
OP_R0_NoCol
Move.l Direction(pc),a2
Add.l DirStep1(pc),a2 ;ownPlrExamDirection := Direction + DirStep1
Move.l Directions(pc),d1
Cmp d1,a2
Bls OP_OK2
Sub.l d1,a2 ;if ownPlrExamDirection > Directions: ownPlrExamDirection -= Directions
OP_OK2
Bra OP_DirectionLoop_Start
;--------------------------------------------
; Limit left 2 and advance to next direction
;--------------------------------------------
OP_L1_Lim
Lea.l DS_LenL2(pc),a0
Cmp.l (a0),d1
Bhi OP_L1_NoCol
Move.l d1,(a0) ;if collDist <= DS_LenL2: DS_LenL2 := collDist
OP_L1_NoCol
Move.l Direction(pc),a2
Move.l DirStep1(pc),d1
Cmp a2,d1
Bls OP_OK3
Add.l Directions(pc),a2 ;if ownPlrExamDirection < DirStepSmall: ownPlrExamDirection += Directions
OP_OK3
Sub.l d1,a2 ;ownPlrExamDirection -= DirStepSmall
Bra OP_DirectionLoop_Start
;--------------------------------------------
; Limit right 2 and exit the direction loop
;--------------------------------------------
OP_R1_Lim
Lea.l DS_LenR2(pc),a0
Cmp.l (a0),d1
Bhi OP_R1_NoCol
Move.l d1,(a0) ;if collDist <= DS_LenR2: DS_LenR2 := collDist
OP_R1_NoCol
OP_PlayerFinished
;--------------------
; End of player loop
;--------------------
Subq #4,a1 ;plrNoTimesFour -= 4
Cmp.w #0,a1
Bge OP_PlayersLoop_Start ;loop on plrNoTimesFour >= 0
Rts
; _________________________________________________________
; | Calculate vector size
; |_________________________________________________________
; | in d6: dx
; | in d7: dy
; | out d6: the result
; | preserve d4
; | used up: d2, d3
; | This is sqrt(dx^2+dy^2) as a four-case approximation,
; | where each case is a linear combination of dx and dy.
; |_________________________________________________________
CalculateVectorSize
Cmp.l d6,d7
Bls CV_RegOK ;d7<=d6
Exg.l d6,d7 ;Swap d6 and d7
CV_RegOK ;Holds true: d7 <= d6
Move.l d6,d2
Lsr.w #2,d2 ;d2 := d6/4
Move.l d6,d3 ;d3 := d6
Sub.w d2,d3 ;d3 := 3/4 * d6
Cmp.w d7,d3
Bls CV_CASE1 ;d7 >= 3/4 * d6
Sub.w d2,d3
Cmp.w d7,d3
Bls CV_CASE2 ;d7 >= 1/2 * d6
Sub.w d2,d3
Cmp.w d7,d3
Bls CV_CASE3 ;d7 >= 1/4 * d6
CV_CASE4
Rts ; The result is in d6.
CV_CASE1
Sub.w d2,d6 ;d6 := 3/4*d6
Move.l d7,d3
Lsr.w #1,d3 ;d3 := d7/2
Add.w d3,d6 ;d6 := 3/4*d6+d7/2
Lsr.w #3,d7
Add.w d7,d6 ;d6 := 3/4*d6+d7/2+d7/8
Rts
CV_CASE2
Lsr.w #1,d2
Sub.w d2,d6 ;d6 := d6*7/8
Move.l d7,d3
Lsr.w #4,d3
Sub.w d3,d6 ;d6 := d6*7/8-d7/16
Lsr.w #1,d7
Add.w d7,d6 ;d6 := d6*7/8+d7/2-d7/16
Rts
CV_CASE3
Lsr.w #3,d7 ;d7 := d7/2
Add.w d7,d6 ;d6 := d6+d7/8
Lsr.w #1,d7
Add.w d7,d6 ;d6 := d6+d7/8+d7/16
Rts
;=========================== DEBUGGING =========================
DoStrategyDebug
Bsr DoStrategy
; Move.l a6,d0
; Move.l a5,d1
; In a1 there is the direction of the vector
;
Move.l DS_Len0(pc),d0
Move.l DS_LenL1(pc),d1
Move.l DS_LenR1(pc),d2
; Move.l DS_LenL2(pc),d3
; Move.l DS_LenR2(pc),d4
Rts
; _______________________________
; |
; | CalcTestAndSpeedPoints
; |_______________________________
; |
; | d0-direction IN
; | a12-oxy#
; |
; | a12-speedxy OUT
; | d01-testxy
; |
; | changed regs: d0-d7
; | a1, a2, a4, a5
; |_______________________________
; d4 -xint
; d5 -yint
; d6 -xint+2
; d7 -yint+2
CalcTestAndSpeedPoints_2Pixel
Bsr CalculateSinAndCosFixed
Move.l d4,a4
Move.l d5,a5 ;Store fixed dx,dy for later
Move.l d4,d2
Move.l d5,d3 ;d23 = dxy
Move.l a2,d0
Bsr ConvertAMOSRealToFixed
Move.l d0,a2
Move.l a1,d0
Bsr ConvertAMOSRealToFixed
Move.l d0,a1
Move.l a2,d1 ;so that d0, d1 == xfixed, yfixed
Move.l d0,d4
And.l #$FFFF0000,d4
Move.l d4,d6
Move.l d1,d5
And.l #$FFFF0000,d5
Move.l d5,d7 ;d46:=xint, d57:=yint
Sub.l #$10000,d4
Sub.l #$10000,d5
Add.l #$30000,d6
Add.l #$30000,d7 ;INTS filled
Bsr CTP_StraightLoop
Exg.l d0,a1
Exg.l d1,a2 ;a12:=xyspeed, d01:=xyfixed
Move.l a4,d2
Move.l a5,d3 ;d23 = dxy
Move.l d0,d4
And.l #$FFFF0000,d4
Move.l d4,d6
Move.l d1,d5
And.l #$FFFF0000,d5
Move.l d5,d7 ;d4,d6:=xint d5,d7:=yint
Add.l #$20000,d6
Add.l #$20000,d7 ;INTS filled
Bsr CTP_StraightLoop
Rts ;d0,d1..test,a1,a2..speed
;------------------------------------- d01 ----
CTP_StraightLoop
Add.l d2,d0
Add.l d3,d1
Cmp.l d0,d4 ;x<xint
Bgt CTP_Finished
Cmp.l d1,d5 ;y<yint
Bgt CTP_Finished
Cmp.l d0,d6 ;x>=xint+2
Bls CTP_Finished
Cmp.l d1,d7 ;not y>=yint+2
Bgt CTP_StraightLoop
CTP_Finished
And.l #$FFFF0000,d0
And.l #$FFFF0000,d1
Swap d0
Swap d1
Rts
;------------------------------------
CalcTestAndSpeedPoints_1Pixel
Bsr CalculateSinAndCosFixed
Move.l d4,a4
Move.l d5,a5 ;Store fixed dx,dy
Move.l d4,d2
Move.l d5,d3 ;d2 is dx, d3 is dy
Move.l a2,d0
Bsr ConvertAMOSRealToFixed
Move.l d0,a2
Move.l a1,d0
Bsr ConvertAMOSRealToFixed
Move.l d0,a1
Move.l a2,d1 ;so that d0,d1=x,y fixed
Move.l d0,d4
And.l #$FFFF0000,d4
Move.l d4,d6
Move.l d1,d5
And.l #$FFFF0000,d5
Move.l d5,d7 ;d4,d6:=xint d5,d7:=yint
Sub.l #$10000,d4
Sub.l #$10000,d5
Add.l #$20000,d6
Add.l #$20000,d7 ;INTS filled
Bsr CTP_StraightLoop
Exg.l d0,a1
Exg.l d1,a2 ;a1,a2:=xyspeed,d0,d1:=beginxyfixed
Move.l a4,d2
Move.l a5,d3 ;d2 is dx, d3 is dy
Move.l d0,d4
And.l #$FFFF0000,d4
Move.l d4,d6
Move.l d1,d5
And.l #$FFFF0000,d5
Move.l d5,d7 ;d4,d6:=xint d5,d7:=yint
Add.l #$10000,d6
Add.l #$10000,d7 ;INTS filled
Bsr CTP_StraightLoop
Rts ;d0,d1..test,a1,a2..speed
; _____________________________________________
; |
; | CalculateSinAndCosFixed
; |_____________________________________________
; |
; | d0: direction in
; | d4: sin fixed out
; | d5: cos fixed out
; |
; | change regs: d0,d1,d3,d4,d5,d6,d7
; | a0
; |_____________________________________________
CalculateSinAndCosFixed
Move.l Directions(pc),d6
Lsr.w #2,d6 ;d6 := DirectQuarter
Move.l d0,d7 ;d7 := Direction
Divu.w d6,d7 ;d7 := direction / (direction count / 4)
; remainder is saved in the upper word or d7; d7.w has quadrant
Move.l d7,d1
Swap d1
Ext.l d1 ;d1 := remainder
Btst #0,d7
Beq CSF_FinalDir
Sub.l d6,d1
Neg.l d1 ;Dir=-(Dir-DirsQuarter)
CSF_FinalDir
;Now d1 == DifDirection
Move.l d1,d3 ;StoreDifDirection
Asl.l #2,d1 ; d1 := d1 * 4
Move.l SinTable(pc),a0
Move.l (a0,d1),d0
Bsr ConvertAMOSRealToFixed
Move.l d0,d4
Btst #1,d7
Beq CSF_SinCalculated
Neg.l d4
CSF_SinCalculated
Sub.l d6,d3
Neg.l d3 ;Dir=-(Dir-DirsQuarter)
Asl.l #2,d3
Move.l (a0,d3),d0 ;a0 == SinTable
Bsr ConvertAMOSRealToFixed
Move.l d0,d5
Add.b #1,d7
Btst #1,d7
Beq CSF_CosCalculated
Neg.l d5
CSF_CosCalculated
Rts
; _____________________________________________
; |
; | CalculateSinAndCos
; |_____________________________________________
; |
; | d0: direction in
; | d0: sin out
; | d2: cos out
; |
; | changed regs: d0, d1, d2, d3, d6, d7
; | a0
; |_____________________________________________
CalculateSinAndCos
Move.l Directions(pc),d6
Lsr.w #2,d6 ;d6 := direction count / 4 (DirCntQuarter)
Move.l d0,d7 ;d7 := direction
Divu.w d6,d7 ;d7 := direction / (direction count / 4)
;remainder is saved in the upper word or d7; d7.w has quadrant
Move.l d7,d1
Swap d1
Ext.l d1 ;d1 := remainder of direction / (direction count / 4)
Btst #0,d7
Beq CS_FinalDir
Sub.l d6,d1
Neg.l d1 ;dir = -(dir - direction count / 4)
CS_FinalDir
;Now d1 == DifDirection
Move.l d1,d3 ;StoreDifDirection
Asl.l #2,d3
Move.l SinTable(pc),a0
Move.l (a0,d3),d0 ;Picked from the table
Btst #1,d7
Beq CS_SinCalculated
Add.b #$80,d0
CS_SinCalculated ;The sine is in d0
Sub.l d6,d1
Neg.l d1 ;Dir=-(Dir-DirsQuarter)
Asl.l #2,d1
Move.l (a0,d1),d2 ;Picked from the table
Add.b #1,d7
Btst #1,d7
Beq CS_CosCalculated
Add.b #$80,d2
CS_CosCalculated
Rts
;--------------------------------------------------------------------
; Quick 68000 asm guide, to support the above as a quick reference
;--------------------------------------------------------------------
; Registers: 32-bit registers d0 through d7, and then a0 through a7;
; then there are other registers such as stack pointer.
; .l, .w and .b selects on which part of the register or location to operate:
; .l: 32 bits; .w: 16 bits; .b: 8 bits
; Negative integers are using two's complement representation.
;
; Move.l: copy the 32 bits from 1st to 2nd operand (left to right)
; Move.l (a0,d1),d2: add d1 to the address a0 to get address to read from, and copy the result to d2
; Moveq: move quick a small immediate value to the 32 bits of the register
; Lea: load effective address
; Swap: swap the upper and lower 16-bit words of the register
; Ext.l: extend the sign bit of the lower 16-bit word to all the bits of the upper 16-bit word
; Exg: exchange/swap the values of the two locations, e.g. registers
; Bsr: branch to subroutine
; Rts: return from subroutine
; Bra: branch
; DBra: decrement and branch unless the result is -1 (good for loop control)
; Asl: arithmetic shift left, a bit operation
; Lsr: logical shift right, a bit operation
; Neg.l: multiply the 32 bits of the register -1
; And.l: bitwise and
; Add.l: integer addition
; Sub.l: integer subtraction
; Mulu.w: multiplies (unsigned) the lower 16-bit words, storing the result into the 32 bits of the 2nd operand
; Mulu.l: not possible
; Divu: divide unsigned; the upper 16-bit word has the remainder, whereas the lower 16-bit word has the quotient
; Cmp: compares two values, affecting subsequent Beq, etc.
; Btst #0,d0: test the least significant bit (bits counted from 0, from least significant); affects subsequent Beq
; Beq: branch on equal
; Bne: branch on not equal
; Bhi: branch on higher than (the 2nd operand of Cmp > the 1st operand; somewhat counterintuitive)
; Bls: branch on lower than or same
; Bgt: branch on greater than
; Bge: branch on greater than or equal
; Bmi: branch on minus; used e.g. after Tst
; Bpl: branch on plus; used e.g. after Tst
; Bset x, y: set the bit number x (counting from least significant ones, from zero) in y
; Tst: compare to zero and affect subsequent Beq and Bne
; Ror: bitwise rotate right
; Rol: bitwise rotate left
;--------------------------------------------------------------------
RecordAndReplay.s
[edit | edit source];------------------------------------------------------------------------------
; Record and replay assembly procedures for Duenix for the Amiga
;------------------------------------------------------------------------------
; Player decisions (one of three options 0, 1, and 2, requiring two bits)
; are being stored/saved, to be loaded later.
; The single round/frame requires 6 * 2 bits of storage,
; two bits per player; they are stored in a single 16-bit word.
; One would think this would have been fast enough in
; in AMOS using peeks, pokes and similar.
; The comments have been expanded in 2024 to be excessively detailed,
; which is fine for educational purposes.
; This is Motorola 68000 assembly.
;------------------------------------------------------------------------------
MaxSize = 8000
;-------------------------
; Interface variables
;-------------------------
PMove dc.l 0 ;The beginning of an array of player moves/decisions for the current round.
;Each move is stored in an AMOS integer, so the array takes 4 * 6 bytes.
Record dc.l 0 ;The address of record space, containing recorded decisions of players for all rounds.
;In this space, the decision for all players for a given round takes 16 bits
;(12 bits, plus 4 bits free).
TopPtr dc.l 0 ;The pointer in the record space
;-------------------------
; Procedure entry points
;-------------------------
Bra SavePos
Bra LoadPos
;----------------------
; Procedure SavePos
;----------------------
SavePos
Moveq #0,d1 ;d1 := 0
Moveq #5,d0 ;PlayerNumber := 5
Move.l PMove(pc),a0 ;a0 := PMove address
Lea TopPtr(pc),a2 ;a2 := TopPtr address
SavePos_Loop
Move.l d0,d2
Asl.l #2,d2 ;d2 := PlayerNumber * 4
Move.l (a0,d2),d3 ;d3 := PMove[PlayerNumber], which is one of 0, 1, and 2
Asl.w d0,d3
Asl.w d0,d3 ;d3 := d3 << (2 * PlayerNumber)
Or.w d3,d1 ;d1 := d1 bitor d3
DBra d0,SavePos_Loop ;Go to next PlayerNumber
Move.l Record(pc),a1
Move.l (a2),d2
Move.w d1,(a1,d2) ;Record[TopPtr] := word containing the decisions of all players
Cmp.w #MaxSize,a2
Beq SavePos_Skip
Addq.l #2,(a2) ;TopPtr += 2
SavePos_Skip
Rts
;----------------------
; Procedure LoadPos
;----------------------
LoadPos
Move.l PMove(pc),a0 ;a0 := PMove address
Lea TopPtr(pc),a2 ;a2 := TopPtr address
Move.l Record(pc),a1
Move.l (a2),d2
Move.w (a1,d2),d1 ;d1 := Record[TopPtr]
Cmp.w #MaxSize,d2
Beq LoadPos_Skip
Addq.l #2,(a2) ;TopPtr += 2
LoadPos_Skip
Moveq #5,d0 ;PlayerNumber := 5
LoadPos_Loop
Move.w d1,d2 ;d2 := Record[TopPtr]
Asr.w d0,d2
Asr.w d0,d2
And.w #3,d2 ;d2 := (Record[TopPtr] >> (2 * PlayerNumber)) bitand 0b11
Ext.l d2
Move.l d0,d3
Asl.l #2,d3
Move.l d2,(a0,d3) ;PMove[PlayerNumber] := (Record[TopPtr] >> (2 * PlayerNumber)) bitand 0b11
DBra d0,LoadPos_Loop ;Go to next PlayerNumber
Rts
PutPixel.s
[edit | edit source];------------------------------------------------------------------------------
; DrawPixel - for Duenix for the Amiga
;------------------------------------------------------------------------------
; A set of procedures to draw 1 and 2x2 pixels of a given color.
; It also supports drawing a big (2x2) pixel with conditionally present
; dark boundary pixels around it.
; The logic deals with 5 bitplans; placing a pixel means modifying
; the corresponding bit in each of the 5 bitplans.
; The job seems rather trivial; one has to wonder why doing the same
; in AMOS was too slow (2024).
; This is Motorola 68000 assembly for the Amiga.
;------------------------------------------------------------------------------
;----------------------------------------------------------
; Interface variables
;----------------------------------------------------------
Bitplan0 dc.l 0,0,0,0 ;Addresses of bitplans 0-3
Bitplan4 dc.l 0,0,0,0 ;Address of bitplan 4 and three dummy zeros
pq_x_addr dc.l 0 ;Pixel queue x address
pq_y_addr dc.l 0 ;Pixel queue y address
pq_colour_addr dc.l 0 ;Pixel queue color address
pq_top dc.l 0 ;Top index of the item in the pixel queue
putpix_type dc.b 0
dc.b 0,0,0
;----------------------------------------------------------
; Entry points for procedures
;----------------------------------------------------------
bra Draw_queue_of_pixels
bra Draw_Small_Pixel_Conditioned
bra Draw_Big_Pixel_Conditioned
bra DSP_Conditioned_BigScreen
bra DBP_Conditioned_BigScreen
;----------------------------------------------------------
; Procedure Draw_One_Pixel_BigScreen
; Procedure Draw_One_Pixel
;----------------------------------------------------------
; d0: xcoord (input, does not change)
; d1: ycoord (input, does not change)
; d2: color (input, does not change)
; more input: Bitplan0
;
; used registers: d0-d7 but for d6, a0, a1, a2
;----------------------------------------------------------
Draw_One_Pixel_BigScreen
Move.l d0,d3
Lsr.w #3,d3
Move.l d1,d4
Mulu #80,d4
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 80 + xcoord / 8, which is the offset of the pixel address
bra dop_address_known
Draw_One_Pixel
Move.l d0,d3
Lsr.w #3,d3
Move.l d1,d4
Mulu #40,d4
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 40 + xcoord / 8, which is the offset of the pixel address
dop_address_known
Move.l d0,d3
And.l #7,d3
Sub.l #7,d3
Neg.l d3 ;d3 := 7 - (xcoord band 0b111), which is the bit number
Lea Bitplan0(pc),a1 ;a1 := Bitplan0 address
Moveq #4,d5 ;d5 := bitplan number, and a loop control register (we have 5 bitplans)
Move.l d2,d7 ;d7 := color
dop_Loop_Start
Move.l (a1)+,a2 ;a2 := current bitplan address
Add.l a0,a2
Move.b (a2),d4 ;d4 := the value of the byte of the pixel in the bitplane
Bclr.l d3,d4
Btst #0,d7
Beq dop_Zero
Bset.l d3,d4 ;clear the pixel bit or set it to 1 as applicable
dop_Zero
Move.b d4,(a2) ;write d4 back to the bitplane
Lsr.b #1,d7
DBra d5,dop_Loop_Start
Rts
;--------------------------------------------------------------
; Procedure Draw_Conditioned_Pixel_BigScreen
; Procedure Draw_Conditioned_Pixel
; DCP: Draw conditioned pixel.
; Draw using the color of 1.
; "conditioned" means draw the pixel only if its bitplan 4
; bit is empty.
;--------------------------------------------------------------
; d0: xcoord
; d1: ycoord
;-------------------------------------------------------------
Draw_Conditioned_Pixel_BigScreen
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #80,d4 ;d4 := ycoord * 80
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 80 + xcoord / 8, which is offset of the pixel address
bra dcp_address_known
Draw_Conditioned_Pixel
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #40,d4 ;d4 := ycoord * 40
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 40 + xcoord / 8, which is offset of the pixel address
dcp_address_known
Move.l d0,d3
And.l #7,d3
Sub.l #7,d3
Neg.l d3 ;d3 := 7 - (xcoord band 0b111), which is the bit number
Move.l Bitplan4(pc),a1
Btst.b d3,(a1,a0.l)
Bne dcp_Finished ;If bitplan 4 is non-zero, do not draw anything
Lea Bitplan0(pc),a1 ;a1 := Bitplan0 address
;The first round outside of the loop
Move.l (a1)+,a2
Bset.b d3,(a2,a0.l)
Moveq #2,d2 ;Only 3 bitplans remain
dcp_Loop_Start
Move.l (a1)+,a2
Bclr.b d3,(a2,a0.l)
DBra d2,dcp_Loop_Start
dcp_Finished
Rts
;--------------------------------------
; Procedure DSP_Conditioned_BigScreen
; DSP: Draw small pixel
;--------------------------------------
DSP_Conditioned_BigScreen
;Draw classical pixel
Bsr Draw_One_Pixel_BigScreen
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Rts
Draw_Small_Pixel_Conditioned
;Draw classical pixel
Bsr Draw_One_Pixel
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Rts
;--------------------------------------
; Procedure DBP_Conditioned_BigScreen
; DBP: Draw big pixel.
; The boundary pixels are drawn in
; color 1 and are drawn only
; if the pixel being overwritten
; has color less than 16.
;--------------------------------------
DBP_Conditioned_BigScreen
;Draw classical pixel
Bsr Draw_Big_Pixel_BigScreen
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Rts
Draw_Big_Pixel_Conditioned
;Draw classical pixel
Bsr Draw_Big_Pixel
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d0
Bsr Draw_Conditioned_Pixel
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel
Subq #1,d0
Bsr Draw_Conditioned_Pixel
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Rts
;================================================
; Second, perhaps better take at big pixel
;================================================
;------------------------------------------------
; Procedure Draw_Big_Pixel_BigScreen
;------------------------------------------------
; d0: xcoord
; d1: ycoord
; d2: color
; used: d3, d4, d6, a0
;------------------------------------------------
Draw_Big_Pixel_BigScreen
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #80,d4 ;d4 := ycoord * 80
Add.l d4,d3
Move.l d3,a0 ;a0 := xcoord / 8 + ycoord * 80
Move.l d0,d4
And.w #$7,d4 ;d4 := xcoord band 0b111 (the bit number)
Move.w #$C000,d3
Lsr.w d4,d3 ;d3 := 0xC000 >> (xcoord band 0b111), which is the oring word
Move.w d3,d6
Eor.w #$FFFF,d6 ;d6 := oring word XOR FFFF, which is the anding word
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Add #80,a0
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Rts
;------------------------------------------------
; Procedure Draw_Big_Pixel
; Draws a "big pixel" consisting of 2x2 pixels
;------------------------------------------------
; d0: xcoord
; d1: ycoord
; d2: color
; used: d3, d4, d6, a0
;------------------------------------------------
Draw_Big_Pixel
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #40,d4 ;d4 := ycoord * 40
Add.l d4,d3
Move.l d3,a0 ;a0 := xcoord / 8 + ycoord * 40
Move.l d0,d4
And.w #$7,d4 ;d4 := xcoord band 0b111 (the bit number)
Move.w #$C000,d3
Lsr.w d4,d3 ;d3 := 0xC000 >> (xcoord band 0b111), which is the oring word
Move.w d3,d6
Eor.w #$FFFF,d6 ;d6 := oring word XOR FFFF, which is the anding word
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Add #40,a0
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Rts
;------------------------------------------------------------------------------
; Procedure dbp_Double_Pixel
; Draws two pixels horizontally next to each other. To be called two times,
; to draw the complete 2x2 big pixel.
;------------------------------------------------------------------------------
; a0: offset of the word to be modified, against the base of the bitplans
; d2: color
; d3: oring word
; d6: anding word
;------------------------------------------------------------------------------
dbp_Double_Pixel
Lea Bitplan0(pc),a1 ;a1 := Bitplan0
Moveq #4,d5 ;d5 := bitplan number, and a loop control register (we have 5 bitplans)
Move.l d2,d7 ;d7 := color
dbp_Loop_Start
Move.l (a1)+,a2 ;a2 := a1; a1 += 1
Add.l a0,a2 ;a2 := start of the current bitplan + offset of the byte to be modified
Move.w (a2),d4 ;d4 := content of the byte to be modified
And.w d6,d4
Btst #0,d7
Beq dbp_Zero
Or.w d3,d4
dbp_Zero
Move.w d4,(a2) ;write d4 back to the bitplane
Lsr.b #1,d7
DBra d5, dbp_Loop_Start
Rts
;============================================================
;------------------------------------------------
; Procedure Draw_queue_of_pixels
;------------------------------------------------
; input:
; pq_x_addr
; pq_y_addr
; pq_colour_addr
; pq_top
; putpix_type
; local:
; d0, d1, d2, d3, a0
; a6: index of the current element in the queue
;------------------------------------------------
Draw_queue_of_pixels
Move.l pq_x_addr(pc),a3
Move.l pq_y_addr(pc),a4
Move.l pq_colour_addr(pc),a5
Move.l #-1,a6 ;for each item in the queue (d6 := queue_item_idx)
dq_Loop
Addq #1,a6
Move.l pq_top(pc),a0
Cmp.l (a0),a6
Bge dq_finished ;if queue_item_idx >= pq_top: go to dq_finished
Move.l a6,d0
Asl.w #2,d0
Move.l (a5,d0),d2
Move.l (a4,d0),d1
Move.l (a3,d0),d0
Moveq #0,d3
Move.b putpix_type(pc),d3
Lea.l putpix(pc),a0
Jsr (a0,d3)
Bra dq_Loop
dq_finished
Rts
putpix
Bra Draw_Small_Pixel_Conditioned
Bra Draw_Big_Pixel_Conditioned
Bra DSP_Conditioned_BigScreen
Bra DBP_Conditioned_BigScreen
References
[edit | edit source]- ↑ Dune 3 aneb Achtung! Die Kurve... (1993), MobyGames
- ↑ Cervii (Červi), oldgames.sk
External links
[edit | edit source]- Duenix (1998) from Daniel Polansky on the Amiga, youtube.com