123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668 |
- ' Bliss (track editor for Stunts)
- ' Copyright (C) 2016-2023 Lucas Pedrosa
- ' This program is free software: you can redistribute it and/or modify
- ' it under the terms of the GNU General Public License as published by
- ' the Free Software Foundation, version 3 of the License.
- ' This program is distributed in the hope that it will be useful,
- ' but WITHOUT ANY WARRANTY; without even the implied warranty of
- ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ' GNU General Public License for more details.
- ' You should have received a copy of the GNU General Public License
- ' along with this program. If not, see <http://www.gnu.org/licenses/>.
- ' COMPILATION:
- ' Bliss has been compiled with FreeBasic 1.09.0 for GNU/Linux,
- ' DOS and Windows. It should compile well with any newer version
- ' and likely, with some older versions. You can get FreeBasic at:
- ' - http://www.freebasic.net
- ' For FreeDOS (or any other DOS), compile with:
- ' - fbc bliss.bas
- ' For GNU/Linux, compile with:
- ' - fbc bliss.bas bliss.xpm
- ' For Windows, compile with:
- ' - fbc -s gui bliss.bas bliss.rc
- #include "file.bi"
- #ifndef __FB_DOS__
- #include "http.bi"
- #undef GetParent
- #else
- Dim Shared use_curl As Byte = -1
- #endif
- #ifdef __FB_LINUX__
- #include once "fbgfx.bi"
- #include once "X11/Xlib.bi"
- #include once "X11/Xutil.bi"
- #include once "X11/keysymdef.bi"
-
- Declare Function Linkey As String
- Dim Shared LKdisp As Display Ptr, LKwindow As Window
- Dim Shared LKevent As XEvent, LKsym As KeySym
- Dim Shared LKstring As ZString * 26, LKinitialised As Byte = 0
-
- #define DIR_DIVISOR "/"
- #else
- #define DIR_DIVISOR "\"
- #endif
- #include "vbcompat.bi"
- #include "targalib.bi"
- #include "dir.bi"
- #define UNDOLEVEL 30
- #define MAXPATHS 1000
- #define THISVERSION "2.6.1"
- #define THISVERSION_NOPERIOD 20601
- #define LENGTHOF4AM 1895
- #define MAXCARS 20
- #define FORMAT_RAW 1
- #define FORMAT_COMBINED 2
- #define FORMAT_BINARY_SPLIT 3
- #define FORMAT_TEXT_SPLIT 4
- 'For DOS, there's no point in sacrificing performance, since Bliss would
- 'be the only primary process running
- #ifndef __FB_DOS__
- 'Set this to 0 to disable delays if performance is not good
- #define STRONG_ANTI_HOG -1
- #else
- #define STRONG_ANTI_HOG 0
- #endif
- 'If uncommented, font rendering in the TrackInfo menu will be done
- 'with Draw String and CP437 will be used. Otherwise, PutString will
- 'be used with Latin-1-Plus.
- '#define RENDER_TO_CP437
- #ifdef __FB_DOS__
- #undef ScreenLock
- #define ScreenLock DoNothing
- '#define ScreenLock FakeScreenLock
- #undef ScreenUnlock
- #define ScreenUnlock DoNothing
- '#define ScreenUnlock FakeScreenUnlock
- #undef WindowTitle
- #define WindowTitle DOSScreenTitle
- Declare Sub DoNothing
- Declare Sub DOSScreenTitle(title As String)
- Declare Sub FakeScreenLock
- Declare Sub FakeScreenUnlock
- #endif
- Type EncX 'Encoding translation
- utf32 As Long
- o As UByte 'Output
- End Type
- Type SGrid
- track As UByte
- land As UByte
- bgc As ULong 'Background colour
- border As ULong 'Border colour
- End Type
- Type TransType Field = 1 'To locate an icon for a track code
- x As UByte
- y As UByte
- w As UByte
- h As UByte
- id As ZString * 20
- hflip As UByte
- vflip As UByte
- cr As UByte 'Clockwise rotation
- ccr As UByte 'Counter-clockwise rotation
- xsmall As UByte 'Coordinates to small icon
- ysmall As UByte
- ctype(0 To 3) As UByte 'Connector types
- cto(0 To 3) As UByte 'Connector "to" (possible destinations)
- cisalt(0 To 3) As Byte 'Connector is alternative
- length As UByte 'Weighed length
- material As Byte
- entity As UByte 'What the tile does
- reserved(0 To 18) As UByte
- End Type
- Type ButtonType
- x1 As Short
- y1 As Short
- x2 As Short
- y2 As Short
- value As Short
- title As String
- End Type
- Type SelectorType
- opt(1 To 20) As String
- options As Byte
- current As Byte
- redraw As Byte
- wasinlasttime As Byte
- x1 As Short
- y1 As Short
- x2 As Short
- y2 As Short
- End Type
- Type FilerType
- x1 As Short
- y1 As Short
- x2 As Short
- y2 As Short
- reread As Byte
- mask As String
- End Type
- Type DirLink
- text As String
- directory As String
- End Type
- Type StringerType
- maxlength As Short
- x As Short
- y As Short
- s32 As String 'String in UTF-32 encoding
- sr As String 'String in CP437 (for rendering)
- 'last As String 'To keep the last edited string
- cursor_pos As Short
- t As Double
- fileonly As Byte
- cursor As Byte
- redraw As Byte
- init As Byte
- background As ULong
- End Type
- Type MetaData
- title As String
- author As String
- cyear As Short
- cmonth As Byte
- cday As Byte
- tool As String
- toolversion As ULong 'Example: 21305 for 2.13.5
- comment As String
- championship As String
- editing_time As Long 'In seconds
- End Type
- Type TrackVector
- Union
- coors As UShort 'Packed coordinates
- Type
- x As Byte
- y As Byte
- End Type
- End Union
- bearing As Byte 'Where it's going
- origin As Byte 'Where it came from
- e As Byte 'Error
- End Type
- Type TrackSection
- Union 'Starting node coordinates
- initial As UShort
- Type
- xo As Byte
- yo As Byte
- End Type
- End Union
- Union 'Ending node coordinates
- final As UShort
- Type
- xf As Byte
- yf As Byte
- End Type
- End Union
- solving As Byte 'Flag for this section being solved
- origin As Byte 'Direction from which the section was entered
- bearing As Byte 'Starting bearing
- parent(2) As Short 'Parent sections
- child(2) As Short 'Child sections
- finishes As Byte 'Leads to the finish line
- cycle As Byte 'Leads to a cycle
- wrongway As Byte 'Leads to wrong way
- errors As Byte 'Contains local errors
- e As Byte 'Error code
- End Type
- Type TrackError
- e As Byte 'Error type/code
- Union 'Error coordinates if applicable
- coors As UShort
- Type
- x As Byte
- y As Byte
- End Type
- End Union
- section As Short
- End Type
- Type TrackPath
- p As String 'The path itself
- e As Byte 'The error status
- finishes As Byte
- End Type
- Type Scoreboard
- racer As String
- handicap As Byte
- realtime As String
- hctime As String 'Handicapped time or effective points
- car As String
- style As String
- verified As Byte
- End Type
- Type Car
- id As String * 4
- cname As String
- handicap As Single
- End Type
- Declare Function Enc_UTF32_to_CP437 (s As String) As String
- Declare Function Enc_UTF32_to_Latin1 (s As String) As String
- Declare Function Enc_UTF32_to_UTF8 (s As String) As String
- Declare Function Enc_UTF8_to_UTF32 (s As String) As String
- Declare Function ConvertColour(c As String) As String
- Declare Sub DrawPanel
- Declare Sub DrawSpot(x As UByte, y As UByte, inked As Byte = 0)
- Declare Sub DrawTrack
- Declare Sub DrawBox(x1 As Short, y1 As Short, x2 As Short, y2 As Short)
- Declare Sub MenuBox(boxwidth As Short, boxheight As Short, title As String)
- Declare Sub SelectBackground
- Declare Sub LoadFont (fontfile As String)
- Declare Sub PutString (x As Short, y As Short, s As String, col As ULong, col2 As ULong = RGB(&HFF, 0, &HFF))
- Declare Sub TCentre(y As Short = -1, text As String = "", colour As ULong = RGB(255, 255, 255))
- Declare Sub TCont(text As String, eol As Byte = 0)
- Declare Sub AddButton(x As Short = -1, y As Short = -1, title As String, value As Short)
- Declare Sub StackButton(title As String, value As Short = -1, direction As Byte = 0, separation As UShort = 16)
- Declare Sub EndOfButtonStack
- Declare Function ManageButtons As Short
- Declare Sub ManageIcons
- Declare Function ManageString(ByRef s As String) As String
- Declare Function ManageSelector(sel As SelectorType) As Byte
- Declare Sub Error_Message(text As String, title As String = "Error!")
- Declare Sub Menu_License
- Declare Sub Menu_StartNewTrack
- Declare Sub Menu_LoadTrack
- Declare Sub Menu_SaveTrack
- Declare Sub Menu_TrackInfo
- Declare Sub Menu_Help
- Declare Sub Menu_Analysis
- Declare Sub Menu_Scenery
- Declare Sub Menu_Settings
- Declare Sub Menu_Tournaments
- Declare Sub Menu_TrackShot
- Declare Sub Menu_Colouring
- Declare Sub LoadConfiguration
- Declare Sub LoadGraphics
- Declare Sub LoadTrack(trk As String)
- Declare Sub SaveTrack(trk As String)
- Declare Sub SaveTrackImage(trk As String)
- Declare Sub LoadMetaData(filenumber As Short = 0, content As String = "")
- Declare Sub SaveMetaData(filenumber As Short)
- Declare Function GetMetaDataFromRegistry As Byte
- Declare Sub InitFiles(mask As String, x1 As Short, y1 As Short, x2 As Short, y2 As Short)
- Declare Sub DetectDrives
- Declare Sub SortFiles
- Declare Function ManageFiles(akey As String = "") As String
- Declare Sub ChangeTrackDirectory(d As String)
- Declare Sub LoadTransformations
- Declare Sub SaveTransformations
- Declare Function FindStart As TrackVector
- Declare Sub CheckTrack
- Declare Function GetNext(slot As TrackVector, detour As Byte = 0) As TrackVector
- Declare Sub GenerateSections
- Declare Sub SolveSection(sn As Short)
- Declare Sub SolvePath(pn As Short)
- Declare Function PathToError(te As Short) As String
- Declare Function PathToFinishLine(which As Byte = 0) As String
- Declare Sub FollowPath(s As String, e As Byte = 0)
- Declare Sub TrackErrorMessage(e As UByte)
- Declare Sub DetectTerrainErrors(ByRef e As UByte, ByRef x As Byte, ByRef y As Byte)
- Declare Function PathLength(n As Short, weighed As Byte = 0) As Long
- Declare Function Timey(t As Long) As String
- Declare Function AntiTimey(t As String) As Long
- Declare Sub SelectByTyping
- Declare Sub SmartSelect(etype As String, direction As Byte = 1)
- Declare Sub CreatePath
- Declare Sub PutIcon(u As UByte, v As UByte, x As UShort, y As UShort)
- Declare Sub PutSmallIcon(u As UByte, v As UByte, x As UShort, y As UShort)
- Declare Sub StartUp
- Declare Sub QuitProgram
- Declare Sub Editor
- Declare Sub UpdateTitleBar
- Declare Sub ClearTrack(x As UByte, y As UByte)
- Declare Sub PickTrack(x As UByte, y As UByte)
- Declare Sub SetTrack(x As UByte, y As UByte, code As UByte)
- Declare Function GetParent(x As UByte, y As UByte) As UByte
- Declare Sub BuildClosedCircuit
- Declare Sub LinkTiles
- Declare Sub RaiseTerrain(x As UByte, y As UByte)
- Declare Sub LowerTerrain(x As UByte, y As UByte)
- Declare Sub Flood(x As UByte, y As UByte)
- Declare Sub Dry(x As UByte, y As UByte)
- Declare Sub CopyOrCut(cut As Byte = 0)
- Declare Sub Paste
- Declare Sub CheckClipboardImport
- Declare Function GetTrack(x As UByte, y As UByte, x2 As UByte, y2 As UByte) As String
- Declare Sub PutTrack(x As UByte, y As UByte, t As String, forcefull As Byte = 0)
- Declare Function HFlipTrack(t As String) As String
- Declare Function VFlipTrack(t As String) As String
- Declare Function CRotate(t As String) As String
- Declare Function CCRotate(t As String) As String
- Declare Sub NotASquare
- Declare Sub PushUndo
- Declare Sub Undo
- Declare Sub Redo
- Declare Function Hash32 Overload (content As String) As ULong
- Declare Function Hash32 Overload As ULong
- Declare Function PackedClip(m() As SGrid, wi As Byte = -1, he As Byte = -1) As String
- Declare Sub DetectNotStunts(ByRef x As Byte, ByRef y As Byte, ByRef what As Byte)
- Declare Sub UnRLETerrain(s As String)
- Declare Function TMT_GetCurrentTrack(taddress As String) As Byte
- Declare Function TMT_GetMain(taddress As String, ByRef curtrack As String, ByRef deadline As String) As Byte
- Declare Function TMT_GetScoreboard(taddress As String, item() As Scoreboard, ByRef items As Byte) As Byte
- Const ptitle = "Bliss " + THISVERSION '+ " beta"
- '============================== Track structure variables
- Dim Shared grid(1 To 31, 1 To 31) As SGrid
- 'Grid is 30x30, but an extra row and column are added to prevent
- 'segmentation fault in calculations involving path following and
- 'track element shortcut keys when a large element has been placed
- 'across the "fence".
- Dim Shared clipboard As String, pasting As Byte = 0
- Dim Shared last_cb_file_length As Long = 0
- Dim Shared As Byte xselect, yselect, x2select, y2select, selecting = 0
- Dim Shared As Byte xcursor = 1, ycursor = 1, drawkeyboardcursor 'Keyboard cursor
- Dim Shared vlast As TrackVector
- Dim Shared tr(0 To 255) As TransType, itr(0 To 5, 0 To 5, 0 To 11) As UByte
- Dim Shared ttr(0 To 18) As TransType
- Dim Shared section(1 To 255) As TrackSection, sections As Short
- Dim Shared terror(1 To 100) As TrackError, terrors As Short
- Dim Shared path(1 To MAXPATHS) As TrackPath, paths As Short
- Dim Shared As UByte landscape = 4, format_byte = 152
- Dim Shared meta As MetaData, started_editing As Double
- Dim Shared default_format As UByte = FORMAT_COMBINED, thisfileformat As UByte = FORMAT_COMBINED
- Dim Shared default_author As String, racer_weigh As Double = 7.2955
- 'Other objects
- Dim Shared cars As Short, car(1 To MAXCARS) As Car, activecar As Byte
- 'Panel and graphics
- Dim Shared graphic_size As UByte = 16, bigwidth As UByte = 22
- Dim Shared As Short xoffs = 352, yoffs = 22 'Where to draw the track
- Dim Shared As Short xpanel = 0, ypanel = 0 'Where to draw the panel
- Dim Shared As Short xpalette = 198, ypalette = 484
- Dim Shared As Short xpicons = 80, ypicons = 74
- Dim Shared As Short xswitches = 70, yswitches = 380
- Dim Shared current_page As UByte = 0, current_brush As UByte = 1
- Dim Shared current_bgc As ULong = 0
- Dim Shared current_border As ULong = RGB(220, 200, 0)
- Dim Shared current_terrain_brush As UByte = 0
- Dim Shared bigicons As Any Pointer, track_image_buffer As Any Pointer = 0
- Dim Shared imageformat As String
- 'Undo-Redo
- Dim Shared undobuffer(0 To UNDOLEVEL - 1) As String
- Dim Shared As Short undohead = 0, undotail = UNDOLEVEL -1, undopointer = 0
- 'Switches
- Dim Shared As Byte show_errors = -1, allow_errors = 0
- Dim Shared As Byte data_codes = 0, smart_editing = 0
- Dim Shared As Byte show_grid = -1, colouring_mode = 0
- Dim Shared As Byte affect_terrain = 0, affect_track = -1
- 'Toolkit-related variables
- Dim Shared button(1 To 8) As ButtonType, buttons As Byte = 0
- Dim Shared cenx As Short, ceny As Short, lefx As Short
- Dim Shared conx As Short, cony As Short, concolour As ULong = RGB(200, 200, 200)
- 'File-related variables
- Dim Shared As String program_path, track_path, track_file
- Dim Shared big_graphics_file As String
- Dim Shared modified As Byte = 0
- Dim Shared filey(1 To 512) As String, fileys As Short = 0
- Dim Shared filer As FilerType, stringer As StringerType
- Dim Shared dirlinks As Byte = 0, dirlink(1 To 10) As DirLink
- 'Latin-1 font pointers
- Dim Shared As Any Ptr font, mask
- Dim Shared changing_title As Byte 'Flag for window title updates
- 'Encoding translation arrays
- Dim Shared toCP437(100) As EncX = _
- {(&HC1, 65), (&HC9, 144), (&HCD, 73), (&HD3, 79), (&HDA, 85), _
- (&HE1, 160), (&HE9, 130), (&HED, 161), (&HF3, 162), (&HFA, 163), _
- (&HD1, 165), (&HF1, 164), _
- (&HC4, 142), (&HCB, 69), (&HCF, 73), (&HD6, 153), (&HDC, 154), _
- (&HE4, 132), (&HEB, 137), (&HEF, 139), (&HF6, 148), (&HFC, 129), _
- (&HC7, 128), (&HE7, 135), _
- (&HC0, 65), (&HC8, 69), (&HCC, 73), (&HD2, 79), (&HD9, 85), _
- (&HE0, 133), (&HE8, 138), (&HEC, 141), (&HF2, 149), (&HF9, 151), _
- (&HC3, 65), (&HE3, 97), (&HD5, 79), (&HF5, 111), _
- (&HC2, 65), (&HCA, 69), (&HCE, 73), (&HD4, 79), (&HDB, 85), _
- (&HE2, 131), (&HEA, 136), (&HEE, 140), (&HF4, 147), (&HFB, 150), _
- (&HA1, 173), (&HBF, 168), (&HAB, 174), (&HBB, 175), _
- (&H150, 153), (&H151, 148), (&H170, 154), (&H171, 129)}
- 'CP437 to Unicode code points
- Dim Shared fromCP437(128) As Long = _
- {&HC7, &HFC, &HE9, &HE2, &HE4, &HE0, &HE5, &HE7, &HEA, &HEB, &HE8, &HEF, &HEE, &HEC, &HC4, &HC5, _
- &HC9, &HE6, &HC6, &HF4, &HF6, &HF2, &HFB, &HF9, &HFF, &HD6, &HDC, &HA2, &HA3, &HA5, &H20A7, &H192, _
- &HE1, &HED, &HF3, &HFA, &HF1, &HD1, &HAA, &HBA, &HBF, &H2310, &HAC, &HBD, &HBC, &HA1, &HAB, &HBB, _
- &H2591, &H2592, &H2593, &H2502, &H2524, &H2561, &H2562, &H2556, &H2555, &H2563, &H2551, &H2557, &H255D, &H255C, &H255B, &H2510, _
- &H2514, &H2534, &H252C, &H251C, &H2500, &H253C, &H255E, &H255F, &H255A, &H2554, &H2569, &H2566, &H2560, &H2550, &H256C, &H2567, _
- &H2568, &H2564, &H2565, &H2559, &H2558, &H2552, &H2553, &H256B, &H256A, &H2518, &H250C, &H2588, &H2584, &H258C, &H2590, &H2580, _
- &H321, &HDF, &H393, &H3C0, &H3A3, &H3C3, &HB4, &H3C4, &H3A6, &H398, &H3A9, &H3B4, &H221E, &H3C6, &H3B5, &H2229, _
- &H2261, &HB1, &H2265, &H2264, &H2320, &H2321, &HF7, &H2248, &HB0, &H2219, &HB7, &H221A, &H207F, &HB2, &H25A0, &HA0}
- 'Colouring palette
- Dim Shared cpal(0 To 23) As ULong = _
- {0, &HFFE0E000, &HFF5050FF, &HFFE02000, &HFF20E000, &HFFF08000, _
- &HFFA020FF, &HFFE0E0E0, &HFF808080, &HFF404040, &HFF000000, &HFFA0E000, _
- &HFF804020, &HFFE010F0, &HFF20E0A0, &HFFE04040, &HFF4040E0, &HFF00E0E0, _
- &HFFF020B0, &HFFFED000, &HFFE080FF, &HFF806010, &HFFA7E189, &HFF495827 }
- 'DOSBox flag
- Dim Shared dosbox As Byte = 0
- StartUp
- #ifdef __FB_DOS__
- Dim Shared fake_screenlock_level As Short = 0
- dosbox = ScreenRes(1024, 768, 32, 2)
- If dosbox Then ScreenRes 1024, 768, 16, 2
- Width 128, 48
- Line (0, 0)-(1023, 767), RGB(30, 30, 50), BF
- yoffs += 64
- ypanel += 64
- #else
- ScreenRes 1024, 704, 32
- Width 128, 44
- Line (0, 0)-(1023, 703), RGB(30, 30, 50), BF
- HTTP_Start
- #endif
- big_graphics_file = "biggfx"
- LoadConfiguration
- LoadGraphics
- LoadTransformations
- #ifndef RENDER_TO_CP437
- LoadFont "latin1p"
- #endif
- Dim today As Double
- today = Now
- meta.cyear = DatePart("yyyy", today)
- meta.cmonth = DatePart("m", today)
- meta.cday = DatePart("d", today)
- meta.tool = "Bliss"
- meta.toolversion = THISVERSION_NOPERIOD
- meta.author = default_author
- started_editing = Timer
- thisfileformat = default_format
- If bigwidth = 16 Then xoffs += 180
- If Len(Command) Then
- Dim afile As String
-
- afile = Trim(Command)
- If FileExists(afile) Or FileExists(afile + ".trk") Then
- LoadTrack afile
-
- 'This makes the file menus default to the directory
- 'that the track was loaded from
- Dim n As Short
- #ifdef __FB_LINUX__
- n = InStrRev(afile, "/")
- #else
- n = InStrRev(afile, "\")
- #endif
-
- If n Then
- track_path = Left(afile, n)
- Else
- track_path = ""
- End If
- End If
- End If
- UpdateTitleBar
- DrawTrack
- DrawPanel
- Menu_License
- Editor
- ImageDestroy bigicons
- #ifndef RENDER_TO_CP437
- ImageDestroy font
- ImageDestroy mask
- #endif
- #ifndef __FB_DOS__
- HTTP_End
- #endif
- End
- Function PackedClip(m() As SGrid, wi As Byte = -1, he As Byte = -1) As String
- Dim As Byte w, h, c, i, j
- Dim t As String, r As String
-
- If wi = -1 Then w = UBound(m, 1) Else w = wi
- If he = -1 Then h = UBound(m, 2) Else h = he
- t = Chr(w, h)
-
- For j = 1 To h
- For i = 1 to w
- c = 0 : r = ""
- If m(i, j).track Then
- c Or= 1
- r &= Chr(m(i, j).track)
- End If
- If m(i, j).land Then
- c Or= 2
- r &= Chr(m(i, j).land)
- End If
- If m(i, j).border Then
- c Or= 4
- r &= MkL(m(i, j).border)
- End If
- If m(i, j).bgc Then
- c Or= 8
- r &= MkL(m(i, j).bgc)
- End If
-
- t &= Chr(c) & r
- Next i
- Next j
-
- Return t
- End Function
- Sub DrawPanel
- Dim As Short sourcex, sourcey, i
- Dim s As String
- Dim indicator(0 To 8) As Short
-
- indicator(0) = Len(clipboard) <> 0
- indicator(1) = show_errors
- indicator(2) = allow_errors
- indicator(3) = data_codes
- indicator(4) = show_grid
- indicator(5) = affect_track
- indicator(6) = affect_terrain
- indicator(7) = colouring_mode
- indicator(8) = 0
-
- ScreenLock
- Line (xpanel, ypanel)-(xoffs - 1, ypanel + 704), RGB(30, 30, 50), BF
- 'Draw border around menu icons
- Line (xpanel + xpicons - 32, ypanel + ypicons - 32)- STEP (239, 315), RGB(55, 65, 110), B
- Line (xpanel + xpicons - 31, ypanel + ypicons - 33)- STEP (239, 315), RGB(20, 20, 20), B
- If dosbox Then
- Put (xpanel + xpicons, ypanel + ypicons), bigicons, (13 * bigwidth, 12 * 22)- STEP (8 * bigwidth - 1, 219), Trans
- Else
- Put (xpanel + xpicons, ypanel + ypicons), bigicons, (13 * bigwidth, 12 * 22)- STEP (8 * bigwidth - 1, 219), Alpha
- End If
-
- 'Draw switch indicator icons
- For i = 0 To 8
- PutIcon 21 + i, 12 - 2 * indicator(i), xpanel + xswitches + bigwidth * i, ypanel + yswitches
- Next i
-
- Select Case landscape
- Case 0 : s = "Desert"
- Case 1 : s = "Tropical"
- Case 2 : s = "Alpine"
- Case 3 : s = "City"
- Case 4 : s = "Country"
- Case Else : s = "Background #" + Trim(Str(landscape))
- End Select
- Draw String (100 - Len(s) * 4, 640 + ypanel), s, RGB(70, 200, 240)
- If landscape < 5 Then
- For i = 0 To 9
- PutSmallIcon i + 31, landscape + 21, xpanel + i * graphic_size + 20, ypanel + 664
- Next i
- Else
- Draw String (72, 664), "Chaotic", RGB(240, 160, 50)
- End If
-
- 'Display border for coordinates and pointed element
- 'and colouring options if activated
- If colouring_mode Then
- Line (xpanel + 16, ypanel + 420)- STEP (165, 47), RGB(55, 65, 110), B
- Line (xpanel + 17, ypanel + 419)- STEP (165, 47), RGB(20, 20, 20), B
- Line (xpanel + xpalette, ypanel + 420)- STEP (132, 47), RGB(55, 65, 110), B
- Line (xpanel + xpalette + 1, ypanel + 419)- STEP (132, 47), RGB(20, 20, 20), B
- If current_bgc Then
- Line (xpanel + xpalette + 16, ypanel + 434)- STEP (21, 21), current_bgc, BF
- Else
- Line (xpanel + xpalette + 16, ypanel + 434)- STEP (21, 21), RGB(100, 100, 100), B
- End If
- If current_border Then
- Line (xpanel + xpalette + 48, ypanel + 434)- STEP (21, 21), current_border, B
- Line (xpanel + xpalette + 49, ypanel + 435)- STEP (19, 19), current_border, B
- Else
- Line (xpanel + xpalette + 48, ypanel + 434)- STEP (21, 21), RGB(100, 100, 100), B, &H5555
- End If
- Else
- Line (xpanel + 16, ypanel + 420)- STEP (314, 47), RGB(55, 65, 110), B
- Line (xpanel + 17, ypanel + 419)- STEP (314, 47), RGB(20, 20, 20), B
- End If
-
- 'Display current brush
- Line (xpanel + 16, ypanel + ypalette + 1)-(xpanel + 181, ypanel + ypalette + 131), RGB(55, 65, 110), B
- Line (xpanel + 17, ypanel + ypalette)-(xpanel + 182, ypanel + ypalette + 130), RGB(20, 20, 20), B
- If current_page >= 10 Then
- If current_terrain_brush <= 18 Then _
- PutIcon ttr(current_terrain_brush).x + 2, ttr(current_terrain_brush).y + 1, xpanel + 88, ypanel + ypalette + 44
-
- Select Case current_terrain_brush
- Case 0 : s = "Grass"
- Case 1 To 5 : s = "Water"
- Case 6 To 18 : s = "Mountain"
- Case Else : s = "Invalid"
- End Select
- Draw String (xpanel + 99 - Len(s) * 4, ypanel + ypalette + 82), s, RGB(255, 255, 255)
- Else
- If tr(current_brush).h = 1 And tr(current_brush).w = 1 Then
- PutIcon tr(current_brush).x, tr(current_brush).y, xpanel + 88, ypanel + ypalette + 44
- ElseIf tr(current_brush).h = 2 And tr(current_brush).w = 2 Then
- PutIcon tr(current_brush).x, tr(current_brush).y, xpanel + 77, ypanel + ypalette + 33
- PutIcon tr(current_brush).x + 1, tr(current_brush).y, xpanel + 99, ypanel + ypalette + 33
- PutIcon tr(current_brush).x, tr(current_brush).y + 1, xpanel + 77, ypanel + ypalette + 55
- PutIcon tr(current_brush).x + 1, tr(current_brush).y + 1, xpanel + 99, ypanel + ypalette + 55
- ElseIf tr(current_brush).h = 2 And tr(current_brush).w = 1 Then
- PutIcon tr(current_brush).x, tr(current_brush).y, xpanel + 88, ypanel + ypalette + 33
- PutIcon tr(current_brush).x, tr(current_brush).y + 1, xpanel + 88, ypanel + ypalette + 55
- ElseIf tr(current_brush).h = 1 And tr(current_brush).w = 2 Then
- PutIcon tr(current_brush).x, tr(current_brush).y, xpanel + 77, ypanel + ypalette + 44
- PutIcon tr(current_brush).x + 1, tr(current_brush).y, xpanel + 99, ypanel + ypalette + 44
- End If
- Draw String (xpanel + 99 - Len(Trim(tr(current_brush).id)) * 4, ypanel + ypalette + 82), Trim(tr(current_brush).id), RGB(255, 255, 255)
- End If
-
- 'Draw palette
- If current_page = 10 Then
- Put (xpanel + xpalette, ypanel + ypalette), bigicons, (0, 12 * 22)- STEP (6 * bigwidth - 1, 6 * 22 - 1), PSet
-
- 'Draw palette grid
- For i = 0 To 6
- Line (xpanel + xpalette, ypanel + ypalette + 22 * i)- STEP (6 * bigwidth - 1, 0), 0
- Line (xpanel + xpalette + bigwidth * i, ypanel + ypalette)- STEP (0, 6 * 22 - 1), 0
- Next i
- ElseIf current_page >= 11 Then
- Line (xpanel + xpalette, ypanel + ypalette)- STEP(6 * bigwidth - 1, 6 * 22 - 1), RGB(&H0B, &H64, &H1B), BF
- Line (xpanel + xpalette, ypanel + ypalette)- STEP(6 * bigwidth, 6 * 22), 0, B
- Put (xpanel + xpalette + bigwidth, ypanel + ypalette + 2 * 22), bigicons, (2 * bigwidth, 14 * 22)- STEP (2 * bigwidth - 1, 2 * 22 - 1), PSet
- Put (xpanel + xpalette + 3 * bigwidth, ypanel + ypalette + 2 * 22), bigicons, (2 * bigwidth, 16 * 22)- STEP (2 * bigwidth - 1, 2 * 22 - 1), PSet
- Else
- sourcex = 6 * bigwidth * (current_page Mod 5)
- sourcey = 6 * 22 * (current_page \ 5)
-
- 'Draw palette grid
- Line (xpanel + xpalette, ypanel + ypalette)- STEP(6 * bigwidth - 1, 6 * 22 - 1), RGB(&H0B, &H64, &H1B), BF
- For i = 0 To 6
- Line (xpanel + xpalette, ypanel + ypalette + 22 * i)- STEP (6 * bigwidth - 1, 0), 0
- Line (xpanel + xpalette + bigwidth * i, ypanel + ypalette)- STEP (0, 6 * 22 - 1), 0
- Next i
-
- 'Draw palette icons
- If dosbox Then
- Put (xpanel + xpalette, ypanel + ypalette), bigicons, (sourcex, sourcey)- STEP (6 * bigwidth - 1, 6 * 22 - 1), Trans
- Else
- Put (xpanel + xpalette, ypanel + ypalette), bigicons, (sourcex, sourcey)- STEP (6 * bigwidth - 1, 6 * 22 - 1), Alpha
- End If
- End If
-
- Line (xpanel + xpalette, ypanel + ypalette + 22 * 7)- STEP (6 * bigwidth - 1, 2 * 22 - 1), RGB(30, 30, 50), BF
- If current_page < 10 Then
- Line (xpanel + xpalette + (current_page Mod 5) * bigwidth, ypanel + ypalette + (current_page \ 5 + 7) * 22)- STEP (21, 21), RGB(40, 160, 160), BF
- Else
- Line (xpanel + xpalette + 5 * bigwidth, ypanel + ypalette + (current_page - 3) * 22)- STEP (21, 21), RGB(40, 160, 160), BF
- End If
-
- 'Draw palette page list buttons
- If dosbox Then
- Put (xpanel + xpalette, ypanel + ypalette + 22 * 7), bigicons, (7 * bigwidth, 12 * 22)- STEP (6 * bigwidth - 1, 2 * 22 - 1), Trans
- Else
- Put (xpanel + xpalette, ypanel + ypalette + 22 * 7), bigicons, (7 * bigwidth, 12 * 22)- STEP (6 * bigwidth - 1, 2 * 22 - 1), Alpha
- End If
- ScreenUnlock
- End Sub
- Sub DrawSpot(x As UByte, y As UByte, inked As Byte = 0)
- 'Draw the full contents of a square in the map (both track and terrain)
- Dim As UByte c, t
- Dim As ULong bgc, border
- Dim As Short xg, yg
- Dim conflict As Byte
-
- c = grid(x, y).land
- t = grid(x, y).track
- bgc = grid(x, y).bgc
- border = grid(x, y).border
- xg = (x - 1) * bigwidth
- yg = (y - 1) * 22
- If track_image_buffer = 0 Then
- xg += xoffs
- yg += yoffs
- End If
-
- 'First, draw the terrain
- If c > 18 Then
- If show_errors Then
- PutIcon 6, 12, xg, yg
- If data_codes <> 0 AndAlso t = 0 Then
- Draw String (xg + 4, yg + 4), Hex(c, 2), RGB(0, 0, 0)
- End If
- Else
- PutIcon 0, 12, xg, yg
- End If
- Else
- If show_errors Then
- Select Case c
- Case 0, 6
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- Case 7
- If t = 0 Or t = 4 Or t = 14 Or t = 24 Or t = 39 Or t = 59 Or t = 98 Then
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- Else
- PutIcon 6, 13, xg, yg
- End If
- Case 8
- If t = 0 Or t = 5 Or t = 15 Or t = 25 Or t = 36 Or t = 56 Or t = 95 Then
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- Else
- PutIcon 6, 13, xg, yg
- End If
- Case 9
- If t = 0 Or t = 4 Or t = 14 Or t = 24 Or t = 38 Or t = 58 Or t = 97 Then
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- Else
- PutIcon 6, 13, xg, yg
- End If
- Case 10
- If t = 0 Or t = 5 Or t = 15 Or t = 25 Or t = 37 Or t = 57 Or t = 96 Then
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- Else
- PutIcon 6, 13, xg, yg
- End If
- Case 11 To 18
- If t = 0 Then
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- Else
- PutIcon 6, 13, xg, yg
- End If
- Case Else 'The ones that have water
- If (tr(t).w > 1 Or tr(t).h > 1) And (t < 105 Or t > 108) Then
- PutIcon 6, 16, xg, yg
- Else
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- End If
- End Select
- Else
- PutIcon ttr(c).x + 2, ttr(c).y + 1, xg, yg
- End If
- End If
-
- 'Paint background colour if any
- If bgc Then
- Line track_image_buffer, (xg, yg)- Step (bigwidth - 1, 21), bgc, BF
- End If
-
- 'If grid view is active, show grid between terrain and track
- 'If show_grid Then Line (xg, yg)- Step (bigwidth, 22), 0, B
- If show_grid Then
- If track_image_buffer = 0 Then
- Line (xg + bigwidth - 1, yg)-(xg, yg), 0
- Line -(xg, yg + 21), 0
- Else
- Line track_image_buffer, (xg + bigwidth - 1, yg)-(xg, yg), RGB(0, 0, 0)
- Line track_image_buffer, -(xg, yg + 21), RGB(0, 0, 0)
- End If
- End If
-
- 'Second, if it's a slope, draw the guides
- If (c = 7 Or c = 9) And (t = 4 Or t = 14 Or t = 24) Then 'North and South
- PutIcon 6, 15, xg, yg
- ElseIf (c = 8 Or c = 10) And (t = 5 Or t = 15 Or t = 25) Then 'East and West
- PutIcon 7, 15, xg, yg
- End If
-
- 'Then draw the track
- If t >= 182 And t <= 252 Then
- If show_errors Then
- If data_codes Then
- Draw String (xg + 4, yg + 4), Hex(t, 2), RGB(200, 180, 0)
- Else
- PutIcon 6, 14, xg, yg
- End If
- End If
- ElseIf t < 182 Then
- If t = &H42 Then 'Vertical tunnel
- If (y = 1 OrElse grid(x, y - 1).track <> &H42) And (y = 30 OrElse grid(x, y + 1).track <> &H42) then
- PutIcon tr(t).x, tr(t).y, xg, yg
- ElseIf y > 1 And y < 30 AndAlso grid(x, y - 1).track = &H42 AndAlso grid(x, y + 1).track = &H42 Then
- PutIcon 8, 17, xg, yg
- ElseIf y > 1 AndAlso grid(x, y - 1).track = &H42 Then
- PutIcon 9, 17, xg, yg
- Else
- PutIcon 7, 17, xg, yg
- End If
- ElseIf t = &H43 Then 'Horizontal tunnel
- If (x = 1 OrElse grid(x - 1, y).track <> &H43) And (x = 30 OrElse grid(x + 1, y).track <> &H43) then
- PutIcon tr(t).x, tr(t).y, xg, yg
- ElseIf x > 1 And x < 30 AndAlso grid(x - 1, y).track = &H43 AndAlso grid(x + 1, y).track = &H43 Then
- PutIcon 8, 16, xg, yg
- ElseIf x > 1 AndAlso grid(x - 1, y).track = &H43 Then
- PutIcon 9, 16, xg, yg
- Else
- PutIcon 7, 16, xg, yg
- End If
- ElseIf data_codes <> 0 AndAlso (tr(t).w > 1 Or tr(t).h > 1) Then
- PutIcon tr(t).xsmall, tr(t).ysmall, xg, yg
- Else
- PutIcon tr(t).x, tr(t).y, xg, yg
- End If
- conflict = 0
- If x > 1 AndAlso tr(grid(x - 1, y).track).w = 2 Then conflict = -1
- If y > 1 AndAlso tr(grid(x, y - 1).track).h = 2 Then conflict = -1
- If (x > 1 And y > 1) AndAlso (tr(grid(x - 1, y - 1).track).h = 2 And tr(grid(x - 1, y - 1).track).w = 2) Then conflict = -1
- If conflict <> 0 And show_errors <> 0 Then
- If track_image_buffer = 0 Then
- Line (xg, yg)-(xg + bigwidth - 1, yg + 21), RGB(&HF0, &HD0, 0), B
- Else
- Line track_image_buffer, (xg, yg)-(xg + bigwidth - 1, yg + 21), RGB(&HF0, &HD0, 0), B
- End If
- End If
- ElseIf t = 253 Then
- If data_codes Then
- PutIcon 7, 14, xg, yg
- Else
- If x = 1 Or y = 1 OrElse tr(grid(x - 1, y - 1).track).w < 2 OrElse tr(grid(x - 1, y - 1).track).h < 2 Then
- If show_errors Then PutIcon 6, 14, xg, yg
- Else
- PutIcon tr(grid(x - 1, y - 1).track).x + 1, tr(grid(x - 1, y - 1).track).y + 1, xg, yg
- End If
- End If
- ElseIf t = 254 Then
- If data_codes Then
- PutIcon 8, 14, xg, yg
- Else
- If y = 1 OrElse tr(grid(x, y - 1).track).h < 2 Then
- If show_errors Then PutIcon 6, 14, xg, yg
- Else
- PutIcon tr(grid(x, y - 1).track).x, tr(grid(x, y - 1).track).y + 1, xg, yg
- End If
- End If
- ElseIf t = 255 Then
- If data_codes Then
- PutIcon 9, 14, xg, yg
- Else
- If x = 1 OrElse tr(grid(x - 1, y).track).w < 2 Then
- If show_errors Then PutIcon 6, 14, xg, yg
- Else
- PutIcon tr(grid(x - 1, y).track).x + 1, tr(grid(x - 1, y).track).y, xg, yg
- End If
- End If
- End If
-
- 'Draw border if any
- If border Then
- If y < 1 OrElse grid(x, y - 1).border <> border Then _
- Line track_image_buffer, (xg, yg)- Step (bigwidth - 1, 1), border, B
- If x < 1 OrElse grid(x - 1, y).border <> border Then _
- Line track_image_buffer, (xg, yg)- Step (1, 21), border, B
- If y > 29 OrElse grid(x, y + 1).border <> border Then _
- Line track_image_buffer, (xg, yg + 21)- Step (bigwidth - 1, -1), border, B
- If x > 29 OrElse grid(x + 1, y).border <> border Then _
- Line track_image_buffer, (xg + bigwidth - 1, yg)- Step (-1, 21), border, B
- End If
-
- 'Mark as selected if it is
- If xselect Then
- Dim As Short xs1, xs2, ys1, ys2
-
- If xselect <= x2select Then xs1 = xselect : xs2 = x2select Else xs1 = x2select : xs2 = xselect
- If yselect <= y2select Then ys1 = yselect : ys2 = y2select Else ys1 = y2select : ys2 = yselect
-
- If x >= xs1 And x <= xs2 And _
- y >= ys1 And y <= ys2 Then
- If dosbox Then
- PutIcon 9, 15, xg, yg
- Else
- PutIcon 8, 15, xg, yg
- End If
- End If
- End If
-
- 'Also mark it if just requested
- If inked Then PutIcon 8, 15, xg, yg
- End Sub
- Sub DrawTrack
- Dim As Short x, y
-
- ScreenLock
- If track_image_buffer = 0 Then
- If show_grid Then
- Line (xoffs, yoffs)-(xoffs + 30 * bigwidth, yoffs + 30 * 22), 0, B
- Else
- Line (xoffs, yoffs)-(xoffs + 30 * bigwidth, yoffs + 30 * 22), RGB(30, 30, 50), B
- End If
- Else
- If show_grid Then
- Line track_image_buffer, (0, 0)-(30 * bigwidth, 30 * 22), RGB(0, 0, 0), B
- Else
- Line track_image_buffer, (0, 0)-(30 * bigwidth, 30 * 22), RGB(30, 30, 50), B
- End If
- End If
- For y = 1 To 30
- For x = 1 To 30
- DrawSpot x, y
- Next x
- Next y
- ScreenUnlock
- End Sub
- 'Detect whether something exists on the grid that could not have
- 'been created by Stunts built-in editor
- Sub DetectNotStunts(ByRef x As Byte, ByRef y As Byte, ByRef what As Byte)
- Dim As Byte i, j
-
- what = 0
-
- 'Non-standard terrain elements
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).land > 18 Then
- what = 1
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Non-standard track elements
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).track >= &HB6 And grid(i, j).track <= &HFC Then
- what = 2
- x = i : y = j
- Exit Sub
- ElseIf grid(i, j).track = 2 Or grid(i, j).track = 3 Then
- what = 3 'Player's or Opponent's car
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Big track element without its corresponding fillers
- For j = 1 To 30
- For i = 1 To 30
- If tr(grid(i, j).track).w = 2 Then
- If i = 30 OrElse grid(i + 1, j).track <> 255 Then _
- what = 4
- End If
- If tr(grid(i, j).track).h = 2 Then
- If j = 30 OrElse grid(i, j + 1).track <> 254 Then
- what = 4
- ElseIf tr(grid(i, j).track).w = 2 Then
- If i = 30 OrElse grid(i + 1, j + 1).track <> 253 Then _
- what = 4
- End If
- End If
- If what Then
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Filler without a parent track element
- For j = 1 To 30
- For i = 1 To 30
- Select Case grid(i, j).track
- Case 253
- If i = 1 Or j = 1 OrElse _
- (tr(grid(i - 1, j - 1).track).h < 2 Or _
- tr(grid(i - 1, j - 1).track).w < 2) Then what = 5
- Case 254
- If j = 1 OrElse tr(grid(i, j - 1).track).h < 2 Then what = 5
- Case 255
- If i = 1 OrElse tr(grid(i - 1, j).track).w < 2 Then what = 5
- End Select
- If what Then
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Mountain corner with something on top
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).land >= 11 And grid(i, j).track <> 0 Then
- what = 6
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Mountain side with illegal element on top
- For j = 1 To 30
- For i = 1 To 30
- Select Case grid(i, j).land
- Case 7
- If InStr(Chr(0, 4, 14, &H18, &H3B, &H27, &H62), Chr(grid(i, j).track)) = 0 Then _
- what = 7
- Case 8
- If InStr(Chr(0, 5, 15, &H19, &H38, &H24, &H5F), Chr(grid(i, j).track)) = 0 Then _
- what = 7
- Case 9
- If InStr(Chr(0, 4, 14, &H18, &H3A, &H26, &H61), Chr(grid(i, j).track)) = 0 Then _
- what = 7
- Case 10
- If InStr(Chr(0, 5, 15, &H19, &H39, &H25, &H60), Chr(grid(i, j).track)) = 0 Then _
- what = 7
- End Select
- If what Then
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Water with illegal element on top
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).land >= 1 And grid(i, j).land <= 5 Then
- If InStr(Chr(0, &H68, &H23, &H67, &H22, &H69, &H6A, _
- &H6B, &H6C, &HAB, &HAE, &HAC, &HAD, &HFD, &HFE, _
- &HFF), Chr(grid(i, j).track)) = 0 Then
-
- what = 8
- x = i : y = j
- Exit Sub
- End If
- End If
- Next i
- Next j
-
- 'It is still possible to draw a part of a big element, not
- 'including the parent block, on water and go undetected!
- End Sub
- Sub DetectTerrainErrors(ByRef e As UByte, ByRef x As Byte, ByRef y As Byte)
- Dim As Byte i, j
-
- e = 0
-
- 'Non-standard terrain elements - Error 40
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).land > 18 Then
- e = 40
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Mountain borders mismatch - Error 41
- Dim tvert(0 To 18, 0 To 1, 0 To 1) As Byte
-
- 'First create terrain element descriptors
- tvert(6, 0, 0) = 1 : tvert(6, 0, 1) = 1
- tvert(6, 1, 0) = 1 : tvert(6, 1, 1) = 1
-
- tvert(7, 0, 0) = 1 : tvert(7, 0, 1) = 1
- tvert(7, 1, 0) = 0 : tvert(7, 1, 1) = 0
-
- tvert(8, 0, 0) = 1 : tvert(8, 0, 1) = 0
- tvert(8, 1, 0) = 1 : tvert(8, 1, 1) = 0
-
- tvert(9, 0, 0) = 0 : tvert(9, 0, 1) = 0
- tvert(9, 1, 0) = 1 : tvert(9, 1, 1) = 1
-
- tvert(10, 0, 0) = 0 : tvert(10, 0, 1) = 1
- tvert(10, 1, 0) = 0 : tvert(10, 1, 1) = 1
-
- tvert(11, 0, 0) = 1 : tvert(11, 0, 1) = 0
- tvert(11, 1, 0) = 0 : tvert(11, 1, 1) = 0
-
- tvert(12, 0, 0) = 0 : tvert(12, 0, 1) = 0
- tvert(12, 1, 0) = 1 : tvert(12, 1, 1) = 0
-
- tvert(13, 0, 0) = 0 : tvert(13, 0, 1) = 0
- tvert(13, 1, 0) = 0 : tvert(13, 1, 1) = 1
-
- tvert(14, 0, 0) = 0 : tvert(14, 0, 1) = 1
- tvert(14, 1, 0) = 0 : tvert(14, 1, 1) = 0
-
- tvert(15, 0, 0) = 1 : tvert(15, 0, 1) = 1
- tvert(15, 1, 0) = 1 : tvert(15, 1, 1) = 0
-
- tvert(16, 0, 0) = 1 : tvert(16, 0, 1) = 0
- tvert(16, 1, 0) = 1 : tvert(16, 1, 1) = 1
-
- tvert(17, 0, 0) = 0 : tvert(17, 0, 1) = 1
- tvert(17, 1, 0) = 1 : tvert(17, 1, 1) = 1
-
- tvert(18, 0, 0) = 1 : tvert(18, 0, 1) = 1
- tvert(18, 1, 0) = 0 : tvert(18, 1, 1) = 1
-
- 'Now check to the right and below
- For j = 1 To 30
- For i = 1 To 30
- If i < 30 Then
- If tvert(grid(i, j).land, 0, 1) <> tvert(grid(i + 1, j).land, 0, 0) _
- Or tvert(grid(i, j).land, 1, 1) <> tvert(grid(i + 1, j).land, 1, 0) Then
-
- e = 41
- x = i + 1 : y = j
- Exit Sub
- End If
- End If
-
- If j < 30 Then
- If tvert(grid(i, j).land, 1, 0) <> tvert(grid(i, j + 1).land, 0, 0) _
- Or tvert(grid(i, j).land, 1, 1) <> tvert(grid(i, j + 1).land, 0, 1) Then
-
- e = 41
- x = i : y = j + 1
- Exit Sub
- End If
- End If
- Next i
- Next j
-
- 'Mountain corner with something on top - Error 50
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).land >= 11 And grid(i, j).track <> 0 Then
- e = 50
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
-
- 'Mountain side with illegal element on top - Error 51
- For j = 1 To 30
- For i = 1 To 30
- Select Case grid(i, j).land
- Case 7
- If InStr(Chr(0, 4, 14, &H18, &H3B, &H27, &H62), Chr(grid(i, j).track)) = 0 Then _
- e = 51
- Case 8
- If InStr(Chr(0, 5, 15, &H19, &H38, &H24, &H5F), Chr(grid(i, j).track)) = 0 Then _
- e = 51
- Case 9
- If InStr(Chr(0, 4, 14, &H18, &H3A, &H26, &H61), Chr(grid(i, j).track)) = 0 Then _
- e = 51
- Case 10
- If InStr(Chr(0, 5, 15, &H19, &H39, &H25, &H60), Chr(grid(i, j).track)) = 0 Then _
- e = 51
- End Select
- If e Then
- x = i : y = j
- Exit Sub
- End If
- Next i
- Next j
- End Sub
- Sub DoNothing
- End Sub
- Sub DOSScreenTitle(title As String)
- Line (0, 0)-(1023, 31), RGB(60, 60, 100), BF
- Draw String (512 - Len(title) * 4, 8), title, RGB(255, 255, 255)
- PutIcon 24, 6, 16, 4
- End Sub
- Sub DrawBox(x1 As Short, y1 As Short, x2 As Short, y2 As Short)
- Line (x1, y1)-(x2, y2), RGB(30, 30, 50), BF
- Line (x1 + 2, y1 + 2)-(x2 - 2, y2 - 2), RGB(200, 200, 200), B
- Line (x1 + 3, y1 + 3)-(x2 - 3, y2 - 3), RGB(200, 200, 200), B
- End Sub
- Sub MenuBox(boxwidth As Short, boxheight As Short, title As String)
- Dim xcentre As Short, ycentre As Short
-
- xcentre = xoffs + 15 * bigwidth
- ycentre = yoffs + 15 * 22
-
- DrawBox xcentre - boxwidth * 8, _
- ycentre - boxheight * 8, _
- xcentre + boxwidth * 8, _
- ycentre + boxheight * 8
-
- If Len(title) Then
- Draw String (xcentre - Len(title) * 4, _
- ycentre - (boxheight - 1) * 8 + 2), _
- title, RGB(255, 255, 255)
- Line (xcentre - (boxwidth - 6) * 8, _
- ycentre - (boxheight - 4) * 8)- _
- (xcentre + (boxwidth - 6) * 8, _
- ycentre - (boxheight - 4) * 8 + 1), _
- RGB(200, 200, 200), B
- ceny = ycentre - (boxheight - 4) * 8 + 12
- Else
- ceny = ycentre - boxheight * 8 + 8
- End If
-
- cenx = xcentre
- lefx = xcentre - boxwidth * 8 + 16
- End Sub
- Sub SelectBackground
- Dim As Short i, j, centre
- Dim s As String, akey As String
- Dim As Integer xm, ym, wm, bm
- Dim As Byte current, previous = -1
- Dim custom_background As UByte = 5, update_custom As Byte = 0
- Dim text(0 To 5) As String
-
- text(0) = "Desert"
- text(1) = "Tropical"
- text(2) = "Alpine"
- text(3) = "City"
- text(4) = "Country"
- text(5) = "Custom/Chaotic"
-
- MenuBox 25, 25 - 3 * (allow_errors <> 0), "Select Background"
- centre = xoffs + 15 * bigwidth
-
- For i = 0 To 4 - (allow_errors <> 0)
- s = text(i)
- Draw String (centre - Len(s) * 4, i * 50 + ceny + 16), s, RGB(70, 200, 240)
- If i = 5 Then
- Draw String (centre - 56, ceny + 286), "Background #" + Hex(custom_background, 2), RGB(240, 160, 50)
- Else
- For j = 0 To 9
- PutIcon j, i + 22, centre + (j - 5) * bigwidth, i * 50 + ceny + 32
- Next j
- End If
- Next i
-
- buttons = 0 : ceny += (292 - 50 * (allow_errors <> 0))
- StackButton " Cancel ", 1
- EndOfButtonStack
- ceny -= (292 - 50 * (allow_errors <> 0))
-
- Do
- GetMouse xm, ym, wm, bm
-
- If xm >= centre - 5 * bigwidth - 16 And xm < centre + 5 * bigwidth + 16 _
- AndAlso ym >= ceny + 8 And ym < ceny + 256 - (50 * (allow_errors <> 0)) Then
-
- current = (ym - ceny - 8) \ 50
- Else
- current = -1
- End If
-
- If current <> previous Then
- If previous >= 0 Then
- ScreenLock
- Line (centre - 5 * bigwidth - 16, 50 * previous + ceny + 8)- _
- Step (10 * bigwidth + 31, 49), RGB(30, 30, 50), BF
- s = text(previous)
- Draw String (centre - Len(s) * 4, previous * 50 + ceny + 16), s, RGB(70, 200, 240)
- If previous = 5 Then
- Draw String (centre - 56, ceny + 286), "Background #" + Hex(custom_background, 2), RGB(240, 160, 50)
- Else
- For j = 0 To 9
- PutIcon j, previous + 22, centre + (j - 5) * bigwidth, previous * 50 + ceny + 32
- Next j
- End If
- ScreenUnlock
- End If
- If current >= 0 Then
- ScreenLock
- Line (centre - 5 * bigwidth - 16, 50 * current + ceny + 8)- _
- Step (10 * bigwidth + 31, 49), RGB(10, 10, 10), BF
- s = text(current)
- Draw String (centre - Len(s) * 4, current * 50 + ceny + 16), s, RGB(70, 200, 240)
- If current = 5 Then
- Draw String (centre - 56, ceny + 286), "Background #" + Hex(custom_background, 2), RGB(240, 160, 50)
- Else
- For j = 0 To 9
- PutIcon j, current + 22, centre + (j - 5) * bigwidth, current * 50 + ceny + 32
- Next j
- End If
- ScreenUnlock
- End If
-
- previous = current
- End If
-
- If bm = 1 Then
- If current >= 0 Then
- landscape = current
- If landscape = 5 Then landscape = custom_background
- Exit Do
- End If
- ElseIf bm = 2 Then
- Exit Do
- End If
-
- If ManageButtons Then Exit Do
-
- akey = InKey
- Select Case akey
- Case "=", "+"
- custom_background += 1
- update_custom = -1
- Case "-"
- custom_background -= 1
- update_custom = -1
- Case "0" To "9"
- custom_background ShL= 4
- custom_background Or= ValInt(akey)
- update_custom = -1
- Case "A" To "F", "a" To "f"
- custom_background ShL= 4
- custom_background Or= (ASC(UCase(akey)) - 55)
- update_custom = -1
- Case Chr(27) : Exit Do
- End Select
-
- If update_custom Then
- If allow_errors Then
- If current = 5 Then
- Line (centre - 56, ceny + 286)- Step (111, 15), RGB(10, 10, 10), BF
- Else
- Line (centre - 56, ceny + 286)- Step (111, 15), RGB(30, 30, 50), BF
- End If
- Draw String (centre - 56, ceny + 286), "Background #" + Hex(custom_background, 2), RGB(240, 160, 50)
- End If
- update_custom = 0
- End If
- Loop
-
- buttons = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
- End Sub
- Sub TCentre(y As Short = -1, text As String = "", colour As ULong = RGB(255, 255, 255))
- If y >= 0 Then ceny = y
- cenx = xoffs + 15 * bigwidth - 4 * Len(text)
- If Len(text) Then Draw String (cenx, ceny), text, colour
- cenx = xoffs + 15 * bigwidth
- ceny += 16
- conx = lefx : cony = ceny
- End Sub
- Sub TCont(text As String, eol As Byte = 0)
- Draw String (conx, cony), text, concolour
- If eol Then
- cony += 16
- conx = lefx
- Else
- conx += 8 * Len(text)
- End If
- End Sub
- Function Timey(t As Long) As String
- Dim As Byte c, s, m, h
- Dim As String r, result
-
- c = t Mod 100 : t \= 100
- s = t Mod 60 : t \= 60
- m = t Mod 60 : t \= 60
- h = t
-
- r = Str(c) : r = String(2 - Len(r), "0") + r
- result = r
- r = Str(s) : r = String(2 - Len(r), "0") + r
- result = r + "." + result
- r = Str(m)
- If h Then r = String(2 - Len(r), "0") + r
- result = r + ":" + result
- If h Then
- result = Str(h) + ":" + result
- End If
-
- Return result
- End Function
- Sub TLeft(y As Short = -1, text As String = "", colour As ULong = RGB(255, 255, 255))
- If y >= 0 Then ceny = y
- If Len(text) Then
- #ifdef RENDER_TO_CP437
- Draw String (lefx, ceny), text, colour
- #else
- PutString lefx, ceny, text, colour
- #endif
- End If
- cenx = xoffs + 15 * bigwidth
- ceny += 16
- conx = lefx : cony = ceny
- End Sub
- Sub AddButton(x As Short = -1, y As Short = -1, title As String, value As Short)
- buttons += 1
- If x >= 0 Then button(buttons).x1 = x Else button(buttons).x1 = cenx
- If y >= 0 Then button(buttons).y1 = y Else button(buttons).y1 = ceny
- button(buttons).x2 = button(buttons).x1 + 8 * Len(title) + 16
- button(buttons).y2 = button(buttons).y1 + 31
- button(buttons).title = title
- button(buttons).value = value
-
- Line (button(buttons).x1, button(buttons).y1)-(button(buttons).x2, button(buttons).y1 + 31), RGB(200, 200, 200), B
- Line (button(buttons).x1 + 1, button(buttons).y1 + 1)-(button(buttons).x2 - 1, button(buttons).y1 + 30), RGB(200, 200, 200), B
- Line (button(buttons).x1 + 2, button(buttons).y1 + 2)-(button(buttons).x2 - 2, button(buttons).y1 + 29), RGB(30, 30, 50), BF
- Draw String (button(buttons).x1 + 8, button(buttons).y1 + 8), title, RGB(200, 200, 200)
-
- ceny = button(buttons).y1
- cenx = button(buttons).x2 + 8
- End Sub
- Sub StackButton(title As String, value As Short = -1, direction As Byte = 0, separation As UShort = 16)
- Static lastvalue As Short = 0, first As Short = 0
- Dim i As Short
- If Len(title) = 0 Then
- first = 0
- Exit Sub
- End If
-
- buttons += 1
- If first = 0 Then first = buttons : lastvalue = 0
-
- If value Then
- button(buttons).value = value
- lastvalue = value
- Else
- lastvalue += 1
- button(buttons).value = lastvalue
- End If
-
- button(buttons).title = title
- button(buttons).y1 = ceny : button(buttons).y2 = ceny + 31
- If direction > 0 Then 'Stack to the right
- If buttons = first Then
- button(buttons).x1 = cenx
- Else
- button(buttons).x1 = button(buttons - 1).x2 + separation
- End If
- button(buttons).x2 = button(buttons).x1 + 8 * Len(title) + 16
- ElseIf direction < 0 Then 'Stack to the left
- If buttons = first Then
- button(buttons).x2 = cenx
- Else
- button(buttons).x2 = button(buttons - 1).x1 - separation
- End If
- button(buttons).x1 = button(buttons).x2 - 8 * Len(title) - 16
- Else 'Stack around a centre
- If buttons = first Then
- button(buttons).x1 = cenx - Len(title) * 4 - 8
- button(buttons).x2 = cenx + Len(title) * 4 + 8
- Else
- For i = first To buttons - 1
- button(i).x1 -= (Len(title) * 4 + 8 + separation \ 2)
- button(i).x2 -= (Len(title) * 4 + 8 + separation \ 2)
- Next i
- button(buttons).x1 = button(buttons - 1).x2 + separation
- button(buttons).x2 = button(buttons).x1 + Len(title) * 8 + 16
- End If
- End If
- End Sub
- Sub EndOfButtonStack
- Dim i As Short
-
- StackButton ""
- For i = 1 To buttons
- Line (button(i).x1, button(i).y1)-(button(i).x2, button(i).y1 + 31), RGB(200, 200, 200), B
- Line (button(i).x1 + 1, button(i).y1 + 1)-(button(i).x2 - 1, button(i).y1 + 30), RGB(200, 200, 200), B
- Line (button(i).x1 + 2, button(i).y1 + 2)-(button(i).x2 - 2, button(i).y1 + 29), RGB(30, 30, 50), BF
- Draw String (button(i).x1 + 8, button(i).y1 + 8), button(i).title, RGB(200, 200, 200)
- Next i
- End Sub
- Function ManageButtons As Short
- Static ex As Byte = 0
- Dim As Integer xm, ym, wm, bm
- Dim i As Byte, active As Byte = 0
-
- GetMouse xm, ym, wm, bm
-
- For i = 1 To buttons
- If xm >= button(i).x1 And xm <= button(i).x2 And ym >= button(i).y1 And ym <= button(i).y2 Then
- active = i
- Exit For
- End If
- Next i
-
- If active <> ex Then
- If ex <> 0 And ex <= buttons Then
- Line (button(ex).x1, button(ex).y1)-(button(ex).x2, button(ex).y2), RGB(200, 200, 200), B
- Line (button(ex).x1 + 1, button(ex).y1 + 1)-(button(ex).x2 - 1, button(ex).y2 - 1), RGB(200, 200, 200), B
- Line (button(ex).x1 + 2, button(ex).y1 + 2)-(button(ex).x2 - 2, button(ex).y2 - 2), RGB(30, 30, 50), BF
- Draw String (button(ex).x1 + 8, button(ex).y1 + 8), button(ex).title, RGB(200, 200, 200)
- End If
- If active <> 0 And active <= buttons Then
- Line (button(active).x1, button(active).y1)-(button(active).x2, button(active).y2), RGB(200, 200, 200), BF
- Draw String (button(active).x1 + 8, button(active).y1 + 8), button(active).title, RGB(30, 30, 50)
- End If
- ex = active
- End If
-
- If bm = 1 And active <> 0 And active <= buttons Then
- Return button(active).value
- Else
- Return 0
- End If
- End Function
- Sub ManageIcons
- Dim As Integer xm, ym, wm, bm
- Dim As Short xi, yi
- Dim and_now As Byte
- Dim tempboard As String
- Static highlit As Byte = -1, exwm As Integer
- Static internal_bgc As Byte = 0
- Dim oname(0 To 19) As String
-
- oname(0) = "New Track"
- oname(1) = "Save Track"
- oname(2) = "Load Track"
- oname(3) = "Exit Bliss"
-
- oname(4) = "Select"
- oname(5) = "Copy"
- oname(6) = "Cut"
- oname(7) = "Paste"
-
- oname(8) = "Flip Horizontally"
- oname(9) = "Flip Vertically"
- oname(10) = "Rotate Clockwise"
- oname(11) = "Rotate Ctr-clockwise"
-
- oname(12) = "Track Information"
- oname(13) = "Undo"
- oname(14) = "Redo"
- oname(15) = "Help"
-
- oname(16) = "Generate Scenery"
- oname(17) = "Track Analysis"
- oname(18) = "Tournaments"
- oname(19) = "Settings"
-
- GetMouse xm, ym, wm, bm
-
- 'Calculate menu item position
- If xm < xpanel + xpicons Or xm >= xpanel + xpicons + 176 Or _
- ym < ypanel + ypicons Or ym >= ypanel + ypicons + 220 Then
- and_now = -1
- Else
- xi = (xm - xpanel - xpicons) \ 44
- yi = (ym - ypanel - ypicons) \ 44
- and_now = yi * 4 + xi
- End If
-
- If highlit <> and_now Then
- ScreenLock
- If highlit <> -1 Then
- Line ((highlit Mod 4) * 44 + xpanel + xpicons, (highlit \ 4) * 44 + ypanel + ypicons)- STEP (43, 43), RGB(30, 30, 50), BF
- If dosbox Then
- Put ((highlit Mod 4) * 44 + xpanel + xpicons, (highlit \ 4) * 44 + ypanel + ypicons), bigicons, (13 * bigwidth + (highlit Mod 4) * 44, 12 * 22 + (highlit \ 4) * 44)- STEP(bigwidth * 2 - 1, 43), Trans
- Else
- Put ((highlit Mod 4) * 44 + xpanel + xpicons, (highlit \ 4) * 44 + ypanel + ypicons), bigicons, (13 * bigwidth + (highlit Mod 4) * 44, 12 * 22 + (highlit \ 4) * 44)- STEP(bigwidth * 2 - 1, 43), Alpha
- End If
- End If
- Line (xpanel + xpicons, ypanel + ypicons + 236)- Step (175, 15), RGB(30, 30, 50), BF
- If and_now <> -1 Then
- Line (xi * 44 + xpanel + xpicons, yi * 44 + ypanel + ypicons)- STEP (43, 43), RGB(30, &HF2, &HF3), BF
- If dosbox Then
- Put (xi * 44 + xpanel + xpicons, yi * 44 + ypanel + ypicons), bigicons, (13 * bigwidth + (and_now Mod 4) * 44, 12 * 22 + (and_now \ 4) * 44)- STEP(bigwidth * 2 - 1, 43), Trans
- Else
- Put (xi * 44 + xpanel + xpicons, yi * 44 + ypanel + ypicons), bigicons, (13 * bigwidth + (and_now Mod 4) * 44, 12 * 22 + (and_now \ 4) * 44)- STEP(bigwidth * 2 - 1, 43), Alpha
- End If
- Draw String (xpanel + xpicons + 4 * bigwidth - Len(oname(and_now)) * 4, ypanel + ypicons + 236), oname(and_now), RGB(200, 200, 200)
- End If
- ScreenUnlock
- highlit = and_now
- End If
-
- 'Activate menu icon option
- If highlit <> -1 And bm = 1 Then
- Select Case highlit
- Case 0 : Menu_StartNewTrack
- Case 1 : Menu_SaveTrack
- Case 2 : Menu_LoadTrack
- Case 3 : QuitProgram
- Case 4
- selecting = -1 : xselect = 0 : DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Case 5, 6
- CopyOrCut highlit = 6
- If highlit = 6 Then PushUndo
- DrawPanel
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Case 7
- Paste
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Case 8 'Flip horizontally
- If pasting Then
- clipboard = HFlipTrack(clipboard)
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- ElseIf xselect Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = HFlipTrack(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Else
- tempboard = GetTrack(1, 1, 30, 30)
- tempboard = HFlipTrack(tempboard)
- PutTrack 1, 1, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- End If
- Case 9 'Flip vertically
- If pasting Then
- clipboard = VFlipTrack(clipboard)
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- ElseIf xselect Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = VFlipTrack(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Else
- tempboard = GetTrack(1, 1, 30, 30)
- tempboard = VFlipTrack(tempboard)
- PutTrack 1, 1, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- End If
- Case 10 'Rotate clockwise
- If pasting Then
- clipboard = CRotate(clipboard)
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- ElseIf xselect Then
- If x2select - xselect = y2select - yselect Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = CRotate(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Else
- NotASquare
- End If
- Else
- tempboard = GetTrack(1, 1, 30, 30)
- tempboard = CRotate(tempboard)
- PutTrack 1, 1, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- End If
- Case 11 'Rotate counter-clockwise
- If pasting Then
- clipboard = CCRotate(clipboard)
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- ElseIf xselect Then
- If x2select - xselect = y2select - yselect Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = CCRotate(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Else
- NotASquare
- End If
- Else
- tempboard = GetTrack(1, 1, 30, 30)
- tempboard = CCRotate(tempboard)
- PutTrack 1, 1, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- End If
- Case 12 : Menu_TrackInfo
- Case 13 'Undo
- If Not pasting Then
- Undo
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- End If
- Case 14 'Redo
- If Not pasting Then
- Redo
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- End If
- Case 15 : Menu_Help
- Case 16 : Menu_Scenery
- Case 17 : Menu_Analysis
- Case 18 : Menu_Tournaments
- Case 19 : Menu_Settings
- End Select
- End If
-
- 'Check to update switch indicators
- If xm >= xpanel + xswitches AndAlso _
- xm < xpanel + xswitches + 9 * 22 AndAlso _
- ym >= ypanel + yswitches AndAlso _
- ym < ypanel + yswitches + 22 Then
-
- If bm = 1 Then
- xi = (xm - xswitches - xpanel) \ 22
- PutIcon 21 + xi, 13, xpanel + xswitches + bigwidth * xi, ypanel + yswitches
-
- Select Case xi
- Case 0 : clipboard = ""
- Case 1 : show_errors = Not show_errors
- Case 2 : allow_errors = Not allow_errors
- Case 3 : data_codes = Not data_codes
- Case 4 : show_grid = Not show_grid
- Case 5 : affect_track = Not affect_track
- Case 6 : affect_terrain = Not affect_terrain
- Case 7 : colouring_mode = Not colouring_mode
- Case 8 : Menu_TrackShot
- End Select
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- DrawTrack
- DrawPanel
- End If
- End If
-
- If colouring_mode Then
- 'Colouration - Background colour
- If xm >= xpanel + xpalette + 16 AndAlso ym >= ypanel + 434 AndAlso _
- xm < xpanel + xpalette + 38 AndAlso ym < ypanel + 456 Then
-
- Dim As ULong r, g, b
- If wm > exwm Then
- internal_bgc = (internal_bgc + 1) Mod 24
- current_bgc = cpal(internal_bgc)
- If internal_bgc Then
- r = .7 * ((current_bgc ShR 16) And 255)
- g = .7 * ((current_bgc ShR 8) And 255)
- b = .7 * (current_bgc And 255)
- current_bgc = RGB(r, g, b)
- Else
- current_bgc = 0
- End If
- DrawPanel
- ElseIf wm < exwm Then
- internal_bgc = (internal_bgc + 23) Mod 24
- current_bgc = cpal(internal_bgc)
- If internal_bgc Then
- r = .7 * ((current_bgc ShR 16) And 255)
- g = .7 * ((current_bgc ShR 8) And 255)
- b = .7 * (current_bgc And 255)
- current_bgc = RGB(r, g, b)
- Else
- current_bgc = 0
- End If
- DrawPanel
- ElseIf bm = 2 Then
- current_bgc = 0
- internal_bgc = 0
- DrawPanel
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 2
- ElseIf bm = 1 Then
- Menu_Colouring
- End If
- 'Colouration - Border colour
- ElseIf xm >= xpanel + xpalette + 48 AndAlso ym >= ypanel + 434 AndAlso _
- xm < xpanel + xpalette + 70 AndAlso ym < ypanel + 456 Then
-
- Dim q As Byte
-
- If wm > exwm Then
- For i As Byte = 0 To 23
- If cpal(i) = current_border Then q = i
- Next i
-
- q = (q + 1) Mod 24
- current_border = cpal(q)
- DrawPanel
- ElseIf wm < exwm Then
- For i As Byte = 0 To 23
- If cpal(i) = current_border Then q = i
- Next i
-
- q = (q + 23) Mod 24
- current_border = cpal(q)
- DrawPanel
- ElseIf bm = 2 Then
- current_border = 0
- DrawPanel
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 2
- ElseIf bm = 1 Then
- Menu_Colouring
- End If
- End If
- End If
-
- exwm = wm
- End Sub
- Sub ManageKeyboardCursor(forceupdate As Byte = 0)
- Static As Byte oldx = 1, oldy = 1
- Dim As Integer xm, ym, wm, bm
-
- If forceupdate OrElse oldx <> xcursor Or oldy <> ycursor Then
- drawkeyboardcursor = -1
- For j As Byte = oldy - 1 To oldy + 1
- For i As Byte = oldx - 1 To oldx + 1
- If i >= 1 AndAlso i <= 30 AndAlso j >= 1 AndAlso j <= 30 _
- Then DrawSpot i, j
- Next i
- Next j
-
-
- Dim As Short xx, yy
- xx = xoffs + 22 * (xcursor - 1)
- yy = yoffs + 22 * (ycursor - 1)
-
- If current_page = 10 Or allow_errors <> 0 Then
- Line (xx, yy)- Step (21, 21), RGB(250, 250, 250), B
- Line (xx + 1, yy + 1)- Step (19, 19), RGB(250, 250, 250), B
- ElseIf current_page < 10 Then
- Dim As Byte w, h
- Dim v As UByte
- Dim As Byte ex, ey
-
- Select Case grid(xcursor, ycursor).track
- Case 255 : ex = xcursor - 1 : ey = ycursor
- Case 254 : ex = xcursor : ey = ycursor - 1
- Case 253 : ex = xcursor - 1 : ey = ycursor - 1
- Case Else : ex = xcursor : ey = ycursor
- End Select
- If ex < 1 Then ex = 1
- If ey < 1 Then ey = 1
- v = grid(ex, ey).track
- If v Then
- DrawSpot ex, ey, -1
- If tr(v).w = 2 And ex < 30 Then
- DrawSpot ex + 1, ey, -1
- If tr(v).h = 2 And ey < 30 Then DrawSpot ex + 1, ey + 1, -1
- End If
- If tr(v).h = 2 And ey < 30 Then DrawSpot ex, ey + 1, -1
- End If
-
- If xcursor < 30 Then w = tr(current_brush).w Else w = 1
- If ycursor < 30 Then h = tr(current_brush).h Else h = 1
- Line (xx, yy)- Step (22 * w - 1, 22 * h - 1), RGB(200, 200, 200), B
- Line (xx, yy)- Step (21, 21), RGB(250, 250, 250), B
- Line (xx + 1, yy + 1)- Step (19, 19), RGB(250, 250, 250), B
- End If
-
- Dim s As String, coorpos As Short
-
- coorpos = xpanel + 170
- If colouring_mode Then coorpos -= 72
-
- ScreenLock
- Line (coorpos - 74, ypanel + 432)- STEP (155, 31), RGB(30, 30, 50), BF
- s = "[" + Trim(Str(xcursor)) + ", " + Trim(Str(ycursor)) + "]"
- If selecting = -3 Then s = "[" + Trim(Str(xselect)) + ", " + Trim(Str(yselect)) + "]-" + s
- Draw String (coorpos - Len(s) * 4, ypanel + 430), s, RGB(200, 200, 200)
- If data_codes Then
- s = "Ter[" + Hex(grid(xcursor, ycursor).land) + "h] Trk[" + Hex(grid(xcursor, ycursor).track) + "h]"
- Else
- s = Trim(tr(GetParent(xcursor, ycursor)).id)
- End If
- Draw String (coorpos - Len(s) * 4, ypanel + 446), s, RGB(200, 200, 200)
- ScreenUnlock
-
- oldx = xcursor : oldy = ycursor
- End If
-
- If drawkeyboardcursor Then
- GetMouse xm, ym, wm, bm
-
- If bm <> 0 Then
- drawkeyboardcursor = 0
- For j As Byte = ycursor - 1 To ycursor + 1
- For i As Byte = xcursor - 1 To xcursor + 1
- If i >= 1 AndAlso i <= 30 AndAlso j >= 1 AndAlso j <= 30 _
- Then DrawSpot i, j
- Next i
- Next j
- End If
- End If
- End Sub
- Function ManageSelector(sel As SelectorType) As Byte
- Dim isin As Byte
- Dim As Integer xm, ym, wm, bm
-
- If sel.current = 0 Then sel.current = 1
-
- GetMouse xm, ym, wm, bm
- If xm >= sel.x1 And xm <= sel.x2 And ym >= sel.y1 And ym <= sel.y2 Then
- isin = -1
- Else
- isin = 0
- End If
-
- 'Redraw
- If sel.redraw <> 0 Or isin <> sel.wasinlasttime Then
- ScreenLock
- With sel
- If isin Then
- Line (.x1, .y1)-(.x2, .y2), RGB(200, 200, 200), BF
- Draw String (.x1 + 8, (.y1 + .y2) \ 2 - 8), .opt(.current), RGB(30, 30, 50)
- Draw String (.x2 - 16, (.y1 + .y2) \ 2 - 8), Chr(25), RGB(30, 30, 50)
- Else
- Line (.x1, .y1)-(.x2, .y2), RGB(200, 200, 200), B
- Line (.x1 + 1, .y1 + 1)-(.x2 - 1, .y2 - 1), RGB(200, 200, 200), B
- LIne (.x1 + 2, .y1 + 2)-(.x2 - 2, .y2 - 2), RGB(30, 30, 50), BF
- Draw String (.x1 + 8, (.y1 + .y2) \ 2 - 8), .opt(.current), RGB(200, 200, 200)
- Draw String (.x2 - 16, (.y1 + .y2) \ 2 - 8), Chr(25), RGB(200, 200, 200)
- End If
- End With
- ScreenUnlock
- sel.redraw = 0
- If isin Then sel.wasinlasttime = -1 Else sel.wasinlasttime = 0
- End If
-
- 'Clicked on the pull-down selector
- If bm = 1 And isin Then
- Dim bgcopy As UByte Ptr, newy1 As Short, newy2 As Short
- Dim thisone As Byte, thelastone As Byte
-
- With sel
- newy1 = .y1
- newy2 = .y1 + 32 * .options + 3
- If newy2 > 700 Then
- newy1 = newy1 - newy2 + 700
- newy2 = 700
- End If
-
- bgcopy = ImageCreate(.x2 - .x1 + 1, 32 * .options + 4)
- Get (.x1, newy1)-(.x2, newy2), bgcopy
-
- ScreenLock
- Line (.x1, newy1)-(.x2, newy2), RGB(200, 200, 200), B
- Line (.x1 + 1, newy1 + 1)-(.x2 - 1, newy2 - 1), RGB(200, 200, 200), B
- Line (.x1 + 2, newy1 + 2)-(.x2 - 2, newy2 - 2), RGB(30, 30, 50), BF
-
- For i As Byte = 1 To .options
- Draw String (.x1 + 8, newy1 + 32 * i - 24), .opt(i), RGB(200, 200, 200)
- Next i
- ScreenUnlock
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- thelastone = -1
- Do
- GetMouse xm, ym, wm, bm
- If xm < .x1 Or xm > .x2 Or ym < newy1 + 2 Or ym > newy2 - 2 Then Exit Do
- thisone = (ym - newy1) \ 32 + 1
-
- If thisone <> thelastone Then
- If thelastone >= 1 And thelastone <= .options Then
- Line (.x1 + 2, newy1 + 32 * (thelastone - 1) + 2)-(.x2 - 2, newy1 + 32 * thelastone + 1), RGB(30, 30, 50), BF
- Draw String (.x1 + 8, newy1 + 32 * thelastone - 24), .opt(thelastone), RGB(200, 200, 200)
- End If
- If thisone >= 1 And thisone <= .options Then
- Line (.x1 + 2, newy1 + 32 * (thisone - 1) + 2)-(.x2 - 2, newy1 + 32 * thisone + 1), RGB(200, 200, 200), BF
- Draw String (.x1 + 8, newy1 + 32 * thisone - 24), .opt(thisone), RGB(30, 30, 50)
- End If
- thelastone = thisone
- End If
-
- If bm = 1 And thisone >= 1 And thisone <= .options Then
- sel.current = thisone
- Exit Do
- End If
- Loop
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Put (.x1, newy1), bgcopy, PSet
- ImageDestroy bgcopy
- End With
-
- sel.redraw = -1
- Return sel.current
- End If
-
- Return 0
- End Function
- Function ManageString(ByRef s As String) As String
- Dim akey As String
-
- If stringer.init <> 0 Or stringer.sr <> s Then
- stringer.t = Timer
- stringer.cursor = -1
- stringer.redraw = -1
- stringer.init = 0
- stringer.s32 = Enc_UTF8_to_UTF32(s)
- #ifdef RENDER_TO_CP437
- stringer.sr = Enc_UTF32_to_CP437(stringer.s32)
- #else
- stringer.sr = Enc_UTF32_to_Latin1(stringer.s32)
- #endif
-
- stringer.cursor_pos = Len(stringer.sr)
- 'stringer.last = s
- End If
-
- #ifdef __FB_LINUX__
- akey = LinKey
- #else
- akey = InKey
- #endif
-
- Select Case akey
- Case "A" To "Z", "a" To "z", "0" To "9", "_", "."
- If Len(stringer.sr) < stringer.maxlength Then
- stringer.sr = Left(stringer.sr, stringer.cursor_pos) + akey + Mid(stringer.sr, stringer.cursor_pos + 1)
- stringer.s32 = Left(stringer.s32, 4 * stringer.cursor_pos) + akey + String(3, 0) + Mid(stringer.s32, 4 * stringer.cursor_pos + 1)
-
- stringer.cursor_pos += 1
- stringer.redraw = -1
- End If
- Case " " To Chr(126)
- If Len(stringer.sr) < stringer.maxlength And stringer.fileonly = 0 Then
- stringer.sr = Left(stringer.sr, stringer.cursor_pos) + akey + Mid(stringer.sr, stringer.cursor_pos + 1)
- stringer.s32 = Left(stringer.s32, 4 * stringer.cursor_pos) + akey + String(3, 0) + Mid(stringer.s32, 4 * stringer.cursor_pos + 1)
-
- stringer.cursor_pos += 1
- stringer.redraw = -1
- End If
- Case Chr(8)
- If stringer.cursor_pos > 0 Then
- stringer.sr = Left(stringer.sr, stringer.cursor_pos - 1) + Mid(stringer.sr, stringer.cursor_pos + 1)
- stringer.s32 = Left(stringer.s32, 4 * stringer.cursor_pos - 4) + Mid(stringer.s32, 4 * stringer.cursor_pos + 1)
-
- stringer.cursor_pos -= 1
- stringer.redraw = -1
- End If
- Case Chr(13), Chr(27)
- Return akey
- Case Chr(255) + Chr(77), Chr(0, &H53, &HFF, 0, 0)
- If stringer.cursor_pos < Len(stringer.sr) Then
- stringer.cursor_pos += 1
- stringer.redraw = -1
- End If
- Case Chr(255) + Chr(75), Chr(0, &H51, &HFF, 0, 0)
- If stringer.cursor_pos > 0 Then
- stringer.cursor_pos -= 1
- stringer.redraw = -1
- End If
- Case Chr(255) + Chr(83), Chr(127)
- If Len(stringer.sr) >= stringer.cursor_pos Then
- stringer.sr = Left(stringer.sr, stringer.cursor_pos) + Mid(stringer.sr, stringer.cursor_pos + 2)
- stringer.s32 = Left(stringer.s32, 4 * stringer.cursor_pos) + Mid(stringer.s32, 4 * stringer.cursor_pos + 5)
- stringer.redraw = -1
- End If
- Case Chr(255) + Chr(71), Chr(0, &H50, &HFF, 0, 0)
- stringer.cursor_pos = 0
- stringer.redraw = -1
- Case Chr(255) + Chr(79), Chr(0, &H57, &HFF, 0, 0)
- stringer.cursor_pos = Len(stringer.sr)
- stringer.redraw = -1
- Case Else
- If Len(akey) > 1 Then
- Dim akey32 As Long
-
- If Left(akey, 1) = Chr(0) Then Return akey
-
- akey32 = CvL(Enc_UTF8_to_UTF32(akey))
- If akey32 >= 128 And stringer.fileonly = 0 Then
- If Len(stringer.sr) < stringer.maxlength Then
- #ifdef RENDER_TO_CP437
- 'Use CP437 as target codepage (to render with Draw String)
- stringer.sr = Left(stringer.sr, stringer.cursor_pos) + Enc_UTF32_to_CP437(MkL(akey32)) + Mid(stringer.sr, stringer.cursor_pos + 1)
- #else
- 'Use Latin-1 as target codepage (to render with PutString)
- stringer.sr = Left(stringer.sr, stringer.cursor_pos) + Enc_UTF32_to_Latin1(MkL(akey32)) + Mid(stringer.sr, stringer.cursor_pos + 1)
- #endif
- stringer.s32 = Left(stringer.s32, 4 * stringer.cursor_pos) + MkL(akey32) + Mid(stringer.s32, 4 * stringer.cursor_pos + 1)
-
- stringer.cursor_pos += 1
- stringer.redraw = -1
- End If
- End If
-
- 'This line was here, but looks terribly wrong!!!
- 'Return akey
- ElseIf Len(akey) = 1 And stringer.fileonly = 0 Then 'DOS extended CP437
- Dim akey32 As Long
-
- akey32 = fromCP437(Asc(akey) - 128)
- If Len(stringer.sr) < stringer.maxlength Then
- stringer.sr = Left(stringer.sr, stringer.cursor_pos) + Enc_UTF32_to_CP437(MkL(akey32)) + Mid(stringer.sr, stringer.cursor_pos + 1)
- stringer.s32 = Left(stringer.s32, 4 * stringer.cursor_pos) + MkL(akey32) + Mid(stringer.s32, 4 * stringer.cursor_pos + 1)
-
- stringer.cursor_pos += 1
- stringer.redraw = -1
- End If
- End If
- End Select
-
- If Timer - stringer.t > .2 Then
- stringer.cursor = Not stringer.cursor
- stringer.t = Timer
- stringer.redraw = -1
- End If
-
- If stringer.redraw <> 0 Or Len(akey) <> 0 Then _
- s = Enc_UTF32_to_UTF8(stringer.s32)
-
- If stringer.redraw Then
- ScreenLock
- Line(stringer.x, stringer.y)- STEP (8 * stringer.maxlength + 7, 15), stringer.background, BF
- #ifdef RENDER_TO_CP437
- Draw String (stringer.x, stringer.y), stringer.sr, RGB(160, 160, 240)
- #else
- PutString stringer.x, stringer.y, stringer.sr, RGB(160, 160, 240)
- #endif
- If stringer.cursor Then
- Line (stringer.x + 8 * stringer.cursor_pos, stringer.y)- STEP (7, 15), RGB(200, 200, 200), BF
- End If
- ScreenUnlock
-
- stringer.redraw = 0
- End If
-
- Return akey
- End Function
- Sub Error_Message(text As String, title As String = "Error!")
- Dim v As Short
- Dim As Integer xm, ym, wm, bm
-
- MenuBox 28, 10, title
- ceny += 16
- TCentre , text, RGB(200, 200, 240)
- ceny += 24
-
- buttons = 0
- StackButton " OK "
- EndOfButtonStack
-
- Do
- v = ManageButtons
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until v <> 0 Or Len(InKey) <> 0
- buttons = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- Do : Loop Until Len(InKey) = 0
- DrawTrack
- End Sub
- Sub Menu_Scenery
- Dim update As Byte = -1, i As Short, j As Short
- Dim As Integer xm, ym, wm, bm
- Dim bar(0 To 9) As UByte, sel(0 To 9) As SelectorType
- Dim thing(0 To 9) As UByte
- Dim tempy As Short, v As Short, scratch As SelectorType
- Dim akey As String, lastchanged As Byte
-
- 'Define what tile each bar represents
- thing(0) = &H99 : thing(1) = &H98 : thing(2) = &H97
- thing(3) = &H9A : thing(4) = &HA3 : thing(5) = &H9F
- thing(6) = &H9B : thing(7) = &HA7 : thing(8) = &HAF : thing(9) = &HAB
-
- Select Case landscape
- Case 0 'Desert
- bar(1) = 20 : bar(6) = 5
- Case 1 'Tropical
- bar(2) = 20 : bar(4) = 7 : bar(6) = 6
- bar(8) = 3 : bar(9) = 10
- Case 2 'Alpine
- bar(0) = 20 : bar(4) = 5 : bar(5) = 8
- Case 3 'City
- bar(0) = 15 : bar(4) = 15 : bar(6) = 7
- bar(8) = 9 : bar(9) = 10 : bar(3) = 2
- Case 4 'Country
- bar(0) = 15 : bar(3) = 5 : bar(5) = 7
- bar(6) = 3 : bar(7) = 8 : bar(9) = 5
- End Select
-
- MenuBox 35, 28, "Generate Scenery"
- lefx += 16 : ceny += 16
- PutIcon 24, 6, lefx, ceny
- PutIcon 24, 7, lefx, ceny + 32
- PutIcon 24, 8, lefx, ceny + 64
- PutIcon 24, 9, lefx, ceny + 96
- PutIcon 26, 6, lefx, ceny + 128
- PutIcon 26, 7, lefx, ceny + 160
- PutIcon 26, 8, lefx, ceny + 192
- PutIcon 26, 9, lefx, ceny + 224
- PutIcon 26, 11, lefx, ceny + 256
- PutIcon 26, 10, lefx, ceny + 288
-
- For i = 0 To 9
- sel(i).redraw = -1
- If i < 3 Then
- sel(i).current = 1
- Else
- sel(i).current = 2
- End If
- sel(i).options = 2
- sel(i).opt(1) = "Everywhere"
- If i = 9 Then
- sel(i).opt(2) = "On water"
- Else
- sel(i).opt(2) = "By the road"
- End If
- sel(i).x1 = lefx + 360
- sel(i).y1 = ceny + 32 * i
- sel(i).x2 = lefx + 487
- sel(i).y2 = ceny + 32 * i + 19
- Next i
-
- buttons = 0
- tempy = ceny
- ceny += 330 : cenx += 240
- StackButton "Generate", 1, -1
- StackButton " Cancel ", 2, -1
- EndOfButtonStack
- scratch.redraw = -1
- scratch.x1 = lefx
- scratch.y1 = ceny
- scratch.x2 = lefx + 199
- scratch.y2 = ceny + 31
- scratch.current = 1
- scratch.options = 2
- scratch.opt(1) = "Use free space"
- scratch.opt(2) = "Remove old scenery"
- ceny = tempy
-
- Do
- If update Then
- ScreenLock
- For i = 0 To 9
- Dim p As String
-
- p = Str(bar(i)) + "%"
- Line (lefx + 30, 32 * i + ceny)- Step(304, 19), RGB(160, 160, 160), B
- Line (lefx + 31, 32 * i + ceny + 1)- Step(302, 17), RGB(160, 160, 160), B
- Line (lefx + 32, 32 * i + ceny + 2)- Step(300, 15), RGB(30, 30, 50), BF
- Line (lefx + 32, 32 * i + ceny + 2)- Step(3 * bar(i), 15), RGB(0, 160, 160), BF
- Draw String (lefx + 192 - 4 * Len(p), 32 * i + ceny + 3), p, RGB(250, 250, 250)
- Next i
- ScreenUnlock
- update = 0
- End If
-
- GetMouse xm, ym, wm, bm
- akey = InKey
- If STRONG_ANTI_HOG Then Sleep 1
-
- If bm = 1 Then
- If xm >= lefx + 32 And xm <= lefx + 332 AndAlso _
- ym >= ceny + 2 And (ym - ceny - 2) Mod 32 < 22 AndAlso _
- (ym - ceny - 2) \ 32 <= 9 Then
-
- Dim n As Short
- lastchanged = (ym - ceny - 2) \ 32
- n = bar(lastchanged)
- bar(lastchanged) = (xm - lefx - 32) \ 3
-
- If bar(lastchanged) <> n Then update = -1
- End If
- End If
-
- Select Case akey
- Case Chr(13) : v = 1 : Exit Do
- Case Chr(27) : v = 2 : Exit Do
- End Select
-
- For i = 0 To 9
- Dim test As Short
-
- test = sel(i).current
- ManageSelector sel(i)
- If sel(i).current <> test Then update = -1
- Next i
- ManageSelector scratch
- v = ManageButtons
-
- 'Ensure values don't add up greater than 100%
- If update Then
- Dim total As Short, howmany As Short
- Dim factor As Double, topvalue As Byte
-
- If sel(9).current = 2 Then topvalue = 8 Else topvalue = 9
-
- For j = 1 To 2
- total = 0 : howmany = 0
- For i = 0 To topvalue
- If sel(i).current = j Then
- total += bar(i)
- If i <> lastchanged Then howmany += 1
- End If
- Next i
- If total > 100 Then
- If sel(lastchanged).current = j Then
- factor = (100 - bar(lastchanged)) / (total - bar(lastchanged))
- Else
- factor = 100 / total
- End If
-
- For i = 0 To topvalue
- If sel(i).current = j And i <> lastchanged Then
- bar(i) *= factor
- End If
- Next i
- End If
- Next j
- End If
- Loop Until v <> 0
- buttons = 0
-
- 'Generate the requested scenery
- If v = 1 Then
- Dim As Short openfield, water, bytheroad
- Dim map(1 To 30, 1 To 30) As Byte, s As String
-
- 'First remove old scenery if requested
- If scratch.current = 2 Then
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).track >= &H97 And grid(i, j).track <= &HB2 Then _
- grid(i, j).track = 0
- Next i
- Next j
- End If
-
- 'Calculate how many tiles of each type are available
- For j = 1 To 30
- For i = 1 To 30
- Select Case grid(i, j).land
- Case 1 To 5 'Water
- If grid(i, j).track Then
- map(i, j) = -1 'Cannot be used
- Else
- map(i, j) = 2 'Water
- water += 1
- End If
- Case Is >= 7 'Mountain borders
- map(i, j) = -1 'Cannot be used
- Case Else 'Grass or mountain top
- If grid(i, j).track Then
- map(i, j) = -1 'Cannot be used
- Else
- Dim isbytheroad As Byte
-
- s = ""
- If j < 30 Then s &= Chr(grid(i, j + 1).track) Else s &= Chr(0)
- If j > 1 Then s &= Chr(grid(i, j - 1).track) Else s &= Chr(0)
- If i < 30 Then s &= Chr(grid(i + 1, j).track) Else s &= Chr(0)
- If i > 1 Then s &= Chr(grid(i - 1, j).track) Else s &= Chr(0)
-
- For n As Byte = 1 To 4
- Dim k As UByte
-
- k = ASC(Mid(s, n, 1))
- If (k > 0 And k < &H97) Or k >= &HFD Then
- isbytheroad = -1
- map(i, j) = 10 + n - 1 'By the road (with direction)
- bytheroad += 1
- Exit For
- End If
- Next n
-
- If Not isbytheroad Then
- map(i, j) = 1 'Open field
- openfield += 1
- End If
- End If
- End Select
- Next i
- Next j
-
- 'Fill with scenery
- For round As Byte = 1 To 2
- For i = 0 To 9
- Dim amount As Short, whichfrom As Byte, whichto As Byte
-
- 'Calculate how many of each type to place
- If sel(i).current = 1 Then 'Everywhere (open field)
- whichfrom = 1 : whichto = 1
- amount = openfield * bar(i) / 100 - 1
- ElseIf i = 9 Then 'Water
- whichfrom = 2 : whichto = 2
- amount = water * bar(i) / 100 - 1
- Else 'By the road
- whichfrom = 10 : whichto = 13
- amount = bytheroad * bar(i) / 100 - 1
- End If
-
- 'Place the scenery (open field goes last)
- If (whichfrom = 1 And round = 2) Or _
- (whichfrom <> 1 And round = 1) Then
-
- For j = 1 To amount
- Dim As Byte x, y
-
- Do
- x = Int(Rnd * 30) + 1
- y = Int(Rnd * 30) + 1
-
- If map(x, y) >= whichfrom And map(x, y) <= whichto Then
- If i < 4 Then
- grid(x, y).track = thing(i)
- ElseIf i = 9 Then
- grid(x, y).track = thing(i) + Int(Rnd * 4)
- ElseIf whichfrom = 10 Then
- grid(x, y).track = thing(i) + map(x, y) - 10
- Else
- grid(x, y).track = thing(i) + Int(Rnd * 4)
- End If
- map(x, y) = -1
- Exit Do
- ElseIf whichfrom = 1 And map(x, y) >= 10 Then
- If i < 4 Then
- grid(x, y).track = thing(i)
- Else
- grid(x, y).track = thing(i) + Int(Rnd * 4)
- End If
- ElseIf i = 9 And whichfrom = 1 And map(x, y) = 2 Then
- grid(x, y).track = thing(i) + Int(Rnd * 4)
- End If
- Loop
- Next j
- End If
- Next i
- Next round
-
- 'We've done changes so push to the undo buffer
- PushUndo
-
- modified = -1
- End If
-
- DrawTrack
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
- End Sub
- Sub Menu_Settings
- Dim top As Short, v As Short, akey As String, i As Short
- Dim As SelectorType theformat, thegrid, theconfview, theconfgen
- Dim As Integer xm, ym, wm, bm
- Dim content(1 To 4, 0 To 1) As String
- Dim pointed As Byte, previous As Byte, update As Byte
- Dim validtrack As Byte = -1, briefestwinning As Long
- Dim e As Byte, s As String, t As Double
- Dim switched_to_raw As Byte = 0
-
- GenerateSections
- If sections > 254 Or paths >= MAXPATHS Then
- validtrack = 0
- ElseIf paths = 0 Then
- validtrack = 0
- End If
- DetectTerrainErrors e, 0, 0
-
- If e >= 40 And e <= 49 Then validtrack = 0
-
- briefestwinning = 100000
- For i = 1 To paths
- If path(i).finishes Then
- Dim m As Long
-
- m = PathLength(i, 1)
- If m < briefestwinning Then briefestwinning = m
- End If
- Next i
- If briefestwinning = 100000 Then validtrack = 0
-
- MenuBox 37, 27, "Settings"
-
- lefx += 8 : ceny += 16
- top = ceny
-
- theformat.x1 = lefx
- theformat.x2 = lefx + 239
- theformat.y1 = top + 208
- theformat.y2 = top + 239
- theformat.options = 4
- theformat.opt(1) = "Def. format: One file"
- theformat.opt(2) = "Def. format: Split binary"
- theformat.opt(3) = "Def. format: Split text"
- theformat.opt(4) = "Def. format: Raw"
- Select Case default_format
- Case FORMAT_BINARY_SPLIT : theformat.current = 2
- Case FORMAT_TEXT_SPLIT : theformat.current = 3
- Case FORMAT_RAW : theformat.current = 4
- Case Else : theformat.current = 1
- End Select
- theformat.redraw = -1
-
- thegrid.x1 = lefx
- thegrid.x2 = lefx + 239
- thegrid.y1 = top + 256
- thegrid.y2 = top + 287
- thegrid.options = 2
- thegrid.opt(1) = "Grid ON at start up"
- thegrid.opt(2) = "Grid OFF at start up"
- If show_grid Then
- thegrid.current = 1
- Else
- thegrid.current = 2
- End If
- thegrid.redraw = -1
-
- theconfview.x1 = lefx + 304
- theconfview.x2 = lefx + 543
- theconfview.y1 = top + 208
- theconfview.y2 = top + 239
- theconfview.options = 2
- theconfview.opt(1) = "Show track tile conflicts"
- theconfview.opt(2) = "Hide track tile conflicts"
- If show_errors Then
- theconfview.current = 1
- Else
- theconfview.current = 2
- End If
- theconfview.redraw = -1
-
- theconfgen.x1 = lefx + 304
- theconfgen.x2 = lefx + 543
- theconfgen.y1 = top + 256
- theconfgen.y2 = top + 287
- theconfgen.options = 2
- theconfgen.opt(1) = "Allow producing conflicts"
- theconfgen.opt(2) = "Prevent tile conflicts"
- If allow_errors Then
- theconfgen.current = 1
- Else
- theconfgen.current = 2
- End If
- theconfgen.redraw = -1
-
-
- content(1, 0) = "Track path:"
- For i = 1 To dirlinks
- If Trim(LCase(dirlink(i).text)) = "tracks" Then
- content(1, 1) = Trim(dirlink(i).directory)
- Exit For
- End If
- Next i
- If content(1, 1) = "" Then content(1, 1) = track_path
-
- content(2, 0) = "Stunts path:"
- For i = 1 To dirlinks
- If Trim(LCase(dirlink(i).text)) = "stunts" Then
- content(2, 1) = Trim(dirlink(i).directory)
- Exit For
- End If
- Next i
-
- content(3, 0) = "Default author:"
- content(3, 1) = default_author
-
- If validtrack Then
- content(4, 0) = "Racer calibration time with THIS track (OWOOT, Porsche March Indy)"
- content(4, 1) = Timey(briefestwinning * racer_weigh)
- Else
- content(4, 0) = "Racer calibration time (race 4am.trk in OWOOT, Porsche March Indy):"
- content(4, 1) = Timey(LENGTHOF4AM * racer_weigh)
- End If
-
- For i = 1 To 4
- s = content(i, 1)
- TLeft , content(i, 0), RGB(200, 200, 200)
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- TLeft
- Next i
-
- ceny += 128
- buttons = 0
- StackButton " Cancel ", 2
- StackButton " Save ", 1
- EndOfButtonStack
-
- previous = -1
- Do
- GetMouse xm, ym, wm, bm
-
- If xm >= lefx - 4 And xm < lefx + 547 And ym >= top - 8 And ym < top + 184 Then
- pointed = (ym - top + 8) \ 48
- Else
- pointed = -1
- End If
-
- If pointed <> previous Or update <> 0 Then
- ScreenLock
- If previous <> -1 Then
- Line (lefx - 4, 48 * previous + top - 8)- Step (551, 47), RGB(30, 30, 50), BF
- ceny = 48 * previous + top
- s = content(previous + 1, 1)
- TLeft , content(previous + 1, 0), RGB(200, 200, 200)
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- End If
- If pointed <> -1 Then
- Line (lefx - 4, 48 * pointed + top - 8)- Step (551, 47), RGB(10, 10, 10), BF
- ceny = 48 * pointed + top
- s = content(pointed + 1, 1)
- TLeft , content(pointed + 1, 0), RGB(200, 200, 200)
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- End If
- ScreenUnlock
- previous = pointed
- End If
-
- If bm = 1 And pointed <> -1 Then
- stringer.init = -1
- stringer.maxlength = 64
- stringer.fileonly = 0
- stringer.x = lefx
- stringer.y = 48 * pointed + top + 16
- stringer.background = RGB(10, 10, 10)
-
- Do
- akey = ManageString(content(pointed + 1, 1))
- v = ManageButtons
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until akey = Chr(13) Or akey = Chr(27) Or v <> 0
- t = Timer
- Do : Loop Until Timer >= t + .3
- Do : Loop Until Len(InKey) = 0
-
- content(pointed + 1, 1) = Trim(content(pointed + 1, 1))
- If pointed = 0 And content(1, 1) = "" Then content(1, 1) = ExePath
- If pointed = 3 Then
- Dim cents As Long
-
- cents = AntiTimey(content(4, 1))
- If cents < 6000 Then cents = 6000
- If cents > 60000 Then cents = 60000
- content(4, 1) = Timey(cents)
- End If
- update = -1
- End If
-
- ManageSelector theformat
- ManageSelector thegrid
- ManageSelector theconfview
- ManageSelector theconfgen
- v = ManageButtons
- akey = InKey
- If STRONG_ANTI_HOG Then Sleep 1
-
- Select Case akey
- Case Chr(13) : v = 1 : Exit Do
- Case Chr(27) : v = 2 : Exit DO
- End Select
- Loop Until v
- buttons = 0
-
- DrawTrack
-
- 'Update configuration
- If v = 1 Then
- 'Update track directory
- content(1, 1) = Trim(content(1, 1))
- If Len(content(1, 1)) <> 0 And Right(content(1, 1), 1) <> DIR_DIVISOR Then content(1, 1) &= DIR_DIVISOR
- For i = 1 To dirlinks
- If Trim(LCase(dirlink(i).text)) = "tracks" Then
- dirlink(i).directory = content(1, 1)
- Exit For
- End If
- Next i
- If i > dirlinks Then
- dirlinks += 1
- dirlink(dirlinks).text = "Tracks"
- dirlink(dirlinks).directory = content(1, 1)
- End If
-
- 'Update Stunts directory
- If Len(content(1, 1)) <> 0 And Right(content(2, 1), 1) <> DIR_DIVISOR Then content(2, 1) &= DIR_DIVISOR
- For i = 1 To dirlinks
- If Trim(LCase(dirlink(i).text)) = "stunts" Then
- dirlink(i).directory = content(2, 1)
- Exit For
- End If
- Next i
- If i > dirlinks Then
- dirlinks += 1
- dirlink(dirlinks).text = "Stunts"
- dirlink(dirlinks).directory = content(2, 1)
- End If
-
- 'Update author
- default_author = Trim(content(3, 1))
-
- Dim ff As Integer
-
- ff = FreeFile
- Open program_path + "bliss.cfg" For Output As ff
- Print #ff, "; Bliss configuration file"
- Print #ff,
- Print #ff, "; Starting track directory. Bliss home directory by default"
- Print #ff, "tracks=" + content(1, 1)
- Print #ff,
- If dirlinks Then
- If dirlinks > 1 Or LCase(dirlink(1).text) <> "tracks" Then
- Print #ff, "; Other directories"
- For i = 1 To dirlinks
- Select Case Trim(LCase(dirlink(i).text))
- Case "tracks"
- Case "stunts" : Print #ff, "stunts=" + Trim(dirlink(i).directory)
- Case Else
- Print #ff, "dirlink=" + Trim(dirlink(i).text) + ":" + Trim(dirlink(i).directory)
- End Select
- Next i
- Print #ff,
- End If
- End If
- Print #ff, "; Default author name"
- If Len(content(3, 1)) = 0 Then
- Print #ff, "; author=Your Name"
- Else
- Print #ff, "author=" + content(3, 1)
- End If
- Print #ff,
- Print #ff, "; Racer speed calibration quotient"
- If validtrack Then
- racer_weigh = AntiTimey(content(4, 1)) / briefestwinning
- Else
- racer_weigh = AntiTimey(content(4, 1)) / LENGTHOF4AM
- End If
- Print #ff, "calibration="; racer_weigh
- Print #ff,
- Print #ff, "; Default format for new tracks"
-
- If theformat.current = 4 And default_format <> FORMAT_RAW Then switched_to_raw = -1
-
- Select Case theformat.current
- Case 1 : Print #ff, "format=bliss" : default_format = FORMAT_COMBINED
- Case 2 : Print #ff, "format=split" : default_format = FORMAT_BINARY_SPLIT
- Case 3 : Print #ff, "format=text" : default_format = FORMAT_TEXT_SPLIT
- Case 4 : Print #ff, "format=none" : default_format = FORMAT_RAW
- End Select
-
- Print #ff,
- Print #ff, "; Show grid at start time"
- If thegrid.current = 1 Then
- Print #ff, "grid=yes"
- Else
- Print #ff, "grid=no"
- End If
- Print #ff,
- Print #ff, "; Enable generating track conflicts (superpositions)"
- If theconfgen.current = 1 Then
- Print #ff, "superpositions=yes"
- Else
- Print #ff, "superpositions=no"
- End If
- Print #ff,
- Print #ff, "; Show terrain conflict warnings"
- If theconfview.current = 1 Then
- Print #ff, "warnings=yes"
- Else
- Print #ff, "warnings=no"
- End If
- Print #ff,
- Print #ff, "; Image format when saving a track-shot"
- Print #ff, "imageformat=" + imageformat
-
- Print #ff,
- Print #ff, "; Use curl in order to support https"
- If use_curl Then
- Print #ff, "curl=yes"
- Else
- Print #ff, "curl=no"
- End If
- Close ff
- End If
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
-
- If switched_to_raw Then
- MenuBox 28, 14, "Warning!"
- ceny += 16
- TCentre , "You are setting default format to RAW", RGB(200, 200, 240)
- ceny += 16
- TCentre , "Track title and author's name as well as", RGB(200, 200, 240)
- TCentre , "other metadata will be LOST if you save", RGB(200, 200, 240)
- TCentre , "your track in this format!", RGB(200, 200, 240)
- ceny += 24
-
- buttons = 0
- StackButton " OK "
- EndOfButtonStack
-
- Do
- v = ManageButtons
- Loop Until v <> 0 Or Len(InKey) <> 0
- buttons = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- Do : Loop Until Len(InKey) = 0
- DrawTrack
- End If
- End Sub
- Sub Menu_StartNewTrack
- Dim v As Short, akey As String
- Dim As Short x, y, i, top
- Dim As Integer xm, ym, wm, bm
- Dim ttitle(1 To 100) As String, terrain(1 To 100) As String
- Dim terrains As Short, first_terrain As Short
-
- MenuBox 28, 10, "Start New Track"
- ceny += 16
- TCentre , "Current track data will be lost!", RGB(200, 200, 240)
- TCentre , "Are you sure you want to clear the map?", RGB(200, 200, 240)
- ceny += 16
-
- StackButton " OK ", 1
- StackButton " Cancel ", 2, , 50
- EndOfButtonStack
- Do
- v = ManageButtons
- akey = InKey
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until v <> 0 Or akey <> ""
- buttons = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- DrawTrack
- DrawPanel
- If v <> 1 Then Exit Sub 'User cancelled
-
-
- '---------- Terrain selection
- MenuBox 35, 37, "Select Terrain"
-
- 'Load terrains
- Open program_path + "terrains.dat" For Binary Access Read As 100
- Get #100, 5, terrains
- For i = 1 To terrains
- Get #100, 2 * i + 5, v
- Seek #100, v
- Get #100, , v
- ttitle(i) = Space(v)
- Get #100, , ttitle(i)
- Get #100, , v
- terrain(i) = Space(v)
- Get #100, , terrain(i)
- Next i
- Close 100
-
-
- 'Clear grid
- For y = 1 To 30
- For x = 1 To 30
- grid(x, y).land = 0
- grid(x, y).track = 0
- grid(x, y).bgc = 0
- grid(x, y).border = 0
- Next x
- Next y
-
-
- Dim As Short selected_t, pointed_t, old_t
-
- ceny += 16
- top = ceny
- lefx += 240
- first_terrain = 1
- For i = first_terrain To first_terrain + 27
- TLeft , ttitle(i), RGB(160, 160, 240)
- Next i
- TLeft
- StackButton " Create Track ", 1
- EndOfButtonStack
-
- ScreenLock
- DrawBox lefx - 184, top, lefx - 184 + 135, top + 135
- Line (lefx - 176, top + 8)- Step (119, 119), RGB(0, 100, 0), BF
- ScreenUnlock
-
- old_t = 1
- selected_t = 1
- Do
- GetMouse xm, ym, wm, bm
- If xm >= lefx - 8 And xm < lefx + 272 And ym >= top And ym < top + 16 * terrains Then
- pointed_t = (ym - top) \ 16 + 1
- Else
- pointed_t = -1
- End If
-
- If pointed_t <> old_t Then
- ScreenLock
- If old_t <> -1 Then
- If old_t = selected_t Then Color RGB(160, 160, 240) Else Color RGB(30, 30, 50)
- Line (lefx - 8, top + 16 * (old_t - 1))- Step (271, 15), , BF
- If old_t = selected_t Then Color RGB(10, 10, 10) Else Color RGB(160, 160, 240)
- Draw String (lefx, top + 16 * (old_t - 1)), ttitle(old_t)
- End If
- If pointed_t <> -1 Then
- If pointed_t = selected_t Then Color RGB(160, 160, 240) Else Color RGB(30, 30, 50)
- Line (lefx - 8, top + 16 * (pointed_t - 1))- Step (271, 15), , BF
- If pointed_t = selected_t Then Color RGB(250, 250, 250) Else Color RGB(200, 200, 250)
- Draw String (lefx, top + 16 * (pointed_t - 1)), ttitle(pointed_t)
- End If
- ScreenUnlock
- old_t = pointed_t
- End If
-
- If bm = 1 And pointed_t <> -1 Then
- old_t = selected_t
- selected_t = pointed_t
- UnRLETerrain terrain(selected_t)
- ScreenLock
- For y = 1 To 30
- For x = 1 To 30
- Dim As ULong c1, c2
- Dim style As Byte
-
- Select Case grid(x, y).land
- Case 0 : style = 0 : c1 = RGB(0, 100, 0)
- Case 1 : style = 0 : c1 = RGB(0, 0, 100)
- Case 2 : style = 1 : c1 = RGB(0, 0, 100) : c2 = RGB(0, 100, 0)
- Case 3 : style = 2 : c1 = RGB(0, 100, 0) : c2 = RGB(0, 0, 100)
- Case 4 : style = 1 : c1 = RGB(0, 100, 0) : c2 = RGB(0, 0, 100)
- Case 5 : style = 2 : c1 = RGB(0, 0, 100) : c2 = RGB(0, 100, 0)
- Case 6 : style = 0 : c1 = RGB(0, 200, 0)
- Case 7, 10 : style = 0 : c1 = RGB(0, 160, 0)
- Case 8, 9 : style = 0 : c1 = RGB(0, 240, 0)
- Case 11 : style = 2 : c1 = RGB(0, 200, 0) : c2 = RGB(0, 100, 0)
- Case 12 : style = 1 : c1 = RGB(50, 255, 50) : c2 = RGB(0, 100, 0)
- Case 13 : style = 2 : c1 = RGB(0, 100, 0) : c2 = RGB(0, 200, 0)
- Case 14 : style = 1 : c1 = RGB(0, 100, 0) : c2 = RGB(0, 130, 0)
- Case 15 : style = 2 : c1 = RGB(0, 200, 0) : c2 = RGB(0, 220, 0)
- Case 16 : style = 1 : c1 = RGB(0, 200, 0) : c2 = RGB(50, 255, 50)
- Case 17 : style = 2 : c1 = RGB(0, 220, 0) : c2 = RGB(0, 200, 0)
- Case 18 : style = 1 : c1 = RGB(0, 130, 0) : c2 = RGB(0, 200, 0)
- Case Else : style = 0 : c1 = RGB(100, 0, 0)
- End Select
-
- Select Case style
- Case 0 : Line (lefx - 180 + 4 * x, top + 4 * y + 4)- Step (3, 3), c1, BF
- Case 1
- Line (lefx - 180 + 4 * x, top + 4 * y + 4)- Step (0, 3), c1
- Line - Step (3, 0), c1
- Line - Step (-3, -3), c1
- Paint Step (1, 2), c1
- Line (lefx - 180 + 4 * x, top + 4 * y + 4)- Step (3, 0), c2
- Line - Step (0, 3), c2
- Line - Step (-3, -3), c2
- Paint Step (2, 1), c2
- Case Else
- Line (lefx - 180 + 4 * x, top + 4 * y + 4)- Step (0, 3), c1
- Line - Step (3, -3), c1
- Line - Step (-3, 0), c1
- Paint Step (1, 1), c1
- Line (lefx - 180 + 4 * x + 3, top + 4 * y + 4)- Step (0, 3), c2
- Line - Step (-3, 0), c2
- Line - Step (3, -3), c2
- Paint Step (-1, 2), c2
- End Select
- Next x
- Next y
- ScreenUnlock
- End If
-
- v = ManageButtons
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until v <> 0 Or InKey = Chr(13)
- buttons = 0
-
-
- modified = 0
- track_file = ""
- landscape = 4
- thisfileformat = default_format
- format_byte = 152 'Fixed for Bliss
- Dim today As Double
- today = Now
- meta.title = ""
- meta.author = default_author
- meta.cyear = DatePart("yyyy", today)
- meta.cmonth = DatePart("m", today)
- meta.cday = DatePart("d", today)
- meta.tool = "Bliss"
- meta.toolversion = THISVERSION_NOPERIOD
- meta.comment = ""
- meta.championship = ""
- meta.editing_time = 0
- track_file = ""
- UpdateTitleBar
- started_editing = Timer
- PushUndo
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
-
- DrawTrack
- DrawPanel
- End Sub
- Sub Menu_LoadTrack
- Dim v As Short
- Dim As Integer xm, ym, wm, bm
- Dim As Short bx1, bx2, by1, by2
- Dim s As String, selected_track As String, akey As String
- Dim olds As String
-
- buttons = 0
- MenuBox 28, 28, "Load Track"
-
- bx1 = lefx + 8 : by1 = ceny : bx2 = lefx + 407 : by2 = ceny + 31
- DrawBox bx1, by1, bx2, by2
- InitFiles "trk;rpl", lefx + 8, ceny + 40, lefx + 407, ceny + 351
-
- cenx -= 16 : ceny += 40
-
- StackButton " Load ", 1, -1
- StackButton " Cancel ", 2, -1
- EndOfButtonStack
-
- selected_track = ""
- stringer.init = -1
- stringer.maxlength = 40
- stringer.fileonly = -1
- stringer.x = bx1 + 16
- stringer.y = by1 + 8
- stringer.background = RGB(30, 30, 50)
-
- #ifdef __FB_LINUX__ 'Empty keyboard buffer
- For i As Byte = 1 To 32
- akey = LinKey
- Next i
- #endif
-
- olds = ""
- Do
- v = ManageButtons
- s = selected_track
- akey = ManageString(selected_track)
- If s <> selected_track And Len(selected_track) <> 0 Then akey = Chr(1) + selected_track
- s = ManageFiles(akey)
- If STRONG_ANTI_HOG Then Sleep 1
-
- Select Case akey
- Case Chr(13)
- Do : Loop Until MultiKey(&H1C) = 0
- v = 1
- Case Chr(27)
- Do : Loop Until MultiKey(1) = 0
- v = 2
- End Select
-
- If Len(s) <> 0 And olds <> s Then
- selected_track = s
- stringer.cursor_pos = Len(s)
- ScreenLock
- DrawBox bx1, by1, bx2, by2
- Draw String (bx1 + 16, by1 + 8), s + Space(30 - Len(s)), RGB(160, 160, 240)
- ScreenUnlock
- olds = s
- End If
- Loop Until v = 1 Or v = 2
- buttons = 0
-
- #ifdef __FB_LINUX__
- Do : Loop Until LinKey = ""
- #endif
- Do : Loop Until InKey = ""
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- If v = 1 And Len(selected_track) <> 0 Then
- If InStr(selected_track, ".") = 0 Then selected_track = selected_track + ".trk"
- If FileExists(track_path + selected_track) Then
- LoadTrack track_path + selected_track
- track_file = selected_track
- DrawTrack
- PushUndo
- Else
- DrawTrack
- buttons = 0
- Error_Message "File not found or wrong name"
- End If
- Else
- DrawTrack
- End If
-
- DrawPanel
- End Sub
- Sub Menu_Analysis
- Dim As Integer xm, ym, wm, bm
- Dim As Short i, v
- Dim As Byte x, y, page
- Dim e As UByte
- Dim As Short winning, safe, cycles
- Dim As Short shortestsafe, shortestwinning, n
- Dim As Long briefestsafe, briefestwinning, m
- Dim As Byte flow_fatal, wrong_way
- Dim As Byte terrain_crash, terrain_fatal, terrain_warning
- Dim As ULong normal = RGB(160, 160, 240), bright = RGB(180, 180, 80)
- Dim As SelectorType current_car
-
- GenerateSections
- If sections > 254 Or paths >= MAXPATHS Then
- Error_Message "Track is too complex. Too many splits!"
- Exit Sub
- ElseIf paths = 0 Then
- Error_Message "Track has no valid path", "Track Analysis"
- Exit Sub
- End If
- DetectTerrainErrors e, x, y
-
- Select Case e
- Case 40 : terrain_crash = -1
- Case 41 To 49 : terrain_fatal = -1
- Case 50 To 59 : terrain_warning = -1
- End Select
-
- DetectNotStunts x, y, e
-
- shortestsafe = 10000
- shortestwinning = 10000
- briefestsafe = 1000000
- briefestwinning = 100000
- For i = 1 To paths
- If path(i).finishes Then
- winning += 1
- n = PathLength(i)
- m = PathLength(i, 1)
- If n < shortestwinning Then shortestwinning = n
- If m < briefestwinning Then briefestwinning = m
- If path(i).e = 0 Then
- safe += 1
- If n < shortestsafe Then shortestsafe = n
- If m < briefestsafe Then briefestsafe = m
- End If
- End If
- If path(i).e = 82 Then
- cycles += 1
- ElseIf path(i).e >= 70 And path(i).e <= 79 Then
- flow_fatal = -1
- End If
- Next i
-
- 'Load car selector
- current_car.options = cars
- current_car.current = activecar
- For i = 1 To UBound(current_car.opt)
- If i > cars Then Exit For
- current_car.opt(i) = car(i).cname
- Next i
- current_car.redraw = -1
- current_car.x1 = 512
- current_car.x2 = 719
- current_car.y1 = 200
- current_car.y2 = 223
-
- Do
- Select Case page
- Case 0 '----------------------------------------------
- Dim As Short xrecalc, yrecalc, sxrecalc, syrecalc
-
- MenuBox 30, 23, "Track Analysis"
- lefx += 8
- TLeft
-
- concolour = normal : TCont "Total paths: "
- concolour = bright : TCont Str(paths), -1
- concolour = normal : TCont "Winning paths: "
- concolour = bright : TCont Str(winning), -1
- If winning Then
- concolour = normal : TCont "Shortest winning path: "
- concolour = bright : TCont Str(shortestwinning) + " tiles", -1
- concolour = normal : TCont "Estimated winning time: "
- xrecalc = conx : yrecalc = cony
- concolour = bright : TCont Timey(briefestwinning * racer_weigh * car(activecar).handicap) + " (" + Trim(Str(briefestwinning)) + " tokens)", -1
- End If
- concolour = normal : TCont "Safe paths: "
- concolour = bright : TCont Str(safe), -1
- If safe Then
- concolour = normal : TCont "Shortest safe path: "
- concolour = bright : TCont Str(shortestsafe) + " tiles", -1
- concolour = normal : TCont "Estimated winning time on a safe path: "
- sxrecalc = conx : syrecalc = cony
- concolour = bright : TCont Timey(briefestsafe * racer_weigh * car(activecar).handicap), -1
- End If
- concolour = normal : TCont "Cycles: "
- concolour = bright : TCont Str(cycles), -1
- TCont "", -1
- concolour = normal : TCont "Prognosis:", -1
- concolour = bright
- If terrain_crash Then
- TCont "Stunts will crash because of terrain errors", -1
- ElseIf terrain_fatal Then
- TCont "Track will not run, due to terrain errors", -1
- ElseIf winning Then
- If flow_fatal Then
- TCont "Track will fail because of path flow error", -1
- ElseIf terrain_warning Then
- TCont "Track will run, but terrain problems may occur", -1
- ElseIf e Then
- TCont "Stunts will run the track. Using the internal", -1
- TCont "editor will corrupt it, though", -1
- Else
- TCont "Track will run fine", -1
- End If
- Else
- TCont "Track will fail because there's no winning path", -1
- End If
-
- concolour = normal : cony += 16
- current_car.y1 = cony - 3
- If winning Then TCont "Times estimated based on:"
-
- ceny += 248
- buttons = 0
- StackButton "See paths", 1
- If winning Then StackButton "See times", 2
- StackButton " OK ", 3
- EndOfButtonStack
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- current_car.redraw = -1
- current_car.x1 = 680
- current_car.x2 = current_car.x1 + 219
- current_car.y2 = current_car.y1 + 23
- Do
- If winning Then ManageSelector current_car
- If current_car.current <> activecar Then
- conx = xrecalc : cony = yrecalc
- Line (conx, cony)- Step (200, 15), RGB(30, 30, 50), BF
- concolour = bright
- activecar = current_car.current
- TCont Timey(briefestwinning * racer_weigh * car(activecar).handicap) + " (" + Trim(Str(briefestwinning)) + " tokens)", -1
- If sxrecalc Then
- conx = sxrecalc : cony = syrecalc
- Line (conx, cony)- Step (100, 15), RGB(30, 30, 50), BF
- TCont Timey(briefestsafe * racer_weigh * car(activecar).handicap), -1
- End If
- End If
- v = ManageButtons
-
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until v <> 0 Or Len(InKey) <> 0
- buttons = 0
- DrawTrack
- If v = 3 Or v = 0 Then Exit Do
- page = v
- Case 1 '------------------------------------------------
- Dim As Short first = 1, current = 1, top, ex, exfirst
- Dim pathdata(1 To paths, 2) As String
- Dim paintcol As ULong, update As Byte = -1
- Dim akey As String, exw As Integer
- Dim knob As Double, plen1 As Long, plen2 As Long
-
- For i = 1 To paths
- plen1 = PathLength(i)
- plen2 = PathLength(i, 1)
- pathdata(i, 0) = "Path " + Str(i) + ": " + Str(plen1) + " tiles - " + Timey(plen2 * racer_weigh * car(activecar).handicap)
- If path(i).finishes Then
- pathdata(i, 1) = "Complete"
- If path(i).e Then
- pathdata(i, 1) &= ", with warnings"
- Else
- pathdata(i, 1) &= ", safe"
- End If
- If plen1 = shortestwinning Then pathdata(i, 1) &= " (opp's path)"
- If plen2 = briefestwinning Then pathdata(i, 1) &= " - Fastest"
- Else
- pathdata(i, 1) = "Incomplete"
- If path(i).e = 72 Then
- pathdata(i, 1) &= ", wrong way"
- ElseIf section(ASC(Right(path(i).p, 1))).cycle Then
- pathdata(i, 1) &= ", cyclic"
- End If
- End If
- Next i
-
- MenuBox 30, 32, "Track Analysis"
-
- ceny += 16 : top = ceny
- lefx += 8
-
- ceny += 392
- buttons = 0
- StackButton "Follow path", 1
- If winning Then StackButton "See times", 2
- StackButton "Main page", 3
- StackButton " OK ", 4
- EndOfButtonStack
- Do
- GetMouse xm, ym, exw, bm
- Loop Until bm = 0
- Do
- If update Then
- ceny = top
- ScreenLock
- Line (lefx + 416, top)- Step (15, 359), RGB(30, 30, 50), BF
- Line (lefx + 423, top)- Step (1, 359), RGB(200, 200, 200), B
- If paths > 1 Then knob = (current - 1) / (paths - 1) Else knob = 0
- Line (lefx + 416, top + 344 * knob)- Step (15, 15), RGB(200, 200, 200), BF
- For i = first To first + 7
- If i > paths Then Exit For
- If i = current Then
- paintcol = RGB(10, 10, 10)
- Else
- paintcol = RGB(30, 30, 50)
- End If
- Line (lefx - 4, top + 48 * (i - first) - 4)- Step (379, 39), paintcol, BF
- TLeft , pathdata(i, 0), normal
- TLeft , pathdata(i, 1), bright
- TLeft
- Next i
- ScreenUnlock
- update = 0
- End If
-
- akey = InKey
- GetMouse xm, ym, wm, bm
- If STRONG_ANTI_HOG Then Sleep 1
-
- If bm = 1 Then
- ex = current : exfirst = first
- If xm >= lefx - 4 And xm < lefx + 376 And _
- ym >= top And ym < top + 380 Then
-
- current = first + (ym - top + 4) \ 48
- If current > paths Then current = paths
- If current > first + 7 Then current = first + 7
- End If
- If xm >= lefx + 416 And xm < lefx + 432 And _
- ym >= top And ym < top + 360 Then
-
- current = (ym - top) * paths / 360 + 1
- If current > paths Then current = paths
- If first > current Then
- first = current
- ElseIf current > first + 7 Then
- first = current - 7
- End If
- End If
- If current <> ex Or first <> exfirst Then update = -1
- End If
- If wm <> exw Then
- If wm > exw Then
- If first > 1 Then
- first -= 1
- If current > first + 7 Then current -= 1
- update = -1
- End If
- Else
- If first + 7 < paths Then
- first += 1
- If current < first Then current = first
- update = -1
- End If
- End If
- exw = wm
- End If
-
- Select Case akey
- Case Chr(255, 72)
- If current > 1 Then
- current -= 1
- If first > current Then first = current
- update = -1
- End If
- Case Chr(255, 80)
- If current < paths Then
- current += 1
- If first + 7 < current Then first += 1
- update = -1
- End If
- Case Chr(27) : v = 0 : Exit Do
- Case Chr(13) : v = 1 : Exit Do
- End Select
-
- v = ManageButtons
- If v <> 0 Then Exit Do
- Loop
- buttons = 0
- DrawTrack
- Select Case v
- Case 1
- FollowPath path(current).p
- drawkeyboardcursor = -1
- ManageKeyboardCursor -1
- Exit Do
- Case 2 : page = 2
- Case 3 : page = 0
- Case Else : Exit Do
- End Select
- Case 2 '----------------------------------------------
- Dim As Short xtimes, ytimes, ynorh
- Dim As String rhname(1 To 8), norhname(1 To 3)
- Dim As Single rhratio(1 To 8), norhratio(1 To 3)
- Dim i As Byte
-
- rhname(1) = "Duplode" : rhratio(1) = 6.8815
- rhname(2) = "Marco" : rhratio(2) = 6.8863
- rhname(3) = "FinRok" : rhratio(3) = 7.0758
- rhname(4) = "Zak McKracken" : rhratio(4) = 7.6161
- rhname(5) = "Cas" : rhratio(5) = 7.6255
- rhname(6) = "Nach" : rhratio(6) = 7.6588
- rhname(7) = "AbuRaf70" : rhratio(7) = 7.9953
- rhname(8) = "Shoegazing Leo" : rhratio(8) = 9.2796
-
- norhname(1) = "Marco" : norhratio(1) = 7.4313
- norhname(2) = "Duplode" : norhratio(2) = 7.6066
- norhname(3) = "Cas" : norhratio(3) = 8.3744
-
- MenuBox 30, 31, "Track Analysis"
-
- lefx += 112
- TLeft
- TCentre , "Estimated OWOOT times for famous racers", RGB(200, 200, 200)
- TLeft
- ytimes = cony : xtimes = conx + 160
- For i = 1 To 8
- concolour = normal
- TCont rhname(i)
- conx = xtimes
- concolour = bright
- TCont Timey(briefestwinning * rhratio(i) * car(activecar).handicap), 1
- Next i
-
- ceny += 144
- TLeft
- TCentre , "Estimated OWOOT NoRH times for famous racers", RGB(200, 200, 200)
- TLeft
- ynorh = cony
- For i = 1 To 3
- concolour = normal
- TCont norhname(i)
- conx = xtimes
- concolour = bright
- TCont Timey(briefestwinning * norhratio(i) * car(activecar).handicap), 1
- Next i
-
- ceny += 64
- TLeft
- TCentre , "Estimations based on selected car", RGB(200, 200, 200)
- TLeft
-
- current_car.options = cars
- For i = 1 To cars
- current_car.opt(i) = car(i).cname
- Next i
-
- current_car.redraw = -1
- current_car.x1 = cenx - 100
- current_car.x2 = current_car.x1 + 199
- current_car.y1 = ceny
- current_car.y2 = current_car.y1 + 23
-
- ceny += 48
- buttons = 0
- StackButton "Main page", 1
- StackButton "See paths", 2
- StackButton " OK ", 3
- EndOfButtonStack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- Do
- ManageSelector current_car
- If current_car.current <> activecar Then
- activecar = current_car.current
- concolour = bright
- cony = ytimes
- lefx = xtimes : conx = xtimes
- Line (xtimes, ytimes)- Step(79, 127), RGB(30, 30, 50), BF
- For i = 1 To 8
- TCont Timey(briefestwinning * rhratio(i) * car(activecar).handicap), 1
- Next i
- cony = ynorh
- Line (xtimes, ynorh)- Step(79, 47), RGB(30, 30, 50), BF
- For i = 1 To 3
- TCont Timey(briefestwinning * norhratio(i) * car(activecar).handicap), 1
- Next i
- End If
- v = ManageButtons
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until Len(InKey) <> 0 Or v <> 0
- buttons = 0
- DrawTrack
- Select Case v
- Case 1 : page = 0
- Case 2 : page = 1
- Case Else : Exit Do
- End Select
- End Select
- Loop
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
- End Sub
- Sub Menu_Colouring
- Dim updatecols As Byte, bluish As ULong
- Dim tempcol(0 To 23, 0 To 1) As ULong
- Dim As ULong r, g, b
- Dim As ULong temp_bgc, temp_border
- Dim As Integer xm, ym, bm, wm
- Dim As Byte kx, ky, usekeyboard
- Dim v As Short, akey As String, dy As Short
-
- temp_bgc = current_bgc
- temp_border = current_border
-
- For i As Short = 0 To 23
- tempcol(i, 0) = cpal(i)
- r = (cpal(i) ShR 16) And 255
- g = (cpal(i) ShR 8) And 255
- b = cpal(i) And 255
-
- tempcol(i, 1) = RGB(Int(.7 * r), Int(.7 * g), Int(.7 * b))
- Next i
- tempcol(0, 1) = 0
-
- bluish = RGB(160, 160, 240)
-
- MenuBox 36, 24, "Colouring"
-
- dy = ceny
-
- TLeft
- TLeft , " Border colour"
- TLeft
- TLeft , " Red", bluish
- TLeft , " Green", bluish
- TLeft , " Blue", bluish
- TLeft
- TLeft
-
- TLeft , " Background colour"
- TLeft
- TLeft , " Red", bluish
- TLeft , " Green", bluish
- TLeft , " Blue", bluish
- TLeft
- TLeft
- TLeft , " Preview"
- TLeft
- TLeft
-
- buttons = 0
- StackButton " Set colours ", 1
- StackButton " Clear ", 2
- StackButton " Uncolour map ", 3
- StackButton " Cancel ", 4
- EndOfButtonStack
-
- updatecols = -1
- Do
- If updatecols <> 0 Then
- ScreenLock
- For i As Short = 0 To 1
- Dim c As ULong
-
- If i Then c = temp_bgc Else c = temp_border
-
- For j As Short = 0 To 2
- Dim reg As UByte
-
- Line (494, 112 * i + 20 * j + 46 + dy)- Step (266, 10), RGB(30, 30, 50), BF
- Line (500, 112 * i + 20 * j + 50 + dy)- Step (255, 2), RGB(128, 128, 128), BF
- Select Case j
- Case 0 : reg = (c And &HFF0000) ShR 16
- Case 1 : reg = (c And &HFF00) ShR 8
- Case Else : reg = c And 255
- End Select
- Circle (500 + reg, 112 * i + 20 * j + 51 + dy), 4, RGB(200, 200, 200), , , , F
- Next j
-
- For j As Short = 0 To 3
- For k As Short = 0 To 5
- If j + k = 0 Then
- Line (24 * k + 790, 112 * i + 24 * j + 16 + dy)- Step (22, 22), RGB(128, 128, 128), B
- Line (24 * k + 791, 112 * i + 24 * j + 17 + dy)- Step (20, 20), RGB(30, 30, 50), BF
- Else
- Line (24 * k + 790, 112 * i + 24 * j + 16 + dy)- Step (22, 22), tempcol(6 * j + k, i), BF
- End If
- If usekeyboard AndAlso kx = k And ky = 4 * i + j Then
- Line (24 * k + 795, 112 * i + 24 * j + 21 + dy)- Step (12, 12), RGB(200, 200, 200), B
- Line (24 * k + 796, 112 * i + 24 * j + 22 + dy)- Step (10, 10), RGB(0, 0, 0), B
- End If
- Next k
- Next j
- Next i
-
- If temp_bgc Then
- Line (510, 238 + dy)- Step (21, 21), temp_bgc, BF
- If temp_border Then
- Line (510, 238 + dy)- Step (21, 21), temp_border, B
- Line (511, 239 + dy)- Step (19, 19), temp_border, B
- End If
- Else
- Line (510, 238 + dy)- Step (21, 21), RGB(30, 30, 50), BF
- If temp_border = 0 Then
- Line (510, 238 + dy)- Step (21, 21), RGB(128, 128, 128), B, &H5555
- Else
- Line (510, 238 + dy)- Step (21, 21), temp_border, B
- Line (511, 239 + dy)- Step (19, 19), temp_border, B
- End If
- End If
- ScreenUnlock
-
- updatecols = 0
- End If
-
- GetMouse xm, ym, wm, bm
- akey = InKey
- If STRONG_ANTI_HOG Then Sleep 1
-
- If bm = 1 Then
- If xm >= 500 And xm <= 755 Then
- Select Case ym
- Case 46 + dy To 65 + dy 'Update border red
- temp_border And= &HFF00FFFF
- r = (xm - 500) ShL 16
- temp_border Or= r
- updatecols = -1
- Case 66 + dy To 85 + dy 'Update border green
- temp_border And= &HFFFF00FF
- g = (xm - 500) ShL 8
- temp_border Or= g
- updatecols = -1
- Case 86 + dy To 105 + dy 'Update border blue
- temp_border And= &HFFFFFF00
- b = (xm - 500)
- temp_border Or= b
- updatecols = -1
- Case 158 + dy To 177 + dy 'Update background red
- temp_bgc And= &HFF00FFFF
- r = (xm - 500) ShL 16
- temp_bgc Or= r
- updatecols = -1
- Case 178 + dy To 197 + dy 'Update background green
- temp_bgc And= &HFFFF00FF
- g = (xm - 500) ShL 8
- temp_bgc Or= g
- updatecols = -1
- Case 198 + dy To 217 + dy 'Update background blue
- temp_bgc And= &HFFFFFF00
- b = (xm - 500)
- temp_bgc Or= b
- updatecols = -1
- End Select
- Elseif xm >= 790 And ym >= 16 + dy And xm < 934 And ym < 112 + dy Then
- temp_border = tempcol((xm - 790) \ 24 + 6 * ((ym - 16 - dy) \ 24), 0)
- updatecols = -1
- ElseIf xm >= 790 And ym >= 332 And xm < 934 And ym < 224 + dy Then
- temp_bgc = tempcol((xm - 790) \ 24 + 6 * ((ym - 128 - dy) \ 24), 1)
- updatecols = -1
- End If
- End If
-
- v = ManageButtons
-
- Select Case akey
- Case Chr(255, 72)
- If ky > 0 Then ky -= 1 : updatecols = -1
- usekeyboard = -1
- Case Chr(255, 80)
- If ky < 7 Then ky += 1 : updatecols = -1
- usekeyboard = -1
- Case Chr(255, 77)
- If kx < 5 Then kx += 1 : updatecols = -1
- usekeyboard = -1
- Case Chr(255, 75)
- If kx > 0 Then kx -= 1 : updatecols = -1
- usekeyboard = -1
- Case Chr(13)
- Dim tb As ULong
- If ky >= 4 Then
- tb = tempcol(6 * (ky - 4) + kx, 1)
-
- If temp_bgc = tb Then
- v = 1
- Else
- temp_bgc = tb
- End If
- Else
- tb = tempcol(6 * ky + kx, 0)
-
- If temp_border = tb Then
- v = 1
- Else
- temp_border = tb
- End If
- End If
- updatecols = -1
- usekeyboard = -1
- Case "C", "c", Chr(3) : v = 2
- Case Chr(0, 83), Chr(8) : v = 3
- Case Chr(27) : v = 4
- End Select
-
- If v Then
- Select Case v
- Case 1 'Set colours
- current_bgc = temp_bgc
- current_border = temp_border
- Exit Do
- Case 2 'Clear
- temp_bgc = 0
- temp_border = 0
- updatecols = -1
- Case 3 'Uncolour map
- For j As Byte = 1 To 30
- For i As Byte = 1 To 30
- grid(i, j).border = 0
- grid(i, j).bgc = 0
- Next i
- Next j
- PushUndo
- Exit Do
- Case 4 'Cancel
- Exit Do
- End Select
- End If
- Loop
-
- buttons = 0
-
- Do
- GetMouse 0, 0, 0, bm
- Loop Until bm = 0
-
- DrawTrack
- DrawPanel
-
- Do : Loop Until Len(InKey) = 0
- End Sub
- Sub Menu_Help
- Dim top As Short, page As Byte = 3
- Dim v As Short, f AS Integer, fline As Short = 1
- Dim maline(1 To 1500) As String, malines As Short = 0
-
- If FileExists(program_path & "manual.txt") Then
- f = FreeFile
- Open program_path & "manual.txt" For Input As f
- Do Until EoF(f)
- malines += 1
- Line Input #f, maline(malines)
- maline(malines) = Left(maline(malines), 72)
- Loop
- Close f
- End If
-
- Dim akey As String, idletimer As Double
- idletimer = Timer
-
- Do
- Select Case page
- Case 1
- MenuBox 30, 38, "Help - Option keys"
-
- TLeft
-
- top = ceny
- lefx += 8
-
- TLeft , "F1 - F12", RGB(180, 180, 80)
- TLeft , " Ctrl-Q", RGB(180, 180, 80)
- TLeft , " Ctrl-E", RGB(180, 180, 80)
- TLeft , " Ctrl-D", RGB(180, 180, 80)
- TLeft , " Ctrl-G", RGB(180, 180, 80)
- TLeft , " Ctrl-R", RGB(180, 180, 80)
- TLeft , " Ctrl-S", RGB(180, 180, 80)
- TLeft , " Ctrl-T", RGB(180, 180, 80)
- TLeft , " Ctrk-K", RGB(180, 180, 80)
- TLeft , " Ctrl-O", RGB(180, 180, 80)
- TLeft , " Ctrl", RGB(180, 180, 80)
- TLeft , " Ctrl-W", RGB(180, 180, 80)
- TLeft , " Ctrl-C", RGB(180, 180, 80)
- TLeft , " Ctrl-X", RGB(180, 180, 80)
- TLeft , " Ctrl-V", RGB(180, 180, 80)
- TLeft , " F", RGB(180, 180, 80)
- TLeft , " Shift-F", RGB(180, 180, 80)
- TLeft , " R", RGB(180, 180, 80)
- TLeft , " Shift-R", RGB(180, 180, 80)
- TLeft , " Ctrl-Z", RGB(180, 180, 80)
- TLeft , " Ctrl-Y", RGB(180, 180, 80)
- TLeft , " U", RGB(180, 180, 80)
- TLeft , " C", RGB(180, 180, 80)
- TLeft , " Arrows", RGB(180, 180, 80)
- TLeft , " Tab", RGB(180, 180, 80)
- TLeft , " Enter", RGB(180, 180, 80)
- TLeft , " Del", RGB(180, 180, 80)
- TLeft , " P", RGB(180, 180, 80)
- TLeft , " \", RGB(180, 180, 80)
-
- ceny = top
- lefx += 80
-
- TLeft , "Select palette page (2xF1 for help)", RGB(160, 160, 240)
- TLeft , "Toggle debug mode", RGB(160, 160, 240)
- TLeft , "Allow/disallow conflict generation", RGB(160, 160, 240)
- TLeft , "Toggle conflict-warning display", RGB(160, 160, 240)
- TLeft , "Display/hide grid", RGB(160, 160, 240)
- TLeft , "Redraw track", RGB(160, 160, 240)
- TLeft , "Take a track-shot", RGB(160, 160, 240)
- TLeft , "Toggle terrain affected by paste", RGB(160, 160, 240)
- TLeft , "Toggle track affected by paste", RGB(160, 160, 240)
- TLeft , "Toggle colouring mode", RGB(160, 160, 240)
- TLeft , "Select by dragging with left mouse button", RGB(160, 160, 240)
- TLeft , "Select/Deselect the whole grid", RGB(160, 160, 240)
- TLeft , "Copy selection", RGB(160, 160, 240)
- TLeft , "Cut selection", RGB(160, 160, 240)
- TLeft , "Paste clipboard", RGB(160, 160, 240)
- TLeft , "Flip horizontally", RGB(160, 160, 240)
- TLeft , "Flip vertically", RGB(160, 160, 240)
- TLeft , "Rotate clockwise", RGB(160, 160, 240)
- TLeft , "Rotate counter-clockwise", RGB(160, 160, 240)
- TLeft , "Undo", RGB(160, 160, 240)
- TLeft , "Redo", RGB(160, 160, 240)
- TLeft , "Link tiles at pointer/keyboard cursor", RGB(160, 160, 240)
- TLeft , "Check track for errors", RGB(160, 160, 240)
- TLeft , "Move keyboard cursor", RGB(160, 160, 240)
- TLeft , "Switch between the grid and the palette", RGB(160, 160, 240)
- TLeft , "Paste current element/Create closed-circuit", RGB(160, 160, 240)
- TLeft , "Delete at keyboard cursor or selection", RGB(160, 160, 240)
- TLeft , "Pick element at keyboard cursor position", RGB(160, 160, 240)
- TLeft , "In manual mode, select element by hex typing", RGB(160, 160, 240)
-
- TLeft
- TLeft
- buttons = 0
- StackButton " User Manual ", 3
- StackButton " Tile Shorcuts ", 2
- StackButton " Back ", 1
- EndOfButtonStack
-
- Dim As Integer xm, ym, wm, bm
-
- Do
- v = ManageButtons
- GetMouse xm, ym, wm, bm
- akey = InKey
-
- 'This is to prevent the program from hogging the CPU
- If xm <> -1 Or Len(akey) <> 0 Then idletimer = Timer
- If Timer > idletimer + 1 Then Sleep 500
-
- Select Case akey
- Case Chr(27) : v = 1 : Exit Do
- Case Chr(13) : v = 2 : Exit Do
- End Select
- Loop Until v <> 0
- buttons = 0
-
- If v = 1 Then page = -1 Else page = v
- Case 2
- MenuBox 30, 29, "Help - Tile shortcuts"
-
- TLeft
-
- top = ceny
- lefx += 8
-
- TLeft , " Space", RGB(180, 180, 80)
- TLeft , " A", RGB(180, 180, 80)
- TLeft , " B", RGB(180, 180, 80)
- TLeft , " D", RGB(180, 180, 80)
- TLeft , " E", RGB(180, 180, 80)
- TLeft , " G", RGB(180, 180, 80)
- TLeft , " H", RGB(180, 180, 80)
- TLeft , " I", RGB(180, 180, 80)
- TLeft , " J", RGB(180, 180, 80)
- TLeft , " K", RGB(180, 180, 80)
- TLeft , " L", RGB(180, 180, 80)
- TLeft , " M", RGB(180, 180, 80)
- TLeft , " N", RGB(180, 180, 80)
- TLeft , " O", RGB(180, 180, 80)
- TLeft , " Q", RGB(180, 180, 80)
- TLeft , " S", RGB(180, 180, 80)
- TLeft , " T", RGB(180, 180, 80)
- TLeft , " V", RGB(180, 180, 80)
- TLeft , " W", RGB(180, 180, 80)
- TLeft , " X, Y, Z", RGB(180, 180, 80)
-
- ceny = top
- lefx += 80
-
- TLeft , "Find element by name", RGB(160, 160, 240)
- TLeft , "Banked road", RGB(160, 160, 240)
- TLeft , "Boulevard (highway)", RGB(160, 160, 240)
- TLeft , "Split (detour)", RGB(160, 160, 240)
- TLeft , "Elevated road", RGB(160, 160, 240)
- TLeft , "Spin (cork up/down)", RGB(160, 160, 240)
- TLeft , "Chicane", RGB(160, 160, 240)
- TLeft , "Pipe", RGB(160, 160, 240)
- TLeft , "Ramp (jump)", RGB(160, 160, 240)
- TLeft , "Crossroad", RGB(160, 160, 240)
- TLeft , "Loop", RGB(160, 160, 240)
- TLeft , "Change material", RGB(160, 160, 240)
- TLeft , "Scenery", RGB(160, 160, 240)
- TLeft , "Start/Finish line", RGB(160, 160, 240)
- TLeft , "Corner", RGB(160, 160, 240)
- TLeft , "Straightway", RGB(160, 160, 240)
- TLeft , "Tunnel and slalom", RGB(160, 160, 240)
- TLeft , "Transitions", RGB(160, 160, 240)
- TLeft , "Corkscrew", RGB(160, 160, 240)
- TLeft , "Side, bottom and corner fillers", RGB(160, 160, 240)
-
-
- TLeft
- TLeft
- buttons = 0
- StackButton " User Manual ", 3
- StackButton " Option Keys ", 2
- StackButton " Back ", 1
- EndOfButtonStack
-
- Dim As Integer xm, ym, wm, bm
-
- Do
- v = ManageButtons
- GetMouse xm, ym, wm, bm
- akey = InKey
-
- 'This is to prevent the program from hogging the CPU
- If xm <> -1 Or Len(akey) <> 0 Then idletimer = Timer
- If Timer > idletimer + 1 Then Sleep 500
-
- Select Case akey
- Case Chr(27) : v = 1 : Exit Do
- Case Chr(13) : v = 3 : Exit Do
- End Select
- Loop Until v <> 0
- buttons = 0
-
- If v = 1 Then
- page = -1
- ElseIf v = 2 Then
- page = 1
- Else
- page = 3
- End If
- Case 3
- Dim As Integer w, exw, x, y, b
- Dim drlines As Short = 33
- Dim exfline As Short = 0, s As String, n As Short
-
- MenuBox 38, 40, "Help - User Manual"
-
- top = ceny
- ceny += 512
- TLeft
- TLeft
- buttons = 0
- StackButton " Tile Shortcuts ", 2
- StackButton " Option Keys ", 1
- StackButton " Back ", 3
- EndOfButtonStack
-
- GetMouse x, y, w
- exw = w
-
- Do
- If fline <> exfline Then
- ceny = top
- Line (xoffs + 40, top)- Step (73 * 8, 33 * 16), RGB(30, 30, 50), BF
- For i As Short = 0 To drlines - 1
- s = Trim(maline(fline + i))
- n = InStr(s, ".")
- If n > 1 And n <= 4 And ValInt(s) > 0 Then
- TLeft , maline(fline + i), RGB(180, 180, 80)
- Else
- TLeft , maline(fline + i), RGB(160, 160, 240)
- End If
- Next i
- exfline = fline
- End If
-
- v = ManageButtons
- GetMouse x, y, w, b
- akey = InKey
- If w <> - 1 AndAlso w <> exw Then
- If w < exw Then akey = Chr(255, 80) Else akey = Chr(255, 72)
- exw = w
- End If
-
- If b = 1 AndAlso x > xoffs + 330 - 80 _
- AndAlso x < xoffs + 300 + 80 AndAlso y >= top Then
-
- Dim m As Short
-
- m = (y - top) \ 16 + fline
- If m <= malines Then
- s = Trim(maline(m))
- n = InStr(s, ".")
- If n > 0 And n <= 3 And ValInt(s) Then
- For i As Short = 1 To malines
- If Trim(maline(i)) = "." & ValInt(s) & "." Then
- fline = i
- Exit For
- End If
- Next i
- If fline + drlines - 1 > malines Then fline = malines - drlines + 1
- End If
- End If
- End If
-
- 'This is to prevent the program from hogging the CPU
- If x <> -1 Or Len(akey) <> 0 Then idletimer = Timer
- If Timer > idletimer + 1 Then Sleep 500
-
- Select Case akey
- Case Chr(255, 72)
- If fline > 1 Then fline -= 1
- Case Chr(255, 80)
- If fline + drlines - 1 < malines Then fline += 1
- Case Chr(255, 73)
- fline -= 30
- If fline < 1 Then fline = 1
- Case Chr(255, 81)
- fline += 30
- If fline + drlines - 1 > malines Then fline = malines - drlines + 1
- Case Chr(255, 71)
- fline = 1
- Case Chr(255, 79)
- fline = malines - drlines + 1
- Case Chr(27) : v = 3 : Exit Do
- Case Chr(13) : v = 1 : Exit Do
- End Select
- Loop Until v <> 0
-
- buttons = 0
- If v = 3 Then page = -1 Else page = v
- End Select
-
- Dim bm As Integer
- Do
- GetMouse 0, 0, 0, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
- DrawTrack
- Loop Until page = -1
- End Sub
- Sub Menu_License
- Dim As Integer xm, ym, wm, bm
- Dim v As Short
-
- MenuBox 27, 32, "Bliss " + THISVERSION '+ Chr(225)
-
- TCentre , "Track editor for Stunts v1.0 and v1.1", RGB(160, 160, 240)
- TCentre , "Copyright (c) 2016-" & Left(__DATE_ISO__, 4) & " - Lucas Pedrosa", RGB(160, 160, 240)
- TCentre
- TCentre , "This program comes with ABSOLUTELY NO WARRANTY.", RGB(160, 160, 240)
- TCentre , "This is free software and you are welcome", RGB(160, 160, 240)
- TCentre , "to redistribute it under the conditions of the", RGB(160, 160, 240)
- TCentre , "GNU GPLv3 license. For more information on this", RGB(160, 160, 240)
- TCentre , "license, read the file license.txt that comes", RGB(160, 160, 240)
- TCentre , "included or visit http://www.gnu.org/licenses/", RGB(160, 160, 240)
- TCentre
- TCentre , "Thank you for using my editor!!", RGB(160, 160, 240)
- TCentre , "Bliss is dedicated especially to the", RGB(160, 160, 240)
- TCentre , "Stunts racing community, to the tournament", RGB(160, 160, 240)
- TCentre , "organisers and to the people of DSI, creators", RGB(160, 160, 240)
- TCentre , "of Stunts, a magnificent game.", RGB(160, 160, 240)
- TCentre , "Special thanks go to Duplode, for the amazing", RGB(160, 160, 240)
- TCentre , "feedback and effort in beta-testing during the", RGB(160, 160, 240)
- TCentre , "different stages of development.", RGB(160, 160, 240)
- TCentre
- TCentre
- TCentre , "Contact:", RGB(160, 160, 240)
- TCentre , "xlucas@mailo.com", RGB(50, 200, 240)
- TCentre
- TCentre , "Website:", RGB(160, 160, 240)
- TCentre , "http://www.raceforkicks.com/bliss", RGB(50, 200, 240)
- TCentre
-
- buttons = 0
- StackButton " Continue ", 1
- EndOfButtonStack
-
- Dim idletimer as Double, akey As String
- idletimer = Timer
- Do
- v = ManageButtons
- akey = InKey
- 'This is to prevent the program from hogging the CPU
- If xm <> -1 Or Len(akey) <> 0 Then idletimer = Timer
- If Timer > idletimer + 1 Then Sleep 500
- Loop Until v = 1 Or akey <> ""
- buttons = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- DrawTrack
- End Sub
- Sub Menu_SaveTrack
- Dim v As Short
- Dim As Integer xm, ym, wm, bm
- Dim As Short bx1, bx2, by1, by2
- Dim s As String, selected_track As String, akey As String
- Dim olds As String
- Dim sel As SelectorType
-
- buttons = 0
- MenuBox 28, 28, "Save Track"
- bx1 = lefx + 8 : by1 = ceny : bx2 = lefx + 407 : by2 = ceny + 31
- DrawBox bx1, by1, bx2, by2
- InitFiles "trk;rpl", lefx + 8, ceny + 40, lefx + 407, ceny + 351
-
- cenx -= 16 : ceny += 40
-
- sel.redraw = -1
- Select Case thisfileformat
- Case FORMAT_RAW : sel.current = 4 'On request by Dreadnaut
- Case FORMAT_COMBINED : sel.current = 1
- Case FORMAT_BINARY_SPLIT : sel.current = 2
- Case FORMAT_TEXT_SPLIT : sel.current = 3
- Case Else 'Just in case I add a format or something
- sel.current = 1
- End Select
-
- sel.opt(1) = "One file"
- sel.opt(2) = "Binary split"
- sel.opt(3) = "Text split"
- sel.opt(4) = "Raw (no metadata)"
- sel.options = 4
- sel.y1 = ceny
- sel.y2 = sel.y1 + 31
- sel.x1 = cenx - 24 * 16
- sel.x2 = sel.x1 + 160
-
- StackButton " Save ", 1, -1
- StackButton " Cancel ", 2, -1
- EndOfButtonStack
-
- selected_track = track_file
- stringer.init = -1
- stringer.maxlength = 40
- stringer.fileonly = -1
- stringer.x = bx1 + 16
- stringer.y = by1 + 8
- stringer.background = RGB(30, 30, 50)
-
- #ifdef __FB_LINUX__ 'Empty keyboard buffer
- For i As Byte = 1 To 32
- akey = LinKey
- Next i
- #endif
-
- olds = ""
- Do
- v = ManageButtons
- ManageSelector sel
-
- s = selected_track
- akey = ManageString(selected_track)
- If s <> selected_track And Len(selected_track) <> 0 Then akey = Chr(1) + selected_track
- s = ManageFiles(akey)
- If STRONG_ANTI_HOG Then Sleep 1
-
- Select Case akey
- Case Chr(13)
- v = 1
- Do : Loop Until MultiKey(&H1D) = 0
- Case Chr(27)
- v = 2
- Do : Loop Until MultiKey(1) = 0
- End Select
-
- If Len(s) <> 0 And olds <> s Then
- selected_track = s
- stringer.cursor_pos = Len(s)
- ScreenLock
- DrawBox bx1, by1, bx2, by2
- Draw String (bx1 + 16, by1 + 8), s + Space(30 - Len(s)), RGB(160, 160, 240)
- ScreenUnlock
- olds = s
- End If
- Loop Until (v = 1 And Len(selected_track) <> 0) Or v = 2
- buttons = 0
-
- #ifdef __FB_LINUX__
- Do : Loop Until LinKey = ""
- #endif
- Do : Loop Until InKey = ""
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- If v = 1 And Len(selected_track) <> 0 Then
- If InStr(selected_track, ".") = 0 Then selected_track = selected_track + ".trk"
- If FileExists(track_path + selected_track) Then
- DrawTrack
- MenuBox 28, 10, "Warning!"
- ceny += 16
- If sel.current = 4 Then
- TCentre , "An image with that name already exists.", RGB(200, 200, 240)
- Else
- TCentre , "A track with that name already exists.", RGB(200, 200, 240)
- End If
- TCentre , "Are you sure you want to OVERWRITE it?", RGB(200, 200, 240)
- ceny += 16
-
- buttons = 0
- StackButton " SAVE ", 1, , 50
- StackButton " Cancel ", 2, , 50
- EndOfButtonStack
- Do
- v = ManageButtons
- akey = InKey
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until v <> 0 Or akey <> ""
- buttons = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- If v = 1 Then
- If sel.current = 1 Then
- thisfileformat = FORMAT_COMBINED
- ElseIf sel.current = 2 Then
- thisfileformat = FORMAT_BINARY_SPLIT
- ElseIf sel.current = 3 Then
- thisfileformat = FORMAT_TEXT_SPLIT
- Else
- thisfileformat = FORMAT_RAW 'Do not save meta-data
- End If
- SaveTrack track_path + selected_track
- track_file = selected_track
- End If
- Else
- If Open(track_path + selected_track For Output As 101) Then
- DrawTrack
- buttons = 0
- Error_Message "Invalid track file name"
- Else
- Close 101
- If Right(LCase(selected_track), 4) = ".rpl" Then
- DrawTrack
- buttons = 0
- Error_Message "Can't write to replay if it doesn't exist"
- Else
- If sel.current = 1 Then
- thisfileformat = FORMAT_COMBINED
- ElseIf sel.current = 2 Then
- thisfileformat = FORMAT_BINARY_SPLIT
- ElseIf sel.current = 3 Then
- thisfileformat = FORMAT_TEXT_SPLIT
- Else
- thisfileformat = FORMAT_RAW 'Do not save meta-data
- End If
- SaveTrack track_path + selected_track
- track_file = selected_track
- End If
- End If
- End If
- End If
-
- DrawTrack
- DrawPanel
- End Sub
- Sub LinkTiles
- Dim As Short xr, yr, i, j, n, v
- Dim As Integer xm, ym, wm, bm
- Dim connector(0 To 3) As Byte, connectors As Byte
-
- GetMouse xm, ym, wm, bm
- If drawkeyboardcursor Then
- xr = xcursor
- yr = ycursor
- ElseIf xm >= xoffs And ym >= yoffs Then
- xr = (xm - xoffs) \ bigwidth + 1
- yr = (ym - yoffs) \ 22 + 1
- If xr > 30 Or yr > 30 Then Exit Sub
- End If
-
- v = GetParent(xr, yr)
-
- 'First try to find a 1x1 tile
- If yr > 1 Then
- connector(0) = tr(GetParent(xr, yr - 1)).ctype(2)
- If connector(0) Then connectors += 1
- End If
- If xr < 30 Then
- connector(1) = tr(GetParent(xr + 1, yr)).ctype(3)
- If connector(1) Then connectors += 1
- End If
- If yr < 30 Then
- connector(2) = tr(GetParent(xr, yr + 1)).ctype(0)
- If connector(2) Then connectors += 1
- End If
- If xr > 1 Then
- connector(3) = tr(GetParent(xr - 1, yr)).ctype(1)
- If connector(3) Then connectors += 1
- End If
- If connectors >= 2 Then
- For i = v + 1 To v + 256
- n = i Mod 256
- If tr(n).w = 1 And tr(n).h = 1 Then
- If tr(n).ctype(0) = connector(0) And tr(n).ctype(1) = connector(1) _
- And tr(n).ctype(2) = connector(2) And tr(n).ctype(3) = connector(3) Then
-
- PushUndo
- SetTrack xr, yr, n
- Exit Sub
- End If
- End If
- Next i
- End If
- End Sub
- #ifdef __FB_LINUX__
- Sub LKinitialise
- ScreenControl FB.GET_WINDOW_HANDLE, LKwindow
- LKdisp = XOpenDisplay(0)
- XSelectInput LKdisp, LKwindow, KeyPressMask Or KeyReleaseMask
- End Sub
- Function Linkey As String
- Dim tempkey As Long 'KeySym type seems to be a Long
-
- If Not LKinitialised Then
- LKinitialise
- LKinitialised = -1
- End If
-
- If XPending(LKdisp) Then
- XNextEvent LKdisp, @LKevent
- If LKevent.type = KeyPress Then
- 'XLookupString fills only as many bytes as necessary, so
- 'the string has to be zeroed to prevent trailing bytes from
- 'the last query to populate in the next if shorter
- LKstring = String(25, 0)
- XLookupString @LKevent.xkey, @LKstring, 25, @LKsym, 0
-
- tempkey = XLookupKeysym(@LKevent.xkey, 0)
- 'If tempkey = XK_Alt_L Or tempkey = XK_Alt_R Then LKaltpressed = -1
-
- If Len(LKstring) Then
- Return LKstring
- Else
- Return Chr(0) & MkL(tempkey)
- End If
- End If
- Else
- Return ""
- End If
- End Function
- #endif
- Sub LoadConfiguration
- Dim s As String, n As UShort
- Dim As String param, value
-
- default_author = "Anonymous"
- imageformat = "tga"
- Open program_path + "bliss.cfg" For Input As 100
- Do While Not EOF(100)
- Line Input #100, s
- s = Trim(s)
- n = InStr(s, ";")
- If n Then s = Left(s, n - 1)
- n = InStr(s, "=")
- If n Then
- param = LCase(Trim(Left(s, n - 1)))
- value = Trim(Mid(s, n + 1))
-
- Select Case param
- Case "track", "tracks"
- track_path = value
- If Right(track_path, 1) <> "/" And Right(track_path, 1) <> "\" Then
- #ifdef __FB_LINUX__
- track_path = track_path + "/"
- #else
- track_path = track_path + "\"
- #endif
- End If
- If dirlinks < 10 Then
- dirlinks += 1
- dirlink(dirlinks).text = "Tracks"
- dirlink(dirlinks).directory = track_path
- End If
- Case "dirlink"
- Dim mysplit As UByte
-
- If dirlinks < 10 Then
- dirlinks += 1
- mysplit = InStr(value, ":")
- If mysplit Then
- dirlink(dirlinks).text = Trim(Left(value, mysplit - 1))
- dirlink(dirlinks).directory = Trim(Mid(value, mysplit + 1))
- Else
- dirlink(dirlinks).text = Trim(value)
- dirlink(dirlinks).directory = Trim(value)
- End If
-
- If Right(dirlink(dirlinks).directory, 1) <> "/" And Right(dirlink(dirlinks).directory, 1) <> "\" Then
- #ifdef __FB_LINUX__
- dirlink(dirlinks).directory &= "/"
- #else
- dirlink(dirlinks).directory &= "\"
- #endif
- End If
- End If
- Case "stunts"
- If dirlinks < 10 Then
- dirlinks += 1
- dirlink(dirlinks).text = "Stunts"
- dirlink(dirlinks).directory = Trim(value)
- End If
-
- If Right(dirlink(dirlinks).directory, 1) <> "/" And Right(dirlink(dirlinks).directory, 1) <> "\" Then
- #ifdef __FB_LINUX__
- dirlink(dirlinks).directory &= "/"
- #else
- dirlink(dirlinks).directory &= "\"
- #endif
- End If
- Case "superposition", "superpositions"
- If LCase(value) = "true" Or LCase(value) = "yes" Or LCase(value) = "on" Then
- allow_errors = -1
- Else
- allow_errors = 0
- End If
- Case "warning", "warnings"
- If LCase(value) = "true" Or LCase(value) = "yes" Or LCase(value) = "on" Then
- show_errors = -1
- Else
- show_errors = 0
- End If
- Case "grid"
- If LCase(value) = "true" Or LCase(value) = "yes" Or LCase(value) = "on" Then
- show_grid = -1
- Else
- show_grid = 0
- End If
- Case "format"
- Select Case LCase(Trim(value))
- Case "stunts", "none" : default_format = FORMAT_RAW
- Case "tb", "trackblaster" : default_format = FORMAT_RAW
- Case "bliss", "overlay", "combined"
- default_format = FORMAT_COMBINED
- Case "companion", "split", "binary"
- default_format = FORMAT_BINARY_SPLIT
- Case "text", "text-split", "human", "human-readable"
- default_format = FORMAT_TEXT_SPLIT
- End Select
- Case "author"
- default_author = Trim(value)
- Case "calibration", "speed" 'Racer speed weigh value
- racer_weigh = Val(value)
-
- If racer_weigh < 4 Then racer_weigh = 4
- If racer_weigh > 20 Then racer_weigh = 20
- Case "imageformat"
- value = LCase(Trim(value))
- If Left(value, 1) = "." Then value = Mid(value, 2)
- Select Case value
- Case "bmp", "gif", "pcx", "jpg", "png"
- imageformat = value
- Case "jpeg"
- imageformat = "jpg"
- Case Else
- imageformat = "tga"
- End Select
- Case "curl"
- If LCase(value) = "true" Or LCase(value) = "yes" Or LCase(value) = "on" Then
- use_curl = -1
- Else
- use_curl = 0
- End If
- End Select
- End If
- Loop
- Close 100
-
- If FileExists(program_path + "handicap.cfg") Then
- Open program_path + "handicap.cfg" For Input As 100
- Do While Not EOF(100)
- Line Input #100, s
- s = Trim(s)
- If Len(s) <> 0 And Left(s, 1) <> ";" Then
- cars += 1
- If Mid(s, 5, 1) = ";" Then
- car(cars).id = Left(s, 4)
- s = Mid(s, 6)
- Else
- car(cars).id = "****"
- End If
-
- n = InStr(s, ";")
- If n = 0 Then
- cars -= 1
- Else
- car(cars).cname = Trim(Left(s, n - 1))
- If Len(car(cars).cname) = 0 Then car(cars).cname = "Unknown"
- car(cars).handicap = Val(Mid(s, n + 1))
- If car(cars).handicap < 0.005 Or car(cars).handicap > 5 Then _
- car(cars).handicap = 1.5
- End If
- End If
-
- If car(cars).handicap = 1 Then activecar = cars
- If cars = MAXCARS Then Exit Do
- Loop
- Close 100
-
- If activecar = 0 Then activecar = 1
- Else
- 'No handicap file. Only one car: Porsche March Indy
- cars = 1 : activecar = 1
- car(1).id = "PMIN" : car(1).cname = "Porsche March Indy"
- car(1).handicap = 1
- End If
- End Sub
- Sub LoadFont (fontfile As String)
- Dim As Byte x, y
- Dim f As String, b As UByte, i As Short
- Dim ff As String
-
- ff = fontfile
- If InStr(ff, ".") = 0 Then ff &= ".fnt"
- Open program_path + ff For Binary Access Read As 1
- f = Space(Lof(1))
- Get #1, , f
- Close 1
- font = ImageCreate(8, 16 * 256)
- mask = ImageCreate(8, 16 * 256)
- Line font, (0, 0)-(15, 16 * 256 -1), RGB(0, 0, 0), BF
- Line mask, (0, 0)-(15, 16 * 256 -1), RGB(255, 0, 255), BF
- For i = 0 To 255
- For y = 0 To 15
- b = Asc(Mid(f, 16 * i + y, 1))
- For x = 0 To 7
- If b And 2 ^ x Then
- PSet font, (x, 16 * i + y), RGB(255, 255, 255)
- PSet mask, (x, 16 * i + y), RGB(0, 0, 0)
- End If
- Next x
- Next y
- Next i
- End Sub
- Sub LoadGraphics
- Dim gf As String
- Dim f As Integer
- Dim As UShort gwidth, gheight, x, y, i
- Dim As UByte r, g, b, a, count
- Dim rle As Byte
- Dim col As ULong
- Dim buffer As UByte Ptr, fp As ULong
-
- f = FreeFile
-
- gf = big_graphics_file
- If InStr(gf, ".") = 0 Then gf = gf + ".tga"
-
- Open program_path + gf For Binary Access Read As f
- Get #f, 13, gwidth
- Get #f, , gheight
-
- bigicons = ImageCreate(gwidth, gheight)
- buffer = Allocate(LOF(f) + 1024)
- Get #f, 1, *buffer, LOF(f)
-
- If dosbox Then
- fp = 18
- x = 0 : y = 0
- Do
- count = buffer[fp]
- rle = count And 128
- count = count And 127
- fp += 1
-
- If rle Then
- b = buffer[fp]
- g = buffer[fp + 1]
- r = buffer[fp + 2]
- a = buffer[fp + 3]
- fp += 4
-
- For i = 0 To count
- If a >= 128 Then
- PSet bigicons, (x, y), RGB(r, g, b)
- Else
- PSet bigicons, (x, y), RGB(255, 0, 255)
- End If
- x += 1
- If x = gwidth Then x = 0 : y += 1
- Next i
- Else
- For i = 0 To count
- b = buffer[fp]
- g = buffer[fp + 1]
- r = buffer[fp + 2]
- a = buffer[fp + 3]
- fp += 4
-
- If a >= 128 Then
- PSet bigicons, (x, y), RGB(r, g, b)
- Else
- PSet bigicons, (x, y), RGB(255, 0, 255)
- End If
- x += 1
- If x = gwidth Then x = 0 : y += 1
- Next i
- End If
- Loop Until y >= gheight
- Else
- fp = 18
- x = 0 : y = 0
- Do
- count = buffer[fp]
- rle = count And 128
- count = count And 127
- fp += 1
-
- If rle Then
- b = buffer[fp]
- g = buffer[fp + 1]
- r = buffer[fp + 2]
- a = buffer[fp + 3]
- fp += 4
-
- For i = 0 To count
- PSet bigicons, (x, y), RGBA(r, g, b, a)
- x += 1
- If x = gwidth Then x = 0 : y += 1
- Next i
- Else
- For i = 0 To count
- b = buffer[fp]
- g = buffer[fp + 1]
- r = buffer[fp + 2]
- a = buffer[fp + 3]
- fp += 4
-
- PSet bigicons, (x, y), RGBA(r, g, b, a)
- x += 1
- If x = gwidth Then x = 0 : y += 1
- Next i
- End If
- Loop Until y >= gheight
- End If
-
- Close f
- Deallocate buffer
- End Sub
- Sub LoadMetaData(filenumber As Short = 0, content As String = "")
- Dim s As String, l As Short
- Dim c As String
-
- If Len(content) Then
- c = content
- Else
- l = LOF(filenumber) - Seek(filenumber) + 1
- c = Space(l)
- Get #filenumber, , c
- End If
-
- 'Initialise meta-data
- meta.title = ""
- meta.author = ""
- meta.comment = ""
- meta.championship = ""
- meta.cyear = 0
- meta.cmonth = 0
- meta.cday = 0
- meta.editing_time = -1
- started_editing = Timer
-
- 'Read meta-data
- s = Left(c, 8)
-
- If Left(s, 4) = "smdf" Then
- thisfileformat = FORMAT_BINARY_SPLIT
- c = Mid(c, 9) 'Skip obsolete track hash
-
- Do While Len(c)
- s = Left(c, 4) : l = CvShort(Mid(c, 5, 2))
- c = Mid(c, 7)
-
- 'Field length has to be positive
- If l <= 0 Then Exit Do
-
- Select Case s
- Case "Titl"
- meta.title = Left(c, l)
- c = Mid(c, l + 1)
- Case "Autr"
- meta.author = Left(c, l)
- c = Mid(c, l + 1)
- Case "Comm"
- meta.comment = Left(c, l)
- c = Mid(c, l + 1)
- Case "Chmp"
- meta.championship = Left(c, l)
- c = Mid(c, l + 1)
- Case "Date"
- If l <> 4 Then Exit Do
- meta.cyear = CvShort(Left(c, 2))
- meta.cmonth = ASC(Mid(c, 3, 1))
- meta.cday = ASC(Mid(c, 4, 1))
- c = Mid(c, 5)
- Case "Tool"
- l -= 4
- If l <= 0 Then Exit Do
- meta.tool = Left(c, l) : c = Mid(c, l + 1)
- meta.toolversion = CvL(Left(c, 4))
- c = Mid(c, 5)
- Case "Etim"
- If l <> 4 Then Exit Do
- meta.editing_time = CvL(Left(c, 4))
- c = Mid(c, 5)
- Case "Colr"
- Dim t As String, last_bgc As ULong, last_border As ULong
- Dim As UByte i, j
- Dim pending As UByte
-
- t = Left(c, l)
- c = Mid(c, l + 1)
-
- i = 1 : j = 1 : pending = 0
- Do While Len(t) <> 0 Or pending
- If pending = 0 Then
- pending = ASC(Left(t, 1))
- last_border = CvL(ConvertColour(Mid(t, 2, 2)))
- last_bgc = CvL(ConvertColour(Mid(t, 4, 2)))
- t = Mid(t, 6)
- End If
-
- grid(i, j).border = last_border
- grid(i, j).bgc = last_bgc
- pending -= 1
- i += 1
- If i = 31 Then i = 1 : j += 1
- If j = 31 Then Exit Do
- Loop
- Case Else
- c = Mid(c, l + 1)
- End Select
- Loop
- ElseIf Left(s, 7) = "[smdf]" + Chr(13) Or Left(s, 7) = "[smdf]" + Chr(10) Then
- thisfileformat = FORMAT_TEXT_SPLIT
-
- If Right(s, 1) = Chr(10) Or Right(s, 1) = Chr(13) Then
- 'Using CRLF or LFCR for end of line. Skip both characters
- c = Mid(c, 9)
- Else
- 'Using either CR or LF for end of line. Skip it
- c = Mid(c, 8)
- End If
-
- 'Make sure the string ends with an end-of-line character
- If Right(c, 1) <> Chr(13) And Right(c, 1) <> Chr(10) Then c &= Chr(10)
-
- Dim titi As Double
- s = ""
- Do While Len(c)
- If Left(c, 1) = Chr(13) Or Left(c, 1) = Chr(10) Then
- 'EOL character. Process the accumulated string if any
- Dim n As Short, id As String, vval As String
-
- s = Trim(s)
- n = InStr(s, "=")
- If n Then 'Ignore lines that don't contain a "="
- id = LCase(RTrim(Left(s, n - 1)))
- vval = LTrim(Mid(s, n + 1))
-
- Select Case id
- Case "title", "titl" : meta.title = Left(vval, 64)
- Case "author", "autr" : meta.author = Left(vval, 64)
- Case "comment", "comm" : meta.comment = Left(vval, 64)
- Case "tour_info", "chmp" : meta.championship = Left(vval, 64)
- Case "creation_date", "date"
- meta.cyear = ValInt(vval)
- meta.cmonth = 0 : meta.cday = 0
- If meta.cyear < 1900 Then meta.cyear = 1900
- If meta.cyear > 3000 Then meta.cyear = 3000
- n = InStr(vval, "-")
- If n Then
- vval = Mid(vval, n + 1)
- meta.cmonth = ValInt(vval)
- If meta.cmonth < 0 Or meta.cmonth > 12 Then meta.cmonth = 0
- n = InStr(vval, "-")
- If n Then
- vval = Mid(vval, n + 1)
- meta.cday = ValInt(vval)
- If meta.cday < 0 Or meta.cday > 31 Then meta.cday = 0
- End If
- End If
- Case "tool" : meta.tool = Left(vval, 64)
- Case "tool_version"
- n = InStr(vval, ".")
- If n Then
- meta.toolversion = ValInt(Left(vval, n - 1))
- meta.toolversion *= 10000
- vval = Mid(vval, n + 1)
- n = InStr(vval, ".")
- If n Then
- meta.toolversion += 100 * ValInt(Left(vval, n - 1))
- meta.toolversion += ValInt(Mid(vval, n + 1))
- Else
- meta.toolversion += 100 * ValInt(vval)
- End If
- Else
- meta.toolversion = ValInt(vval)
- meta.toolversion *= 10000
- End If
- Case "editing_time", "etim" : meta.editing_time = ValInt(vval)
- End Select
- End If
-
- s = ""
- Else
- 'Not and EOL character, add the character to the line
- s &= Left(c, 1)
- End If
- c = Mid(c, 2)
- Loop
- Else
- Exit Sub 'No valid metadata found
- 'Notice that the metadata file has to be UTF-8 or ASCII with
- 'no BOM. Otherwise, we'll get here and no metadata will be loaded.
- End If
- End Sub
- Sub LoadTrack(trk As String)
- Dim As Short x, y, n, i
- Dim ticks As UShort, s As String
- Dim mytrack As String
- Dim pathtofile As String
- Dim isrpl As Byte = 0
-
- #ifdef __FB_LINUX__
- n = InStrRev(trk, "/")
- #else
- n = InStrRev(trk, "\")
- #endif
- pathtofile = Left(trk, n)
-
- mytrack = trk
- If InStr(mytrack, ".") = 0 Then mytrack = mytrack + ".trk"
-
- Open mytrack For Binary Access Read As 100
- If Right(LCase(mytrack), 4) = ".rpl" Then
- isrpl = -1
- track_file = Space(9)
- Get #100, 14, track_file
- n = InStr(track_file, Chr(0))
- track_file = LCase(Left(track_file, n - 1)) + ".trk"
- Get #100, 25, ticks
- If ticks + 1828 = LOF(100) Then 'v1.1 replay file
- Seek #100, 27
- Else
- Get #100, 23, ticks
- If ticks + 1826 = LOF(100) Then 'v1.0 replay file
- Seek #100, 25
- Else 'Track file renamed as replay? Or corrupt?
- Seek #100, 1
- End If
- End If
- Else
- track_file = ""
- For i = Len(mytrack) To 1 Step -1
- If Mid(mytrack, i, 1) = "/" Or Mid(mytrack, i, 1) = "\" Then
- track_file = Mid(mytrack, i + 1)
- Exit For
- End If
- Next i
- If Len(track_file) = 0 Then track_file = mytrack
- End If
-
- 'Load track contents
- For y = 30 To 1 Step -1
- For x = 1 To 30
- Get #100, , grid(x, y).track
- Next x
- Next y
- Get #100, , landscape
- For y = 1 To 30
- For x = 1 To 30
- Get #100, , grid(x, y).land
-
- grid(x, y).bgc = 0
- grid(x, y).border = 0
- Next x
- Next y
- Get #100, , format_byte
-
- 'Initialise meta-data
- meta.title = ""
- meta.author = ""
- meta.comment = ""
- meta.championship = ""
- meta.cyear = 0
- meta.cmonth = 0
- meta.cday = 0
- meta.editing_time = -1
- started_editing = Timer
-
- 'Load meta-data
- s = pathtofile + Left(track_file, InStr(track_file, ".")) + "smd"
- If isrpl = 0 And LOF(100) > 1802 Then
- Seek #100, 1803
- LoadMetaData 100
- thisfileformat = FORMAT_COMBINED 'Overlay
- ElseIf FileExists(s) Then
- Close 100
- Open s For Binary Access Read As 100
- 'We know this is a split format, but still don't know if
- 'it's text or binary. We'll assume binary and if it isn't,
- 'LoadMetaData will change the global variable thisfileformat
- 'accordingly.
- thisfileformat = FORMAT_BINARY_SPLIT 'Split
- LoadMetaData 100
- ElseIf GetMetaDataFromRegistry Then
- Select Case format_byte
- Case 150
- 'Format 150 was used in earlier versions of Bliss,
- 'before metadata were introduced
- meta.tool = "Bliss"
- meta.toolversion = 20100
- thisfileformat = FORMAT_COMBINED 'Use overlay if modified
- Case 151, 152, 2
- 'Format 151 was used previously for tracks including
- 'their metadata in the same file. It was discontinued
- 'after version 2.3.3
- 'Format 152 corresponded originally to tracks whose
- 'metadata was being stored separately. Currently, all
- 'Bliss tracks are generated with format code 152
- 'Format 2 was being issued as a bug on new tracks
- 'made with versions prior to 2.5.4, maybe even several
- 'versions before. This was fixed, but tracks still
- 'exist carrying this value
- meta.tool = "Probably, Bliss"
- meta.toolversion = 20303
- thisfileformat = FORMAT_COMBINED 'Bliss, so also use overlay
- Case 0
- 'Stunts produces files with format 0 and so does
- 'Track Blaster. Other tools might issue this same
- 'format code, but I can't tell if that's the case.
- Dim mywhat As Byte
-
- 'Here verify the elements on the track to see if
- 'it was made with Track Blaster
- DetectNotStunts 0, 0, mywhat
- If mywhat Then
- meta.tool = "Track Blaster Pro"
- meta.toolversion = 50300
- Else
- meta.tool = "Stunts"
- meta.toolversion = 10100
- End If
- thisfileformat = FORMAT_BINARY_SPLIT 'Prefer split for these files
- Case Else
- meta.tool = "Unknown"
- meta.toolversion = 0
- thisfileformat = FORMAT_BINARY_SPLIT 'Unknown format - prefer split
- End Select
- End If
- Close 100
-
- UpdateTitleBar
-
- modified = 0
- End Sub
- Sub Redo
- 'If already at the head, then there's nothing to redo
- If undopointer = undohead Then Exit Sub
-
- 'Increment the pointer
- undopointer = (undopointer + 1) Mod UNDOLEVEL
-
- 'Recover the grid
- If Len(undobuffer(undopointer)) = 0 Then _
- undobuffer(undopointer) = Chr(30, 30) + String(1800, 0)
- PutTrack 1, 1, undobuffer(undopointer), -1
- DrawTrack
- End Sub
- Sub SaveMetaData(filenumber As Short)
- Dim l As Short
-
- If thisfileformat = FORMAT_BINARY_SPLIT Or _
- thisfileformat = FORMAT_COMBINED Then
-
- 'Stunts Meta-Data Format
- Put #filenumber, , "smdf" 'Magic word
- Put #filenumber, , MKL(0) 'Skip obsolete track hash
-
- l = Len(meta.title)
- If l Then
- Put #filenumber, , "Titl"
- Put #filenumber, , l : Put #filenumber, , meta.title
- End If
- l = Len(meta.author)
- If l Then
- Put #filenumber, , "Autr"
- Put #filenumber, , l : Put #filenumber, , meta.author
- End If
- l = Len(meta.comment)
- If l Then
- Put #filenumber, , "Comm"
- Put #filenumber, , l : Put #filenumber, , meta.comment
- End If
- l = Len(meta.championship)
- If l Then
- Put #filenumber, , "Chmp"
- Put #filenumber, , l : Put #filenumber, , meta.championship
- End If
- If meta.cyear Then
- Put #filenumber, , "Date" : l = 4
- Put #filenumber, , l
- Put #filenumber, , meta.cyear
- Put #filenumber, , meta.cmonth
- Put #filenumber, , meta.cday
- End If
- l = Len(meta.tool)
- If l = 0 Then
- meta.tool = "Bliss"
- meta.toolversion = THISVERSION_NOPERIOD
- l = 10
- End If
- l += 4
- Put #filenumber, , "Tool"
- Put #filenumber, , l
- Put #filenumber, , meta.tool
- Put #filenumber, , meta.toolversion
- If meta.editing_time >= 0 Then
- If started_editing < Timer Then _
- meta.editing_time += (Timer - started_editing)
- started_editing = Timer
- Put #filenumber, , "Etim"
- l = 4
- Put #filenumber, , l
- Put #filenumber, , meta.editing_time
- End If
-
- 'Save colouration if any
- Dim As Byte i, j, q = 0
- Dim p As String, last_bgc As ULong, last_border As ULong
- Dim count As Short
-
- last_bgc = grid(1, 1).bgc
- last_border = grid(1, 1).border
- For j = 1 To 30
- For i = 1 To 30
- If grid(i, j).border <> 0 OrElse grid(i, j).bgc <> 0 Then q = -1
- If grid(i, j).border <> last_border OrElse _
- grid(i, j).bgc <> last_bgc OrElse count = 255 Then
-
- p &= Chr(count) & ConvertColour(MkL(last_border)) & ConvertColour(MkL(last_bgc))
- last_bgc = grid(i, j).bgc
- last_border = grid(i, j).border
- count = 1
- Else
- count += 1
- End If
- Next i
- Next j
- p &= Chr(count) & ConvertColour(MkL(last_border)) & ConvertColour(MkL(last_bgc))
-
- If q Then
- Put #filenumber, , "Colr"
- Put #filenumber, , MkShort(Len(p))
- Put #filenumber, , p
- End If
- ElseIf thisfileformat = FORMAT_TEXT_SPLIT Then
- 'Stunts text meta-data format
- Put #filenumber, , "[smdf]" + Chr(13, 10)
-
- If Len(meta.title) Then
- Put #filenumber, , "title="
- Put #filenumber, , meta.title + Chr(13, 10)
- End If
-
- If Len(meta.author) Then
- Put #filenumber, , "author="
- Put #filenumber, , meta.author + Chr(13, 10)
- End If
-
- If Len(meta.comment) Then
- Put #filenumber, , "comment="
- Put #filenumber, , meta.comment + Chr(13, 10)
- End If
-
- If Len(meta.championship) Then
- Put #filenumber, , "tour_info="
- Put #filenumber, , meta.championship + Chr(13, 10)
- End If
-
- If meta.cyear Then
- Dim s As String
-
- s = "creation_date="
- s &= Trim(Str(meta.cyear)) & "-" & Trim(Str(meta.cmonth))
- s &= "-" & Trim(Str(meta.cday))
-
- Put #filenumber, , s + Chr(13, 10)
- End If
- l = Len(meta.tool)
- If l = 0 Then
- meta.tool = "Bliss"
- meta.toolversion = THISVERSION_NOPERIOD
- End If
- Put #filenumber, , "tool="
- Put #filenumber, , meta.tool + Chr(13, 10)
- Put #filenumber, , "tool_version="
-
- Dim As UByte v1, v2, v3
- v1 = meta.toolversion \ 10000
- v2 = (meta.toolversion Mod 10000) \ 100
- v3 = meta.toolversion Mod 100
- Put #filenumber, , Trim(Str(v1))
- If v2 Or v3 Then Put #filenumber, , "." & Trim(Str(v2))
- If v3 Then Put #filenumber, , "." & Trim(Str(v3))
- Put #filenumber, , Chr(13, 10)
-
- If meta.editing_time >= 0 Then
- If started_editing < Timer Then _
- meta.editing_time += (Timer - started_editing)
-
- started_editing = Timer
- Put #filenumber, , "editing_time="
- Put #filenumber, , Trim(Str(meta.editing_time)) + Chr(13, 10)
- End If
- End If
- End Sub
- Sub SaveTrack(trk As String)
- Dim mytrack As String, otherfile As String
- Dim ticks As Short, isrpl As Byte = 0
- Dim As Short x, y, i
- Dim hashvalue As ULong
-
-
- mytrack = trk
- If InStr(mytrack, ".") = 0 Then mytrack = mytrack + ".trk"
- otherfile = Left(mytrack, InStr(mytrack, ".")) + "smd"
-
- If Right(LCase(mytrack), 4) = ".rpl" Then
- isrpl = -1
- Open mytrack For Binary As 100
- Get #100, 25, ticks
- If ticks + 1828 = LOF(100) Then 'v1.1 replay file
- Seek #100, 27
- Else
- Get #100, 23, ticks
- If ticks + 1826 = LOF(100) Then 'v1.0 replay file
- Seek #100, 25
- Else 'Track file renamed as replay? Or corrupt?
- Seek #100, 1
- End If
- End If
- Else
- Open mytrack For Output As 100 : Close 100
- Open mytrack For Binary As 100
- track_file = ""
- For i = Len(mytrack) To 1 Step -1
- If Mid(mytrack, i, 1) = "/" Or Mid(mytrack, i, 1) = "\" Then
- track_file = Mid(mytrack, i + 1)
- Exit For
- End If
- Next i
- If Len(track_file) = 0 Then track_file = mytrack
- End If
- For y = 30 To 1 Step -1
- For x = 1 To 30
- Put #100, , grid(x, y).track
- Next x
- Next y
- Put #100, , landscape
- For y = 1 To 30
- For x = 1 To 30
- Put #100, , grid(x, y).land
- Next x
- Next y
- Put #100, , format_byte
-
- 'Write meta-data
- If Not isrpl AndAlso (thisfileformat <> FORMAT_RAW) Then
- If thisfileformat = FORMAT_BINARY_SPLIT Or _
- thisfileformat = FORMAT_TEXT_SPLIT Then
-
- Close 100 : Open otherfile For Output As 100
- Close 100 : Open otherfile For Binary As 100
- End If
-
- SaveMetaData 100
- End If
- Close 100
-
- 'Delete SMD file if saved in a format other than split
- If thisfileformat <> FORMAT_BINARY_SPLIT And _
- thisfileformat <> FORMAT_TEXT_SPLIT And _
- FileExists(otherfile) Then Kill otherfile
-
- UpdateTitleBar
-
- modified = 0
- End Sub
- Sub SaveTrackImage(trk As String)
- Dim n As Short, extension As String, tfile As String
- Dim As Short iwidth, iheight, ixstart, iystart
- Dim finalbuffer As ULong Ptr
- Dim tempxselect As Byte
-
- 'If there's a selection, save selection, otherwise, whole track
- If xselect Then
- If xselect <= x2select Then
- ixstart = bigwidth * (xselect - 1)
- Else
- ixstart = bigwidth * (x2select - 1)
- End If
- If yselect <= y2select Then
- iystart = bigwidth * (yselect - 1)
- Else
- iystart = bigwidth * (y2select - 1)
- End If
- iwidth = bigwidth * (Abs(x2select - xselect) + 1)
- iheight = bigwidth * (Abs(y2select - yselect) + 1)
- Else
- iwidth = 660 : iheight = 660
- ixstart = 0 : iystart = 0
- End If
-
- If show_grid Then
- track_image_buffer = ImageCreate(661, 661, 32)
- iwidth += 1 : iheight += 1
- Else
- track_image_buffer = ImageCreate(660, 660, 32)
- End If
- finalbuffer = ImageCreate(iwidth, iheight, 32)
-
- tempxselect = xselect
- xselect = 0
- DrawTrack
- xselect = tempxselect
- 'Kill alpha channel
- Dim pvalue As ULong
- For j As Short = 0 To 659
- For i As Short = 0 To 659
- pvalue = Point(i, j, track_image_buffer)
- PSet track_image_buffer, (i, j), pvalue Or &HFF000000ul
- Next i
- Next j
- 'Get the part that's being saved
- Get track_image_buffer, (ixstart, iystart)-_
- (ixstart + iwidth - 1, iystart + iheight - 1), finalbuffer
-
- n = InStrRev(trk, ".")
- If n Then
- extension = LCase(Mid(trk, n))
- tfile = trk
- Else
- extension = ".tga"
- tfile = trk + extension
- End If
-
- Select Case extension
- Case ".bmp" : BSave tfile, finalbuffer
- Case ".tga" : TargaSave tfile, finalbuffer
- Case ".jpg", ".png", ".pcx", ".gif"
- BSave track_path + "temp.bmp", finalbuffer
- Shell "convert " + track_path + "temp.bmp " + tfile
- Kill track_path + "temp.bmp"
- End Select
-
- ImageDestroy track_image_buffer
- ImageDestroy finalbuffer
- track_image_buffer = 0
- End Sub
- Sub FollowPath(s As String, e As Byte = 0)
- Dim As TrackVector slot, oldslot
- Dim As Byte w, h, juststarted = -1, gofast = 0
- Dim As Short n, pointed = 0
-
- 'Null tracks are not to be followed
- If section(1).final = section(1).initial And section(1).finishes = 0 Then Exit Sub
-
- Do
- pointed += 1
- n = ASC(Mid(s, pointed, 1))
- slot.coors = section(n).initial
- slot.bearing = section(n).bearing
-
- Do
- If slot.coors = section(n).final And juststarted = 0 Then
- xcursor = slot.x
- ycursor = slot.y
- Exit Do
- End If
-
- 'This part may cause artifacts when big items are used
- 'across the border of the grid
- If gofast = 0 Then
- w = tr(grid(slot.x, slot.y).track).w
- h = tr(grid(slot.x, slot.y).track).h
- Line (xoffs + (slot.x - 1) * 22, yoffs + (slot.y - 1) * 22)- _
- Step(bigwidth * w - 1, 22 * h - 1), RGB(100, 240, 240), BF
-
- For j As Byte = 1 To h
- For i As Byte = 1 To w
- PutIcon tr(grid(slot.x, slot.y).track).x + i - 1, tr(grid(slot.x, slot.y).track).y + j - 1, _
- xoffs + bigwidth * (slot.x + i - 2), yoffs + 22 * (slot.y + j - 2)
- Next i
- Next j
- Sleep 100
- End If
-
- DrawSpot slot.x, slot.y
- If w = 2 And slot.x < 30 Then
- DrawSpot slot.x + 1, slot.y
- If h = 2 And slot.y < 30 Then DrawSpot slot.x + 1, slot.y + 1
- End If
- If h = 2 And slot.y < 30 Then DrawSpot slot.x, slot.y + 1
-
- oldslot = slot
- slot = GetNext(slot)
- If e Then 'e <> 0 means follow to error
- If slot.e = e Then
- xcursor = oldslot.x
- ycursor = oldslot.y
- Exit Do, Do
- End If
- End If
- juststarted = 0
-
- If Len(InKey) Then gofast = -1
- Loop
- Loop Until pointed = Len(s)
-
- DrawTrack
- ManageKeyboardCursor -1
- End Sub
- Sub GenerateSections
- Dim vector As TrackVector
- Dim lastchecked As Short = 0
-
- vector = FindStart
- If vector.e Then
- sections = 0
- paths = 0
- terrors = 0
- Exit Sub
- End If
-
- terrors = 0
-
- sections = 1
- section(1).initial = vector.coors
- section(1).bearing = vector.bearing
- section(1).origin = vector.bearing XOr 2
-
- SolveSection 1
-
- paths = 1
-
- path(1).p = Chr(1)
- path(1).e = 0
- path(1).finishes = 0
- SolvePath 1
- End Sub
- Function GetMetaDataFromRegistry As Byte
- Dim s As String, h As ULong
- Dim As Byte original
-
- h = Hash32
-
- Select Case h
- Case &H57F9D21A : meta.title = "Default" : original = -1
- Case &H9F88F8DB : meta.title = "Bernie's" : original = -1
- Case &H142A0681 : meta.title = "Cherry's" : original = -1
- Case &HC3477BBF : meta.title = "Helen's" : original = -1
- Case &H843C5C7F : meta.title = "Joe's" : original = -1
- Case &H2C1625C5 : meta.title = "Skid's" : original = -1
- Case &HF8680B47
- meta.title = "4:00am"
- meta.author = "Cas"
- meta.cyear = 2006 : meta.cmonth = 2 : meta.cday = 28
- meta.tool = "Cas-Stunts" : meta.toolversion = 10000
- meta.editing_time = -1
- meta.comment = "Always raced with Porsche March Indy"
- meta.championship = "Paleke's WSC - March 2006; ZakStunts - May 2015"
- Case &H136836E9
- meta.title = "Napalm"
- meta.author = "Cas"
- meta.cyear = 0
- meta.tool = "Bliss" : meta.toolversion = 20100
- meta.editing_time = -1
- meta.comment = ""
- meta.championship = "ZakStunts ZCT183 - September 2016"
- Case &HA6460C26
- meta.title = "Bliss"
- meta.author = "Cas"
- meta.cyear = 2016 : meta.cmonth = 10 : meta.cday = 17
- meta.tool = "Bliss" : meta.toolversion = 20500
- meta.editing_time = 1066
- meta.comment = "Race this track to measure your relative lap"
- meta.championship = "Race for Immortality - October/November 2016"
- Case Else 'Use external registry
- Dim found As Short = -1
- If FileExists("bliss.reg") Then
- Dim f As Integer, n As Short, s As String, rs As Short
- Dim shash As String, fpointer As Long
-
- f = FreeFile
- Open "bliss.reg" For Binary Access Read As f
- 'First four bytes are magic number (not checked now)
- Get #f, 5, rs 'Get registry size (max number of tracks)
- Get #f, , n 'Get number of registry entries
- s = Space(4 * n)
- Get #f, , s 'Read hash table
-
- shash = MkL(h) : found = -1
- For i As Short = 0 To n - 1
- If Mid(s, 4 * i + 1, 4) = shash Then
- found = i
- Exit For
- End If
- Next i
-
- If found >= 0 Then
- Get #f, 5 + 4 * rs + 4 * found, fpointer
- Get #f, fpointer + 1, n 'Get metadata length
- s = Space(n)
- Get #f, , s
- LoadMetadata , s
- End If
- Close f
- End If
- #ifndef __FB_DOS__
- 'If it looks like a ZakStunts track, try to retrieve
- 'the metadata from the site
- If found = -1 AndAlso UCase(Left(track_file, 3)) = "ZCT" Then
- Dim length As Long, trackaddr As String
- Dim content As ZString Ptr, s As String
- Dim dif As Boolean = False
-
- DrawTrack
- MenuBox 25, 9, "Identifying Track"
-
- lefx += 8
- TLeft , "Identifying ZakStunts champ track...", RGB(160, 160, 240)
- TLeft , "Verifying track content...", RGB(160, 160, 240)
- trackaddr = "zak.stunts.hu/tracks/" & UCase(Left(track_file, Len(track_file) - 4)) & ".trk"
- length = HTTP_Download(trackaddr, content)
- If length > 0 Then
- Dim As Byte x, y
- Dim u As Short = 0
-
- For y = 30 To 1 Step -1
- For x = 1 To 30
- If content[u] <> grid(x, y).track Then
- dif = True
- Exit For, For
- End If
- u += 1
- Next x
- Next y
- If content[u] <> landscape Then dif = True
- u += 1
- For y = 1 To 30
- For x = 1 To 30
- If content[u] <> grid(x, y).land Then
- dif = True
- Exit For, For
- End If
- u += 1
- Next x
- Next y
- If Not dif Then
- TLeft , "Verified.", RGB(160, 160, 240)
- Else
- TLeft , "Couldn't verify!", RGB(160, 160, 240)
- Sleep 300
- End If
- If content <> 0 Then Deallocate content : content = 0
- End If
- If Not dif Then
- TLeft , "Retrieving metadata from ZakStunts...", RGB(160, 160, 240)
- trackaddr = UCase(Left(track_file, Len(track_file) - 4))
- trackaddr = "zak.stunts.hu/tracks/" & trackaddr
- length = HTTP_Download(trackaddr, content)
- If length > 0 Then
- Dim n As Long
-
- 'Get the track name in form "Cxxx"
- s = Left(track_file, Len(track_file) - 4)
- s = "C" + Mid(s, 4) + " - "
- n = InStr(*content, s)
-
- If n Then
- s = Mid(*content, n + Len(s), 255)
- n = InStr(s, "<")
- If n Then s = Left(s, n - 1)
- n = InStr(s, "(by ")
- If n Then
- 'Title and author
- meta.title = Trim(Left(s, n - 1))
- s = Mid(s, n + 4)
- n = InStr(s, ")")
- If n Then s = Left(s, n - 1)
- meta.author = Trim(s)
- Else
- 'Title only
- meta.title = Trim(s)
- meta.author = ""
- End If
- meta.championship = "ZakStunts " & UCase(Left(track_file, Len(track_file) - 4))
- End If
- Deallocate content
- End If
- End If
- End If
- #endif
- End Select
-
- If original Then
- meta.author = "DSI"
- meta.comment = "Original track"
- meta.championship = ""
- meta.tool = "Stunts"
- meta.toolversion = 10000
- meta.editing_time = -1
- meta.cyear = 1990
- meta.cmonth = 10
- meta.cday = 0
- Return 0
- Else
- Return -1
- End If
- End Function
- Function GetNext(slot As TrackVector, detour As Byte = 0) As TrackVector
- Dim newslot As TrackVector
- Dim As UByte curel, newel, isaramp = 0, isabridge = 0
-
- 'Current element is the nature of the element at current slot
- curel = grid(slot.x, slot.y).track
- newslot.origin = slot.bearing XOr 2
-
- Select Case slot.bearing
- Case 0 'North
- If tr(curel).cisalt(slot.bearing) Then
- newslot.x = slot.x + 1
- Else
- newslot.x = slot.x
- End If
- newslot.y = slot.y - 1
-
- 'See if this is a ramp or bridge
- If tr(curel).ctype(0) = 2 Then
- If tr(curel).w = 1 And tr(curel).h = 1 AndAlso _
- tr(curel).ctype(2) = 1 Then
-
- isaramp = -1
- Else
- isabridge = -1
- End If
-
- If detour Then newslot.y -= 1 'Skip one slot (jump)
- End If
-
- If newslot.x > 30 Or newslot.y < 1 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
- Select Case newel
- Case 255 : newslot.x -= 1
- Case 254 : newslot.y -= 1
- Case 253 : newslot.x -= 1 : newslot.y -= 1
- End Select
- If newslot.x < 1 Or newslot.y < 1 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
-
- If tr(newel).ctype(2) = 0 Then 'New tile does not accept
- If (isaramp <> 0 Or isabridge <> 0) And detour = 0 Then
- newslot = GetNext(slot, -1)
- Return newslot
- ElseIf isaramp Then
- newslot.e = 73 'Jump distance is too long
- Return newslot
- ElseIf tr(curel).ctype(slot.bearing) = 2 Then
- newslot.e = 74 'Stunts won't allow interrupting this bridge
- Return newslot
- Else
- newslot.e = 81 'End of track, interrupted
- Return newslot
- End If
- ElseIf tr(newel).ctype(2) <> tr(curel).ctype(0) Then
- newslot.e = 70 'Track types mismatch
- End If
-
- 'Accepted, but... is the jump feasible?
- If isaramp And detour Then
- If grid(slot.x, slot.y).land = 9 Then
- newslot.e = 21 'Jump is not feasible
- ElseIf grid(slot.x, slot.y).land = 0 And grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- ElseIf isabridge And detour Then
- If grid(slot.x, slot.y).land <> 6 Or grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- End If
-
- If newslot.x - (tr(newel).cisalt(2) <> 0) _
- <> slot.x - (tr(curel).cisalt(0) <> 0) Then
-
- newslot.e = 81 'Track not properly connected
- End If
-
- 'Straightway before jump is too short?
- If slot.origin <> (slot.bearing XOr 2) _
- Or tr(curel).entity = ASC("t") _
- Or tr(curel).entity = ASC("h") Then 'Turn, tunnel or chicane?
-
- 'Yes, it's one of those. Ramp ahead?
- If tr(newel).w = 1 And tr(newel).h = 1 AndAlso _
- tr(newel).ctype(2) = 1 And tr(newel).ctype(0) = 2 Then
-
- 'Yes. Is it a jump?
- If newslot.y - 1 >= 1 AndAlso _
- tr(GetParent(newslot.x, newslot.y - 1)).ctype(2) <> 2 Then
-
- newslot.e = 71 'Straightway before jump is too short
- End If
- End If
- End If
-
- Select Case tr(newel).cto(2)
- Case 0 : newslot.e = 4 'No exit!
- Case 1 : newslot.bearing = 0 'North
- Case 2 : newslot.bearing = 1 'East
- Case 4 : newslot.bearing = 2 'South
- Case 8 : newslot.bearing = 3 'West
- Case 3 'Split: North or East
- If detour Then
- newslot.bearing = 1
- Else
- newslot.bearing = 0
- End If
- Case 9 'Split: North or West
- If detour Then
- newslot.bearing = 3
- Else
- newslot.bearing = 0
- End If
- Case Else : newslot.bearing = 0 'This should never happen
- End Select
- Case 1 'East
- If tr(curel).cisalt(slot.bearing) Then
- newslot.y = slot.y + 1
- Else
- newslot.y = slot.y
- End If
- newslot.x = slot.x + tr(curel).w
-
- 'See if this is a ramp or bridge
- If tr(curel).ctype(1) = 2 Then
- If tr(curel).w = 1 And tr(curel).h = 1 AndAlso _
- tr(curel).ctype(3) = 1 Then
-
- isaramp = -1
- Else
- isabridge = -1
- End If
-
- If detour Then newslot.x += 1 'Skip one slot (jump)
- End If
-
- If newslot.x > 30 Or newslot.y > 30 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
- Select Case newel
- Case 255 : newslot.x -= 1
- Case 254 : newslot.y -= 1
- Case 253 : newslot.x -= 1 : newslot.y -= 1
- End Select
- If newslot.x < 1 Or newslot.y < 1 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
-
- If tr(newel).ctype(3) = 0 Then 'New tile does not accept
- If (isaramp <> 0 Or isabridge <> 0) And detour = 0 Then
- newslot = GetNext(slot, -1)
- Return newslot
- ElseIf isaramp Then
- newslot.e = 73 'Jump distance is too long
- Return newslot
- ElseIf tr(curel).ctype(slot.bearing) = 2 Then
- newslot.e = 74 'Stunts won't allow interrupting this bridge
- Return newslot
- Else
- newslot.e = 81 'End of track, interrupted
- Return newslot
- End If
- ElseIf tr(newel).ctype(3) <> tr(curel).ctype(1) Then
- newslot.e = 70 'Track types mismatch
- End If
- 'Accepted, but... is the jump feasible?
- If isaramp And detour Then
- If grid(slot.x, slot.y).land = 8 Then
- newslot.e = 21 'Jump is not feasible
- ElseIf grid(slot.x, slot.y).land = 0 And grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- ElseIf isabridge And detour Then
- If grid(slot.x, slot.y).land <> 6 Or grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- End If
-
- If newslot.y - (tr(newel).cisalt(3) <> 0) _
- <> slot.y - (tr(curel).cisalt(1) <> 0) Then
-
- newslot.e = 81 'Track not properly connected
- End If
-
- 'Straightway before jump is too short?
- If slot.origin <> (slot.bearing XOr 2) _
- Or tr(curel).entity = ASC("t") _
- Or tr(curel).entity = ASC("h") Then 'Turn, tunnel or chicane?
-
- 'Yes, it's one of those. Ramp ahead?
- If tr(newel).w = 1 And tr(newel).h = 1 AndAlso _
- tr(newel).ctype(3) = 1 And tr(newel).ctype(1) = 2 Then
-
- 'Yes. Is it a jump?
- If newslot.x + 1 <= 30 AndAlso _
- tr(GetParent(newslot.x + 1, newslot.y)).ctype(3) <> 2 Then
-
- newslot.e = 71 'Straightway before jump is too short
- End If
- End If
- End If
-
- Select Case tr(newel).cto(3)
- Case 0 : newslot.e = 4 'No exit!
- Case 1 : newslot.bearing = 0 'North
- Case 2 : newslot.bearing = 1 'East
- Case 4 : newslot.bearing = 2 'South
- Case 8 : newslot.bearing = 3 'West
- Case 3 'Split: East or North
- If detour Then
- newslot.bearing = 0
- Else
- newslot.bearing = 1
- End If
- Case 6 'Split: East or South
- If detour Then
- newslot.bearing = 2
- Else
- newslot.bearing = 1
- End If
- Case Else : newslot.bearing = 1 'This should never happen
- End Select
- Case 2 'South
- If tr(curel).cisalt(slot.bearing) Then
- newslot.x = slot.x + 1
- Else
- newslot.x = slot.x
- End If
- newslot.y = slot.y + tr(curel).h
-
- 'See if this is a ramp or bridge
- If tr(curel).ctype(2) = 2 Then
- If tr(curel).w = 1 And tr(curel).h = 1 AndAlso _
- tr(curel).ctype(0) = 1 Then
-
- isaramp = -1
- Else
- isabridge = -1
- End If
-
- If detour Then newslot.y += 1 'Skip one slot (jump)
- End If
-
- If newslot.x > 30 Or newslot.y > 30 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
- Select Case newel
- Case 255 : newslot.x -= 1
- Case 254 : newslot.y -= 1
- Case 253 : newslot.x -= 1 : newslot.y -= 1
- End Select
- If newslot.x < 1 Or newslot.y < 1 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
-
- If tr(newel).ctype(0) = 0 Then 'New tile does not accept
- If (isaramp <> 0 Or isabridge <> 0) And detour = 0 Then
- newslot = GetNext(slot, -1)
- Return newslot
- ElseIf isaramp Then
- newslot.e = 73 'Jump distance is too long
- Return newslot
- ElseIf tr(curel).ctype(slot.bearing) = 2 Then
- newslot.e = 74 'Stunts won't allow interrupting this bridge
- Return newslot
- Else
- newslot.e = 81 'End of track, interrupted
- Return newslot
- End If
- ElseIf tr(newel).ctype(0) <> tr(curel).ctype(2) Then
- newslot.e = 70 'Track types mismatch
- End If
- 'Accepted, but... is the jump feasible?
- If isaramp And detour Then
- If grid(slot.x, slot.y).land = 7 Then
- newslot.e = 21 'Jump is not feasible
- ElseIf grid(slot.x, slot.y).land = 0 And grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- ElseIf isabridge And detour Then
- If grid(slot.x, slot.y).land <> 6 Or grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- End If
-
- If newslot.x - (tr(newel).cisalt(0) <> 0) _
- <> slot.x - (tr(curel).cisalt(2) <> 0) Then
-
- newslot.e = 81 'Track not properly connected
- End If
-
- 'Straightway before jump is too short?
- If slot.origin <> (slot.bearing XOr 2) _
- Or tr(curel).entity = ASC("t") _
- Or tr(curel).entity = ASC("h") Then 'Turn, tunnel or chicane?
-
- 'Yes, it's one of those. Ramp ahead?
- If tr(newel).w = 1 And tr(newel).h = 1 AndAlso _
- tr(newel).ctype(0) = 1 And tr(newel).ctype(2) = 2 Then
-
- 'Yes. Is it a jump?
- If newslot.y + 1 <= 30 AndAlso _
- tr(GetParent(newslot.x, newslot.y + 1)).ctype(0) <> 2 Then
-
- newslot.e = 71 'Straightway before jump is too short
- End If
- End If
- End If
-
- Select Case tr(newel).cto(0)
- Case 0 : newslot.e = 4 'No exit!
- Case 1 : newslot.bearing = 0 'North
- Case 2 : newslot.bearing = 1 'East
- Case 4 : newslot.bearing = 2 'South
- Case 8 : newslot.bearing = 3 'West
- Case 6 'Split: South or East
- If detour Then
- newslot.bearing = 1
- Else
- newslot.bearing = 2
- End If
- Case 12 'Split: South or West
- If detour Then
- newslot.bearing = 3
- Else
- newslot.bearing = 2
- End If
- Case Else : newslot.bearing = 2 'This should never happen
- End Select
- Case 3 'West
- If tr(curel).cisalt(slot.bearing) Then
- newslot.y = slot.y + 1
- Else
- newslot.y = slot.y
- End If
- newslot.x = slot.x - 1
-
- 'See if this is a ramp or bridge
- If tr(curel).ctype(3) = 2 Then
- If tr(curel).w = 1 And tr(curel).h = 1 AndAlso _
- tr(curel).ctype(1) = 1 Then
-
- isaramp = -1
- Else
- isabridge = -1
- End If
-
- If detour Then newslot.x -= 1 'Skip one slot (jump)
- End If
-
- If newslot.x < 1 Or newslot.y > 30 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
- Select Case newel
- Case 255 : newslot.x -= 1
- Case 254 : newslot.y -= 1
- Case 253 : newslot.x -= 1 : newslot.y -= 1
- End Select
- If newslot.x < 1 Or newslot.y < 1 Then _
- newslot.e = 80 : Return newslot 'Grid border reached
-
- newel = grid(newslot.x, newslot.y).track
-
- If tr(newel).ctype(1) = 0 Then 'New tile does not accept
- If (isaramp <> 0 Or isabridge <> 0) And detour = 0 Then
- newslot = GetNext(slot, -1)
- Return newslot
- ElseIf isaramp Then
- newslot.e = 73 'Jump distance is too long
- Return newslot
- ElseIf tr(curel).ctype(slot.bearing) = 2 Then
- newslot.e = 74 'Stunts won't allow interrupting this bridge
- Return newslot
- Else
- newslot.e = 81 'End of track, interrupted
- Return newslot
- End If
- ElseIf tr(newel).ctype(1) <> tr(curel).ctype(3) Then
- newslot.e = 70 'Track types mismatch
- End If
- 'Accepted, but... is the jump feasible?
- If isaramp And detour Then
- If grid(slot.x, slot.y).land = 10 Then
- newslot.e = 21 'Jump is not feasible
- ElseIf grid(slot.x, slot.y).land = 0 And grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- ElseIf isabridge And detour Then
- If grid(slot.x, slot.y).land <> 6 Or grid(newslot.x, newslot.y).land = 6 Then
- newslot.e = 21 'Jump is not feasible
- End If
- End If
-
- If newslot.y - (tr(newel).cisalt(1) <> 0) _
- <> slot.y - (tr(curel).cisalt(3) <> 0) Then
-
- newslot.e = 81 'Track not properly connected
- End If
-
- 'Straightway before jump is too short?
- If slot.origin <> (slot.bearing XOr 2) _
- Or tr(curel).entity = ASC("t") _
- Or tr(curel).entity = ASC("h") Then 'Turn, tunnel or chicane?
-
- 'Yes, it's one of those. Ramp ahead?
- If tr(newel).w = 1 And tr(newel).h = 1 AndAlso _
- tr(newel).ctype(1) = 1 And tr(newel).ctype(3) = 2 Then
-
- 'Yes. Is it a jump?
- If newslot.x - 1 >= 1 AndAlso _
- tr(GetParent(newslot.x - 1, newslot.y)).ctype(1) <> 2 Then
-
- newslot.e = 71 'Straightway before jump is too short
- End If
- End If
- End If
-
- Select Case tr(newel).cto(1)
- Case 0 : newslot.e = 4 'No exit!
- Case 1 : newslot.bearing = 0 'North
- Case 2 : newslot.bearing = 1 'East
- Case 4 : newslot.bearing = 2 'South
- Case 8 : newslot.bearing = 3 'West
- Case 9 'Split: West or North
- If detour Then
- newslot.bearing = 0
- Else
- newslot.bearing = 3
- End If
- Case 12 'Split: West or South
- If detour Then
- newslot.bearing = 2
- Else
- newslot.bearing = 3
- End If
- Case Else : newslot.bearing = 3 'This should never happen
- End Select
- End Select
-
- Return newslot
- End Function
- 'Get the code of the parent element
- Function GetParent(x As UByte, y As UByte) As UByte
- Select Case grid(x, y).track
- Case 255
- If x > 1 Then
- If tr(grid(x - 1, y).track).w = 2 Then
- Return grid(x - 1, y).track
- End If
- End If
- Case 254
- If y > 1 Then
- If tr(grid(x, y - 1).track).h = 2 Then
- Return grid(x, y - 1).track
- End If
- End If
- Case 253
- If x > 1 And y > 1 Then
- If tr(grid(x - 1, y - 1).track).w = 2 And tr(grid(x - 1, y - 1).track).h = 2 Then
- Return grid(x - 1, y - 1).track
- End If
- End If
- End Select
-
- Return grid(x, y).track
- End Function
- 'Read a rectangle from the grid into a string
- Function GetTrack(x As UByte, y As UByte, x2 As UByte, y2 As UByte) As String
- Dim As Byte i, j, c
- Dim s As String, t As String
-
- s = Chr(x2 - x + 1, y2 - y + 1)
- For j = y To y2
- For i = x To x2
- c = 0 : t = ""
- If grid(i, j).track Then
- c Or= 1
- t &= Chr(grid(i, j).track)
- End If
- If grid(i, j).land Then
- c Or= 2
- t &= Chr(grid(i, j).land)
- End If
- If grid(i, j).border Then
- c Or= 4
- t &= MkL(grid(i, j).border)
- End If
- If grid(i, j).bgc Then
- c Or= 8
- t &= MkL(grid(i, j).bgc)
- End If
-
- s &= Chr(c) & t
- Next i
- Next j
-
- Return s
- End Function
- 'Generate a 32bit hash value out of the given string
- Function Hash32 Overload (content As String) As ULong
- Dim i As Short, hash As ULong
- Dim u As UByte
-
- For i = 1 To Len(content)
- u = ASC(Mid(content, i, 1))
-
- If u Then
- hash XOr= (u + 11)
- hash XOr= (121 * i)
- Else
- hash *= 31
- hash += 3
- End If
- Next i
-
- Return hash
- End Function
- Function Hash32 Overload As ULong
- Dim trackstring As String, h As ULong
-
- For j As Byte = 30 To 1 Step - 1
- For i As Byte = 1 To 30
- trackstring &= Chr(grid(i, j).track)
- Next i
- Next j
- trackstring &= Chr(landscape)
- For j As Byte = 1 To 30
- For i As Byte = 1 To 30
- trackstring &= Chr(grid(i, j).land)
- Next i
- Next j
-
- Return Hash32(trackstring)
- End Function
- 'Flip buffer rectangle horizontally
- Function HFlipTrack(t As String) As String
- Dim As Byte w, h, c
- w = ASC(Left(t, 1))
- h = ASC(Mid(t, 2, 1))
-
- Dim temp(1 To w, 1 To h) As SGrid
- Dim s As String, i As Byte, j As Byte, n As Short
-
- 'Read and flip
- n = 3 : i = w : j = 1
- Do While n <= Len(t)
- c = ASC(Mid(t, n, 1))
- n += 1
- If c And 1 Then 'Track is non-zero
- temp(i, j).track = tr(ASC(Mid(t, n, 1))).hflip
- n += 1
- End If
- If c And 2 Then 'Terrain is non-zero
- temp(i, j).land = ttr(ASC(Mid(t, n, 1))).hflip
- n += 1
- End If
- If c And 4 Then 'Border colour is non-zero
- temp(i, j).border = CvL(Mid(t, n, 4))
- n += 4
- End If
- If c And 8 Then 'Background colour is non-zero
- temp(i, j).bgc = CvL(Mid(t, n, 4))
- n += 4
- End If
-
- i -= 1
- If i = 0 Then i = w : j += 1
- Loop
-
- 'Fix
- For j = 1 To h
- For i = 1 To w - 1
- If temp(i, j).track = 255 Or temp(i, j).track = 253 Then
- Swap temp(i, j).track, temp(i + 1, j).track
- i += 1
- End If
- Next i
- Next j
- 'Put back into the string
- s = PackedClip(temp())
-
- Return s
- End Function
- Sub InitFiles(mask As String, x1 As Short, y1 As Short, x2 As Short, y2 As Short)
- Dim As String s, t
- Dim attr As Integer
- Dim i As Short
- Dim justreloading As Byte
-
- filer.mask = mask
- If x1 Then
- filer.x1 = x1
- filer.y1 = y1
- filer.x2 = x2
- filer.y2 = y2
- justreloading = 0
- DrawBox x1, y1, x2, y2
- Else
- x1 = filer.x1
- y1 = filer.y1
- x2 = filer.x2
- y2 = filer.y2
- justreloading = -1
- Line (x1 + 4, y1 + 4)-(x2 - 32, y2 - 4), RGB(30, 30, 50), BF
- End If
- filer.reread = -1
-
- fileys = 0
- #ifdef __FB_LINUX__
- If track_path <> "/" And track_path <> "\" Then
- fileys = 1
- filey(1) = "*.."
- End If
- #else
- DetectDrives
- #endif
-
- For i As UByte = 1 To dirlinks
- If track_path <> dirlink(i).directory Then
- fileys += 1
- filey(fileys) = "* - " + dirlink(i).text + " - "
- End If
- Next i
-
- s = Dir(track_path + "*.*", 49, attr)
- Do
- If Len(s) Then
- If attr And 16 Then
- If s <> "." Then
- fileys += 1
- filey(fileys) = "*" + s
- End If
- Else
- i = 1
- Do
- t = LCase(Mid(mask, i))
- i = InStr(t, ";")
- If i Then t = Left(t, i - 1)
- t = Trim(t)
- If Len(t) = 0 Then Exit Do
- If Right(LCase(s), Len(t) + 1) = "." + t Then
- fileys += 1
- filey(fileys) = s
- Exit Do
- End If
- If i = 0 Then Exit Do Else i += 1
- Loop
- End If
- s = Dir(attr)
- Else
- Exit Do
- End If
- Loop Until fileys = 512
-
- SortFiles
-
- If Not justreloading Then
- AddButton x2 - 24, y1, Chr(24), 101
- AddButton x2 - 24, y2 - 32, Chr(25), 102
- End If
- End Sub
- Function ManageFiles(akey As String = "") As String
- Static first As Short, exfirst As Short = -1
- Static lit As Short, exlit As Short
- Static wheel As Integer
- Dim i As Short, v As Short
- Dim As Integer xm, ym, wm, bm
-
- If filer.reread Then
- first = 1 : exfirst = -1
- lit = -1 : exlit = -1
- filer.reread = 0
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- wheel = wm
- End If
-
- GetMouse xm, ym, wm, bm
- v = ManageButtons
- If v = 101 Or wm > wheel Then
- If first > 1 Then first -= 1 Else v = 0
- wheel = wm
- ElseIf v = 102 Or wm < wheel Then
- If first + 17 < fileys Then first += 1 Else v = 0
- wheel = wm
- End If
-
- If Len(akey) Then
- If ASC(akey) = 1 Then 'Search for file name in list
- For i = 1 To fileys
- If Left(LCase(filey(i)), Len(akey) - 1) = LCase(Mid(akey, 2)) Then
- first = i
- If first + 17 > fileys Then first = fileys - 17
- If first < 1 Then first = 1
- Exit For
- End If
- Next i
- Else
- Select Case akey
- Case Chr(255) + Chr(73)
- If first > 18 Then first -= 18 Else first = 1
- Case Chr(255) + Chr(81)
- If first + 35 < fileys Then first += 18 Else first = fileys - 17
- End Select
- End If
- End If
-
- If first <> exfirst Then
- ScreenLock
- Line (filer.x1 + 4, filer.y1 + 4)-(filer.x2 - 32, filer.y2 - 4), RGB(30, 30, 50), BF
- For i = 0 To 17
- If first + i > fileys Then Exit For
- If Left(filey(first + i), 1) = "*" Then
- Draw String (filer.x1 + 16, filer.y1 + 12 + i * 16), "[" + Mid(filey(first + i), 2) + "]", RGB(160, 240, 160)
- Else
- Draw String (filer.x1 + 16, filer.y1 + 12 + i * 16), filey(first + i), RGB(160, 160, 240)
- End If
- Next i
- ScreenUnlock
- exfirst = first
- End If
-
- If xm >= filer.x1 + 16 And xm <= filer.x2 - 32 And ym >= filer.y1 + 12 And ym <= filer.y2 - 12 Then
- lit = (ym - filer.y1 - 12) \ 16
- Else
- lit = -1
- End If
-
- If lit <> exlit Then
- If exlit <> -1 And first + exlit <= fileys Then
- If Left(filey(first + exlit), 1) = "*" Then
- Draw String (filer.x1 + 16, filer.y1 + 12 + exlit * 16), "[" + Mid(filey(first + exlit), 2) + "]", RGB(160, 240, 160)
- Else
- Draw String (filer.x1 + 16, filer.y1 + 12 + exlit * 16), filey(first + exlit), RGB(160, 160, 240)
- End If
- End If
- If lit <> -1 And first + lit <= fileys Then
- If Left(filey(first + lit), 1) = "*" Then
- Draw String (filer.x1 + 16, filer.y1 + 12 + lit * 16), "[" + Mid(filey(first + lit), 2) + "]", RGB(255, 255, 255)
- Else
- Draw String (filer.x1 + 16, filer.y1 + 12 + lit * 16), filey(first + lit), RGB(255, 255, 255)
- End If
- End If
- exlit = lit
- End If
-
- If bm = 1 And lit <> -1 And first + lit <= fileys Then
- If Left(filey(first + lit), 1) = "*" Then
- If Mid(filey(first + lit), 2, 1) = " " Then
- For i As UByte = 1 To dirlinks
- If Mid(filey(first + lit), 5, Len(dirlink(i).text)) = dirlink(i).text Then
- track_path = dirlink(i).directory
- Exit For
- End If
- Next i
- Else
- ChangeTrackDirectory Mid(filey(first + lit), 2)
- End If
- InitFiles filer.mask, 0, 0, 0, 0
- Else
- Return filey(first + lit)
- End If
- End If
-
- If v = 101 Or v = 102 Then Sleep 30, 1
- Return ""
- End Function
- Sub CreatePath
- Dim As Byte firstx, firsty, bearing, material = 1
- Dim As UByte addthing
- Dim As String buffer, akey
- Dim As Integer bm
-
- Do
- GetMouse 0, 0, 0, bm
- Loop Until bm = 0
-
- firstx = xcursor
- firsty = ycursor
-
- PushUndo
-
- Do
- GetMouse 0, 0, 0, bm
- If bm Then Exit Do
-
- akey = InKey
- Select Case akey
- Case Chr(255, 72)
- Case Chr(27) : Undo : Exit Do
- Case Chr(13)
- If Len(buffer) = 0 Then Undo
- Exit Do
- End Select
-
- If addthing Then
- addthing = 0
- End If
- Loop
-
- Do
- GetMouse 0, 0, 0, bm
- Loop Until bm = 0
- End Sub
- Sub ChangeTrackDirectory(d As String)
- Dim i As Short
-
- #ifndef __FB_LINUX__
- If Len(d) = 2 And Right(d, 1) = ":" Then
- track_path = UCase(d) + "\"
- Exit Sub
- End If
- #endif
-
- If d <> ".." Then
- #ifdef __FB_LINUX__
- track_path = track_path + d + "/"
- #else
- track_path = track_path + d + "\"
- #endif
- Exit Sub
- End If
-
- For i = Len(track_path) - 1 To 1 Step -1
- #ifdef __FB_LINUX__
- If Mid(track_path, i, 1) = "/" Then
- #else
- If Mid(track_path, i, 1) = "\" Then
- #endif
- track_path = Left(track_path, i)
- Exit Sub
- End If
- Next i
-
- track_path = CurDir
- #ifdef __FB_LINUX__
- If Right(track_path, 1) <> "/" Then track_path = track_path + "/"
- #else
- If Right(track_path, 1) <> "\" Then track_path = track_path + "\"
- #endif
- End Sub
- 'Convert 32bit to 16bit colour or vice-versa in string form
- Function ConvertColour(c As String) As String
- Dim As UByte r, g, b
- Dim s As UShort, l As ULong
- Dim t As String
-
- If Len(c) = 2 Then
- s = CvShort(c)
- If s = &B1111100000011111 Then
- 'Transparent colour translates to no colouration
- t = MkL(0)
- Else
- r = (s ShR 8) And &B11111000
- g = (s ShR 3) And &B11111100
- b = (s ShL 3) And &B11111000
-
- t = MkL(RGB(r, g, b))
- End If
- ElseIf Len(c) = 4 Then
- l = CvL(c)
- If l Then
- r = (l ShR 19) And &B11111
- g = (l ShR 10) And &B111111
- b = (l ShR 3) And &B11111
-
- s = r
- s = (s ShL 6) Or g
- s = (s ShL 5) Or b
- t = MkShort(s)
- Else
- 'No colouration translates as transparent colour
- t = MkShort(&B1111100000011111)
- End If
- End If
-
- Return t
- End Function
- Sub CopyOrCut(cut As Byte = 0)
- If xselect Then
- If xselect > x2select Then Swap xselect, x2select
- If yselect > y2select Then Swap yselect, y2select
-
- clipboard = GetTrack(xselect, yselect, x2select, y2select)
-
- 'Update temporary file so as to export clipboard --------
- Dim cllen As Short, f As Integer
-
- f = FreeFile
- If FileExists(program_path & "clip.tmp") Then
- cllen = FileLen(program_path & "clip.tmp")
- Else
- cllen = 0
- End If
-
- 'Make sure new length is different from previous one
- 'This will allow Bliss instances to realise the clipboard
- 'was changed without having to open the file
- Open program_path & "clip.tmp" For Output As f : Close f
- Open program_path & "clip.tmp" For Binary Access Write As f
- If cllen <> Len(clipboard) + 1 Then
- Dim b As Byte = 0
- Put #f, , b
- Else
- Dim b As Byte = 1
- Put #f, , b
- b = 0
- Put #f, , b
- End If
- Put #f, , clipboard
-
- last_cb_file_length = LOF(f)
- Close f
- '------------------------------
-
- 'xclip = xselect : x2clip = x2select
- 'yclip = yselect : y2clip = y2select
-
- If cut Then
- For j As Byte = yselect To y2select
- For i As Byte = xselect To x2select
- If affect_terrain Then grid(i, j).land = 0
- If affect_track Then
- If allow_errors Then
- ClearTrack i, j
- Else
- grid(i, j).track = 0
- End If
- End If
- Next i
- Next j
- modified = -1
- End If
-
- xselect = 0 : DrawTrack
- End If
- End Sub
- Function AntiTimey(t As String) As Long
- Dim n As Short, cents As Long
- Dim s As String
-
- s = t
-
- n = InStr(s, ":")
- If n = 0 Then
- cents = 100 * Val(s)
- Return cents
- End If
-
- cents = ValInt(s) * 6000
- s = Mid(s, n + 1)
- n = InStr(s, ":")
- If n = 0 Then
- cents += 100 * Val(s)
- Return cents
- End If
-
- cents *= 24
- cents += 6000 * ValInt(s)
- s = Mid(s, n + 1)
- cents += 100 * Val(s)
- Return cents
- End Function
- Sub BuildClosedCircuit
- Dim As UByte corner, straightway, tile
- Dim material As Byte, i As Short, j As Short
-
- If xselect = 0 Then
- Error_Message "First select a region to build a closed-circuit"
- DrawTrack
- Exit Sub
- End If
-
- If xselect > x2select Then Swap xselect, x2select
- If yselect > y2select Then Swap yselect, y2select
-
- If tr(current_brush).material >= 1 And tr(current_brush).material <= 3 Then
- material = tr(current_brush).material
-
- tile = grid(xselect, yselect).track
- If x2select - xselect > 1 And y2select - yselect > 1 _
- And tr(tile).ctype(0) = 0 And tr(tile).ctype(1) <> 0 _
- And tr(tile).ctype(2) <> 0 And tr(tile).ctype(3) = 0 Then
- 'It's a North-West corner. Find big or small corner of the
- 'same material. If the selection is too narrow, always use
- 'small corners
-
- For i = 1 To 190
- If tr(i).h = 3 - tr(tile).h And tr(i).ctype(0) = 0 And tr(i).ctype(1) <> 0 _
- And tr(i).ctype(2) <> 0 And tr(i).ctype(3) = 0 _
- And tr(i).material = material Then Exit For
- Next i
- corner = i
- Else
- 'If still not drawn, use small corners
-
- For i = 1 To 190
- If tr(i).h = 1 And tr(i).ctype(0) = 0 And tr(i).ctype(1) <> 0 _
- And tr(i).ctype(2) <> 0 And tr(i).ctype(3) = 0 _
- And tr(i).material = material Then Exit For
- Next i
- corner = i
- End If
-
- 'Find a straightway
- For i = 1 To 190
- If Chr(tr(i).entity) = "s" And tr(i).material = material And tr(i).ctype(0) <> 0 Then _
- Exit For
- Next i
- straightway = i
- ElseIf tr(current_brush).entity = ASC("e") Then
- 'It's going to be an elevated circuit
- straightway = current_brush
- If tr(straightway).ctype(0) = 0 Then straightway = tr(straightway).cr
- corner = &H69
- ElseIf tr(current_brush).entity = ASC("a") Then
- 'It's going to be a banked circuit
- straightway = &H30
- corner = &H34
- ElseIf tr(current_brush).entity = ASC("Q") Then
- If tr(current_brush).ctype(0) = 2 OrElse tr(current_brush).ctype(1) = 2 _
- OrElse tr(current_brush).ctype(2) = 2 Then
- straightway = &H67 'It's elevated
- corner = &H69
- Else
- straightway = &H30 'It's banked
- corner = &H34
- End If
- ElseIf tr(current_brush).entity = ASC("b") Then
- straightway = &H6D 'Boulevard (no corners)
- corner = 0
- ElseIf current_brush >= &H97 And current_brush <= &HB2 Then
- ScreenLock 'Scenery - fill with it
- For j = yselect To y2select
- For i = xselect To x2select
- SetTrack i, j, current_brush
- Next i
- Next j
- ScreenUnlock
- Exit Sub
- Else
- Exit Sub 'Can't do anything with this item
- End If
-
- 'Push to undo buffer
- PushUndo
-
- If xselect = x2select Then
- 'Draw vertical straightway
- For i = yselect To y2select
- SetTrack xselect, i, straightway
- Next i
- ElseIf yselect = y2select Then
- 'Draw horizontal straightway
- straightway = tr(straightway).cr
- For i = xselect To x2select
- SetTrack i, yselect, straightway
- Next i
- Else
- 'Draw corners
- SetTrack xselect, yselect, corner : corner = tr(corner).cr
- SetTrack x2select - tr(corner).w + 1, yselect, corner : corner = tr(corner).cr
- SetTrack x2select - tr(corner).w + 1, y2select - tr(corner).h + 1, corner : corner = tr(corner).cr
- SetTrack xselect, y2select - tr(corner).h + 1, corner
-
- 'Draw straightways
- For i = yselect + tr(corner).h To y2select - tr(corner).h
- SetTrack xselect, i, straightway
- Next i
- straightway = tr(straightway).cr
- For i = xselect + tr(corner).w To x2select - tr(corner).w
- SetTrack i, yselect, straightway
- Next i
- straightway = tr(straightway).cr
- For i = yselect + tr(corner).h To y2select - tr(corner).h
- SetTrack x2select, i, straightway
- Next i
- straightway = tr(straightway).cr
- For i = xselect + tr(corner).w To x2select - tr(corner).w
- SetTrack i, y2select, straightway
- Next i
- End If
-
- DrawTrack
- End Sub
- Function CCRotate(t As String) As String
- Dim As Byte w, h, c
- h = ASC(Left(t, 1))
- w = ASC(Mid(t, 2, 1))
-
- Dim temp(1 To w, 1 To h) As SGrid
- Dim s As String, i As Byte, j As Byte, n As Short
-
- 'Read and rotate
- n = 3 : i = 1 : j = h
- Do While n <= Len(t)
- c = ASC(Mid(t, n, 1))
- n += 1
- If c And 1 Then 'Track is non-zero
- temp(i, j).track = tr(ASC(Mid(t, n, 1))).ccr
- n += 1
- End If
- If c And 2 Then 'Terrain is non-zero
- temp(i, j).land = ttr(ASC(Mid(t, n, 1))).ccr
- n += 1
- End If
- If c And 4 Then 'Border colour is non-zero
- temp(i, j).border = CvL(Mid(t, n, 4))
- n += 4
- End If
- If c And 8 Then 'Background colour is non-zero
- temp(i, j).bgc = CvL(Mid(t, n, 4))
- n += 4
- End If
-
- j -= 1
- If j = 0 Then i += 1 : j = h
- Loop
-
- 'Fix
- For j = 1 To h
- For i = 1 To w
- If tr(temp(i, j).track).w = 2 And tr(temp(i, j).track).h = 2 Then
- If j > 1 Then
- temp(i, j - 1).track = temp(i, j).track
- If i < w then temp(i + 1, j - 1).track = 255
- End If
- If i < w Then temp(i + 1, j).track = 253
- temp(i, j).track = 254
- ElseIf tr(temp(i, j).track).w = 2 Then
- If i < w Then temp(i + 1, j).track = 255
- ElseIf tr(temp(i, j).track).h = 2 Then
- If j > 1 Then temp(i, j - 1).track = temp(i, j).track
- temp(i, j).track = 254
- End If
- Next i
- Next j
- 'Put back into the string
- s = PackedClip(temp())
-
- Return s
- End Function
- Function CRotate(t As String) As String
- Dim As Byte w, h, c
- h = ASC(Left(t, 1))
- w = ASC(Mid(t, 2, 1))
-
- Dim temp(1 To w, 1 To h) As SGrid
- Dim s As String, i As Byte, j As Byte, n As Short
-
- 'Read and rotate
- n = 3 : i = w : j = 1
- Do While n <= Len(t)
- c = ASC(Mid(t, n, 1))
- n += 1
- If c And 1 Then 'Track is non-zero
- temp(i, j).track = tr(ASC(Mid(t, n, 1))).cr
- n += 1
- End If
- If c And 2 Then 'Terrain is non-zero
- temp(i, j).land = ttr(ASC(Mid(t, n, 1))).cr
- n += 1
- End If
- If c And 4 Then 'Border colour is non-zero
- temp(i, j).border = CvL(Mid(t, n, 4))
- n += 4
- End If
- If c And 8 Then 'Background colour is non-zero
- temp(i, j).bgc = CvL(Mid(t, n, 4))
- n += 4
- End If
-
- j += 1
- If j > h Then i -= 1 : j = 1
- Loop
-
- 'Fix
- For j = 1 To h
- For i = 1 To w
- If tr(temp(i, j).track).w = 2 And tr(temp(i, j).track).h = 2 Then
- If i > 1 Then
- temp(i - 1, j).track = temp(i, j).track
- If j < h then Temp(i - 1, j + 1).track = 254
- End If
- If j < h Then temp(i, j + 1).track = 253
- temp(i, j).track = 255
- ElseIf tr(temp(i, j).track).w = 2 Then
- If i > 1 Then temp(i - 1, j).track = temp(i, j).track
- temp(i, j).track = 255
- ElseIf tr(temp(i, j).track).h = 2 Then
- If j < h Then temp(i, j + 1).track = 254
- End If
- Next i
- Next j
- 'Put back into the string
- s = PackedClip(temp())
-
- Return s
- End Function
- Sub DetectDrives
- Dim i As Byte
-
- For i = 3 To 26
- Open Chr(64 + i) + ":\NUL" For Input As 101
- If Err = 0 Then
- fileys += 1
- filey(fileys) = "*" + Chr(64 + i) + ":"
- Close 101
- End If
- Next i
- End Sub
- Sub SmartSelect(etype As String, direction As Byte = 1)
- Dim As Byte checkconnections = -1, checkmaterial = -1
- Dim As Byte connector(0 To 3), material
- Dim i As Short
-
- 'Check to see if there are open connectors
- If vlast.x = 0 Or vlast.y = 0 OrElse grid(vlast.x, vlast.y).track = 0 Then
- 'Nothing has yet been placed or there's an empty space there
- checkconnections = 0
- material = tr(current_brush).material
- If material = 0 Then checkmaterial = 0
- Else
- Dim n As UByte = GetParent(vlast.x, vlast.y)
-
- material = tr(n).material
- If material = 0 Then checkmaterial = 0
-
- 'Check North
- If vlast.y > 1 AndAlso grid(vlast.x + tr(n).cisalt(0), vlast.y - 1).track = 0 Then _
- connector(2) = tr(n).ctype(0)
- 'Check East
- If vlast.x <= 30 - tr(n).w AndAlso grid(vlast.x + tr(n).w, vlast.y + tr(n).cisalt(1)).track = 0 Then _
- connector(3) = tr(n).ctype(1)
- 'Check South
- If vlast.y <= 30 - tr(n).h AndAlso grid(vlast.x + tr(n).cisalt(2), vlast.y + tr(n).h).track = 0 Then _
- connector(0) = tr(n).ctype(2)
- 'Check West
- If vlast.x > 1 AndAlso grid(vlast.x - 1, vlast.y + tr(n).cisalt(3)).track = 0 Then _
- connector(1) = tr(n).ctype(3)
-
- 'If no connector, then don't check
- If connector(0) + connector(1) + connector(2) + connector(3) = 0 Then checkconnections = 0
- End If
-
-
- Dim As Short searchstart, searchend
- Dim q As Byte
-
- 'Prepare to search left or right
- If direction > 0 Then
- searchstart = current_brush + 1
- searchend = current_brush + 256
- Else
- searchstart = current_brush + 255
- searchend = current_brush
- End If
-
- 'Try to find a coincidence. First for everything, then go
- 'eliminating restrictions
- Do
- For i = searchstart To searchend Step direction
- Dim n As UByte
-
- n = i Mod 256
-
- 'See if type matches
- If UCase(Chr(tr(n).entity)) = UCase(etype) Then
- q = 0
- If checkconnections Then
- For j As Byte = 0 To 3
- If connector(j) <> 0 And tr(n).ctype(j) = connector(j) Then
- q = -1 'At least one connector matches
- Exit For
- End If
- Next j
- Else
- q = -1 'Not checking connections, so assume OK
- End If
-
- If checkmaterial Then
- If tr(n).material <> material Then q = 0
- End If
-
- If q Then Exit For 'Everything matches
- End If
- Next i
-
- If q Then Exit Do
-
- 'See what we can give up to obtain a result
- If checkmaterial Then
- checkmaterial = 0 'Give up checking material
- ElseIf checkconnections Then
- checkconnections = 0 'Give up checking connections
- Else
- Exit Do 'Couldn't find anything
- End If
- Loop
-
- If q Then
- current_brush = i
- DrawPanel
- End If
- End Sub
- Sub SolvePath(pn As Short)
- Dim As UByte thissection, c1, c2
-
- thissection = ASC(Right(path(pn).p, 1))
-
- 'Propagate errors
- If section(thissection).errors Then
- If section(thissection).e >= 40 Then
- 'Path-fatal errors. Path ends here
- path(pn).e = section(thissection).e
- Exit Sub
- Else
- 'Prioritise early errors if not path-fatal (warnings)
- If path(pn).e = 0 Then path(pn).e = section(thissection).e
- End If
- End If
-
- 'See if it ends at the finish line
- If section(thissection).final = section(1).initial Then
- path(pn).finishes = -1
- Exit Sub
- End If
-
- c1 = section(thissection).child(0)
- c2 = section(thissection).child(1)
-
- If c2 = 0 Then
- If c1 = 0 Then 'No child (weird)
- Exit Sub
- Else 'Joint (one child)
- If InStr(path(pn).p, Chr(c1)) Then 'It's a cycle!
- path(pn).e = 82
- Exit Sub
- End If
- path(pn).p &= Chr(c1)
- SolvePath pn
- End If
- Else 'Split (two children)
- If paths = MAXPATHS Then Exit Sub
- paths += 1
- path(paths).p = path(pn).p
- path(paths).e = path(pn).e
- path(paths).finishes = path(pn).finishes
- path(pn).p &= Chr(c1)
- path(paths).p &= Chr(c2)
- SolvePath paths
- SolvePath pn
- End If
- End Sub
- 'Analyse a section of the track, finding errors and handling
- 'split points recursively. Save information in the sections array
- Sub SolveSection(sn As Short)
- Dim As TrackVector v, oldv
- Dim As Short i, n
-
- v.coors = section(sn).initial
- v.bearing = section(sn).bearing
- v.origin = section(sn).origin
- section(sn).e = 0
- section(sn).errors = 0
- section(sn).solving = -1
- section(sn).finishes = 0
- section(sn).cycle = 0
- section(sn).final = 0
- section(sn).wrongway = 0
- Do
- oldv = v
- v = GetNext(v)
-
- If v.e Then
- terrors += 1
- terror(terrors).coors = oldv.coors
- terror(terrors).e = v.e
- terror(terrors).section = sn
- End If
-
- Select Case v.e
- Case 70 To 79 'Path flow fatal errors
- If section(sn).e < 40 Then section(sn).e = v.e
- section(sn).errors = -1
- section(sn).solving = 0
- section(sn).final = oldv.coors
- section(sn).child(0) = 0
- section(sn).child(1) = 0
- Exit Do
- Case 80 To 89 'Path flow non-fatal errors
- If section(sn).e = 0 Then section(sn).e = v.e
- section(sn).errors = -1
- section(sn).solving = 0
- section(sn).final = oldv.coors
- section(sn).child(0) = 0
- section(sn).child(1) = 0
- Exit Do
- Case 20 To 39 'Warnings
- If section(sn).e = 0 Then section(sn).e = v.e
- section(sn).errors = -1
- End Select
-
- 'Found finish line
- If v.coors = section(1).initial Then
- section(sn).final = v.coors
- section(sn).child(0) = 0
- section(sn).child(1) = 0
- section(sn).finishes = -1
- Exit Do
- End If
-
- 'Reached a split?
- n = 0
- For i = 0 To 3 'Count number of connectors
- If tr(grid(v.x, v.y).track).ctype(i) Then n += 1
- Next i
-
- 'Yes. It's a split
- If n = 3 Then
- section(sn).final = v.coors
-
- 'See if this is a previously solved node
- For i = 1 To sections
- If v.coors = section(i).initial Then
- If 2 ^ section(i).bearing <> tr(grid(v.x, v.y).track).cto(v.bearing XOr 2) Then
- 'Make sure it ends here
- section(sn).child(0) = 0
- section(sn).child(1) = 0
-
- 'Wrong way!
- section(sn).wrongway = -1
- section(sn).errors = -1
- If section(sn).e < 40 Then section(sn).e = 72
- terrors += 1
- terror(terrors).coors = v.coors
- terror(terrors).e = 72
- terror(terrors).section = sn
- ElseIf section(i).solving Then
- 'Make sure it ends here
- section(sn).child(0) = 0
- section(sn).child(1) = 0
-
- 'This is a cycle!
- section(sn).cycle = -1
- If section(sn).e < 40 Then section(sn).e = 82
- terrors += 1
- terror(terrors).coors = v.coors
- terror(terrors).e = 82
- terror(terrors).section = sn
- Else
- 'Connect sections
- section(sn).child(0) = i
- section(sn).child(1) = 0
- section(i).parent(1) = sn
-
- 'Inherit child's errors and finish status
- section(sn).finishes = section(i).finishes
- section(sn).cycle = section(i).cycle
- section(sn).wrongway = section(i).wrongway
- If section(sn).e < 40 Then section(sn).e = section(i).e
- End If
- section(sn).solving = 0
- Exit Do
- End If
- Next i
-
- 'It's a new node
- n = tr(grid(v.x, v.y).track).cto(v.bearing XOr 2)
- Select Case n
- Case 1, 2, 4, 8 'Only one direction
- Dim daughter As Short
-
- 'Create new section and solve it
- sections += 1
- section(sections).initial = v.coors
- section(sections).bearing = Log(n) / Log(2)
- section(sections).origin = v.origin
- daughter = sections
- SolveSection daughter
-
- 'Inherit new section's status
- section(sn).finishes = section(daughter).finishes
- section(sn).cycle = section(daughter).cycle
- section(sn).wrongway = section(daughter).wrongway
- If section(sn).e = 0 Then section(sn).e = section(daughter).e
-
- 'Create parental links
- section(sn).child(0) = daughter
- section(sn).child(1) = 0
- section(sections).parent(0) = sn
- section(sections).parent(1) = 0
- Case Else 'Two directions
- Dim As Short daughter(1 To 2), daughters = 0
-
- 'Always solve the straight node first
- For i = v.bearing To v.bearing + 3
- Dim direction As Byte
-
- direction = i Mod 4
- If direction <> (v.bearing XOr 2) And _
- tr(grid(v.x, v.y).track).ctype(direction) <> 0 Then
-
- 'Create each node and solve it
- sections += 1
- If sections > 254 Then Exit Sub
- section(sections).initial = v.coors
- section(sections).bearing = direction
- section(sections).origin = v.origin
- daughters += 1
- daughter(daughters) = sections
- SolveSection sections
- End If
- Next i
-
- 'Carefully inherit the status
- If section(daughter(1)).finishes Or section(daughter(2)).finishes Then _
- section(sn).finishes = -1
- If section(daughter(1)).cycle And section(daughter(2)).cycle Then _
- section(sn).cycle = -1
- If section(sn).e = 0 Then
- section(sn).e = section(daughter(1)).e
- If section(sn).e = 0 Or section(daughter(2)).e = 4 Then section(sn).e = section(daughter(2)).e
- End If
- If section(daughter(1)).wrongway And section(daughter(2)).wrongway Then _
- section(sn).wrongway = -1
-
- 'Create parental links
- section(sn).child(0) = daughter(1)
- section(sn).child(1) = daughter(2)
- section(daughter(1)).parent(0) = sn
- section(daughter(1)).parent(1) = 0
- section(daughter(2)).parent(0) = sn
- section(daughter(2)).parent(1) = 0
- End Select
- Exit Do
- End If
- Loop
-
- section(sn).solving = 0
- End Sub
- Sub SortFiles
- Dim changes As Byte
- Dim i As Short
-
- 'For now, we use bubble sort
-
- 'First sort by name
- Do
- changes = 0
- For i = 1 To fileys - 1
- If LCase(filey(i)) > LCase(filey(i + 1)) Then
- Swap filey(i), filey(i + 1)
- changes = -1
- End If
- Next i
- Loop Until changes = 0
-
- 'Then place directories first
- Do
- changes = 0
- For i = 1 To fileys - 1
- If Left(filey(i), 1) <> "*" And Left(filey(i + 1), 1) = "*" Then
- Swap filey(i), filey(i + 1)
- changes = -1
- End If
- Next i
- Loop Until changes = 0
-
- #ifndef __FB_LINUX__
- 'Finally, place drives after directories
- Do
- changes = 0
- For i = 1 To fileys - 1
- If Left(filey(i), 1) = "*" And Left(filey(i + 1), 1) = "*" Then
- If Right(filey(i), 1) = ":" And Right(filey(i + 1), 1) <> ":" Then
- Swap filey(i), filey(i + 1)
- changes = -1
- End If
- Else
- Exit For
- End If
- Next i
- Loop Until changes = 0
- #endif
- End Sub
- Sub LoadTransformations
- Dim As Short x, y, p
-
- Open program_path + "xlation.dat" For Binary Access Read As 100
- For x = 0 To 255
- Get #100, , tr(x)
- Next x
- For x = 0 To 18
- Get #100, , ttr(x)
- Next x
- For p = 0 To 11
- For y = 0 To 5
- For x = 0 To 5
- Get #100, , itr(x, y, p)
- Next x
- Next y
- Next p
- Close 100
- End Sub
- Sub SaveTransformations
- Dim As Short x, y, p
-
- Open program_path + "xlation.dat" For Binary Access Write As 100
- For x = 0 To 255
- Put #100, , tr(x)
- Next x
- For x = 0 To 18
- Put #100, , ttr(x)
- Next x
- For p = 0 To 11
- For y = 0 To 5
- For x = 0 To 5
- Put #100, , itr(x, y, p)
- Next x
- Next y
- Next p
- Close 100
- End Sub
- #ifndef __FB_DOS__
- Function TMT_GetCurrentTrack(taddress As String) As Byte
- Dim mysite As ZString Ptr, length As Long
- Dim baseaddr As String, descfile As ZString Ptr
- Dim As Short n, m
- Dim trackfn As String, tbinary As UByte Ptr
- Dim As Byte i, j
- Dim As String title, author
-
- MenuBox 25, 10, "Getting current track"
-
- lefx += 16
- TLeft
-
- If InStr(LCase(taddress), "stunts.hu") Then
- TLeft , "Trying to connect to ZakStunts...", RGB(160, 160, 240)
- length = HTTP_Download("zak.stunts.hu/track.json", mysite)
- If length < 0 Then Return -1
-
- n = InStr(*mysite, "file" & Chr(34))
- Dim tempstring As String
- tempstring = Mid(*mysite, n + 7, 200)
- trackfn = ""
- For i As Short = 1 To Len(tempstring)
- Select Case Mid(tempstring, i, 1)
- Case "\"
- Case Chr(34) : Exit For
- Case Else : trackfn &= Mid(tempstring, i, 1)
- End Select
- Next i
-
- n = InStr(*mysite, Chr(34) + "track" + Chr(34))
- m = InStr(n + 1, *mysite, Chr(34) + "name" + Chr(34))
- If m Then
- m += 6
- m = InStr(m, *mysite, "-") + 1
- n = InStr(m + 1, *mysite, Chr(34))
- title = Mid(*mysite, m + 1, n - m - 1)
- Else
- title = ""
- End If
- n = InStr(*mysite, "author" + Chr(34))
- If n Then
- n += 9
- m = InStr(n, *mysite, Chr(34))
- author = Mid(*mysite, n, m - n)
- End If
-
- Deallocate mysite : mysite = 0
- Else
- TLeft , "Trying to connect to the server...", RGB(160, 160, 240)
-
- If LCase(Left(taddress, 4)) = "btp:" Then
- baseaddr = Mid(taddress, 5)
- Else
- baseaddr = taddress
- End If
-
- length = HTTP_Download(baseaddr + "/tour.cfg", descfile)
- If length < 0 Then Return -1
- If LCase(Left(*descfile, 4)) <> "tour" Then Return -1
-
- n = InStr(*descfile, "tracktitle=")
- If n Then
- n += 11
- m = InStr(n, *descfile, Chr(10))
- If m Then
- title = Mid(*descfile, n, m - n)
- If Right(title, 1) = Chr(13) Then title = Left(title, Len(title) - 1)
- End If
- End If
-
- n = InStr(*descfile, "trackauthor=")
- If n Then
- n += 12
- m = InStr(n, *descfile, Chr(10))
- If m Then
- author = Mid(*descfile, n, m - n)
- If Right(author, 1) = Chr(13) Then author = Left(author, Len(author) - 1)
- End If
- End If
-
- n = InStr(*descfile, "trackfile=")
- If n Then
- n += 10
- m = InStr(n, *descfile, Chr(10))
- If m Then
- trackfn = Mid(*descfile, n, m - n)
- If Right(trackfn, 1) = Chr(13) Then trackfn = Left(trackfn, Len(trackfn) - 1)
- End If
- End If
- If InStr(trackfn, ".") = 0 Then trackfn &= ".trk"
-
- Deallocate descfile : descfile = 0
- End If
-
- Dim baretrackname As String, slashpos As Short
- slashpos = InStrRev(trackfn, "/")
- If slashpos Then baretrackname = Mid(trackfn, slashpos + 1) Else baretrackname = trackfn
-
- TLeft , "Downloading '" + baretrackname + "'...", RGB(160, 160, 240)
-
- If InStr(LCase(taddress), "stunts.hu") Then
- length = HTTP_Download(trackfn, tbinary)
- Else
- length = HTTP_Download(baseaddr + "/" + trackfn, tbinary)
- End If
- If length < 0 OrElse (InStr(LCase(taddress), "stunts.hu") <> 0 And length <> 1802) Then
- DrawTrack
- Print length
- Error_Message "Could not download the track " + trackfn
- Return -1
- End If
-
- n = InStrRev(trackfn, "/")
- If n Then trackfn = Mid(trackfn, n + 1)
- n = InStrRev(trackfn, "\")
- If n Then trackfn = Mid(trackfn, n + 1)
-
- n = 0
- For j = 30 To 1 Step -1
- For i = 1 To 30
- grid(i, j).track = tbinary[n]
- n += 1
- Next i
- Next j
- landscape = tbinary[n]
- n += 1
- For j = 1 To 30
- For i = 1 To 30
- grid(i, j).land = tbinary[n]
- n += 1
- Next i
- Next j
- format_byte = tbinary[n]
- PushUndo
-
- If length > 1802 Then
- Dim s As String
-
- For i = 1 To length - 1802
- s &= Chr(tbinary[i + 1801])
- Next i
-
- LoadMetaData , s
- Else
- meta.title = title
- meta.author = author
- meta.cyear = 0
- meta.cmonth = 0
- meta.cday = 0
- Select Case format_byte
- Case 0
- meta.tool = "Track Blaster"
- meta.toolversion = 50300
- Case 150
- meta.tool = "Bliss"
- meta.toolversion = 20100
- Case 151, 152
- meta.tool = "Bliss"
- meta.toolversion = 20400
- Case Else
- meta.tool = "Unknown"
- meta.toolversion = 0
- End Select
- meta.comment = ""
- If LCase(Trim(taddress)) = "zak.stunts.hu" Then
- meta.championship = "ZakStunts " + UCase(Left(trackfn, 6))
- Else
- meta.championship = ""
- End If
- meta.editing_time = -1
- End If
-
- Deallocate tbinary
-
- modified = -1
- track_file = LCase(trackfn)
- UpdateTitleBar
- DrawTrack
- Return 0
- End Function
- Function TMT_GetMain(taddress As String, ByRef curtrack As String, ByRef deadline As String) As Byte
- Dim zaksite As ZString Ptr, length As Long
- Dim As String title, author
- Dim As Short n, m
- Dim trackfn As String
-
- If LCase(Trim(taddress)) = "zak.stunts.hu" Then 'Use Zak's Protocol
- ' length = HTTP_Download("zak.stunts.hu/", zaksite, -1)
- '
- ' If length < 0 Then Return -1
- '
- ' n = InStr(*zaksite, "zct")
- ' trackfn = "ZCT" + Mid(*zaksite, n + 3, 3)
- ' n = InStr(n + 1, *zaksite, "-")
- ' m = InStr(n, *zaksite, "<")
- ' If n <> 0 And m <> 0 And m > n Then
- ' title = Mid(*zaksite, n + 2, m - n - 2)
- ' title = Trim(title)
- ' n = InStr(m, *zaksite, ">")
- ' If n Then
- ' m = InStr(n, *zaksite, ";")
- ' If m Then
- ' n = InStr(m, *zaksite, "<")
- ' If n Then author = Trim(Mid(*zaksite, m + 1, n - m - 1))
- ' End If
- ' End If
- ' End If
- '
- ' n = InStr(*zaksite, "deadline" + Chr(34) + ">")
- ' If n = 0 Then
- ' deadline = "Unknown"
- ' Else
- ' n += 10
- ' m = InStr(n, *zaksite, "<")
- ' deadline = Trim(Mid(*zaksite, n, m - n))
- ' End If
- length = HTTP_Download("zak.stunts.hu/track.json", zaksite)
- If length < 0 Then Return -1
-
- n = InStr(*zaksite, "ZCT")
- trackfn = "ZCT" + Mid(*zaksite, n + 3, 3) + ".trk"
- m = InStr(n + 1, *zaksite, "-")
- If m Then
- n = InStr(m + 1, *zaksite, Chr(34))
- title = Mid(*zaksite, m + 2, n - m - 2)
- End If
- n = InStr(*zaksite, "author" + Chr(34))
- If n Then
- n += 9
- m = InStr(n, *zaksite, Chr(34))
- author = Mid(*zaksite, n, m - n)
- End If
- n = InStr(*zaksite, "deadline" + Chr(34))
- If n Then
- n += 11
- m = InStr(n, *zaksite, Chr(34))
- deadline = Mid(*zaksite, n, m - n)
- End If
-
- Deallocate zaksite : zaksite = 0
- If Len(title) Then
- curtrack = title
- If Len(author) Then curtrack &= " (by " + author + ")"
- Else
- curtrack = trackfn
- End If
-
- Return 0
- Else 'Use Bliss Tournament Protocol
- Dim baseaddr As String, descfile As ZString Ptr
-
- If LCase(Left(taddress, 4)) = "btp:" Then
- baseaddr = Mid(taddress, 5)
- Else
- baseaddr = taddress
- End If
-
- length = HTTP_Download(baseaddr + "/tour.cfg", descfile)
- If length < 0 Then Return -1
- If LCase(Left(*descfile, 4)) <> "tour" Then Return -1
-
- n = InStr(*descfile, "tracktitle=")
- If n Then
- n += 11
- m = InStr(n, *descfile, Chr(10))
- If m Then
- title = Mid(*descfile, n, m - n)
- If Right(title, 1) = Chr(13) Then title = Left(title, Len(title) - 1)
- End If
- End If
-
- n = InStr(*descfile, "trackauthor=")
- If n Then
- n += 12
- m = InStr(n, *descfile, Chr(10))
- If m Then
- author = Mid(*descfile, n, m - n)
- If Right(author, 1) = Chr(13) Then author = Left(author, Len(author) - 1)
- End If
- End If
-
- n = InStr(*descfile, "trackfile=")
- If n Then
- n += 10
- m = InStr(n, *descfile, Chr(10))
- If m Then
- trackfn = Mid(*descfile, n, m - n)
- If Right(trackfn, 1) = Chr(13) Then trackfn = Left(trackfn, Len(trackfn) - 1)
- End If
- End If
- If InStr(trackfn, ".") = 0 Then trackfn &= ".trk"
-
- n = InStr(*descfile, "deadline=")
- If n Then
- n += 9
- m = InStr(n, *descfile, Chr(10))
- If m Then
- deadline = Mid(*descfile, n, m - n)
- If Right(deadline, 1) = Chr(13) Then deadline = Left(deadline, Len(deadline) - 1)
- End If
- End If
-
- Deallocate descfile : descfile = 0
- If Len(title) Then
- curtrack = title
- If Len(author) Then curtrack &= " (by " + author + ")"
- Else
- curtrack = trackfn
- End If
-
- Return 0
- End If
- End Function
- Function TMT_GetScoreboard(taddress As String, item() As Scoreboard, ByRef items As Byte) As Byte
- If InStr(LCase(Trim(taddress)), "zak.stunts.hu") Then
- 'New scoreboard found at:
- 'zak.stunts.hu/api/races/ZCTxxx/scoreboard
-
- Dim filestring As ZString Ptr, length As Long, s As String
- Dim As Long n, m, t1, t2
-
- items = 0
-
- length = HTTP_Download("zak.stunts.hu/track.json", filestring)
- If length < 0 Then Return -1
-
- n = InStr(*filestring, "ZCT")
- s = "ZCT" + Mid(*filestring, n + 3, 3)
-
- length = HTTP_Download("zak.stunts.hu/api/races/" + s + "/scoreboard", filestring)
- If length < 0 Then Return -1
-
- m = 1
- For i As Byte = 1 To 100
- n = InStr(m, *filestring, Chr(34) + "racer" + Chr(34))
- If n = 0 Then Exit For
-
- n = InStr(n, *filestring, Chr(34) + "name" + Chr(34))
- n = InStr(n + 6, *filestring, Chr(34))
- m = InStr(n + 1, *filestring, Chr(34))
- item(i).racer = Mid(*filestring, n + 1, m - n - 1)
-
- n = InStr(m, *filestring, Chr(34) + "model" + Chr(34))
- n = InStr(n + 7, *filestring, Chr(34))
- m = InStr(n + 1, *filestring, Chr(34))
- item(i).car = Mid(*filestring, n + 1, m - n - 1)
-
- n = InStr(m, *filestring, Chr(34) + "lap_time" + Chr(34))
- n = InStr(n + 10, *filestring, ":")
- m = InStr(n + 1, *filestring, ",")
- t1 = ValInt(Mid(*filestring, n + 1, m - n - 1))
- item(i).realtime = Timey(t1)
-
- n = InStr(m, *filestring, Chr(34) + "corrected_time" + Chr(34))
- n = InStr(n + 16, *filestring, ":")
- m = InStr(n + 1, *filestring, ",")
- t2 = ValInt(Mid(*filestring, n + 1, m - n - 1))
- item(i).hctime = Timey(t2)
-
- item(i).handicap = (100 * t2) \ t1 - 100
-
- items += 1
- If i = UBound(item) Then Exit For
- Next i
-
- Deallocate filestring
-
- '~ Dim zaksite As ZString Ptr, length As Long
- '~ Dim trackfn As String
- '~ Dim As Long n, m
-
- '~ length = HTTP_Download("zak.stunts.hu/", zaksite, -1)
- '~ If length < 0 Then Return -1
-
- '~ n = InStr(*zaksite, "ZCT")
- '~ trackfn = "ZCT" + Mid(*zaksite, n + 3, 3)
-
- '~ length = HTTP_Download("zak.stunts.hu/tracks/" + trackfn, zaksite, -1)
- '~ If length < 0 Then Return -1
-
- '~ If InStr(*zaksite, "No results") Then
- '~ items = 0
- '~ Return 0
- '~ End If
-
- '~ m = 1
- '~ For i As Byte = 1 To 100
- '~ n = InStr(m, *zaksite, "rank" + Chr(34) + ">" + Trim(Str(i)) + "<")
- '~ If n = 0 Then items = i - 1 : Exit For
-
- '~ m = InStr(n, *zaksite, "racer" + Chr(34)) + 8
- '~ n = InStr(m, *zaksite, ">") + 1
- '~ m = InStr(n, *zaksite, "<")
- '~ item(i).racer = Trim(Mid(*zaksite, n, m - n))
-
- '~ n = InStr(m, *zaksite, "time" + Chr(34)) + 6
- '~ m = InStr(n, *zaksite, "<")
- '~ item(i).hctime = Trim(Mid(*zaksite, n, m - n))
-
- '~ n = InStr(m, *zaksite, "car-image" + Chr(34)) + 16
- '~ m = InStr(n, *zaksite, Chr(34))
- '~ item(i).car = Trim(Mid(*zaksite, n, m - n))
-
- '~ n = InStr(m, *zaksite, "(") + 1
- '~ m = InStr(n, *zaksite, "%")
- '~ item(i).handicap = ValInt(Mid(*zaksite, n, m - n))
-
- '~ n = InStr(m, *zaksite, "original-time" + Chr(34)) + 15
- '~ m = InStr(n, *zaksite, "<")
- '~ item(i).realtime = Trim(Mid(*zaksite, n, m - n))
- '~ n = m + 1
-
- '~ If i = UBound(item) Then items = i : Exit For
- '~ Next i
- Else
- Dim baseaddr As String, scfile As UByte Ptr, tourfile As ZString Ptr
- Dim length As Long, i As Short, n As Short, s As String
- Dim sbfname As String
-
- If LCase(Left(taddress, 5)) = "btp:" Then
- baseaddr = Mid(taddress, 6)
- Else
- baseaddr = taddress
- End If
-
- length = HTTP_Download(baseaddr + "/tour.cfg", tourfile)
- If length < 0 Then Return -1
- If LCase(Left(*tourfile, 4)) <> "tour" Then Return -1
-
- Dim m As Long
- n = InStr(*tourfile, "scoreboard=")
- If n Then
- n += 11
- m = InStr(n, *tourfile, Chr(10))
- If m Then
- sbfname = Mid(*tourfile, n, m - n)
- If Right(sbfname, 1) = Chr(13) Then sbfname = Left(sbfname, Len(sbfname) - 1)
- End If
- End If
-
- Deallocate tourfile : tourfile = 0
- length = HTTP_Download(baseaddr + "/" + sbfname, scfile)
-
- If length = 0 Then
- items = 0
- Return 0
- End if
-
- 'Skip all control characters other than character 10
- s = ""
- For i = 0 To length - 1
- If scfile[i] >= 32 Or scfile[i] = 10 Then s &= Chr(scfile[i])
- Next i
-
- Deallocate scfile : scfile = 0
- Dim sbx As Scoreboard, l As String
- Dim pass As Byte
-
- items = 0
- Do While Len(s)
- n = InStr(s, Chr(10))
- If n Then
- l = Left(s, n - 1)
- s = Mid(s, n + 1)
- Else
- l = s
- s = ""
- End If
-
- l = Trim(l)
- If Left(l, 1) = "[" And Right(l, 1) = "]" Then
- If pass <> 0 Then
- items += 1
- item(items) = sbx
- Else
- sbx.racer = "Unknown"
- sbx.car = "????"
- sbx.realtime = ""
- sbx.hctime = ""
- sbx.style = ""
- sbx.handicap = 0
- sbx.verified = 0
- pass = -1
- End If
- ElseIf InStr(l, "=") Then
- Dim As String varid, v
-
- varid = LCase(RTrim(Left(l, InStr(l, "=") - 1)))
- v = LTrim(Mid(l, InStr(l, "=") + 1))
-
- Select Case varid
- Case "carid", "car" : sbx.car = v
- Case "name" : sbx.racer = v
- Case "lap" : sbx.realtime = Timey((ValInt(v) - 1828 - 20) * 5)
- Case "laptime" : sbx.realtime = v
- Case "style" : sbx.style = v
- Case "handicap" : sbx.handicap = ValInt(v)
- Case "competing"
- If LCase(v) <> "yes" Then pass = 0
- Case "status"
- If LCase(v) = "verified" Then
- sbx.verified = -1
- ElseIf LCase(v) = "rejected" Then
- pass = 0
- End If
- End Select
- End If
- Loop
- If pass <> 0 Then
- items += 1
- item(items) = sbx
- End If
- End If
-
- 'Make sure the values are valid
- For i As Byte = 1 To items
- item(i).racer = Left(item(i).racer, 20)
- item(i).hctime = Left(item(i).hctime, 8)
- item(i).car = Left(item(i).car, 10)
- item(i).realtime = Left(item(i).realtime, 8)
- If item(i).handicap < -100 Then
- item(i).handicap = -100
- ElseIf item(i).handicap > 100 Then
- item(i).handicap = 100
- End If
- Next i
-
- Return 0
- End Function
- #endif
- Sub TrackErrorMessage(e As UByte)
- Select Case e
- Case 20 : Error_Message "Dangerous path on mountain border", "Warning!"
- Case 21 : Error_Message "Jump is not feasible in OWOOT", "Warning!"
- Case 22 : Error_Message "Inverted jump. Not feasible in OWOOT", "Warning!"
- Case 23 : Error_Message "Water will display as grass", "Warning!"
- Case 24 : Error_Message "Water will be solid here", "Warning!"
- Case 40 : Error_Message "Non-standard terrain element", "Fatal Error!"
- Case 41 : Error_Message "Mountain borders mismatch"
- Case 50 : Error_Message "Objects on mountain corners will not display correctly", "Warning"
- Case 51 : Error_Message "Only straightways and ramps will display on mountain borders", "Warning"
- Case 60 : Error_Message "Start/Finish line not found"
- Case 61 : Error_Message "Too many start/finish lines!"
- Case 62 : Error_Message "Terrain at track start is inadequeate"
- Case 70 : Error_Message "Track type mismatch"
- Case 71 : Error_Message "Straightway before jump is too short"
- Case 72 : Error_Message "Wrong way"
- Case 73 : Error_Message "Jump distance is too long"
- Case 74 : Error_Message "Stunts won't allow interrupting this bridge"
- Case 80 : Error_Message "Grid border reached"
- Case 81 : Error_Message "Path interrupted"
- Case 82 : Error_Message "Cyclic path"
- Case Else : Error_Message "Error #" + Str(e)
- End Select
-
- DrawTrack
- End Sub
- Sub Undo
- 'If the pointer would be at the tail, then there's no undo.
- If ((undotail + 1) Mod UNDOLEVEL) = undopointer Then Exit Sub
-
- 'Decrement the pointer for the next undo
- If undopointer Then undopointer -= 1 Else undopointer = UNDOLEVEL - 1
-
- 'Restore grid
- If Len(undobuffer(undopointer)) = 0 Then _
- undobuffer(undopointer) = Chr(30, 30) + String(1800, 0)
- PutTrack 1, 1, undobuffer(undopointer), -1
- DrawTrack
- End Sub
- Sub UnRLETerrain(ter As String)
- Dim As Short x = 1, y = 1, n = 0
- Dim what As UByte, s As String
-
- s = ter
-
- Do
- If n Then
- grid(x, y).land = what
- n -= 1
- x += 1
- If x = 31 Then x = 1 : y += 1
- Else
- what = ASC(Left(s, 1))
- If what And 128 Then
- n = what And 127
- what = ASC(Mid(s, 2, 1))
- s = Mid(s, 3)
- Else
- grid(x, y).land = what
- s = Mid(s, 2)
- x += 1
- If x = 31 Then x = 1 : y += 1
- End If
- End If
- Loop Until y = 31
- End Sub
- Sub UpdateTitleBar
- Dim s As String
- If Len(Trim(meta.title)) Then
- s = Trim(meta.title)
- If Len(Trim(meta.author)) Then _
- s &= " (by " + Trim(meta.author) + ")"
- ElseIf Len(Trim(track_file)) Then
- s = Trim(track_file)
- If Len(Trim(meta.author)) Then _
- s &= " (by " + Trim(meta.author) + ")"
- End If
-
- If Len(s) Then
- s = ptitle + " - " + s
- Else
- s = ptitle
- End If
-
- #ifdef __FB_DOS__
- WindowTitle Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s))
- #else
- changing_title = -1
- WindowTitle Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s))
- changing_title = 0
- #endif
- End Sub
- 'Flip buffer rectangle horizontally
- Function VFlipTrack(t As String) As String
- Dim As Byte w, h, c
- w = ASC(Left(t, 1))
- h = ASC(Mid(t, 2, 1))
-
- Dim temp(1 To w, 1 To h) As SGrid
- Dim s As String, i As Byte, j As Byte, n As Short
-
- 'Read and flip
- n = 3 : i = 1 : j = h
- Do While n <= Len(t)
- c = ASC(Mid(t, n, 1))
- n += 1
- If c And 1 Then 'Track is non-zero
- temp(i, j).track = tr(ASC(Mid(t, n, 1))).vflip
- n += 1
- End If
- If c And 2 Then 'Terrain is non-zero
- temp(i, j).land = ttr(ASC(Mid(t, n, 1))).vflip
- n += 1
- End If
- If c And 4 Then 'Border colour is non-zero
- temp(i, j).border = CvL(Mid(t, n, 4))
- n += 4
- End If
- If c And 8 Then 'Background colour is non-zero
- temp(i, j).bgc = CvL(Mid(t, n, 4))
- n += 4
- End If
-
- i += 1
- If i > w Then i = 1 : j -= 1
- Loop
-
- 'Fix
- For i = 1 To w
- For j = 1 To h - 1
- If temp(i, j).track = 254 Or temp(i, j).track = 253 Then
- Swap temp(i, j).track, temp(i, j + 1).track
- j += 1
- End If
- Next j
- Next i
- 'Put back into the string
- s = PackedClip(temp())
-
- Return s
- End Function
- 'Push the current grid into the undo buffer
- Sub PushUndo
- 'Advance the pointer
- undopointer = (undopointer + 1) Mod UNDOLEVEL
-
- 'If there were pending redos (the user has been undoing),
- 'drop them, as they are now obsolete
- If undohead <> undopointer Then undohead = undopointer
-
- 'Store current grid
- undobuffer(undohead) = GetTrack(1, 1, 30, 30)
-
- 'If the head reaches the tail (there are already UNDOLEVEL undos
- 'in the buffer), then drop the oldest undo by advancing the tail
- If undohead = undotail Then undotail = (undotail + 1) Mod UNDOLEVEL
- End Sub
- Sub PutIcon(u As UByte, v As UByte, x As UShort, y As UShort)
- If track_image_buffer = 0 Then
- If dosbox Then
- Put (x, y), bigicons, (u * bigwidth, v * 22)- STEP (bigwidth - 1, 21), Trans
- Else
- Put (x, y), bigicons, (u * bigwidth, v * 22)- STEP (bigwidth - 1, 21), Alpha
- End If
- Else
- If dosbox Then
- Put track_image_buffer, (x, y), bigicons, (u * bigwidth, v * 22)- STEP (bigwidth - 1, 21), Trans
- Else
- Put track_image_buffer, (x, y), bigicons, (u * bigwidth, v * 22)- STEP (bigwidth - 1, 21), Alpha
- End If
- End If
- End Sub
- Sub PutSmallIcon(u As UByte, v As UByte, x As UShort, y As UShort)
- If dosbox Then
- Put (x, y), bigicons, (u * graphic_size, v * graphic_size)- STEP (graphic_size - 1, graphic_size - 1), Trans
- Else
- Put (x, y), bigicons, (u * graphic_size, v * graphic_size)- STEP (graphic_size - 1, graphic_size - 1), Alpha
- End If
- End Sub
- Sub CheckClipboardImport
- 'Do not import clipboard if currently pasting (it would mess up)
- If pasting Then Exit Sub
-
- 'Do not delete the clipboard if nothing to import
- If FileExists(program_path & "clip.tmp") AndAlso _
- FileLen(program_path & "clip.tmp") <> last_cb_file_length Then
-
- Dim f As Integer, b As Byte
-
- f = FreeFile
- Open program_path & "clip.tmp" For Binary Access Read As f
- Get #f, , b
- If b Then Get #f, , b
-
- clipboard = Space(LOF(f) - Seek(f) + 1)
- Get #f, , clipboard
-
- last_cb_file_length = LOF(f)
- Close f
- DrawPanel
- End If
- End Sub
- Sub CheckTrack
- Dim v As TrackVector
- Dim As Short i, j
- Dim track_closed As Byte = 0
- Dim e As UByte
- Dim As Byte ex, ey
-
- DetectTerrainErrors e, ex, ey
- If e >= 40 And e <= 49 Then
- TrackErrorMessage e
- DrawTrack
- xcursor = ex : ycursor = ey
- ManageKeyboardCursor -1
- Exit Sub
- End If
-
- v = FindStart
- Select Case v.e
- Case 60
- Error_Message "Start/finish line not found"
- DrawTrack
- Exit Sub
- Case 61
- Error_Message "Too many start/finish lines!"
- DrawTrack
- Exit Sub
- Case 62
- Error_Message "Terrain at track start is inadequate"
- DrawTrack
- Exit Sub
- End Select
-
- GenerateSections
- If sections > 254 Or paths >= MAXPATHS Then
- Error_Message "Track is too complex. Too many splits!"
- Exit Sub
- End If
-
- 'Find track-fatal errors
- For i = 1 To paths
- If path(i).e >= 70 And path(i).e <= 79 Then
- TrackErrorMessage path(i).e
-
- FollowPath path(i).p, path(i).e
- Exit Sub
- End If
- Next i
-
- 'So, track is OK, but is there any warning?
- For i = 1 To paths
- If path(i).e >= 20 And path(i).e <= 29 Then
- TrackErrorMessage path(i).e
-
- FollowPath path(i).p, path(i).e
- Exit Sub
- End If
- Next i
-
- 'See if there's a path to the finish-line with no errors
- For i = 1 To paths
- If path(i).finishes Then
- Error_Message "Found winning path", "Track OK"
- DrawTrack
- FollowPath path(i).p
- Exit Sub
- End If
- Next i
-
- 'Reject tracks that are not closed
- Error_Message "At least one path must be closed"
- DrawTrack
-
- For i = 1 To paths
- FollowPath path(i).p
- Next i
-
- v.coors = section(ASC(Right(path(1).p, 1))).final
- xcursor = v.x : ycursor = v.y
- ManageKeyboardCursor -1
- End Sub
- Sub ClearTrack(x As UByte, y As UByte)
- Dim As Short alterx, altery
- Dim element As UByte
-
- If allow_errors Then
- alterx = x : altery = y
- Else
- Select Case grid(x, y).track
- Case 255 : alterx = x - 1 : altery = y
- Case 254 : alterx = x : altery = y - 1
- Case 253 : alterx = x - 1 : altery = y - 1
- Case Else : alterx = x : altery = y
- End Select
- End If
-
- If alterx < 1 Then alterx = 1
- If altery < 1 Then altery = 1
- element = grid(alterx, altery).track
- grid(alterx, altery).track = 0
- DrawSpot alterx, altery
-
- 'Tunnels
- If element = &H42 Then
- If y > 1 Then DrawSpot x, y - 1
- If y < 30 Then DrawSpot x, y + 1
- ElseIf element = &H43 Then
- If x > 1 Then DrawSpot x - 1, y
- If x < 30 Then DrawSpot x + 1, y
- End If
-
- If Not allow_errors Then
- If tr(element).w > 1 Then
- If alterx + 1 <= 30 Then grid(alterx + 1, altery).track = 0 : DrawSpot alterx + 1, altery
- If tr(element).h > 1 Then
- If alterx + 1 <= 30 And altery + 1 <= 30 Then grid(alterx + 1, altery + 1).track = 0 : DrawSpot alterx + 1, altery + 1
- End if
- End If
- If tr(element).h > 1 Then
- If altery + 1 <= 30 Then grid(alterx, altery + 1).track = 0 : DrawSpot alterx, altery + 1
- End If
- If grid(x, y).track <> 0 Then grid(x, y).track = 0 : DrawSpot x, y
- End If
- End Sub
- Sub Menu_TrackInfo
- Dim As Integer xm, ym, wm, bm
- Dim v As Short, s As String
- Dim et As Long, top As Short
- Dim content(0 To 6, 1 To 2) As String
- Dim As Byte current = -1, former = -1, update = -1
- Dim akey As String
-
- If thisfileformat = FORMAT_RAW Then
- Error_Message "Format set to one-file to allow for metadata", "Warning!"
- thisfileformat = FORMAT_COMBINED
- DrawTrack
- End If
-
- MenuBox 36, 29, "Track Information"
-
- top = ceny
- lefx += 8
- TLeft
- content(0, 1) = "Track title:"
- TLeft , content(0, 1), RGB(200, 200, 200)
- If Len(meta.title) Then
- s = Left(meta.title, 64)
- ElseIf Len(track_file) Then
- s = UCase(Left(track_file, 1)) + LCase(Mid(track_file, 2))
- v = InStr(s, ".")
- If v Then s = Left(s, v - 1)
- Else
- s = "Untitled"
- End If
- content(0, 2) = s
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- TLeft
- content(1, 1) = "Author:"
- TLeft , content(1, 1), RGB(200, 200, 200)
- If Len(meta.author) Then
- s = Left(meta.author, 64)
- Else
- s = "Anonymous"
- End If
- content(1, 2) = s
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- TLeft
- TLeft , "Date created:", RGB(200, 200, 200)
- If meta.cyear Then
- s = Str(meta.cyear)
- If meta.cmonth Then
- s = Str(meta.cmonth) + "-" + s
- If meta.cday Then s = Str(meta.cday) + "-" + s
- End If
- Else
- s = "Unknown"
- End If
- TLeft , s, RGB(160, 160, 240)
- TLeft
- TLeft , "Created with:", RGB(200, 200, 200)
- If meta.toolversion Then
- s = Left(meta.tool, 32) + " " + Str(meta.toolversion \ 10000)
- s &= "." + Str((meta.toolversion Mod 10000) \ 100)
- If meta.toolversion Mod 100 Then s &= "." + Str(meta.toolversion Mod 100)
- Else
- s = Left(meta.tool, 32)
- End If
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- TLeft
- TLeft , "Editing time:", RGB(200, 200, 200)
- If meta.editing_time >= 0 THen
- et = meta.editing_time + Timer - started_editing
- s = ""
- If et >= 3600 Then s = Str(et \ 3600) + "h "
- s &= Str((et Mod 3600) \ 60) + "' "
- s &= Str(et Mod 60) + Chr(34)
- Else
- s = "Unknown"
- End If
- TLeft , s, RGB(160, 160, 240)
- TLeft
- content(5, 1) = "Comment:"
- TLeft , content(5, 1), RGB(200, 200, 200)
- If Len(meta.comment) Then
- s = Left(meta.comment, 64)
- Else
- s = "No comment"
- End If
- content(5, 2) = s
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- TLeft
- content(6, 1) = "Championship information:"
- TLeft , content(6, 1), RGB(200, 200, 200)
- If Len(meta.championship) Then
- s = Left(meta.championship, 64)
- Else
- s = "No info"
- End If
- content(6, 2) = s
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- TLeft
- TLeft
-
- buttons = 0
- StackButton " Cancel ", 2
- StackButton " Update ", 1
- EndOfButtonStack
-
- Do
- GetMouse xm, ym, wm, bm
- If xm < lefx - 8 Or xm >= lefx + 8 * 67 Or ym < top + 8 Or ym >= top + 7 * 48 + 8 Then
- current = -1
- Else
- current = (ym - top - 8) \ 48
- End If
-
- If current <> former Or update = -1 Then
- ScreenLock
- If former = 0 Or former = 1 Or former = 5 Or former = 6 Then
- Line (lefx - 4, top + 8 + 48 * former)- Step (8 * 67 - 1, 47), RGB(30, 30, 50), BF
- ceny = top + 16 + 48 * former
- s = content(former, 2)
- TLeft , content(former, 1), RGB(200, 200, 200)
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- End If
- If current = 0 Or current = 1 Or current = 5 Or current = 6 Then
- Line (lefx - 4, top + 8 + 48 * current)- Step (8 * 67 - 1, 47), RGB(10, 10, 10), BF
- ceny = top + 16 + 48 * current
- s = content(current, 2)
- TLeft , content(current, 1), RGB(200, 200, 200)
- #ifdef RENDER_TO_CP437
- TLeft , Enc_UTF32_to_CP437(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #else
- TLeft , Enc_UTF32_to_Latin1(Enc_UTF8_to_UTF32(s)), RGB(160, 160, 240)
- #endif
- End If
- ScreenUnlock
-
- former = current
- update = 0
- End If
-
- v = ManageButtons
- If STRONG_ANTI_HOG Then Sleep 1
-
- If bm = 1 And (current = 0 Or current = 1 Or current = 5 Or current = 6) Then
- stringer.init = -1
- stringer.maxlength = 64
- stringer.fileonly = 0
- stringer.x = lefx
- stringer.y = 48 * current + top + 32
- stringer.background = RGB(10, 10, 10)
- If current = 0 And content(current, 2) = "Untitled" Then content(current, 2) = ""
- If current = 1 And content(current, 2) = "Anonymous" Then content(current, 2) = ""
- If current = 5 And content(current, 2) = "No comment" Then content(current, 2) = ""
- If current = 6 And content(current, 2) = "No info" Then content(current, 2) = ""
- Do
- akey = ManageString(content(current, 2))
- v = ManageButtons
- Loop Until akey = Chr(13) Or akey = Chr(27) Or v <> 0
- If current = 0 And Trim(content(current, 2)) = "" Then content(current, 2) = "Untitled"
- If current = 1 And Trim(content(current, 2)) = "" Then content(current, 2) = "Anonymous"
- If current = 5 And Trim(content(current, 2)) = "" Then content(current, 2) = "No comment"
- If current = 6 And Trim(content(current, 2)) = "" Then content(current, 2) = "No info"
- update = -1
-
- Dim t As Double
- t = Timer
- Do : Loop Until Timer >= t + .3
- Do : Loop Until Len(InKey) = 0
- End If
-
- akey = InKey
- Loop Until v Or akey = Chr(13) Or akey = Chr(27)
- buttons = 0
-
- If v = 1 Or akey = Chr(13) Then
- meta.title = Trim(content(0, 2))
- If meta.title = "Untitled" Then meta.title = ""
- meta.author = Trim(content(1, 2))
- If meta.author = "Anonymous" Then meta.author = ""
- meta.comment = Trim(content(5, 2))
- If meta.comment = "No comment" Then meta.comment = ""
- meta.championship = Trim(content(6,2))
- If meta.championship = "No info" Then meta.championship = ""
- End If
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
-
- UpdateTitleBar
- DrawTrack
- End Sub
- Sub Menu_Tournaments
- #ifdef __FB_DOS__
- Error_Message "Tournament option not available in DOS"
- #else
- Dim tmt(1 To 10) As String, addr(1 To 10) As String, tmts As Byte
- Dim n As Short, v As Short, current_tournament As Byte, top As Short
- Dim page As Byte, reload_tournament As Byte = -1
- Dim As Integer xm, ym, wm, bm
- Dim As String curtrack, deadline
-
- If FileExists(program_path + "tours.dat") Then
- Dim ff As Integer
-
- ff = FreeFile
- Open program_path + "tours.dat" For Binary Access Read As ff
- While Not EOF(ff)
- tmts += 1
- Get #ff, , n
- tmt(tmts) = Space(n)
- Get #ff, , tmt(tmts)
- Get #ff, , n
- addr(tmts) = Space(n)
- Get #ff, , addr(tmts)
- WEnd
- Close ff
- End If
-
- Do
- Select Case page
- Case 0 'Main page, list of tournaments
- Dim update As Byte = -1
-
- Do
- If update Then
- ScreenLock
- DrawTrack
- If tmts Then
- MenuBox 30, 8 + 3 * tmts, "Tournaments"
- If current_tournament = 0 Then current_tournament = 1
- Line (lefx - 4, ceny + 48 * current_tournament - 40)- Step (455, 47), RGB(10, 10, 10), BF
- Else
- MenuBox 30, 11, "Tournaments"
- End If
-
- top = ceny : lefx += 8
- TLeft
- If tmts Then
- For n = 1 To tmts
- TLeft , tmt(n), RGB(200, 200, 200)
- TLeft , addr(n), RGB(160, 160, 240)
- TLeft
- Next n
- Else
- TLeft
- TCentre , "No tournaments found", RGB(160, 160, 240)
- TLeft
- End If
- TLeft
-
- buttons = 0
- If tmts Then
- StackButton " Connect ", 1
- StackButton " Remove ", 2
- End If
- If tmts < 10 Then StackButton " Add New ", 3
- StackButton " Done ", 10
- EndOfButtonStack
- ScreenUnlock
-
- update = 0
- End If
-
- GetMouse xm, ym, wm, bm
- If STRONG_ANTI_HOG Then Sleep 1
-
- If bm = 1 And tmts <> 0 Then
- If xm >= lefx - 4 And xm <= lefx + 459 And ym >= top + 8 Then
- n = (ym - top - 8) \ 48 + 1
- If n <= tmts And n <> current_tournament Then
- current_tournament = n
- update = -1
- End If
- End If
- End If
-
- v = ManageButtons
- Loop Until v
- buttons = 0
-
- If v = 2 And tmts <> 0 Then 'Remove
- For i As Byte = current_tournament To tmts - 1
- tmt(i) = tmt(i + 1)
- addr(i) = addr(i + 1)
- Next i
- tmts -= 1
- If current_tournament > tmts Then current_tournament = tmts
- ElseIf v = 3 Then
- page = 1
- ElseIf v = 1 Then
- reload_tournament = -1
- page = 2 'Connect
- End If
-
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- Case 1 'Add tournament
- Dim As String title, address, akey
- Dim As Byte which = 0, old = 1
-
- MenuBox 30, 14, "Add Tournament"
-
- lefx += 8 : top = ceny
- TLeft
- TLeft , "Tournament name:", RGB(200, 200, 200)
- TLeft
- TLeft
- TLeft , "Domain name (base address):", RGB(200, 200, 200)
- TLeft
- TLeft
- TLeft
-
- buttons = 0
- StackButton " Cancel ", 2
- StackButton " Create ", 1
- EndOfButtonStack
-
- stringer.x = lefx
- stringer.fileonly = 0
- stringer.maxlength = 40
- stringer.background = RGB(30, 30, 50)
- Do
- If old <> which Then
- Line (lefx, top + 48 * old + 32)- Step (449, 15), RGB(30, 30, 50), BF
- If old Then
- Draw String (lefx, top + 80), address + Space(40 - Len(address)), RGB(160, 160, 240)
- stringer.y = top + 32
- Else
- Draw String (lefx, top + 32), title + Space(40 - Len(title)), RGB(160, 160, 240)
- stringer.y = top + 80
- End If
- stringer.init = -1
- old = which
- End If
-
- v = ManageButtons
- If which Then
- akey = ManageString(address)
- Else
- akey = ManageString(title)
- End If
- If STRONG_ANTI_HOG Then Sleep 1
-
- Select Case akey
- Case Chr(9) : which = 1 - which
- Case Chr(13)
- If which Then
- v = 1 : Exit Do
- Else
- which = 1 - which
- End If
- Case Chr(27) : v = 2 : Exit DO
- End Select
- Loop Until v
- Do : Loop Until Len(InKey) = 0
-
- If v = 1 Then
- tmts += 1
- tmt(tmts) = Trim(title)
- addr(tmts) = Trim(address)
- End If
- page = 0
-
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- Case 2 'Attempt connection to tournament
- Dim result As Byte
-
- If reload_tournament Then
- MenuBox 20, 7, "Please wait"
- TLeft
- TCentre , "Attempting connection...", RGB(160, 160, 240)
-
- result = TMT_GetMain(addr(current_tournament), curtrack, deadline)
- DrawTrack
- Else
- result = 0
- End If
-
- If result Then
- Error_Message "Failed to connect to " + tmt(current_tournament)
- v = 3
- Else
- MenuBox 35, 14, tmt(current_tournament)
-
- lefx += 8
- TLeft
- TLeft , "Current race:", RGB(200, 200, 200)
- TLeft , curtrack, RGB(160, 160, 240)
- TLeft
- TLeft , "Deadline:", RGB(200, 200, 200)
- TLeft , deadline, RGB(160, 160, 240)
- TLeft
- TLeft
-
- buttons = 0
- StackButton " Back ", 3
- StackButton " Get Track ", 1
- StackButton " Scoreboard ", 2
- EndOfButtonStack
-
- Do
- v = ManageButtons
- Loop Until v
- If STRONG_ANTI_HOG Then Sleep 1
- buttons = 0
- reload_tournament = 0
- End If
-
- If v = 1 Then
- DrawTrack
- TMT_GetCurrentTrack addr(current_tournament)
- ElseIf v = 2 Then
- page = 3
- ElseIf v = 3 Then
- page = 0
- End If
-
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- Case 3 'Scoreboard
- Dim item(1 To 100) As Scoreboard, items As Byte
- Dim result As Byte
-
- MenuBox 20, 7, "Please wait"
- TLeft
- TCentre , "Loading scoreboard...", RGB(160, 160, 240)
-
- result = TMT_GetScoreboard(addr(current_tournament), item(), items)
- DrawTrack
-
- If result Then
- Error_Message "Failed to get the scoreboard"
- ElseIf items = 0 Then
- Error_Message "Scoreboard is empty", tmt(current_tournament) + " - Scoreboard"
- Else
- Dim top As Short
- Dim As ULong normal = RGB(160, 160, 240), bright = RGB(180, 180, 80)
-
- Do : Loop Until Len(InKey) = 0
-
- ScreenLock
- MenuBox 35, 9 + items, tmt(current_tournament) + " - Scoreboard"
- lefx += 8
- TLeft
- top = ceny
-
- For i As Byte = 1 To items
- Dim s As String
-
- s = Str(i) : If Len(s) = 1 Then s = " " + s
- concolour = normal
- TCont s + " - " + item(i).racer + " (" + item(i).car + ")"
- concolour = bright : conx = lefx + 320
- If Len(item(i).hctime) = 0 Then
- TCont Space(8) + item(i).realtime
- Else
- TCont item(i).realtime + " " + item(i).hctime
- End If
- If item(i).handicap Then
- s = "(" + Str(item(i).handicap) + "%)"
- ElseIf Len(item(i).style) Then
- s = "(" + item(i).style + ")"
- Else
- s = ""
- End If
- If item(i).verified Then s &= Chr(251)
- concolour = normal
- TCont s, -1
- Next i
- ScreenUnlock
-
- buttons = 0
- ceny = top + 16 * items + 32
- StackButton " OK ", 1
- EndOfButtonStack
-
- Do
- v = ManageButtons
- If STRONG_ANTI_HOG Then Sleep 1
- Loop Until v <> 0 Or Len(InKey) <> 0
-
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- End If
-
- page = 2
- End Select
- Loop Until v = 10
-
- Do : Loop Until Len(InKey) = 0
-
- If tmts Then
- Dim ff As Integer
- ff = FreeFile
- Open program_path + "tours.dat" For Output As ff : Close ff
- Open program_path + "tours.dat" For Binary As ff
- For i As Byte = 1 To tmts
- n = Len(tmt(i))
- Put #ff, , n
- Put #ff, , tmt(i)
- n = Len(addr(i))
- Put #ff, , n
- Put #ff, , addr(i)
- Next i
- Close ff
- Else
- If FileExists(program_path + "tours.dat") Then Kill program_path + "tours.dat"
- End If
- #endif
- End Sub
- Sub Menu_TrackShot
- Dim tiname As String, tsformat As SelectorType
- MenuBox 28, 12, "Track-shot"
-
- TLeft ,
-
- tsformat.redraw = -1
- tsformat.options = 6
- tsformat.opt(1) = "TGA"
- tsformat.opt(2) = "BMP"
- tsformat.opt(3) = "PCX"
- tsformat.opt(4) = "GIF"
- tsformat.opt(5) = "JPG"
- tsformat.opt(6) = "PNG"
- tsformat.current = 1
- For i As Byte = 1 To 6
- If LCase(tsformat.opt(i)) = LCase(imageformat) Then
- tsformat.current = i
- Exit For
- End If
- Next i
- tsformat.x1 = cenx + 8
- tsformat.x2 = cenx + 108
- tsformat.y1 = ceny - 8
- tsformat.y2 = ceny + 23
- TCentre , "Image format: ", RGB(160, 160, 240)
- TLeft ,
- TCentre , "Only TGA and BMP are supported natively", RGB(160, 160, 240)
- TCentre , "Other formats require ImageMagick", RGB(160, 160, 240)
- TLeft ,
-
- buttons = 0
- StackButton " Cancel ", 1
- StackButton " Save ", 2
- EndOfButtonStack
-
- Dim v As Short, akey As String
- Do
- v = ManageButtons
- ManageSelector tsformat
-
- akey = InKey
- If STRONG_ANTI_HOG Then Sleep 1
-
- Select Case akey
- Case Chr(13) : v = 2 : Exit Do
- Case Chr(27) : v = 1 : Exit Do
- End Select
- Loop Until v <> 0
-
- buttons = 0
- DrawTrack
-
- If v = 2 Then
- imageformat = LCase(tsformat.opt(tsformat.current))
- If Len(Trim(track_file)) Then
- If LCase(Right(track_file, 4)) = ".trk" Then
- tiname = Left(track_file, Len(track_file) - 3) + imageformat
- Else
- tiname = track_file + "." + imageformat
- End If
- Else
- tiname = "track." + imageformat
- End If
-
- SaveTrackImage program_path + tiname
- If FileExists(program_path + tiname) Then
- Error_Message "Track image saved as '" & tiname & "'", "Track-shot"
- Else
- Error_Message "Track image could not be saved!"
- End If
- End If
- End Sub
- Sub NotASquare
- Dim v As Short
- MenuBox 32, 10, "Cannot rotate!"
- ceny += 8
- TCentre , "The selected area has to be a square to rotate in-situ", RGB(200, 200, 240)
- TCentre , "Adjust dimensions or copy the selection to the", RGB(200, 200, 240)
- TCentre , "clipboard and then paste before rotating.", RGB(200, 200, 240)
- TCentre
-
- If xselect > x2select Then Swap xselect, x2select
- If yselect > y2select Then Swap yselect, y2select
- If xselect + y2select - yselect <= 30 Then _
- StackButton " Adjust width ", 1
- If yselect + x2select - xselect <= 30 Then _
- StackButton " Adjust height ", 2
- StackButton " Cancel ", 3
- EndOfButtonStack
- Do
- v = ManageButtons
- Loop Until v <> 0 Or InKey <> ""
- buttons = 0
-
- Select Case v
- Case 1 : x2select = xselect + y2select - yselect
- Case 2 : y2select = yselect + x2select - xselect
- End Select
-
- Dim As Integer xm, ym, wm, bm
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- Do : Loop Until Len(InKey) = 0
- DrawTrack
- End Sub
- Sub Paste
- If Len(clipboard) Then pasting = -1
- End Sub
- Function PathLength(n As Short, weighed As Byte = 0) As Long
- Dim l As Long = 0, i As Short
- Dim v As TrackVector, s As Short
- Dim juststarted As Byte
-
- For i = 1 To Len(path(n).p)
- s = ASC(Mid(path(n).p, i, 1))
- v.coors = section(s).initial
- v.bearing = section(s).bearing
- If sections = 1 And section(1).finishes <> 0 Then juststarted = -1
- While v.coors <> section(s).final Or juststarted
- v = GetNext(v)
- juststarted = 0
- If weighed Then
- l += tr(grid(v.x, v.y).track).length
- Else
- If tr(grid(v.x, v.y).track).w > 1 Or tr(grid(v.x, v.y).track).h > 1 Then
- l += 2
- Else
- l += 1
- End If
- End If
- WEnd
- Next i
-
- If weighed Then
- l += 10
- Else
- l += 1
- End If
-
- Return l
- End Function
- Function PathToError(te As Short) As String
- Dim s As String, i As Short, current As Short
-
- 'I believe this function may hang when executed to find
- 'a cycle that's made of more than one section if it happens
- 'to choose the same two or more sections over and over.
-
- current = terror(te).section
- s = Chr(current)
- While current <> 1
- For i = 1 To sections
- If i <> current And section(i).final = section(current).initial Then
- current = i
- s = Chr(i) + s
- Exit For
- End If
- Next i
- Wend
-
- Return s
- End Function
- Function PathToFinishLine(which As Byte = 0) As String
- Dim i As Short
-
-
- Return ""
- End Function
- Sub PickTrack(x As UByte, y As UByte)
- Dim As Short alterx, altery
-
- Select Case grid(x, y).track
- Case 255 : alterx = x - 1 : altery = y
- Case 254 : alterx = x : altery = y - 1
- Case 253 : alterx = x - 1 : altery = y - 1
- Case Else : alterx = x : altery = y
- End Select
-
- If alterx < 1 Then alterx = 1
- If altery < 1 Then altery = 1
-
- current_brush = grid(alterx, altery).track
- End Sub
- Sub SelectByTyping
- Dim As String akey, s
- Dim As Integer xm, ym, wm, bm, xo, yo
- Dim t As Double
-
- GetMouse xo, yo, wm, bm
- t = Timer
-
- Do
- akey = InKey
-
- Select Case akey
- Case ""
- Case Chr(27) : s = "" : Exit Do
- Case Chr(8)
- If Len(s) > 1 Then s = Left(s, Len(s) - 1)
- Case " " To Chr(126) : s = s + akey
- Case Else : Exit Do
- End Select
-
- If Len(akey) And Len(s) Then
- For i As Short = 1 To current_brush + 255
- Dim n As Byte, namey As String
-
- namey = Trim(tr(i).id)
- n = InStr(LCase(namey), LCase(s))
- If n Then
- current_brush = i
- ScreenLock
- DrawPanel
- Draw String (xpanel + 99 - Len(namey) * 4 + (n - 1) * 8, ypanel + ypalette + 82), Mid(namey, n, Len(s)), RGB(50, 200, 250)
- ScreenUnlock
- Exit For
- End If
- Next i
- End If
-
- GetMouse xm, ym, wm, bm
- If bm <> 0 Then
- Exit Do
- ElseIf xo = -1 And xm <> -1 Then
- Exit Do
- ElseIf xo <> -1 And xm = -1 Then
- Exit Do
- ElseIf Sqr((xm - xo) ^ 2 + (ym - yo) ^ 2) > 10 Then
- Exit Do
- End If
- Loop Until Timer > t + 5
- DrawPanel
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
- End Sub
- Sub SetTrack(x As UByte, y As UByte, code As UByte)
-
- 'First, check that the new element can be placed
- If Not allow_errors Then
- If (x = 30 And tr(code).w > 1) Or (y = 30 And tr(code).h > 1) Then
- Exit Sub
- End If
- End If
- ScreenLock
- 'Then make sure to leave no incomplete track elements
- If Not allow_errors Then
- ClearTrack x, y
- If tr(code).w > 1 And x < 30 Then
- ClearTrack x + 1, y
- If tr(code).h > 1 And y < 30 Then ClearTrack x + 1, y + 1
- End If
- If tr(code).h > 1 And y < 30 Then ClearTrack x, y + 1
- End If
-
- 'Finally, place the new element
- grid(x, y).track = code : DrawSpot x, y
-
- 'If it's a tunnel, make it look good
- If code = &H42 Then 'Vertical tunnel
- If y > 1 Then DrawSpot x, y - 1
- If y < 30 Then DrawSpot x, y + 1
- ElseIf code = &H43 Then 'Horizontal tunnel
- If x > 1 Then DrawSpot x - 1, y
- If x < 30 Then DrawSpot x + 1, y
- End If
-
- '... and draw the complemental sub-elements, if any
- If tr(code).w > 1 Then
- If x + 1 <= 30 Then grid(x + 1, y).track = 255 : DrawSpot x + 1, y
- If tr(code).h > 1 Then
- If x + 1 <= 30 And y + 1 <= 30 Then
- grid(x + 1, y + 1).track = 253
- DrawSpot x + 1, y + 1
- End If
- End If
- End If
- If tr(code).h > 1 Then
- If y + 1 <= 30 Then grid(x, y + 1).track = 254 : DrawSpot x, y + 1
- End If
-
- ScreenUnlock
-
- End Sub
- Sub RaiseTerrain(x As UByte, y As UByte)
- ScreenLock
- If x < 30 And y < 30 Then
- Select Case grid(x + 1, y + 1).land
- Case 0 To 5: grid(x + 1, y + 1).land = 11
- Case 9 : grid(x + 1, y + 1).land = 16
- Case 10 : grid(x + 1, y + 1).land = 18
- Case 12 : grid(x + 1, y + 1).land = 8
- Case 13
- grid(x + 1, y + 1).land = 6
- RaiseTerrain x + 1, y
- RaiseTerrain x, y + 1
- Case 14 : grid(x + 1, y + 1).land = 7
- Case 17 : grid(x + 1, y + 1).land = 6
- End Select
- DrawSpot x + 1, y + 1
- End If
- If x > 0 And y > 0 Then
- Select Case grid(x, y).land
- Case 0 To 5 : grid(x, y).land = 13
- Case 7 : grid(x, y).land = 18
- Case 8 : grid(x, y).land = 16
- Case 11
- grid(x, y).land = 6
- RaiseTerrain x - 1, y
- RaiseTerrain x, y - 1
- Case 12 : grid(x, y).land = 9
- Case 14 : grid(x, y).land = 10
- Case 15 : grid(x, y).land = 6
- End Select
- DrawSpot x, y
- End If
- If x > 0 And y < 30 Then
- Select Case grid(x, y + 1).land
- Case 0 To 5: grid(x, y + 1).land = 14
- Case 8 : grid(x, y + 1).land = 15
- Case 9 : grid(x, y + 1).land = 17
- Case 11 : grid(x, y + 1).land = 7
- Case 12
- grid(x, y + 1).land = 6
- RaiseTerrain x - 1, y
- RaiseTerrain x, y + 1
- Case 13 : grid(x, y + 1).land = 10
- Case 16 : grid(x, y + 1).land = 6
- End Select
- DrawSpot x, y + 1
- End If
- If x < 30 And y > 0 Then
- Select Case grid(x + 1, y).land
- Case 0 To 5: grid(x + 1, y).land = 12
- Case 7 : grid(x + 1, y).land = 15
- Case 10 : grid(x + 1, y).land = 17
- Case 11 : grid(x + 1, y).land = 8
- Case 13 : grid(x + 1, y).land = 9
- Case 14
- grid(x + 1, y).land = 6
- RaiseTerrain x, y - 1
- RaiseTerrain x + 1, y
- Case 18 : grid(x + 1, y).land = 6
- End Select
- DrawSpot x + 1, y
- End If
- ScreenUnlock
- End Sub
- Sub LowerTerrain(x As UByte, y As UByte)
- ScreenLock
- If x < 30 And y < 30 Then
- Select Case grid(x + 1, y + 1).land
- Case 6 : grid(x + 1, y + 1).land = 17
- Case 7 : grid(x + 1, y + 1).land = 14
- Case 8 : grid(x + 1, y + 1).land = 12
- Case 11 : grid(x + 1, y + 1).land = 0
- Case 15
- grid(x + 1, y + 1).land = 0
- LowerTerrain x + 1, y
- LowerTerrain x, y + 1
- Case 16 : grid(x + 1, y + 1).land = 9
- Case 18 : grid(x + 1, y + 1).land = 10
- End Select
- DrawSpot x + 1, y + 1
- End If
- If x > 0 And y > 0 Then
- Select Case grid(x, y).land
- Case 6 : grid(x, y).land = 15
- Case 9 : grid(x, y).land = 12
- Case 10 : grid(x, y).land = 14
- Case 13 : grid(x, y).land = 0
- Case 16 : grid(x, y).land = 8
- Case 17
- grid(x, y).land = 0
- LowerTerrain x, y - 1
- LowerTerrain x - 1, y
- Case 18 : grid(x, y).land = 7
- End Select
- DrawSpot x, y
- End If
- If x > 0 And y < 30 Then
- Select Case grid(x, y + 1).land
- Case 6 : grid(x, y + 1).land = 16
- Case 7 : grid(x, y + 1).land = 11
- Case 10 : grid(x, y + 1).land = 13
- Case 14 : grid(x, y + 1).land = 0
- Case 15 : grid(x, y + 1).land = 8
- Case 17 : grid(x, y + 1).land = 9
- Case 18
- grid(x, y + 1).land = 0
- LowerTerrain x - 1, y
- LowerTerrain x, y + 1
- End Select
- DrawSpot x, y + 1
- End If
- If x < 30 And y > 0 Then
- Select Case grid(x + 1, y).land
- Case 6 : grid(x + 1, y).land = 18
- Case 8 : grid(x + 1, y).land = 11
- Case 9 : grid(x + 1, y).land = 13
- Case 12 : grid(x + 1, y).land = 0
- Case 15 : grid(x + 1, y).land = 7
- Case 16
- grid(x + 1, y).land = 0
- LowerTerrain x + 1, y
- LowerTerrain x, y - 1
- Case 17 : grid(x + 1, y).land = 10
- End Select
- DrawSpot x + 1, y
- End If
- ScreenUnlock
- End Sub
- Function Enc_UTF8_to_UTF32 (s As String) As String
- Dim s1 As String, s2 As String, w As Long
- Dim As UByte v1, v2, v3, v4
-
- If Len(s) = 0 Then Return ""
- s1 = s
- s2 = ""
- Do
- v1 = Asc(Left(s1, 1))
-
- 'Note: This code does not check the validity of trailing bytes
- 'for multi-byte codes, that is, it does not make sure that the
- 'highest two bits are 1 and 0. It will work well as long as the
- 'input code is well-behaved. Otherwise, it would be crap anyway.
- 'The check is not performed to avoid making the code longer and
- 'slower unnecessarily.
- If v1 < 128 Then 'ASCII
- w = v1
- s1 = Mid(s1, 2)
- s2 &= MkL(w)
- ElseIf (v1 And 64) = 0 Then 'Invalid. Skip
- s1 = Mid(s1, 2)
- ElseIf (v1 And 32) = 0 Then 'Two-byte code
- v2 = Asc(Mid(s1, 2, 1))
- s1 = Mid(s1, 3)
- w = (v2 And 63) Or ((v1 And 31) ShL 6)
- s2 &= MkL(w)
- ElseIf (v1 And 16) = 0 Then 'Three-byte code
- v2 = Asc(Mid(s1, 2, 1))
- v3 = Asc(Mid(s1, 3, 1))
- s1 = Mid(s1, 4)
- w = (v3 And 63) Or ((v2 And 63) ShL 6) Or ((v1 And 15) ShL 12)
- s2 &= MkL(w)
- ElseIf (v1 And 8) = 0 Then 'Four-byte code
- v2 = Asc(Mid(s1, 2, 1))
- v3 = Asc(Mid(s1, 3, 1))
- v4 = Asc(Mid(s1, 4, 1))
- s1 = Mid(s1, 5)
- w = (v4 And 63) Or ((v3 And 63) ShL 6) Or ((v2 And 63) ShL 12) Or ((v1 And 7) ShL 18)
- s2 &= MkL(w)
- Else 'Invalid leading byte. Skip
- s1 = Mid(s1, 2)
- End If
- Loop Until Len(s1) = 0
-
- Return s2
- End Function
- Function Enc_UTF32_to_UTF8 (s As String) As String
- Dim As UByte v1, v2, v3, v4
- Dim w As Long, s1 As String, s2 As String
-
- If Len(s) = 0 Then Return ""
- s1 = s : s2 = ""
- Do
- w = CvL(Left(s1, 4))
- s1 = Mid(s1, 5)
-
- If w < 128 Then 'ASCII
- v1 = w
- s2 &= Chr(v1)
- ElseIf w < 2 ^ 11 Then 'Two-byte code
- v2 = (w And 63) Or 128
- v1 = ((w ShR 6) And 31) Or &B11000000
- s2 &= Chr(v1) & Chr(v2)
- ElseIf w < 2 ^ 16 Then 'Three-byte code
- v3 = (w And 63) Or 128
- v2 = ((w ShR 6) And 63) Or 128
- v1 = ((w ShR 12) And 15) Or &B11100000
- s2 &= Chr(v1) & Chr(v2) & Chr(v3)
- Else 'Four-byte code
- v4 = (w And 63) Or 128
- v3 = ((w ShR 6) And 63) Or 128
- v2 = ((w ShR 12) And 63) Or 128
- v1 = ((w ShR 18) And 7) Or &B11110000
- s2 &= Chr(v1) & Chr(v2) & Chr(v3) & Chr(v4)
- End If
- Loop Until Len(s1) = 0
-
- Return s2
- End Function
- Function Enc_UTF32_to_CP437 (s As String) As String
- Dim s2 As String, w As Long, v As UByte
-
- If Len(s) = 0 Then Return ""
- For i As Short = 1 To Len(s) - 3 Step 4
- w = CvL(Mid(s, i, 4))
-
- If (w >= 32 And w <= 126) Then
- v = w
- Else
- v = 0
- For j As Short = 0 To UBound(toCP437)
- If toCP437(j).utf32 = 0 Then Exit For
- If w = toCP437(j).utf32 Then
- v = toCP437(j).o
- Exit For
- End If
- Next j
- If v = 0 And w <> 0 Then v = 254
- End If
-
- s2 &= Chr(v)
- Next i
-
- Return s2
- End Function
- Function Enc_UTF32_to_Latin1 (s As String) As String
- Dim s2 As String, w As Long, v As UByte
-
- If Len(s) = 0 Then Return ""
- For i As Short = 1 To Len(s) - 3 Step 4
- w = CvL(Mid(s, i, 4))
-
- If (w >= 32 And w <= 126) Or (w >= &HA0 And w <= &HFF) Then
- v = w
- ElseIf changing_title Then
- 'We're chaning the window title, so Latin-2 codepoints
- 'will be placed where Latin-2 usually puts them
-
- Select Case w
- 'The following code points correspond to Latin-2
- 'actually and are mapped so that Hungarian language
- 'is supported
- Case &H150 : v = 213 'Capital O with double acute
- Case &H170 : v = 219 'Capital U with double acute
- Case &H151 : v = 245 'Lowercase o with double acute
- Case &H171 : v = 251 'Lowercase u with double acute
-
- 'Everything else is a question mark
- Case Else : v = 63
- End Select
- Else
- 'We're goint to map Latin-2 codepoints to special codes
- 'in the font I designed, where I've located the corresponding
- 'characters
- Select Case w
- 'The following code points correspond to Latin-2
- 'actually and are mapped so that Hungarian language
- 'is supported
- Case &H150 : v = 133 'Capital O with double acute
- Case &H170 : v = 139 'Capital U with double acute
- Case &H151 : v = 149 'Lowercase o with double acute
- Case &H171 : v = 155 'Lowercase u with double acute
-
- 'The Euro sign is supported here
- Case &H20AC: v = 132
-
- 'Everything else is an empty rectangle
- Case Else : v = 128
- End Select
- End If
-
- s2 &= Chr(v)
- Next i
-
- Return s2
- End Function
- #ifdef __FB_DOS__
- Sub FakeScreenLock
- If fake_screenlock_level = 0 Then
- ScreenCopy 0, 1
- ScreenSet 1, 0
- End If
- fake_screenlock_level += 1
- End Sub
- Sub FakeScreenUnlock
- fake_screenlock_level -= 1
- If fake_screenlock_level = 0 Then
- ScreenCopy 1, 0
- ScreenSet 0, 0
- ElseIf fake_screenlock_level = -1 Then
- fake_screenlock_level = 0
- End If
- End Sub
- #endif
- Function FindStart As TrackVector
- Dim As Byte i, j
- Dim starts As String, n As Short
- Dim slot As TrackVector
-
- starts = Chr(1, &HB3, &HB4, &HB5, &H86, &H87, &H88, &H89, &H93, &H94, &H95, &H96)
-
- For j = 1 To 30
- For i = 1 To 30
- If InStr(starts, Chr(grid(i, j).track)) Then
- slot.x = i : slot.y = j
- n += 1
- End If
- Next i
- Next j
-
- If n = 0 Then 'No start/finish line
- slot.e = 60
- Return slot
- ElseIf n > 1 Then 'Too many start/finish lines
- slot.e = 61
- Return slot
- Else
- Select Case grid(slot.x, slot.y).track
- Case 1, &H86, &H93 : slot.bearing = 0 'North
- Case &HB5, &H89, &H96 : slot.bearing = 3 'West
- Case &HB3, &H87, &H94 : slot.bearing = 2 'South
- Case Else : slot.bearing = 1 'East
- End Select
- slot.origin = slot.bearing XOr 2
-
- 'Terrain at track start is inadequate
- If grid(slot.x, slot.y).land > 6 Then slot.e = 62
-
- Return slot
- End If
- End Function
- Sub Flood(x As UByte, y As UByte)
- ScreenLock
- If x < 30 And y < 30 Then
- Select Case grid(x + 1, y + 1).land
- Case 0 : grid(x + 1, y + 1).land = 5
- Case 2 To 4 : grid(x + 1, y + 1).land = 1
- End Select
- DrawSpot x + 1, y + 1
- End If
- If x > 0 And y > 0 Then
- Select Case grid(x, y).land
- Case 0 : grid(x, y).land = 3
- Case 2, 4, 5 : grid(x, y).land = 1
- End Select
- DrawSpot x, y
- End If
- If x > 0 And y < 30 Then
- Select Case grid(x, y + 1).land
- Case 0 : grid(x, y + 1).land = 4
- Case 2, 3, 5 : grid(x, y + 1).land = 1
- End Select
- DrawSpot x, y + 1
- End If
- If x < 30 And y > 0 Then
- Select Case grid(x + 1, y).land
- Case 0 : grid(x + 1, y).land = 2
- Case 3 To 5 : grid(x + 1, y).land = 1
- End Select
- DrawSpot x + 1, y
- End If
- ScreenUnlock
- End Sub
- Sub Dry(x As UByte, y As UByte)
- ScreenLock
- If x < 30 And y < 30 Then
- Select Case grid(x + 1, y + 1).land
- Case 1 : grid(x + 1, y + 1).land = 3
- Case 2, 4, 5 : grid(x + 1, y + 1).land = 0
- End Select
- DrawSpot x + 1, y + 1
- End If
- If x > 0 And y > 0 Then
- Select Case grid(x, y).land
- Case 1 : grid(x, y).land = 5
- Case 2 To 4 : grid(x, y).land = 0
- End Select
- DrawSpot x, y
- End If
- If x > 0 And y < 30 Then
- Select Case grid(x, y + 1).land
- Case 1 : grid(x, y + 1).land = 2
- Case 3 To 5 : grid(x, y + 1).land = 0
- End Select
- DrawSpot x, y + 1
- End If
- If x < 30 And y > 0 Then
- Select Case grid(x + 1, y).land
- Case 1 : grid(x + 1, y).land = 4
- Case 2, 3, 5 : grid(x + 1, y).land = 0
- End Select
- DrawSpot x + 1, y
- End If
- ScreenUnlock
- End Sub
- Sub StartUp
- Dim s As String, n As Short
-
- program_path = ""
- #ifdef __FB_LINUX__
- program_path = Environ("HOME") + "/.bliss/"
- If Not FileExists(program_path + "bliss.cfg") Then
- program_path = Environ("HOME") + "/bliss/"
- If Not FileExists(program_path + "bliss.cfg") Then
- program_path = ExePath
- If Right(program_path, 1) <> "/" Then program_path &= "/"
- End If
- End If
- #elseif defined (__FB_DOS__)
- If FileExists("bliss.cfg") Then
- program_path = ""
- Else
- s = Environ("PATH")
- Do
- s = Trim(s)
- If Len(s) = 0 Then
- Screen 0
- Print
- Print "Configuration file not found!"
- Print "Create an empty one or reinstall Bliss."
- Print
- End 1
- End If
-
- n = InStr(s, ";")
- If n Then
- program_path = Left(s, n - 1)
- s = Mid(s, n + 1)
- Else
- program_path = s
- s = ""
- End If
- If Right(program_path, 1) <> "\" Then program_path = program_path + "\"
- If FileExists(program_path + "bliss.cfg") Then Exit Do
- Loop
- End If
- #elseif defined (__FB_WIN32__)
- program_path = Environ("APPDATA") + "\bliss\"
- If Not FileExists(program_path + "bliss.cfg") Then
- program_path = ExePath
- If Right(program_path, 1) <> "\" Then program_path &= "\"
- End If
- #endif
-
- If Not FileExists(program_path + "bliss.cfg") Then
- ScreenRes 640, 64, 32
- Width 80, 4
- Line (0, 0)-(639, 63), RGB(30, 30, 50), BF
- Color RGB(200, 200, 200)
- Draw String (204, 16), "Configuration file not found!"
- Draw String (164, 32), "Create an empty one or reinstall Bliss."
- WindowTitle "Bliss - Error"
-
- Dim t As Double, k As String
- Dim As Integer xm, ym, bm
-
- t = Timer
- Do
- k = Inkey
- If Len(k) Then Exit Do
- GetMouse xm, ym, , bm
- If bm > 0 Then Exit Do
- Loop Until Timer > t + 10
- End 1
- End If
-
- track_path = CurDir
- #ifdef __FB_LINUX__
- If Right(track_path, 1) <> "/" Then track_path = track_path + "/"
- #else
- If Right(track_path, 1) <> "\" Then track_path = track_path + "\"
- #endif
- End Sub
- 'Draw string using the font loaded with LoadFont (used for Latin-1)
- Sub PutString (x As Short, y As Short, s As String, col As ULong, col2 As ULong = RGB(&HFF, 0, &HFF))
- Dim As Any Ptr mystring, mymask
- Dim c As UByte
-
- If Len(s) = 0 Then Exit Sub
-
- mystring = ImageCreate(8 * Len(s), 16, col)
- mymask = ImageCreate(8 * Len(s), 16, 0)
-
- For i As Short = 1 To Len(s)
- c = Asc(Mid(s, i, 1))
- Put mymask, (8 * i - 8, 0), mask, (0, 16 * c)-(7, 16 * c + 15), PSet
- Put mystring, (8 * i - 8, 0), font, (0, 16 * c)-(7, 16 * c + 15), And
- Next i
-
- If col2 <> RGB(&HFF, 0, &HFF) Then _
- Line (x, y)-(x + 8 * Len(s) - 1, y + 15), col2, BF
-
- Put mystring, (0, 0), mymask, Or
- Put (x, y), mystring, Trans
- ImageDestroy mystring
- ImageDestroy mymask
- End Sub
- 'Paste a string based rectangular region on the grid
- Sub PutTrack(x As UByte, y As UByte, t As String, forcefull As Byte = 0)
- Dim As Byte i, j, c
- Dim n As Short
-
- n = 3
- For j = y To y + ASC(Mid(t, 2, 1)) - 1
- For i = x To x + ASC(Left(t, 1)) - 1
- c = ASC(Mid(t, n, 1))
- n += 1
-
- If c And 1 Then
- If affect_track Or forcefull Then _
- grid(i, j).track = ASC(Mid(t, n, 1))
-
- n += 1
- Else
- If affect_track Or forcefull Then _
- grid(i, j).track = 0
- End If
- If c And 2 Then
- If affect_terrain Or forcefull Then _
- grid(i, j).land = ASC(Mid(t, n, 1))
-
- n += 1
- Else
- If affect_terrain Or forcefull Then _
- grid(i, j).land = 0
- End If
- If c And 4 Then
- If colouring_mode Or forcefull Then _
- grid(i, j).border = CvL(Mid(t, n, 4))
-
- n += 4
- Else
- If colouring_mode Or forcefull Then _
- grid(i, j).border = 0
- End If
- If c And 8 Then
- If colouring_mode Or forcefull Then _
- grid(i, j).bgc = CvL(Mid(t, n, 4))
-
- n += 4
- Else
- If colouring_mode Or forcefull Then _
- grid(i, j).bgc = 0
- End If
- Next i
- Next j
- End Sub
- Sub QuitProgram
- Dim v As Short, akey As String
- Dim As Integer xm, ym, wm, bm
-
- If modified Then
- MenuBox 28, 10, "Quit Bliss"
- ceny += 8
- TCentre , "Current track data will be lost!", RGB(200, 200, 240)
- TCentre , "Are you sure you want to leave the program?", RGB(200, 200, 240)
- TCentre
-
- buttons = 0
- StackButton " Quit ", 1
- StackButton " Stay ", 2, , 50
- EndOfButtonStack
- Do
- v = ManageButtons
- akey = InKey
- Loop Until v <> 0 Or akey <> ""
- buttons = 0
- Else
- v = 1
- End If
-
- If v = 1 Then
- 'SaveTransformations '-- COMMENT TO PUBLISH
- ImageDestroy bigicons
-
- #ifndef __FB_DOS__
- HTTP_End
- #endif
- End
- End If
-
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm = 0
-
- DrawTrack
- DrawPanel
- End Sub
- Sub Editor
- Dim As Integer xm, ym, wm, bm
- Dim akey As String, s As String
- Dim As Short xgrid, ygrid 'Coors within a box
- Dim As Short xcross, ycross 'Coors near a vertex
- Dim As Short xbrush, ybrush 'Coors in the centre of current brush
- Dim As Short exgrid, eygrid 'To check when it changes
- Dim As Short stylex, styley 'Last styling coordinates
- Dim As Byte exxcursor = 1, exycursor = 1
- Dim As Byte xpcursor = 0, ypcursor = 0 'Palette cursor
- Dim As Byte inpalette = 0, updatepalette = 0
- Dim tempboard As String 'Temporal rectangle on the grid
- Dim valuecopy As UByte, specialkeylock As Byte
- Dim idletimer As Double, ctrltoselect As Byte
- Dim updatepaste As Byte, stroking As Byte
- Dim previous_page As Byte = 0 'For returning after 2xF1
-
- idletimer = Timer
- Do
- 'Read input
- akey = InKey
- GetMouse xm, ym, wm, bm
-
- 'This is to prevent the program from hogging the CPU
- If xm <> -1 Or Len(akey) <> 0 Then idletimer = Timer
- If Timer > idletimer + 1 Then Sleep 500
-
- 'Check on clipboard import, but not too often
- If Timer > idletimer + .1 Then CheckClipboardImport
- 'CTRL key to select
- If MultiKey(&H1D) Then
- If selecting = 0 Then selecting = -1 : ctrltoselect = -1
- Else
- If (selecting = -1 Or selecting = -3) And ctrltoselect = -1 Then selecting = 0
- ctrltoselect = 0
- End If
-
- 'Calculate coordinates
- xgrid = (xm - xoffs) \ bigwidth + 1
- ygrid = (ym - yoffs) \ 22 + 1
- 'Invalidate border bogus
- If xgrid = 1 And xm < xoffs Then xgrid = -100
- If ygrid = 1 And ym < yoffs Then ygrid = -100
- xcross = (xm - xoffs + (bigwidth ShR 1)) \ bigwidth
- ycross = (ym - yoffs + 11) \ 22
- If tr(current_brush).h = 2 Then
- ybrush = ycross
- Else
- ybrush = ygrid
- End If
- If tr(current_brush).w = 2 Then
- xbrush = xcross
- Else
- xbrush = xgrid
- End If
- If ybrush < 1 Then ybrush = 1
- If ybrush > 30 Then ybrush = 30
- If xbrush < 1 Then xbrush = 1
- If xbrush > 30 Then xbrush = 30
-
- 'Draw coordinates and content at the cursor
- If xgrid <> exgrid Or ygrid <> eygrid Or updatepaste Then
- If pasting Then
- Dim As Byte dx, dy
-
- 'Paste old contents if any
- If Len(tempboard) <> 0 AndAlso exgrid >= 1 And exgrid <= 30 And eygrid >= 1 And eygrid <= 30 Then
- dx = ASC(Left(tempboard, 1)) : dy = ASC(Mid(tempboard, 2, 1))
- xselect = exgrid - dx \ 2
- If xselect < 1 Then xselect = 1
- If xselect + dx - 1 > 30 Then xselect = 30 - dx + 1
- yselect = eygrid - dy \ 2
- If yselect < 1 Then yselect = 1
- If yselect + dy - 1 > 30 Then yselect = 30 - dy + 1
- PutTrack xselect, yselect, tempboard, -1
- End If
-
- If xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- 'Read new region into buffer
- dx = ASC(Left(clipboard, 1)) : dy = ASC(Mid(clipboard, 2, 1))
- xselect = xgrid - dx \ 2
- If xselect < 1 Then xselect = 1
- If xselect + dx - 1 > 30 Then xselect = 30 - dx + 1
- yselect = ygrid - dy \ 2
- If yselect < 1 Then yselect = 1
- If yselect + dy - 1 > 30 Then yselect = 30 - dy + 1
- x2select = xselect + dx - 1
- y2select = yselect + dy - 1
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
-
- 'And place clipboard contents on it
- PutTrack xselect, yselect, clipboard
- Else
- xselect = 0
- End If
-
- updatepaste = 0
- End If
-
- ScreenLock
- If pasting Then DrawTrack
- If xgrid >= 1 And ygrid >= 1 And xgrid <= 30 And ygrid <= 30 Then
- Dim coorpos As Short
-
- coorpos = xpanel + 170
- If colouring_mode Then coorpos -= 72
-
- Line (coorpos - 74, ypanel + 432)- STEP (152, 31), RGB(30, 30, 50), BF
-
- s = "(" + Trim(Str(xgrid)) + ", " + Trim(Str(ygrid)) + ")"
- If selecting = -2 Then s = "(" + Trim(Str(xselect)) + ", " + Trim(Str(yselect)) + ")-" + s
- Draw String (coorpos - Len(s) * 4, ypanel + 430), s, RGB(200, 200, 200)
- If data_codes Then
- s = "Ter[" + Hex(grid(xgrid, ygrid).land) + "h] Trk[" + Hex(grid(xgrid, ygrid).track) + "h]"
- Else
- s = Trim(tr(GetParent(xgrid, ygrid)).id)
- End If
- Draw String (coorpos - Len(s) * 4, ypanel + 446), s, RGB(200, 200, 200)
- End If
- ScreenUnlock
-
- exgrid = xgrid : eygrid = ygrid
- End If
-
- 'Keyboard cursor
- ManageKeyboardCursor
- If inpalette <> 0 And updatepalette <> 0 Then
- ScreenLock
- DrawPanel
- Line (xpanel + xpalette + bigwidth * xpcursor, ypanel + ypalette + 22 * ypcursor) - Step (bigwidth - 1, 21), RGB(200, 200, 200), B
- ScreenUnlock
- updatepalette = 0
- End If
-
- 'Mouse button actions
- If bm = 1 Then
- If selecting <> 0 AndAlso xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- selecting = -2 'Selecting with the mouse
- If xselect = 0 Then
- xselect = xgrid : yselect = ygrid
- x2select = xgrid : y2select = ygrid
- DrawTrack
- ElseIf xgrid <> x2select Or ygrid <> y2select Then
- x2select = xgrid : y2select = ygrid
- DrawTrack
- End If
- ElseIf pasting <> 0 AndAlso xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- tempboard = "" 'Accept paste
- pasting = 0
- xselect = 0
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- modified = -1
- Else
- If xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- If xselect Then
- xselect = 0 : yselect = 0
- x2select = 0 : y2select = 0
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1 Or xm < xoffs
- ElseIf colouring_mode Then
- stroking = -1
-
- If stylex <> xgrid Or styley <> ygrid Then
- Dim As ULong last_bgc, last_border
-
- last_bgc = grid(xgrid, ygrid).bgc
- last_border = grid(xgrid, ygrid).border
- grid(xgrid, ygrid).bgc = current_bgc
- grid(xgrid, ygrid).border = current_border
-
- If last_border <> current_border Then
- DrawTrack
- ElseIf last_bgc <> current_bgc Then
- DrawSpot xgrid, ygrid
- End If
-
- stylex = xgrid : styley = ygrid
- End If
- Else
- stroking = -1
-
- 'Update the track/terrain brush-like
- ScreenLock
- If current_page < 10 Then
- SetTrack xbrush, ybrush, current_brush
- vlast.x = xbrush : vlast.y = ybrush
- ElseIf current_page = 10 Then
- grid(xgrid, ygrid).land = current_terrain_brush
- DrawSpot xgrid, ygrid
- ElseIf current_page = 11 Then
- If current_terrain_brush >= 1 And current_terrain_brush <= 5 Then
- Flood xcross, ycross
- Else
- RaiseTerrain xcross, ycross
- End If
- End If
- ScreenUnlock
- modified = -1
- End If
- ElseIf xgrid >= -5 And xgrid <= -1 And ygrid >= 29 And ygrid <= 30 Then
- current_page = (xgrid + 5) + 5 * (ygrid - 29)
- DrawPanel
- ElseIf xgrid = 0 And ygrid >= 29 And ygrid <= 30 Then
- current_page = ygrid - 19
- DrawPanel
- ElseIf xgrid >= -5 And xgrid <= 0 And ygrid >= 22 And ygrid <= 27 Then
- If current_page < 10 Then
- current_brush = itr(xgrid + 5, ygrid - 22, current_page)
- ElseIf current_page >= 10 Then
- current_terrain_brush = itr(xgrid + 5, ygrid - 22, current_page)
- End If
- Sleep 200 'To avoid picking the wrong element
- DrawPanel
- ElseIf xgrid >= -13 And xgrid <= -7 And ygrid >= 29 And ygrid <= 30 Then
- SelectBackground
- DrawTrack
- DrawPanel
- modified = -1
- End If
- End If
- ElseIf bm = 2 Then
- If xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- If pasting Then
- Dim As Byte dx, dy
-
- 'Cancel pasting
- dx = ASC(Left(tempboard, 1)) : dy = ASC(Mid(tempboard, 2, 1))
- xselect = xgrid - dx \ 2
- If xselect < 1 Then xselect = 1
- If xselect + dx - 1 > 30 Then xselect = 30 - dx + 1
- yselect = ygrid - dy \ 2
- If yselect < 1 Then yselect = 1
- If yselect + dy - 1 > 30 Then yselect = 30 - dy + 1
- PutTrack xselect, yselect, tempboard
- tempboard = ""
- pasting = 0
- xselect = 0
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 2
- ElseIf xselect Then
- xselect = 0 : yselect = 0
- x2select = 0 : y2select = 0
- DrawTrack
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 2 Or xm < xoffs
-
- ElseIf colouring_mode Then
- stroking = -1
-
- If stylex <> xgrid Or styley <> ygrid Then
- Dim As ULong last_bgc, last_border
-
- last_bgc = grid(xgrid, ygrid).bgc
- last_border = grid(xgrid, ygrid).border
- grid(xgrid, ygrid).bgc = 0
- grid(xgrid, ygrid).border = 0
-
- If last_border <> 0 Then
- DrawTrack
- ElseIf last_bgc <> 0 Then
- DrawSpot xgrid, ygrid
- End If
-
- stylex = xgrid : styley = ygrid
- End If
- Else
- stroking = -1
-
- ScreenLock
- If current_page < 10 Then
- ClearTrack xgrid, ygrid
- ElseIf current_page = 10 Then
- grid(xgrid, ygrid).land = 0
- DrawSpot xgrid, ygrid
- Else
- If current_terrain_brush >= 1 And current_terrain_brush <= 5 Then
- Dry xcross, ycross
- Else
- LowerTerrain xcross, ycross
- End If
- End If
- ScreenUnlock
- modified = -1
- End If
- End If
- ElseIf bm = 4 Then
- If xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- If colouring_mode Then
- current_bgc = grid(xgrid, ygrid).bgc
- current_border = grid(xgrid, ygrid).border
- Else
- PickTrack xgrid, ygrid
- End If
- DrawPanel
- End If
- ElseIf bm = 0 Then
- 'Button released -> end of stroke
- If stroking Then
- stroking = 0
- PushUndo
- End If
-
- 'Any styling is interrupted
- stylex = -1 : styley = -1
-
- 'Final selection step
- If selecting = -2 Then selecting = 0
- End If
-
- ManageIcons
-
- 'Handle F11 and F12 for GNU/Linux
- If specialkeylock = 0 Then
- If MultiKey(&H57) Then
- akey = Chr(255) + Chr(133)
- specialkeylock = -1
- ElseIf MultiKey(&H58) Then
- akey = Chr(255) + Chr(134)
- specialkeylock = -1
- End If
- ElseIf MultiKey(&H57) = 0 And MultiKey(&H58) = 0 Then
- specialkeylock = 0
- End If
-
- Select Case akey
- '--- Palette pages
- Case Chr(255) + Chr(59) To Chr(255) + Chr(68)
- 'This check is necessary in GNU/Linux because the
- 'FreeBasic compiler does not support Shift+Functional
- 'keys in InKey for this platform.
- If MultiKey(&H2A) Or MultiKey(&H36) Then
- If ASC(Right(akey, 1)) = 59 Then
- current_page = 10
- DrawPanel
- ElseIf ASC(Right(akey, 1)) = 60 Then
- current_page = 11
- DrawPanel
- End If
- ElseIf current_page = 0 And akey = Chr(255, 59) Then
- current_page = previous_page
- DrawPanel
- Menu_Help
- Else
- previous_page = current_page
- current_page = ASC(Right(akey, 1)) - 59
- DrawPanel
- End If
- Case Chr(255) + Chr(133), Chr(255) + Chr(84)
- current_page = 10
- DrawPanel
- Case Chr(255) + Chr(134), Chr(255) + Chr(85)
- current_page = 11
- DrawPanel
- Case " " 'Switch between mountain and water
- If current_page = 11 Then
- If current_terrain_brush = 0 Or current_terrain_brush > 5 Then
- current_terrain_brush = 1
- Else
- current_terrain_brush = 6
- End If
- DrawPanel
- ElseIf current_page <= 10 Then
- SelectByTyping
- End If
-
- '---- Switches
- Case Chr(5) 'CTRL+E - Allow mixing track elements
- allow_errors = Not allow_errors
- DrawPanel
- Case Chr(4) 'CTRL+D - Display errors and warnings
- show_errors = Not show_errors
- DrawTrack : DrawPanel
- Case Chr(7) 'CTRL+G - Show grid
- show_grid = Not show_grid
- DrawTrack : DrawPanel
- Case Chr(17) 'CTRL+Q - Display codes instead of element names
- data_codes = Not data_codes
- DrawTrack : DrawPanel
- Case Chr(20) 'CTRL+T - Switch terrain affected by paste
- affect_terrain = Not affect_terrain
- If pasting Then updatepaste = -1
- DrawPanel
- Case Chr(11) 'CTRL+K - Switch track affected by paste
- affect_track = Not affect_track
- If pasting Then updatepaste = -1
- DrawPanel
- Case Chr(18) 'CTRL+R - Redraw track
- DrawTrack
-
- '---- Copying, pasting & co.
- Case Chr(3) 'CTRL+C - Copy
- CopyOrCut : DrawPanel
- Case Chr(24) 'CTRL+X - Cut
- CopyOrCut -1 : PushUndo : DrawPanel : modified = -1
- Case Chr(22) 'CTRL+V - Paste
- Paste : modified = -1
- Case Chr(26) 'CTRL+Z - Undo
- If Not pasting Then Undo : modified = -1
- Case Chr(25) 'CTRL+Y - Redo
- If Not pasting Then Redo : modified = -1
- Case Chr(23) 'CTRL+W - Whole-Track Selection / Deselection
- If pasting = 0 And bm = 0 Then
- If xselect Then
- xselect = 0
- Else
- xselect = 1 : yselect = 1
- x2select = 30 : y2select = 30
- End If
- DrawTrack
- End If
-
- '---- Check track
- Case "c", "C" : CheckTrack
-
- '---- Save track image
- Case Chr(19) 'CTRL+S
- Menu_TrackShot
- Case Chr(8) 'CTRL+H - Provide hash value
- Error_Message "Current track hash value is " + Hex(Hash32), "Information requested"
-
- '---- Flipping and rotating
- Case "f" 'Horizontal flipping
- If pasting Then
- clipboard = HFlipTrack(clipboard)
- updatepaste = -1
- ElseIf xselect Then
- If selecting = 0 Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = HFlipTrack(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- End If
- ElseIf current_page < 10 Then
- current_brush = tr(current_brush).hflip
- DrawPanel
- ElseIf current_page = 10 Then
- current_terrain_brush = ttr(current_terrain_brush).hflip
- DrawPanel
- End If
- Case "F" 'Vertical flipping
- If pasting Then
- clipboard = VFlipTrack(clipboard)
- updatepaste = -1
- ElseIf xselect Then
- If selecting = 0 Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = VFlipTrack(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- End If
- ElseIf current_page < 10 Then
- current_brush = tr(current_brush).vflip
- DrawPanel
- ElseIf current_page = 10 Then
- current_terrain_brush = ttr(current_terrain_brush).vflip
- DrawPanel
- End If
- Case "r" 'Clockwise rotation
- If pasting Then
- clipboard = CRotate(clipboard)
- updatepaste = -1
- ElseIf xselect Then
- If selecting = 0 Then
- If x2select - xselect = y2select - yselect Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = CRotate(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Else
- NotASquare
- End If
- End If
- ElseIf current_page < 10 Then
- current_brush = tr(current_brush).cr
- DrawPanel
- ElseIf current_page = 10 Then
- current_terrain_brush = ttr(current_terrain_brush).cr
- DrawPanel
- End If
- Case "R" 'Counter-clockwise rotation
- If pasting Then
- clipboard = CCRotate(clipboard)
- updatepaste = -1
- ElseIf xselect Then
- If selecting = 0 Then
- If x2select - xselect = y2select - yselect Then
- tempboard = GetTrack(xselect, yselect, x2select, y2select)
- tempboard = CCRotate(tempboard)
- PutTrack xselect, yselect, tempboard, -1
- DrawTrack
- PushUndo
- Do
- GetMouse xm, ym, wm, bm
- Loop Until bm <> 1
- Else
- NotASquare
- End If
- End If
- ElseIf current_page < 10 Then
- current_brush = tr(current_brush).ccr
- DrawPanel
- ElseIf current_page = 10 Then
- current_terrain_brush = ttr(current_terrain_brush).ccr
- DrawPanel
- End If
- '---- Track element selectors
- Case "m", "M" 'Material (pavement, dirt, ice)
- Select Case current_brush
- Case 1 : current_brush = &H86
- Case &HB3 To &HB5 : current_brush -= &H2C
- Case &H86 To &H89 : current_brush += 13
- Case &H93 : current_brush = 1
- Case &H94 To &H96 : current_brush += &H1F
- Case 4, 5, 14, 15 : current_brush += 10
- Case 24, 25 : current_brush -= 20
- Case &H4A : current_brush = &H7D
- Case &H7D : current_brush = &H8A
- Case &H8A : current_brush = &H4A
- Case 6 To 9, &H10 To &H13 : current_brush += 10
- Case &H1A To &H1D : current_brush -= 20
- Case &HA To &HD, &H14 To &H17 : current_brush += 10
- Case &H1E To &H21 : current_brush -= 20
- Case &H4B To &H52 : current_brush += &H33
- Case &H7E To &H85 : current_brush += 13
- Case &H8B To &H92 : current_brush -= &H40
- End Select
- DrawPanel
- Case "u", "U" : LinkTiles
- Case "a" To "o", "q" To "w"
- SmartSelect akey
- Case "A" To "O", "Q" To "W"
- SmartSelect akey, -1
- '~ Case "s", "S" 'Street, straightway
- '~ If tr(current_brush).entity = ASC("s") Then
- '~ current_brush = tr(current_brush).cr
- '~ Else
- '~ Dim m As Byte
- '~
- '~ If tr(current_brush).material >= 1 And tr(current_brush).material <= 3 Then
- '~ m = tr(current_brush).material
- '~ Else
- '~ m = 1
- '~ End If
- '~
- '~ For i As UByte = 1 To 190
- '~ If tr(i).material = m And tr(i).entity = ASC("s") Then
- '~ current_brush = i
- '~ Exit For
- '~ End If
- '~ Next i
- '~ End If
- '~ DrawPanel
- Case "x", "X"
- current_brush = 255
- DrawPanel
- Case "y", "Y"
- current_brush = 254
- DrawPanel
- Case "z", "Z"
- current_brush = 253
- DrawPanel
- Case "\"
- If allow_errors Then
- Dim temp_s As String, temp_t As Double
- Dim temp_key As String
-
- Line (xpanel + 77, ypanel + ypalette + 33)- Step (43, 43), RGB(30, 30, 50), BF
- PutIcon 19, 18, xpanel + 77, ypanel + ypalette + 33
- PutIcon 20, 18, xpanel + 99, ypanel + ypalette + 33
- PutIcon 19, 19, xpanel + 77, ypanel + ypalette + 55
- PutIcon 20, 19, xpanel + 99, ypanel + ypalette + 55
-
- 'You have to type a hex value in three seconds
- temp_t = Timer
- temp_s = ""
- Do
- temp_key = InKey
- Select Case temp_key
- Case "0" To "9", "a" To "f", "A" To "F"
- temp_s &= temp_key
- If Len(temp_s) = 2 Then Exit Do
- Case Chr(8), Chr(255, 83)
- temp_s = ""
- temp_t = Timer
- Case ""
- Case Else
- temp_s = ""
- Exit Do
- End Select
- Loop Until Timer >= temp_t + 3
-
- If Len(temp_s) Then
- If current_page = 10 Then
- current_terrain_brush = Abs(ValInt("&H" + temp_s))
- Else
- current_brush = Abs(ValInt("&H" + temp_s))
- End If
- End If
- End If
- DrawPanel
- '~ Case "a" To "o", "q" To "w"
- '~ For i As Short = current_brush + 1 To current_brush + 256
- '~ Dim ii As Short
- '~
- '~ ii = i Mod 256
- '~ If tr(ii).entity = ASC(LCase(akey)) Or tr(ii).entity = ASC(UCase(akey)) Then
- '~ current_brush = ii
- '~ Exit For
- '~ End If
- '~ Next i
- '~ DrawPanel
- '~ Case "A" To "O", "Q" To "W"
- '~ For i As Short = current_brush + 255 To current_brush Step -1
- '~ Dim ii As Short
- '~
- '~ ii = i Mod 256
- '~ If tr(ii).entity = ASC(LCase(akey)) Or tr(ii).entity = ASC(UCase(akey)) Then
- '~ current_brush = ii
- '~ Exit For
- '~ End If
- '~ Next i
- '~ DrawPanel
-
- '--- Move keyboard cursor
- Case Chr(255, 72), Chr(255, 141)
- If inpalette Then
- If ypcursor > 0 Then ypcursor -= 1 : updatepalette = -1
- Else
- If selecting = -1 Then
- xselect = xcursor : x2select = xcursor
- yselect = ycursor : y2select = ycursor
- selecting = -3 'Selecting with the keyboard
- End If
- If ycursor > 1 Then ycursor -= 1
- If selecting = -3 Then
- x2select = xcursor
- y2select = ycursor
- DrawTrack
- End If
- If pasting Then
- SetMouse xoffs + (xcursor - 1) * bigwidth + 11, yoffs + (ycursor - 1) * 22 + 11
- DrawTrack
- End If
- End If
- Case Chr(255, 80), Chr(255, 145)
- If inpalette Then
- If ypcursor < 5 Then ypcursor += 1 : updatepalette = -1
- Else
- If selecting = -1 Then
- xselect = xcursor : x2select = xcursor
- yselect = ycursor : y2select = ycursor
- selecting = -3 'Selecting with the keyboard
- End If
- If ycursor < 30 Then ycursor += 1
- If selecting = -3 Then
- x2select = xcursor
- y2select = ycursor
- DrawTrack
- End If
- If pasting Then
- SetMouse xoffs + (xcursor - 1) * bigwidth + 11, yoffs + (ycursor - 1) * 22 + 11
- DrawTrack
- End If
- End If
- Case Chr(255, 75), Chr(255, 115)
- If inpalette Then
- If xpcursor > 0 Then xpcursor -= 1 : updatepalette = -1
- Else
- If selecting = -1 Then
- xselect = xcursor : x2select = xcursor
- yselect = ycursor : y2select = ycursor
- selecting = -3 'Selecting with the keyboard
- End If
- If xcursor > 1 Then xcursor -= 1
- If selecting = -3 Then
- x2select = xcursor
- y2select = ycursor
- DrawTrack
- End If
- If pasting Then
- SetMouse xoffs + (xcursor - 1) * bigwidth + 11, yoffs + (ycursor - 1) * 22 + 11
- DrawTrack
- End If
- End If
- Case Chr(255, 77), Chr(255, 116)
- If inpalette Then
- If xpcursor < 5 Then xpcursor += 1 : updatepalette = -1
- Else
- If selecting = -1 Then
- xselect = xcursor : x2select = xcursor
- yselect = ycursor : y2select = ycursor
- selecting = -3 'Selecting with the keyboard
- End If
- If xcursor < 30 Then xcursor += 1
- If selecting = -3 Then
- x2select = xcursor
- y2select = ycursor
- DrawTrack
- End If
- If pasting Then
- SetMouse xoffs + (xcursor - 1) * bigwidth + 11, yoffs + (ycursor - 1) * 22 + 11
- DrawTrack
- End If
- End If
- Case Chr(13) 'Insert element
- If inpalette Then
- If current_page < 10 Then
- current_brush = itr(xpcursor, ypcursor, current_page)
- ElseIf current_page = 10 Then
- current_terrain_brush = itr(xpcursor, ypcursor, current_page)
- End If
- DrawPanel
- ElseIf pasting Then
- tempboard = "" 'Accept paste
- pasting = 0 : xselect = 0
- DrawTrack : PushUndo
- modified = -1
- ElseIf xselect Then
- modified = -1
- BuildClosedCircuit
- Else
- modified = -1
- If colouring_mode Then
- Dim As ULong last_bgc, last_border
-
- last_bgc = grid(xcursor, ycursor).bgc
- last_border = grid(xcursor, ycursor).border
- grid(xcursor, ycursor).bgc = current_bgc
- grid(xcursor, ycursor).border = current_border
-
- If last_border <> current_border Then
- DrawTrack
- ElseIf last_bgc <> current_bgc Then
- DrawSpot xcursor, ycursor
- End If
- ElseIf current_page < 10 Then
- SetTrack xcursor, ycursor, current_brush
- vlast.x = xcursor : vlast.y = ycursor
- ElseIf current_page = 10 Then
- grid(xcursor, ycursor).land = current_terrain_brush
- DrawSpot xcursor, ycursor
- End If
- PushUndo
- ManageKeyboardCursor -1
- End If
- Case Chr(255, 83) 'Delete element or block
- modified = -1
- If xselect Then
- If selecting = 0 Then
- For j As Byte = yselect To y2select
- For i As Byte = xselect To x2select
- If affect_track Then grid(i, j).track = 0
- If affect_terrain Then grid(i, j).land = 0
- If colouring_mode Then grid(i, j).border = 0 : grid(i, j).bgc = 0
- Next i
- Next j
- xselect = 0
- DrawTrack
- End If
- Else
- If current_page < 10 Then
- ClearTrack xcursor, ycursor
- ElseIf current_page = 10 Then
- grid(xcursor, ycursor).land = 0
- DrawSpot xgrid, ygrid
- End If
- ManageKeyboardCursor -1
- End If
- PushUndo
- Case "p", "P" 'Pick element
- If drawkeyboardcursor Then
- If colouring_mode Then
- current_border = grid(xcursor, ycursor).border
- current_bgc = grid(xcursor, ycursor).bgc
- Else
- PickTrack xcursor, ycursor
- End If
- DrawPanel
- ElseIf xgrid >= 1 And xgrid <= 30 And ygrid >= 1 And ygrid <= 30 Then
- If colouring_mode Then
- current_border = grid(xgrid, ygrid).border
- current_bgc = grid(xgrid, ygrid).bgc
- Else
- PickTrack xgrid, ygrid
- End If
- DrawPanel
- End If
- Case Chr(9) 'Switch between track and palette
- If colouring_mode Then
- Menu_Colouring
- Else
- inpalette = Not inpalette
- updatepalette = -1
- DrawPanel
- ManageKeyboardCursor -1
- End If
- '~ Case Chr(255, 82) 'INSERT: Activate path creating tool
- '~ If drawkeyboardcursor Then
- '~ CreatePath
- '~ DrawTrack
- '~ End If
- Case Chr(15) 'Switch colouration
- colouring_mode = Not colouring_mode
- DrawPanel
- Case Chr(27), Chr(255) + "k" : QuitProgram
- End Select
- Loop
- End Sub
|