123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855 |
- /*++
- Copyright (c) 2015 Minoca Corp. All Rights Reserved
- Module Name:
- dw.c
- Abstract:
- This module implements a utility to pass idle time.
- Author:
- Evan Green 23-Jul-2015
- Environment:
- POSIX
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/types.h>
- #include <assert.h>
- #include <ctype.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <getopt.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include "swlib.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- #define DwRedrawCash(_Context) \
- DwDrawStandardStat(DwString(DwsCash), 5, (_Context)->Cash, TRUE, FALSE)
- #define DwRedrawWeapons(_Context) \
- DwDrawStandardStat(DwString(DwsGuns), \
- 7, \
- (_Context)->WeaponCount, \
- FALSE, \
- FALSE)
- #define DwRedrawHealth(_Context) \
- DwDrawStandardStat(DwString(DwsHealth), \
- 9, \
- (_Context)->Health, \
- FALSE, \
- (_Context)->Health < 50)
- #define DwRedrawBank(_Context) \
- DwDrawStandardStat(DwString(DwsBank), 11, (_Context)->Bank, TRUE, FALSE)
- #define DwRedrawDebt(_Context) \
- DwDrawStandardStat(DwString(DwsDebt), 13, (_Context)->Debt, TRUE, TRUE)
- #define DW_HEALTH_COLOR(_Context) \
- (((_Context)->Health < 50) ? ConsoleColorDarkRed : ConsoleColorBlack)
- #define DwRedrawHighlightedHealth(_Context) \
- DwDrawStat(DwString(DwsHealth), \
- 9, \
- (_Context)->Health, \
- FALSE, \
- DW_HEALTH_COLOR(_Context), \
- ConsoleColorGray)
- #define DwDrawStandardStat(_Name, _Row, _Value, _Money, _Bad) \
- DwDrawStat((_Name), \
- (_Row), \
- (_Value), \
- (_Money), \
- (_Bad) ? ConsoleColorDarkRed : ConsoleColorGray, \
- (_Bad) ? ConsoleColorGray : ConsoleColorDarkBlue)
- #define DwClearLowerRegion() \
- SwClearRegion(ConsoleColorGray, ConsoleColorBlack, 0, 18, 80, 7)
- #define DwGoodName(_Index) DwString(DwsGoodsNames + (_Index))
- #define DwLocationName(_Index) DwString(DwsLocations + (_Index))
- #define DwWeaponName(_Index) DwString(DwsWeapons + (_Index))
- #define DwString(_Index) DwStrings[Context->Language][_Index]
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define DW_VERSION_MAJOR 1
- #define DW_VERSION_MINOR 0
- #define DW_LANGUAGE_COUNT 2
- #define DW_INITIAL_CASH 2000
- #define DW_INITIAL_WEAPON_COUNT 0
- #define DW_INITIAL_WEAPON_DAMAGE 0
- #define DW_INITIAL_HEALTH 100
- #define DW_INITIAL_BANK 0
- #define DW_INITIAL_DEBT 5500
- #define DW_INITIAL_SPACE 100
- #define DW_INITIAL_LOCATION 0
- #define DW_INITIAL_DAY 1
- #define DW_GOOD_COUNT 12
- #define DW_LOCATION_COUNT 6
- #define DW_WEAPON_COUNT 4
- #define DW_GAME_TIME 31
- #define DW_SUBWAY_SAYINGS_COUNT 31
- #define DW_SONG_COUNT 18
- #define DW_PASSIVE_ACTIVITY_COUNT 5
- #define DW_FINANCIAL_DISTRICT 0
- #define DW_MORE_SPACE 10
- #define DW_MIN_SPACE_PRICE 200
- #define DW_MAX_SPACE_PRICE 300
- #define DW_FLASH_FAST_MICROSECONDS 150000
- #define DW_FLASH_SLOW_MICROSECONDS 200000
- //
- // Define the type of goods that brownies are made of.
- //
- #define DW_BROWNIE_GOOD1 2
- #define DW_BROWNIE_GOOD2 11
- //
- // Define the factors by which extreme prices fluctuate.
- //
- #define DW_SURGE_FACTOR 4
- #define DW_SALE_FACTOR 4
- //
- // Define the interest rates. Loans are brutal.
- //
- #define DW_LOAN_INTEREST_RATE 10
- #define DW_BANK_INTEREST_RATE 5
- //
- // Define high score information.
- //
- #define DW_HIGH_SCORE_MAGIC 0x65706F44
- #define DW_HIGH_SCORE_NAME_SIZE 22
- #define DW_HIGH_SCORE_VALID 0x00000001
- #define DW_HIGH_SCORE_ALIVE 0x00000002
- #define DW_HIGH_SCORE_YOU 0x80000000
- #define DW_HIGH_SCORE_COUNT 18
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure stores the context for the dw application.
- Members:
- Backspace - Stores the backspace character.
- Cash - Stores the amount of cash the player has.
- WeaponCount - Stores the number of weapons the player has.
- WeaponDamage - Stores the sum of the damage the player's weapons can do.
- Health - Stores the amount of health the player has.
- Bank - Stores the amount the player has in the bank.
- Debt - Stores the amount of debt the player is carrying.
- Space - Stores the empty space the player has for more goods.
- Day - Stores the current (game) day of the month.
- Location - Stores the player's location.
- Inventory - Stores the player's inventory of goods, indexed by good.
- Market - Stores today's market prices.
- ExitRequested - Stores a boolean indicating that an exit was requested.
- Language - Stores the language index in use.
- --*/
- typedef struct _DW_CONTEXT {
- char Backspace;
- INT Cash;
- INT WeaponCount;
- INT WeaponDamage;
- INT Health;
- INT Bank;
- INT Debt;
- INT Space;
- INT Day;
- INT Location;
- INT Inventory[DW_GOOD_COUNT];
- INT Market[DW_GOOD_COUNT];
- BOOL ExitRequested;
- INT Language;
- } DW_CONTEXT, *PDW_CONTEXT;
- /*++
- Structure Description:
- This structure stores the data for a good.
- Members:
- MinPrice - Stores the minimum price of the good.
- MaxPrice - Stores the maximum price of the good.
- Sales - Stores a boolean indicating if the good goes on sale.
- Surges - Stores a boolean indicating if the good undergoes shortages.
- --*/
- typedef struct _DW_GOOD {
- INT MinPrice;
- INT MaxPrice;
- BOOL Sales;
- BOOL Surges;
- } DW_GOOD, *PDW_GOOD;
- /*++
- Structure Description:
- This structure stores the data for a location.
- Members:
- PolicePresence - Stores the likelihood that the player will have to deal
- with the popo when going here.
- MinGoods - Stores the minimum number of goods at this market.
- MaxGoods - Stores the maximum number of goods at this market.
- --*/
- typedef struct _DW_LOCATION {
- INT PolicePresence;
- INT MinGoods;
- INT MaxGoods;
- } DW_LOCATION, *PDW_LOCATION;
- /*++
- Structure Description:
- This structure stores the data for a weapon.
- Members:
- Price - Stores the price of the weapon.
- Space - Stores the amount of space the weapon takes up.
- Damage - Stores the amount of damage the weapon does.
- --*/
- typedef struct _DW_WEAPON {
- INT Price;
- INT Space;
- INT Damage;
- } DW_WEAPON, *PDW_WEAPON;
- /*++
- Structure Description:
- This structure stores a single high score entry.
- Members:
- Flags - Stores a bitfield of flags about this entry.
- Year - Stores the year of the high score.
- Month - Stores the month of the high score, 1-12.
- Day - Stores the day of the high score, 1-31.
- Amount - Stores the amount they had.
- Name - Stores the high scorer's name.
- --*/
- typedef struct _DW_HIGH_SCORE_ENTRY {
- ULONG Flags;
- USHORT Year;
- UCHAR Month;
- UCHAR Day;
- LONG Amount;
- CHAR Name[DW_HIGH_SCORE_NAME_SIZE];
- } DW_HIGH_SCORE_ENTRY, *PDW_HIGH_SCORE_ENTRY;
- /*++
- Structure Description:
- This structure stores the complete high score data.
- Members:
- Magic - Stores the magic value DW_HIGH_SCORE_MAGIC.
- Checksum - Stores the checksum of the table, assuming the checksum field
- itself is zero.
- Entries - Stores the array of high score entries.
- --*/
- typedef struct _DW_HIGH_SCORES {
- ULONG Magic;
- ULONG Checksum;
- DW_HIGH_SCORE_ENTRY Entries[DW_HIGH_SCORE_COUNT];
- } DW_HIGH_SCORES, *PDW_HIGH_SCORES;
- typedef enum _DW_STRING_VALUE {
- DwsIntroTitle,
- DwsIntroText,
- DwsHorizontalLine,
- DwsTwoColumnLine,
- DwsColumnTitles,
- DwsSubway,
- DwsMarketGreeting,
- DwsSurgeFormat1,
- DwsSurgeFormat2,
- DwsPressSpace,
- DwsBuyOrJet,
- DwsBuySellJet,
- DwsWhatToBuy,
- DwsWhatToSell,
- DwsHowManyToBuy,
- DwsHowManyToSell,
- DwsWhereTo,
- DwsSubwayLadyFormat,
- DwsSubwayQualifier,
- DwsHearSongFormat,
- DwsProductOfferFormat,
- DwsProductMoreSpace,
- DwsMugged,
- DwsReceiveGiftFormat,
- DwsSendGiftFormat,
- DwsLostGoodsFormat,
- DwsFoundGoodsFormat,
- DwsSharedGoodsFormat,
- DwsSirenSong,
- DwsSirenPrompt,
- DwsSirenResult,
- DwsPassiveActivityFormat,
- DwsFightThreatFormat,
- DwsRunOrFight,
- DwsRunOption,
- DwsFight,
- DwsRun,
- DwsPlayerFire,
- DwsPlayerMissed,
- DwsPlayerHit,
- DwsPlayerUnderFire,
- DwsFled,
- DwsFailedToFlee,
- DwsNotFleeing,
- DwsTheyMissed,
- DwsTheyHit,
- DwsKilled,
- DwsFightVictoryFormat,
- DwsDoctorOffer,
- DwsVisitLoanShark,
- DwsYes,
- DwsLoanRepaymentAmount,
- DwsVisitBank,
- DwsDepositOrWithdraw,
- DwsHowMuchMoney,
- DwsHighScoresTitle,
- DwsHighScoreDead,
- DwsHighScoreFormat,
- DwsPlayAgain,
- DwsMadeHighScores,
- DwsNamePrompt,
- DwsAnonymous,
- DwsYou,
- DwsGoodsNames,
- DwsGoodsSales = DwsGoodsNames + DW_GOOD_COUNT,
- DwsLocations = DwsGoodsSales + DW_GOOD_COUNT,
- DwsWeapons = DwsLocations + DW_LOCATION_COUNT,
- DwsSubwaySayings = DwsWeapons + DW_WEAPON_COUNT,
- DwsSongs = DwsSubwaySayings + DW_SUBWAY_SAYINGS_COUNT,
- DwsPassiveActivities = DwsSongs + DW_SONG_COUNT,
- DwsCash = DwsPassiveActivities + DW_PASSIVE_ACTIVITY_COUNT,
- DwsGuns,
- DwsHealth,
- DwsBank,
- DwsDebt,
- DwsAccess,
- DwsNoAccess,
- DwsStringCount
- } DW_STRING_VALUE, *PDW_STRING_VALUE;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- INT
- DwDecodeStrings (
- PDW_CONTEXT Context
- );
- VOID
- DwDrawIntro (
- PDW_CONTEXT Context
- );
- VOID
- DwDrawGameBoard (
- PDW_CONTEXT Context
- );
- VOID
- DwResetGame (
- PDW_CONTEXT Context
- );
- VOID
- DwPlay (
- PDW_CONTEXT Context
- );
- VOID
- DwDoDailyEvents (
- PDW_CONTEXT Context
- );
- VOID
- DwReceiveOffer (
- PDW_CONTEXT Context
- );
- VOID
- DwPerformActOfGod (
- PDW_CONTEXT Context
- );
- VOID
- DwEncounterPolice (
- PDW_CONTEXT Context
- );
- VOID
- DwVisitFinancialDistrict (
- PDW_CONTEXT Context
- );
- VOID
- DwGenerateMarket (
- PDW_CONTEXT Context
- );
- VOID
- DwParticipateInMarket (
- PDW_CONTEXT Context
- );
- VOID
- DwDrawMarket (
- PDW_CONTEXT Context
- );
- VOID
- DwRedrawInventory (
- PDW_CONTEXT Context
- );
- VOID
- DwPresentNotification (
- PDW_CONTEXT Context,
- PSTR Notification
- );
- VOID
- DwDrawBottomPrompt (
- PSTR Prompt
- );
- VOID
- DwDrawStat (
- PSTR Name,
- INT Row,
- INT Value,
- BOOL Money,
- CONSOLE_COLOR Foreground,
- CONSOLE_COLOR Background
- );
- VOID
- DwDrawLocation (
- PSTR Location
- );
- VOID
- DwRedrawSpace (
- PDW_CONTEXT Context
- );
- VOID
- DwFlashText (
- PDW_CONTEXT Context,
- PSTR String,
- INT XPosition,
- INT YPosition,
- CONSOLE_COLOR Background,
- CONSOLE_COLOR Foreground,
- CONSOLE_COLOR FlashForeground,
- BOOL Fast
- );
- INT
- DwDisplayHighScores (
- PDW_CONTEXT Context
- );
- VOID
- DwLoadHighScores (
- PDW_CONTEXT Context,
- PDW_HIGH_SCORES Scores
- );
- INT
- DwHighScoresFileIo (
- PDW_HIGH_SCORES Scores,
- BOOL Load
- );
- int
- DwCompareHighScores (
- const void *LeftPointer,
- const void *RightPointer
- );
- VOID
- DwFormatMoney (
- PSTR String,
- UINTN StringSize,
- INT Value
- );
- INT
- DwReadCharacterSet (
- PDW_CONTEXT Context,
- PSTR Set
- );
- INT
- DwReadQuantity (
- PDW_CONTEXT Context
- );
- INT
- DwReadString (
- PDW_CONTEXT Context,
- PSTR String,
- INT StringSize
- );
- INT
- DwReadYesNoAnswer (
- PDW_CONTEXT Context,
- PSTR Exposition,
- PSTR Prompt
- );
- INT
- DwReadCharacter (
- PDW_CONTEXT Context
- );
- INT
- DwRandom (
- INT Minimum,
- INT Maximum
- );
- ULONG
- DwChecksum (
- PVOID Buffer,
- ULONG Size
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Store the menu of available goods and how they behave. Don't look!
- //
- DW_GOOD DwGoods[DW_GOOD_COUNT] = {
- {1000, 4000, TRUE, FALSE},
- {15000, 29000, FALSE, TRUE},
- {480, 1280, TRUE, FALSE},
- {5500, 13000, FALSE, TRUE},
- {11, 60, TRUE, FALSE},
- {1500, 4400, FALSE, FALSE},
- {540, 1250, FALSE, TRUE},
- {1000, 2500, FALSE, FALSE},
- {220, 700, FALSE, FALSE},
- {630, 1300, FALSE, FALSE},
- {90, 250, FALSE, TRUE},
- {315, 890, TRUE, FALSE}
- };
- DW_LOCATION DwLocations[DW_LOCATION_COUNT] = {
- {10, (DW_GOOD_COUNT / 2) + 2, DW_GOOD_COUNT},
- {5, (DW_GOOD_COUNT / 2) + 3, DW_GOOD_COUNT},
- {15, (DW_GOOD_COUNT / 2) + 1, DW_GOOD_COUNT},
- {90, (DW_GOOD_COUNT / 2), DW_GOOD_COUNT - 2},
- {20, (DW_GOOD_COUNT / 2) + 1, DW_GOOD_COUNT},
- {70, (DW_GOOD_COUNT / 2), DW_GOOD_COUNT - 1},
- };
- DW_WEAPON DwWeapons[DW_WEAPON_COUNT] = {
- {300, 4, 5},
- {350, 4, 9},
- {290, 4, 4},
- {310, 4, 7},
- };
- //
- // Define all the strings used in the game, localized. Do a very minimal effort
- // to hide from prying "strings".
- //
- PSTR DwStrings[DW_LANGUAGE_COUNT][DwsStringCount] = {
- {
- "E!P!Q!F!!!X!B!S!T",
- "!Cbtfe!po!Kpio!F/!Efmm(t!pme!Esvh!Xbst!hbnf-!Epqf!Xbst!jt!b!" \
- "tjnvmbujpo!pg!bo\n!jnbhjobsz!esvh!nbslfu/!!Epqf!xbst!jt!bo!" \
- "Bmm.Bnfsjdbo!hbnf!xijdi!gfbuvsft\n!cvzjoh-!tfmmjoh-!boe!uszjoh!" \
- "up!hfu!qbtu!uif!dpqt\"\n\n!Uif!gjstu!uijoh!zpv!offe!up!ep!jt!" \
- "qbz!pgg!zpvs!efcu!up!uif!Mpbo!Tibsl/!!Bgufs\n!uibu-!zpvs!hpbm!" \
- "jt!up!nblf!bt!nvdi!npofz!bt!qpttjcmf!)boe!tubz!bmjwf*\"!!Zpv\n!" \
- "ibwf!pof!npoui!pg!hbnf!ujnf!up!nblf!zpvs!gpsuvof/\n\n!Epqf!Xbst!" \
- "ibt!cffo!cspvhiu!up!zpv!dpvsuftz!pg!uif!Ibqqz!Ibdlfs!Gpvoebujpo/",
- ",>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" \
- ">>>>>>>>>,",
- "}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" \
- "!!!!!!!!!}",
- "}!!!!!!!!!!!!Tubut!!!!!!!!!!!!}!Dfousbm!Qbsl!!}!!!!!!!!!!Usfodidpbu!" \
- "!!!!!!!!!}",
- "!T!V!C!X!B!Z",
- "Ifz!evef-!uif!qsjdft!pg!esvht!ifsf!bsf;",
- "Dpqt!nbef!b!cjh!&t!cvtu\"!!Qsjdft!bsf!pvusbhfpvt\"",
- "Beejdut!bsf!cvzjoh!&t!bu!pvusbhfpvt!qsjdft\"",
- "Qsftt!TQBDF!up!dpoujovf",
- "Xjmm!zpv!C?vz-!ps!K?fu@!",
- "Xjmm!zpv!C?vz-!T?fmm-!ps!K?fu@!",
- "Xibu!ep!zpv!xjti!up!cvz@!",
- "Xibu!ep!zpv!xjui!up!tfmm@!",
- "Zpv!dbo!bggpse!&e/!!Ipx!nboz!ep!zpv!cvz@!",
- "Zpv!ibwf!&e/!!Ipx!nboz!ep!zpv!tfmm@!",
- "Xifsf!up-!evef@",
- "Uif!mbez!ofyu!up!zpv!po!uif!tvcxbz!tbje-\n!!!!!#&t#///\n!&t",
- ")bu!mfbtu-!zpv!.uijol.!uibu(t!xibu!tif!tbje*/",
- "Zpv!ifbs!tpnfpof!qmbzjoh!&t",
- "Xpvme!zpv!mjlf!up!cvz!b!&t!gps!%&e@!",
- "cjhhfs!usfodidpbu",
- "Zpv!xfsf!nvhhfe!jo!uif!tvcxbz\"",
- "Zpv!nffu!b!gsjfoe\"!!If!mbzt!tpnf!&t!po!zpv/",
- "Zpv!nffu!b!gsjfoe\"!!Zpv!hjwf!ifs!tpnf!&t/",
- "Qpmjdf!epht!dibtfe!zpv!gps!&e!cmpdlt\"\n!Zpv!espqqfe!tpnf!esvht\"!!" \
- "Uibu(t!b!esbh-!nbo/",
- "Zpv!gjoe!&e!vojut!pg!&t!po!b!efbe!evef!jo!uif!tvcxbz/",
- "Zpvs!nbnb!nbef!cspxojft!xjui!tpnf!pg!zpvs!&t\"!!Uifz!xfsf!hsfbu\"",
- "Uifsf!jt!tpnf!xffe!uibu!tnfmmt!mjlf!qbsbrvbu!ifsf\"!!Ju!mpplt!hppe\"",
- "Xjmm!zpv!tnplf!ju@!",
- "Zpv!ibmmvdjobufe!gps!uisff!ebzt!po!uif!xjmeftu!usjq!zpv!fwfs!" \
- "jnbhjofe\"\n!Uifo!zpv!ejfe!cfdbvtf!zpvs!csbjo!ejtjoufhsbufe\"",
- "Zpv!tupqqfe!up!&t/",
- "Pggjdfs!Ibsebtt!boe!&e!pg!ijt!efqvujft!bsf!dibtjoh!zpv\"",
- "Xjmm!zpv!S?vo!ps!G?jhiu@!",
- "Xjmm!zpv!svo@!",
- "Gjhiu",
- "Svo",
- "Zpv(sf!gjsjoh!po!uifn\"!!",
- "Zpv!njttfe\"",
- "Zpv!ljmmfe!pof\"",
- "Uifz!bsf!gjsjoh!po!zpv-!nbo\"!!",
- "Zpv!mptu!uifn!jo!uif!bmmfzt/",
- "Zpv!dbo(u!mptf!uifn\"",
- "Zpv!tuboe!uifsf!mjlf!bo!jejpu/",
- "Uifz!njttfe\"",
- "Zpv(wf!cffo!iju\"",
- "Uifz!xbtufe!zpv!nbo\"!!Xibu!b!esbh\"",
- "Zpv!ljmmfe!bmm!pg!uifn\"\n!Zpv!gjoe!%&e!po!Pggjdfs!Ibsebtt(!" \
- "dbsdbtt\"\n!",
- "Xjmm!zpv!qbz!%&e!up!ibwf!b!epdups!tfx!zpv!vq@!",
- "Xpvme!zpv!mjlf!up!wjtju!uif!Mpbo!Tibsl@!",
- "Zft",
- "Ipx!nvdi!ep!zpv!hjwf!ijn@!",
- "Xpvme!zpv!mjlf!up!wjtju!uif!Cbol@!",
- "Ep!zpv!xbou!up!E?fqptju!ps!X?juiesbx@!",
- "Ipx!nvdi!npofz@!",
- "I!J!H!I!!!T!D!P!S!F!T",
- ")S/J/Q/*",
- "&23t!!!!!!!!!!&13e.&13e.&15e!!!!!!!!!!&.31t&t",
- "Qmbz!bhbjo@",
- "Dpohsbuvmbujpot\"!!Zpv!nbef!uif!Ijhi!Tdpsft!mjtu\"\n!",
- "Qmfbtf!foufs!zpvs!obnf;!",
- "Nztufsz!Efbmfs",
- "+++!ZPV!+++",
- "Bdje",
- "Dpdbjof",
- "Ibtijti",
- "Ifspjo",
- "Mveft",
- "NEB",
- "Pqjvn",
- "QDQ",
- "Qfzpuf",
- "Tisppnt",
- "Tqffe",
- "Xffe",
- "Uif!nbslfu!ibt!cffo!gmppefe!xjui!difbq!ipnf.nbef!bdje\"",
- NULL,
- "Uif!Nbssblfti!Fyqsftt!ibt!bssjwfe\"",
- NULL,
- "Sjwbm!esvh!efbmfst!sbjefe!b!qibsnbdz!boe!bsf!tfmmjoh!difbq!mveft\"",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Dpmvncjbo!gsfjhiufs!evtufe!uif!Dpbtu!Hvbse\"\n!Xffe!qsjdft!ibwf!" \
- "cpuupnfe!pvu\"",
- "Cspoy",
- "Hifuup",
- "Dfousbm!Qbsl",
- "Nboibuubo",
- "Dpofz!Jtmboe",
- "Cspplmzo",
- "Cbsfuub",
- "/49!Tqfdjbm",
- "Svhfs",
- "Tbuvsebz!Ojhiu!Tqfdjbm",
- "Xpvmeo(u!ju!cf!gvooz!jg!fwfszpof!tveefomz!rvbdlfe!bu!podf@",
- "Uif!Qpqf!xbt!podf!Kfxjti-!zpv!lopx",
- "J(mm!cf!zpv!ibwf!tpnf!sfbmmz!joufsftujoh!esfbnt",
- "Tp!J!uijol!J(n!hpjoh!up!Bntufsebn!uijt!zfbs",
- "Tpo-!zpv!offe!b!zfmmpx!ibjsdvu",
- "J!uijol!ju(t!xpoefsgvm!xibu!uifz(sf!epjoh!xjui!jodfotf!uiftf!ebzt",
- "J!xbto(u!bmxbzt!b!xpnbo-!zpv!lopx",
- "Epft!zpvs!npuifs!lopx!zpv(sf!b!epqf!efbmfs@",
- "Bsf!zpv!ijhi!po!tpnfuijoh@",
- "Pi-!zpv!nvtu!cf!gspn!Dbmjgpsojb",
- "J!vtfe!up!cf!b!ijqqjf-!nztfmg",
- "Uifsf(t!opuijoh!mjlf!ibwjoh!mput!pg!npofz",
- "Zpv!mppl!mjlf!bo!bbsewbsl\"",
- "J!epo(u!cfmjfwf!jo!Spobme!Sfbhbo",
- "Dpvsbhf\"!!Cvti!jt!b!oppemf\"",
- "Ibwfo(u!J!tffo!zpv!po!UW@",
- "J!uijol!ifnpssipje!dpnnfsdjbmt!bsf!sfbmmz!ofbu\"",
- "Xf(sf!xjoojoh!uif!xbs!gps!esvht\"",
- "B!ebz!xjuipvu!epqf!jt!mjlf!ojhiu",
- "Xf!pomz!vtf!31&!pg!pvs!csbjot-!tp!xiz!opu!cvso!pvu!uif!puifs!91&",
- "J(n!tpmjdjujoh!dpousjcvujpot!gps![pncjft!gps!Disjtu",
- "J(e!mjlf!up!tfmm!zpv!bo!fejcmf!qppemf",
- "Xjoofst!epo(u!ep!esvht///!vomftt!uifz!ep",
- "Ljmm!b!dpq!gps!Disjtu\"",
- "J!bn!uif!xbmsvt\"",
- "Kftvt!mpwft!zpv!npsf!uibo!zpv!xjmm!lopx",
- "J!gffm!bo!vobddpvoubcmf!vshf!up!ezf!nz!ibjs!cmvf",
- "Xbto(u!Kbof!Gpoeb!xpoefsgvm!jo!Cbscbsfmmb",
- "Kvtu!tbz!Op//!xfmm-!nbzcf///!pl-!xibu!uif!ifmm\"",
- "Xpvme!zpv!mjlf!b!kfmmz!cbcz@",
- "Esvht!dbo!cf!zpvs!gsjfoe\"",
- "#Bsf!Zpv!Fyqfsjfodfe#!cz!Kjnj!Ifoesjy",
- "#Diffcb!Diffcb#!cz!Upof!Mpd",
- "#Dpnjo(!jo!up!Mpt!Bohfmft#!cz!Bsmp!Hvuisjf",
- "#Dpnnfsdjbm#!cz!Tqbolz!boe!Pvs!Hboh",
- "#Mbuf!jo!uif!Fwfojoh#!cz!Qbvm!Tjnpo",
- "#Mjhiu!Vq#!cz!Tuzy",
- "#Nfyjdp#!cz!Kfggfstpo!Bjsqmbof",
- "#Pof!Uplf!Pwfs!uif!Mjof#!cz!Csfxfs!'!Tijqmfz",
- "#Uif!Tnplfpvu#!cz!Tifm!Tjmwfstufjo",
- "#Xijuf!Sbccju#!cz!Kfggfstpo!Bjsqmbof",
- "#Judizdpp!Qbsl#!cz!Tnbmm!Gbdft",
- "#Xijuf!Qvolt!po!Epqf#!cz!Uif!Uvcft",
- "#Mfhfoe!pg!b!Njoe#!cz!Uif!Nppez!Cmvft",
- "#Fjhiu!Njmft!Ijhi#!cz!Uif!Czset",
- "#Bdbqvmdp!Hpme#!cz!Sjefst!pg!uif!Qvsqmf!Tbhf",
- "#Ljdlt#!cz!Qbvm!Sfwfsf!'!uif!Sbjefst",
- "uif!Ojypo!ubqft",
- "#Mfhbmj{f!Ju#!cz!Npkp!Ojypo!'!Tlje!Spqfs",
- "ibwf!b!cffs",
- "tnplf!b!kpjou",
- "tnplf!b!djhbs",
- "tnplf!b!Ekbsvn",
- "tnplf!b!djhbsfuuf",
- "Dbti",
- "Hvot",
- "Ifbmui",
- "Cbol",
- "Efcu",
- "EX`QMBZ`PME`TDIPPM",
- "ti;!ex;!Dpnnboe!opu!gpvoe/\n",
- },
- {
- "D!B!O!E!Z!!!X!B!S!T",
- "!Cbtfe!po!Kpio!F/!Efmm(t!pme!usbejoh!hbnf-!Dboez!Xbst!jt!b!" \
- "tjnvmbujpo!pg!bo\n!jnbhjobsz!dboez!nbslfu/!!Dboez!Xbst!jt!bo!" \
- "Bmm.Bnfsjdbo!hbnf!xijdi!gfbuvsft\n!cvzjoh-!tfmmjoh-!boe!uszjoh!" \
- "up!hfu!qbtu!uif!wfhhjf!qpmjdf\"\n\n!Uif!gjstu!uijoh!zpv!offe!" \
- "up!ep!jt!qbz!pgg!zpvs!efcu!up!uif!Mpbo!Tibsl/!!Bgufs\n!uibu-!" \
- "zpv!hpbm!jt!up!nblf!bt!nvdi!npofz!bt!qpttjcmf!)boe!tubz!" \
- "bmjwf*\"!!Zpv\n!ibwf!pof!npoui!pg!hbnf!ujnf!up!nblf!zpvs!" \
- "gpsuvof/\n\n",
- ",>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" \
- ">>>>>>>>>>>>,",
- "}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}!!!!!!!!!!!!!!!!!!!!!!!!!!" \
- "!!!!!!!!!!!!}",
- "}!!!!!!!!!!!!Tubut!!!!!!!!!!!!}!Dfousbm!Qbsl!!}!!!!!!!!!!Usfodidpbu" \
- "!!!!!!!!!!}",
- "!!C!!!V!!!T!",
- "Ifz!evef-!uif!qsjdft!pg!dboez!ifsf!bsf;",
- "Uif!GEB!nbef!b!cjh!&t!cvtu\"!!Qsjdft!bsf!pvusbhfpvt\"",
- "Beejdut!bsf!cvzjoh!&t!bu!pvusbhfpvt!qsjdft\"",
- "Qsftt!TQBDF!up!dpoujovf",
- "Xjmm!zpv!C?vz-!ps!K?fu@!",
- "Xjmm!zpv!C?vz-!T?fmm-!ps!K?fu@!",
- "Xibu!ep!zpv!xjti!up!cvz@!",
- "Xibu!ep!zpv!xjui!up!tfmm@!",
- "Zpv!dbo!bggpse!&e/!!Ipx!nboz!ep!zpv!cvz@!",
- "Zpv!ibwf!&e/!!Ipx!nboz!ep!zpv!tfmm@!",
- "Xifsf!up-!evef@",
- "Uif!mbez!ofyu!up!zpv!po!uif!cvt!tbje-\n!!!!!#&t#///\n!&t",
- ")bu!mfbtu-!zpv!.uijol.!uibu(t!xibu!tif!tbje*/",
- "Zpv!ifbs!tpnfpof!qmbzjoh!&t",
- "Xpvme!zpv!mjlf!up!cvz!b!&t!gps!%&e@!",
- "cjhhfs!usfodidpbu",
- "Zpv!xfsf!nvhhfe!jo!uif!cvt!tubujpo\"",
- "Zpv!nffu!b!gsjfoe\"!!If!mbzt!tpnf!&t!po!zpv/",
- "Zpv!nffu!b!gsjfoe\"!!Zpv!hjwf!ifs!tpnf!&t/",
- "Dsb{fe!dijmesfo!dibtfe!zpv!gps!&e!cmpdlt\"\n!Zpv!espqqfe!tpnf!" \
- "dboez\"!!Uibu(t!b!esbh-!nbo/",
- "Zpv!gjoe!&e!vojut!pg!&t!bu!uif!cpuupn!pg!b!wfoejoh!nbdijof/",
- "Zpvs!nbnb!nbef!cspxojft!xjui!tpnf!pg!zpvs!&t\"!!Uifz!xfsf!hsfbu\"",
- "Uifsf!jt!tpnf!tpeb!ifsf!uibu!mpplt!mjlf!Ofx!Dplf\"!!Ju!mpplt!mfhju\"",
- "Xjmm!zpv!esjol!ju@!",
- "Zpv!ibmmvdjobufe!gps!uisff!ebzt!po!uif!xjmeftu!usjq!zpv!fwfs!" \
- "jnbhjofe\"\n!Uifo!zpv!ejfe!cfdbvtf!zpvs!csbjo!ejtjoufhsbufe\"",
- "Zpv!tupqqfe!up!&t/",
- "Dbqubjo!Wfhfubcmft!boe!&e!pg!ijt!dspojft!bsf!dibtjoh!zpv\"",
- "Xjmm!zpv!S?vo!ps!G?jhiu@!",
- "Xjmm!zpv!svo@!",
- "Gjhiu",
- "Svo",
- "Zpv(sf!gjsjoh!po!uifn\"!!",
- "Zpv!njttfe\"",
- "Zpv!hpu!pof\"",
- "Uifz!bsf!gjsjoh!po!zpv-!nbo\"!!",
- "Zpv!mptu!uifn!jo!uif!tvqfsnbslfu/",
- "Zpv!dbo(u!mptf!uifn\"",
- "Zpv!tuboe!uifsf!mjlf!bo!jejpu/",
- "Uifz!njttfe\"",
- "Zpv(wf!cffo!iju\"",
- "Uifz!dpowfsufe!zpv!up!b!wfhbo\"!!Xibu!b!esbh\"",
- "Zpv!hpu!bmm!pg!uifn\"\n!Zpv!gjoe!%&e!po!Dbqubjo!Wfhfubcmft(!" \
- "usvol\"\n!",
- "Xjmm!zpv!qbz!%&e!up!ibwf!b!epdups!gjy!zpv!vq@!",
- "Xpvme!zpv!mjlf!up!wjtju!uif!Mpbo!Tibsl@!",
- "Zft",
- "Ipx!nvdi!ep!zpv!hjwf!ijn@!",
- "Xpvme!zpv!mjlf!up!wjtju!uif!Cbol@!",
- "Ep!zpv!xbou!up!E?fqptju!ps!X?juiesbx@!",
- "Ipx!nvdi!npofz@!",
- "I!J!H!I!!!T!D!P!S!F!T",
- ")wfhbo*",
- "&23t!!!!!!!!!!&13e.&13e.&15e!!!!!!!!!!&.31t&t",
- "Qmbz!bhbjo@",
- "Dpohsbuvmbujpot\"!!Zpv!nbef!uif!Ijhi!Tdpsft!mjtu\"\n!",
- "Qmfbtf!foufs!zpvs!obnf;!",
- "Nztufsz!Efbmfs",
- "+++!ZPV!+++",
- "BjsIfbet",
- "Dbecvsz",
- "Ljttft",
- "Tljuumft",
- "Ujd!Ubdt",
- "Nbmu!Cbmmt",
- "Qjyjf!Tujy",
- "Qpq!Spdlt",
- "Qf{",
- "Cmpx!Qpqt",
- "Tubscvstu",
- "N'Nt",
- "Uif!nbslfu!ibt!cffo!gmppefe!xjui!difbq!ipnf.nbef!BjsIfbet\"",
- NULL,
- "Ju(t!Wbmfoujof(t!Ebz\"!Ljttft!bsf!po!tbmf\"",
- NULL,
- "Sjwbm!hspdfsz!tupsft!bsf!tfmmjoh!difbq!pgg.csboe!Ujd.Ubdt\"",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "B!Ifstifz(t!usvdl!dsbtife!po!uif!ijhixbz\"\nN'Nt!bsf!fwfszxifsf-!" \
- "qsjdft!ibwf!cpuupnfe!pvu\"",
- "Njttjpo",
- "Dbtusp",
- "Qsftjejp",
- "Tvotfu",
- "Svttjbo!Ijmm",
- "Qpusfsp",
- "Tvqfs!Tpblfs",
- "Qfmmfu!Hvo",
- "Sfe!Szefs",
- "Dbq!Hvo",
- "Xpvmeo(u!ju!cf!gvooz!jg!fwfszpof!tveefomz!rvbdlfe!bu!podf@",
- "Uif!Qpqf!xbt!podf!Kfxjti-!zpv!lopx",
- "J(mm!cf!zpv!ibwf!tpnf!sfbmmz!joufsftujoh!esfbnt",
- "Tp!J!uijol!J(n!hpjoh!up!Qfootzmwbojb!uijt!zfbs",
- "Tpo-!zpv!offe!b!zfmmpx!ibjsdvu",
- "J!uijol!ju(t!xpoefsgvm!xibu!uifz(sf!epjoh!xjui!nbqmf!tzsvq!uiftf!ebzt",
- "J!xbto(u!bmxbzt!b!xpnbo-!zpv!lopx",
- "Epft!zpvs!npuifs!lopx!zpv!fbu!tp!nvdi!dboez@",
- "Zpv(sf!tvsf!cpvodz-!bsfo(u!zpv@",
- "Pi-!zpv!nvtu!cf!gspn!Dbmjgpsojb",
- "J!vtfe!up!cf!b!ijqqjf-!nztfmg",
- "Uifsf(t!opuijoh!mjlf!ibwjoh!mput!pg!npofz",
- "Zpv!mppl!mjlf!bo!bbsewbsl\"",
- "J!epo(u!cfmjfwf!jo!dmbttjdbm!qiztjdt",
- "Dpvsbhf\"!!Tjsj!jt!b!oppemf\"",
- "Ibwfo(u!J!tffo!zpv!po!UW@",
- "J!uijol!Hfpshf!Gpsfnbo!hsjmmt!bsf!sfbmmz!ofbu\"",
- "Xf(sf!xjoojoh!uif!xbs!gps!dpuupo!dboez\"",
- "B!ebz!xjuipvu!dboez!jt!mjlf!ojhiu",
- "J!dbo(u!cfmjfwf!J(n!opu!cvuufs\"",
- "J(n!tpmjdjujoh!dpousjcvujpot!gps![pncjft!gps!Cveeib",
- "J(e!mjlf!up!tfmm!zpv!fejcmf!upjmfu!qbqfs",
- "Ofwfs!Yfspy!cvccmf!hvn",
- "Nz!Lju.Lbu!cbst!dpnf!jo!gjwft\"",
- "J!bn!uif!xbmsvt\"",
- "Kftvt!mpwft!zpv!npsf!uibo!zpv!xjmm!lopx",
- "J!gffm!bo!vobddpvoubcmf!vshf!up!ezf!nz!ibjs!cmvf",
- "Xbto(u!Kbof!Gpoeb!xpoefsgvm!jo!Cbscbsfmmb",
- "Opuijoh!siznft!xjui!psbohf!///!fydfqu!cpsbohf\"",
- "Xpvme!zpv!mjlf!b!kfmmz!cbcz@",
- "Dboez!dbo!cf!zpvs!gsjfoe\"",
- "#J!Xbou!Dboez#!cz!Cpx!Xpx!Xpx",
- "#Npuifs!Qpqdpso#!cz!Kbnft!Cspxo",
- "#J!Dbo(u!Ifmq!Nztfmg#!cz!Uif!Gpvs!Upqt",
- "#Tvhbs-!Tvhbs#!cz!Uif!Bsdijft",
- "#Dvqt!boe!Dblft#!cz!TqjobmUbq",
- "#D!jt!gps!Dppljf#!cz!uif!Dppljf!Npotufs",
- "#Mft!Tvdfuuft#!cz!Gsbodf!Hbmmf",
- "#Dboeznbo#!cz!Brvb-!Brvb",
- "#Tbwpz!Usvggmf#!cz!Uif!Cfbumft",
- "#Dipdpmbuf!Kftvt#!cz!Upn!Xbjut",
- "#Tusbxcfssz!Gjfmet!Gpsfwfs#!cz!Uif!Cfbumft",
- "#Tvhbs!Nbhopmjb#!cz!Uif!Hsbufgvm!Efbe",
- "#Cspxo!Tvhbs#!cz!Uif!Spmmjoh!Tupoft",
- "#Qfbdift#!cz!Uif!Qsftjefout!pg!uif!Vojufe!Tubuft",
- "#Xjme!Ipofz!Qjf#!cz!Uif!Cfbumft",
- "#Ebodf!pg!uif!Tvhbs!Qmvn!Gbjsz#!cz!Udibjlpwtlz",
- "#B!Tqppogvm!pg!Tvhbs#!cz!Kvmjf!Boesfxt",
- "#Qpvs!Tpnf!Tvhbs!Po!Nf#!cz!Efg!Mfqqbse",
- "ibwf!b!cvshfs",
- "ibwf!tpnf!dpggff",
- "hsbc!b!rvjdl!gjy!zpvstfmg",
- "hsbc!tpnf!mvodi",
- "ibwf!b!dboez!djhbsfuuf",
- "Npofz",
- "Xfbqpot",
- "Ifbmui",
- "Cbol",
- "Efcu",
- "EX`QMBZ",
- "ti;!ex;!Dpnnboe!opu!gpvoe/\n",
- },
- };
- BOOL DwStringsDecoded;
- INT DwRandomSource;
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- DwMain (
- INT ArgumentCount,
- CHAR **Arguments
- )
- /*++
- Routine Description:
- This routine is the main entry point for the dw utility.
- Arguments:
- ArgumentCount - Supplies the number of command line arguments the program
- was invoked with.
- Arguments - Supplies a tokenized array of command line arguments.
- Return Value:
- Returns an integer exit code. 0 for success, nonzero otherwise.
- --*/
- {
- DW_CONTEXT Context;
- INT PlayAgain;
- INT Result;
- //
- // Seed the bad randomizer, and try to open a decent random source.
- //
- DwRandomSource = open("/dev/urandom", O_RDONLY | O_NONBLOCK);
- if (DwRandomSource < 0) {
- DwRandomSource = open("/dev/random", O_RDONLY | O_NONBLOCK);
- }
- srand(time(NULL));
- memset(&Context, 0, sizeof(Context));
- Result = DwDecodeStrings(&Context);
- if (Result != 0) {
- goto MainEnd;
- }
- SwSetRawInputMode(NULL, NULL);
- DwDrawIntro(&Context);
- if (DwReadCharacterSet(&Context, " ") == -1) {
- goto MainEnd;
- }
- //
- // Shall we play a game?
- //
- do {
- DwResetGame(&Context);
- DwPlay(&Context);
- PlayAgain = DwDisplayHighScores(&Context);
- } while (PlayAgain == 1);
- SwClearRegion(ConsoleColorDefault, ConsoleColorDefault, 0, 0, 80, 25);
- SwMoveCursor(stdout, 0, 0);
- Result = 0;
- MainEnd:
- if (DwRandomSource >= 0) {
- close(DwRandomSource);
- }
- SwRestoreInputMode();
- return Result;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- INT
- DwDecodeStrings (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine decodes all the strings used the app.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- 0 on success.
- ENOMEM on allocation failure.
- 127 if the proper conditions were not met.
- --*/
- {
- PSTR Buffer;
- ULONG Language;
- PSTR NewString;
- BOOL Print;
- size_t Size;
- PSTR Source;
- DW_STRING_VALUE StringIndex;
- if (DwStringsDecoded != FALSE) {
- return 0;
- }
- Print = FALSE;
- Size = 0;
- for (Language = 0; Language < DW_LANGUAGE_COUNT; Language += 1) {
- for (StringIndex = 0; StringIndex < DwsStringCount; StringIndex += 1) {
- Source = DwStrings[Language][StringIndex];
- if (Source != NULL) {
- Size += strlen(Source) + 1;
- }
- }
- }
- Buffer = malloc(Size);
- if (Buffer == NULL) {
- return ENOMEM;
- }
- for (Language = 0; Language < DW_LANGUAGE_COUNT; Language += 1) {
- if (Print != FALSE) {
- printf(" {\n");
- }
- for (StringIndex = 0; StringIndex < DwsStringCount; StringIndex += 1) {
- Source = DwStrings[Language][StringIndex];
- if (Source != NULL) {
- NewString = Buffer;
- if (Print != FALSE) {
- printf(" \"");
- }
- while (*Source != '\0') {
- if (*Source == '\n') {
- *Buffer = '\n';
- } else {
- *Buffer = *Source - 1;
- }
- if (Print != FALSE) {
- if (*Buffer == '\n') {
- printf("\\n");
- } else if (*Buffer == '"') {
- printf("\\\"");
- } else {
- printf("%c", *Buffer);
- }
- }
- Source += 1;
- Buffer += 1;
- }
- if (Print != FALSE) {
- printf("\",\n");
- }
- *Buffer = '\0';
- Buffer += 1;
- DwStrings[Language][StringIndex] = NewString;
- } else {
- if (Print != FALSE) {
- printf(" NULL,\n");
- }
- }
- }
- if (Print != FALSE) {
- printf(" },\n");
- }
- }
- DwStringsDecoded = TRUE;
- for (Language = 0; Language < DW_LANGUAGE_COUNT; Language += 1) {
- if (getenv(DwStrings[Language][DwsAccess]) != NULL) {
- Context->Language = Language;
- break;
- }
- }
- if (Language == DW_LANGUAGE_COUNT) {
- fprintf(stderr, "%s", DwString(DwsNoAccess));
- return 127;
- }
- return 0;
- }
- VOID
- DwDrawIntro (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine prepares the console and draws the introductory screen.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- SwClearRegion(ConsoleColorGray, ConsoleColorDefault, 0, 0, 80, 25);
- SwMoveCursor(stdout, 30, 0);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkBlue,
- DwString(DwsIntroTitle));
- SwMoveCursor(stdout, 0, 5);
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, DwString(DwsIntroText));
- DwDrawBottomPrompt(DwString(DwsPressSpace));
- return;
- }
- VOID
- DwResetGame (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine resets the game context.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Index;
- Context->Backspace = 0x7F;
- Context->Cash = DW_INITIAL_CASH;
- Context->WeaponCount = DW_INITIAL_WEAPON_COUNT;
- Context->WeaponDamage = DW_INITIAL_WEAPON_DAMAGE;
- Context->Health = DW_INITIAL_HEALTH;
- Context->Bank = DW_INITIAL_BANK;
- Context->Debt = DW_INITIAL_DEBT;
- Context->Space = DW_INITIAL_SPACE;
- Context->Day = DW_INITIAL_DAY;
- Context->Location = DW_INITIAL_LOCATION;
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- Context->Inventory[Index] = 0;
- }
- DwDrawGameBoard(Context);
- return;
- }
- VOID
- DwDrawGameBoard (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine draws the static and initial components of the game board.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Row;
- SwClearRegion(ConsoleColorGray, ConsoleColorDefault, 0, 0, 80, 25);
- SwClearRegion(ConsoleColorDarkBlue, ConsoleColorDefault, 1, 1, 78, 16);
- SwMoveCursor(stdout, 3, 0);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkBlue,
- "%02d-01-19%02d",
- DwRandom(1, 12),
- DwRandom(60, 91));
- SwMoveCursor(stdout, 65, 0);
- SwPrintInColor(ConsoleColorGray, ConsoleColorDarkBlue, "Space 100");
- SwMoveCursor(stdout, 1, 1);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- DwString(DwsHorizontalLine));
- SwMoveCursor(stdout, 1, 2);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- DwString(DwsColumnTitles));
- SwMoveCursor(stdout, 1, 3);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- DwString(DwsHorizontalLine));
- for (Row = 4; Row < 16; Row += 1) {
- SwMoveCursor(stdout, 1, Row);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- DwString(DwsTwoColumnLine));
- }
- SwMoveCursor(stdout, 1, 16);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- DwString(DwsHorizontalLine));
- DwRedrawCash(Context);
- DwRedrawWeapons(Context);
- DwRedrawHealth(Context);
- DwRedrawBank(Context);
- DwRedrawDebt(Context);
- return;
- }
- VOID
- DwPlay (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine implements the main game loop.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- //
- // Live day by day.
- //
- while ((Context->Health > 0) && (Context->Day <= DW_GAME_TIME) &&
- (Context->ExitRequested == FALSE)) {
- SwMoveCursor(stdout, 6, 0);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkBlue,
- "%02d",
- Context->Day);
- DwDrawLocation(DwLocationName(Context->Location));
- DwDoDailyEvents(Context);
- if (Context->Health <= 0) {
- break;
- }
- DwParticipateInMarket(Context);
- Context->Day += 1;
- }
- return;
- }
- VOID
- DwDoDailyEvents (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine performs the daily routine, such as fetching market prices,
- and meeting people on the subway.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Chance;
- INT Index;
- CHAR Line[240];
- INT Price;
- PSTR Qualifier;
- PSTR SurgeFormat;
- INT Worth;
- //
- // Go through the regular chores every day except the first.
- //
- if (Context->Day != 1) {
- //
- // Update the loan shark and bank on another day.
- //
- if (Context->Debt != 0) {
- Context->Debt =
- (Context->Debt * (DW_LOAN_INTEREST_RATE + 100)) / 100;
- DwRedrawDebt(Context);
- }
- if (Context->Bank != 0) {
- Context->Bank =
- (Context->Bank * (DW_BANK_INTEREST_RATE + 100)) / 100;
- DwRedrawBank(Context);
- }
- //
- // Determine if something interesting is going to happen.
- //
- Worth = Context->Cash - Context->Debt;
- Chance = 100;
- if (Worth > 3000000) {
- Chance = 130;
- } else if (Worth > 1000000) {
- Chance = 115;
- }
- if (DwRandom(0, Chance) > 75) {
- Chance = 80 + DwLocations[Context->Location].PolicePresence;
- Chance = DwRandom(0, Chance);
- if (Chance < 33) {
- DwReceiveOffer(Context);
- } else if (Chance < 50) {
- DwPerformActOfGod(Context);
- } else {
- DwEncounterPolice(Context);
- }
- }
- if (Context->Health <= 0) {
- return;
- }
- //
- // Sometimes the lady on the subway pipes up.
- //
- if (DwRandom(0, 100) < 15) {
- if (DwRandom(0, 100) < 50) {
- Qualifier = "";
- if (DwRandom(0, 100) < 30) {
- Qualifier = DwString(DwsSubwayQualifier);
- }
- Index = DwRandom(0, DW_SUBWAY_SAYINGS_COUNT);
- snprintf(Line,
- sizeof(Line),
- DwString(DwsSubwayLadyFormat),
- DwString(DwsSubwaySayings + Index),
- Qualifier);
- } else {
- Index = DwRandom(0, DW_SONG_COUNT);
- snprintf(Line,
- sizeof(Line),
- DwString(DwsHearSongFormat),
- DwString(DwsSongs + Index));
- }
- }
- //
- // In a certain part of town, it's possible to visit some special folks.
- //
- if (Context->Location == DW_FINANCIAL_DISTRICT) {
- DwVisitFinancialDistrict(Context);
- }
- }
- //
- // Go get today's market prices, and note any large price fluctuations.
- //
- DwGenerateMarket(Context);
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- Price = Context->Market[Index];
- //
- // If the good is not in the market or has a normal price, then ignore
- // it.
- //
- if ((Price == 0) ||
- ((Price >= DwGoods[Index].MinPrice) &&
- (Price < DwGoods[Index].MaxPrice))) {
- continue;
- }
- //
- // Everyone loves a sale.
- //
- if (Price < DwGoods[Index].MinPrice) {
- DwPresentNotification(Context, DwString(DwsGoodsSales + Index));
- //
- // A surge: help a brother out.
- //
- } else {
- if (DwRandom(0, 100) < 50) {
- SurgeFormat = DwString(DwsSurgeFormat1);
- } else {
- SurgeFormat = DwString(DwsSurgeFormat2);
- }
- snprintf(Line, sizeof(Line), SurgeFormat, DwGoodName(Index));
- DwPresentNotification(Context, Line);
- }
- }
- return;
- }
- VOID
- DwReceiveOffer (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine gives the player a special product offer.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Answer;
- CHAR Line[80];
- INT Price;
- INT Product;
- //
- // Potentially offer the player more space for goods.
- //
- if (DwRandom(0, 100) < 50) {
- Price = DwRandom(DW_MIN_SPACE_PRICE, DW_MAX_SPACE_PRICE);
- if (Price <= Context->Cash) {
- snprintf(Line,
- sizeof(Line),
- DwString(DwsProductOfferFormat),
- DwString(DwsProductMoreSpace),
- Price);
- Answer = DwReadYesNoAnswer(Context, NULL, Line);
- if (Answer == 1) {
- Context->Space += DwRandom(1, 2) * DW_MORE_SPACE;
- Context->Cash -= Price;
- DwRedrawSpace(Context);
- DwRedrawCash(Context);
- }
- }
- //
- // Offer the player a weapon.
- //
- } else {
- Product = DwRandom(0, DW_WEAPON_COUNT);
- Price = DwWeapons[Product].Price;
- if ((Price <= Context->Cash) &&
- (Context->Space >= DwWeapons[Product].Space)) {
- snprintf(Line,
- sizeof(Line),
- DwString(DwsProductOfferFormat),
- DwWeaponName(Product),
- DwWeapons[Product].Price);
- Answer = DwReadYesNoAnswer(Context, NULL, Line);
- if (Answer == 1) {
- Context->Space -= DwWeapons[Product].Space;
- Context->WeaponCount += 1;
- Context->WeaponDamage += DwWeapons[Product].Damage;
- Context->Cash -= Price;
- DwRedrawCash(Context);
- DwRedrawSpace(Context);
- DwRedrawWeapons(Context);
- }
- }
- }
- return;
- }
- VOID
- DwPerformActOfGod (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine performs a non-interactive and random action on the user.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Action;
- INT Amount;
- INT Answer;
- INT Good;
- INT Index;
- CHAR Line[160];
- //
- // Some actions require a good that the player currently has in a certain
- // quantity.
- //
- Amount = DwRandom(3, 7);
- for (Index = 0; Index < 5; Index += 1) {
- Good = DwRandom(0, DW_GOOD_COUNT);
- if (Context->Inventory[Good] >= Amount) {
- break;
- }
- }
- if (Index == 5) {
- Good = -1;
- }
- Action = DwRandom(0, 100);
- //
- // Sometimes there are muggers in the subway.
- //
- if (Action < 10) {
- DwPresentNotification(Context, DwString(DwsMugged));
- Context->Cash = (Context->Cash * DwRandom(80, 95)) / 100;
- DwRedrawCash(Context);
- //
- // Sometimes gifts are given or received.
- //
- } else if (Action < 30) {
- if (Good == -1) {
- //
- // Players lose out if they don't have space to receive gifts.
- //
- if (Amount > Context->Space) {
- Amount = 0;
- }
- Good = DwRandom(0, DW_GOOD_COUNT);
- snprintf(Line,
- sizeof(Line),
- DwString(DwsReceiveGiftFormat),
- DwGoodName(Good));
- Context->Inventory[Good] += Amount;
- Context->Space -= Amount;
- //
- // Well heeled players give gifts to others.
- //
- } else {
- snprintf(Line,
- sizeof(Line),
- DwString(DwsSendGiftFormat),
- DwGoodName(Good));
- Context->Inventory[Good] -= Amount;
- Context->Space += Amount;
- }
- if (Amount != 0) {
- DwPresentNotification(Context, Line);
- DwRedrawSpace(Context);
- DwRedrawInventory(Context);
- }
- //
- // Sometimes people just lose things, or find things.
- //
- } else if (Action < 50) {
- if (Good != -1) {
- snprintf(Line,
- sizeof(Line),
- DwString(DwsLostGoodsFormat),
- DwRandom(3, 7));
- Context->Inventory[Good] -= Amount;
- Context->Space += Amount;
- } else {
- if (Amount > Context->Space) {
- Amount = 0;
- }
- Good = DwRandom(0, DW_GOOD_COUNT);
- snprintf(Line,
- sizeof(Line),
- DwString(DwsFoundGoodsFormat),
- Amount,
- DwGoodName(Good));
- Context->Inventory[Good] += Amount;
- Context->Space -= Amount;
- }
- if (Amount != 0) {
- DwPresentNotification(Context, Line);
- DwRedrawSpace(Context);
- DwRedrawInventory(Context);
- }
- //
- // Sometimes other people share your items.
- //
- } else if ((Action < 60) &&
- ((Context->Inventory[DW_BROWNIE_GOOD1] != 0) ||
- (Context->Inventory[DW_BROWNIE_GOOD2] != 0))) {
- Good = DW_BROWNIE_GOOD1;
- if (Context->Inventory[DW_BROWNIE_GOOD2] >
- Context->Inventory[DW_BROWNIE_GOOD1]) {
- Good = DW_BROWNIE_GOOD2;
- }
- Amount = DwRandom(2, 6);
- if (Amount > Context->Inventory[Good]) {
- Amount = Context->Inventory[Good];
- }
- snprintf(Line,
- sizeof(Line),
- DwString(DwsSharedGoodsFormat),
- DwGoodName(Good));
- Context->Inventory[Good] -= Amount;
- Context->Space += Amount;
- DwPresentNotification(Context, Line);
- DwRedrawSpace(Context);
- DwRedrawInventory(Context);
- //
- // Sometimes there's that offer that's just too good to be true.
- //
- } else if (Action < 65) {
- Answer = DwReadYesNoAnswer(Context,
- DwString(DwsSirenSong),
- DwString(DwsSirenPrompt));
- if (Answer == 1) {
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, "Y");
- SwMoveCursor(stdout, 1, 21);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsSirenResult));
- DwPresentNotification(Context, NULL);
- Context->Health = 0;
- }
- //
- // Occasionally the player just needs to take a break from the hustle to
- // sit and think.
- //
- } else {
- Index = DwRandom(0, DW_PASSIVE_ACTIVITY_COUNT);
- snprintf(Line,
- sizeof(Line),
- DwString(DwsPassiveActivityFormat),
- DwString(DwsPassiveActivities + Index));
- DwPresentNotification(Context, Line);
- Amount = DwRandom(1, 10);
- if (Context->Cash >= Amount) {
- Context->Cash -= Amount;
- }
- DwRedrawCash(Context);
- }
- return;
- }
- VOID
- DwEncounterPolice (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine is called when the player has a brush with the law.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Answer;
- PSTR Choices;
- INT Damage;
- INT Defence;
- INT DoctorCost;
- INT Enemies;
- INT FancyFeet;
- INT MaxEnemies;
- INT Offense;
- PSTR Prompt;
- INT Row;
- PSTR ShotResult;
- INT VictoryCash;
- //
- // How bad could this be?
- //
- MaxEnemies = 4;
- if (Context->Day >= 15) {
- MaxEnemies = 6;
- if (Context->Day > 23) {
- MaxEnemies = 9;
- }
- }
- Enemies = DwRandom(2, MaxEnemies);
- MaxEnemies = Enemies;
- //
- // Loop handlin' bad guys.
- //
- while (Enemies != 0) {
- DwClearLowerRegion();
- Row = 18;
- SwMoveCursor(stdout, 1, Row);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsFightThreatFormat),
- Enemies - 1);
- Row += 1;
- SwMoveCursor(stdout, 1, Row);
- if (Context->WeaponCount != 0) {
- Prompt = DwString(DwsRunOrFight);
- Choices = "rf";
- } else {
- Prompt = DwString(DwsRunOption);
- Choices = "yn";
- }
- SwPrintInColor(ConsoleColorGray, ConsoleColorDarkMagenta, Prompt);
- Answer = DwReadCharacterSet(Context, Choices);
- if (Answer == EOF) {
- return;
- }
- //
- // Fight on, player.
- //
- if (Answer == 'f') {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsFight));
- Row += 1;
- DwFlashText(Context,
- DwString(DwsPlayerFire),
- 1,
- Row,
- ConsoleColorGray,
- ConsoleColorBlack,
- ConsoleColorWhite,
- FALSE);
- Offense = 50 + Context->WeaponDamage;
- ShotResult = DwString(DwsPlayerMissed);
- if (DwRandom(0, 100) < Offense) {
- Enemies -= 1;
- ShotResult = DwString(DwsPlayerHit);
- }
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, ShotResult);
- //
- // Flee from the police!
- //
- } else if ((Answer == 'y') || (Answer == 'r')) {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsRun));
- Row += 1;
- SwMoveCursor(stdout, 1, Row);
- FancyFeet = 65 - (Enemies * 5);
- if (DwRandom(0, 100) < FancyFeet) {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsFled));
- DwPresentNotification(Context, NULL);
- break;
- } else {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsFailedToFlee));
- }
- //
- // Just stand around and hope nothing happens.
- //
- } else {
- Row += 1;
- SwMoveCursor(stdout, 1, Row);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsNotFleeing));
- }
- Row += 1;
- //
- // If there are still enemies, they fire at our hero.
- //
- if (Enemies != 0) {
- SwMoveCursor(stdout, 1, Row);
- DwFlashText(Context,
- DwString(DwsPlayerUnderFire),
- 1,
- Row,
- ConsoleColorGray,
- ConsoleColorBlack,
- ConsoleColorWhite,
- FALSE);
- Defence = 60 - (Enemies * 5);
- if (DwRandom(0, 100) < Defence) {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsTheyMissed));
- } else {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsTheyHit));
- Damage = DwRandom(5, 10);
- if (Damage >= Context->Health) {
- Context->Health = 0;
- } else {
- Context->Health -= Damage;
- }
- }
- DwRedrawHighlightedHealth(Context);
- if (Context->Health <= 0) {
- Row += 1;
- SwMoveCursor(stdout, 1, Row);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsKilled));
- }
- DwPresentNotification(Context, NULL);
- DwRedrawHealth(Context);
- if (Context->Health <= 0) {
- break;
- }
- //
- // Victory!
- //
- } else {
- DwPresentNotification(Context, NULL);
- SwClearRegion(ConsoleColorGray, ConsoleColorDefault, 0, 24, 80, 1);
- VictoryCash = DwRandom(1000, 1500 + (MaxEnemies * 200));
- SwMoveCursor(stdout, 1, Row);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsFightVictoryFormat),
- VictoryCash);
- Context->Cash += VictoryCash;
- DoctorCost = DwRandom(100, 200) *
- (DW_INITIAL_HEALTH - Context->Health) / 5;
- if (DoctorCost > Context->Cash) {
- DoctorCost = Context->Cash;
- }
- if (DoctorCost != 0) {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsDoctorOffer),
- DoctorCost);
- Answer = DwReadYesNoAnswer(Context, NULL, NULL);
- if (Answer == EOF) {
- return;
- }
- if (Answer == 1) {
- Context->Cash -= DoctorCost;
- Context->Health = DW_INITIAL_HEALTH;
- }
- } else {
- DwPresentNotification(Context, NULL);
- }
- DwRedrawCash(Context);
- DwRedrawHealth(Context);
- break;
- }
- }
- return;
- }
- VOID
- DwVisitFinancialDistrict (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine is called to prompt the user and handle visits to the bank and
- potentially the loan shark.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Action;
- INT Answer;
- INT Value;
- //
- // Visit the loan shark if the player has a loan.
- //
- if (Context->Debt != 0) {
- Answer = DwReadYesNoAnswer(Context, NULL, DwString(DwsVisitLoanShark));
- if (Answer == -1) {
- return;
- }
- if (Answer == 1) {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsYes));
- SwMoveCursor(stdout, 1, 20);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsLoanRepaymentAmount));
- Value = DwReadQuantity(Context);
- if (Value > 0) {
- if ((Value <= Context->Cash) && (Value <= Context->Debt)) {
- Context->Cash -= Value;
- Context->Debt -= Value;
- DwRedrawCash(Context);
- if (Context->Debt == 0) {
- SwClearRegion(ConsoleColorDarkBlue,
- ConsoleColorDefault,
- 9,
- 13,
- 20,
- 1);
- } else {
- DwRedrawDebt(Context);
- }
- }
- }
- }
- }
- //
- // Visit the bank.
- //
- Answer = DwReadYesNoAnswer(Context, NULL, DwString(DwsVisitBank));
- if (Answer == -1) {
- return;
- }
- if (Answer == 1) {
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, DwString(DwsYes));
- SwMoveCursor(stdout, 1, 19);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsDepositOrWithdraw));
- Action = DwReadCharacterSet(Context, "dw");
- if (Action == -1) {
- return;
- }
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- "%c",
- toupper(Action));
- SwMoveCursor(stdout, 1, 20);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsHowMuchMoney));
- Value = DwReadQuantity(Context);
- if (Value > 0) {
- if (Action == 'd') {
- if (Value <= Context->Cash) {
- Context->Cash -= Value;
- Context->Bank += Value;
- }
- } else if (Action == 'w') {
- if (Value <= Context->Bank) {
- Context->Cash += Value;
- Context->Bank -= Value;
- }
- }
- DwRedrawBank(Context);
- DwRedrawCash(Context);
- }
- }
- return;
- }
- VOID
- DwGenerateMarket (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine generates a new market's worth of goods and prices.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT EventCount;
- INT GoodsCount;
- INT Index;
- INT TotalGoodsCount;
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- Context->Market[Index] = 0;
- }
- //
- // Determine how many special events will occur today.
- //
- EventCount = 0;
- if (DwRandom(0, 100) < 70) {
- EventCount = 1;
- if (DwRandom(0, 100) < 40) {
- EventCount = 2;
- if (DwRandom(0, 100) < 5) {
- EventCount = 3;
- }
- }
- }
- //
- // Determine what those special events are.
- //
- GoodsCount = 0;
- while (EventCount > 0) {
- Index = DwRandom(0, DW_GOOD_COUNT);
- if (Context->Market[Index] != 0) {
- continue;
- }
- if ((DwGoods[Index].Surges == FALSE) &&
- (DwGoods[Index].Sales == FALSE)) {
- continue;
- }
- GoodsCount += 1;
- EventCount -= 1;
- Context->Market[Index] = DwRandom(DwGoods[Index].MinPrice,
- DwGoods[Index].MaxPrice);
- if (DwGoods[Index].Surges != FALSE) {
- Context->Market[Index] *= DW_SURGE_FACTOR;
- } else if (DwGoods[Index].Sales != FALSE) {
- Context->Market[Index] /= DW_SALE_FACTOR;
- }
- }
- //
- // Determine how many goods will be in the market.
- //
- TotalGoodsCount = DwRandom(DwLocations[Context->Location].MinGoods,
- DwLocations[Context->Location].MaxGoods);
- assert(TotalGoodsCount <= DW_GOOD_COUNT);
- GoodsCount = TotalGoodsCount - GoodsCount;
- while (GoodsCount > 0) {
- Index = DwRandom(0, DW_GOOD_COUNT);
- if (Context->Market[Index] != 0) {
- continue;
- }
- Context->Market[Index] = DwRandom(DwGoods[Index].MinPrice,
- DwGoods[Index].MaxPrice);
- GoodsCount -= 1;
- }
- return;
- }
- VOID
- DwParticipateInMarket (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine is where the player buys and sells goods.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Action;
- INT Choice;
- CHAR ChoiceBuffer[DW_GOOD_COUNT + 1];
- PSTR Choices;
- INT Index;
- INT MaxQuantity;
- PSTR Prompt;
- INT Quantity;
- INT SelectedGood;
- while (Context->ExitRequested == FALSE) {
- DwDrawMarket(Context);
- //
- // Determine if the user has anything in inventory, and can therefore
- // sell.
- //
- Choices = "bj";
- Prompt = DwString(DwsBuyOrJet);
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- if (Context->Inventory[Index] != 0) {
- Choices = "bsj";
- Prompt = DwString(DwsBuySellJet);
- break;
- }
- }
- DwDrawBottomPrompt(Prompt);
- Action = DwReadCharacterSet(Context, Choices);
- if (Action == EOF) {
- break;
- }
- if ((Action == 'b') || (Action == 's')) {
- SwClearRegion(ConsoleColorGray, ConsoleColorDefault, 0, 24, 80, 1);
- SwMoveCursor(stdout, 1, 23);
- if (Action == 'b') {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsWhatToBuy));
- } else {
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsWhatToSell));
- }
- //
- // Create the set of possibilities. For buying, anything in the
- // market is a valid choice. For selling, anything in inventory
- // is a valid choice.
- //
- Choice = 'a';
- Choices = ChoiceBuffer;
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- if (Context->Market[Index] != 0) {
- if ((Action == 'b') || (Context->Inventory[Index] != 0)) {
- *Choices = Choice;
- Choices += 1;
- }
- Choice += 1;
- }
- }
- *Choices = '\0';
- Choice = DwReadCharacterSet(Context, ChoiceBuffer);
- if (Choice == EOF) {
- break;
- }
- //
- // Translate back to figure out which good they were talking about.
- //
- Choice -= 'a';
- SelectedGood = 0;
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- if (Context->Market[Index] != 0) {
- if (Choice == SelectedGood) {
- SelectedGood = Index;
- break;
- }
- SelectedGood += 1;
- }
- }
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwGoodName(SelectedGood));
- //
- // Ask how many they'd like to purchase or sell.
- //
- SwMoveCursor(stdout, 1, 24);
- if (Action == 'b') {
- MaxQuantity = Context->Cash / Context->Market[Index];
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsHowManyToBuy),
- MaxQuantity);
- } else {
- MaxQuantity = Context->Inventory[Index];
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsHowManyToSell),
- MaxQuantity);
- }
- Quantity = DwReadQuantity(Context);
- //
- // Do the deal. The check for space is only needed when buying.
- //
- if ((Quantity > 0) && (Quantity <= MaxQuantity) &&
- ((Action == 's') || (Quantity <= Context->Space))) {
- //
- // Selling is really just buying negative quantities. Chew on
- // that.
- //
- if (Action == 's') {
- Quantity = -Quantity;
- }
- Context->Inventory[SelectedGood] += Quantity;
- Context->Cash -= Quantity * Context->Market[SelectedGood];
- Context->Space -= Quantity;
- DwRedrawCash(Context);
- DwRedrawInventory(Context);
- DwRedrawSpace(Context);
- }
- //
- // They're outta here.
- //
- } else if (Action == 'j') {
- DwClearLowerRegion();
- for (Index = 0; Index < DW_LOCATION_COUNT; Index += 1) {
- SwMoveCursor(stdout, 4 + ((Index % 3) * 28), 18 + (Index / 3));
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- "%d. %s",
- Index + 1,
- DwLocationName(Index));
- }
- DwDrawBottomPrompt(DwString(DwsWhereTo));
- Choice = DwReadCharacterSet(Context, "123456");
- if (Choice == EOF) {
- return;
- }
- //
- // If they want a different place than they are, then ride the
- // subway away from here.
- //
- Choice -= '1';
- if (Choice != Context->Location) {
- assert(Choice < DW_LOCATION_COUNT);
- Context->Location = Choice;
- DwClearLowerRegion();
- //
- // Ride the subway.
- //
- DwDrawLocation("");
- DwFlashText(Context,
- DwString(DwsSubway),
- 33,
- 2,
- ConsoleColorDarkBlue,
- ConsoleColorWhite,
- ConsoleColorDarkBlue,
- TRUE);
- DwDrawLocation(DwLocationName(Choice));
- break;
- }
- }
- }
- return;
- }
- VOID
- DwDrawMarket (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine redraws the current daily market contents.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT ColumnIndex;
- INT Index;
- CHAR Line[16];
- CHAR Price[11];
- INT Row;
- CHAR Selector;
- DwClearLowerRegion();
- Selector = 'A';
- SwMoveCursor(stdout, 1, 18);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsMarketGreeting));
- Row = 19;
- ColumnIndex = 0;
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- if (Context->Market[Index] == 0) {
- continue;
- }
- SwMoveCursor(stdout, 4 + (ColumnIndex * 26), Row);
- snprintf(Line, sizeof(Line), "%c> %s", Selector, DwGoodName(Index));
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, Line);
- DwFormatMoney(Price, sizeof(Price), Context->Market[Index]);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- "%*s",
- 20 - strlen(Line),
- Price);
- Selector += 1;
- if (ColumnIndex == 2) {
- ColumnIndex = 0;
- Row += 1;
- } else {
- ColumnIndex += 1;
- }
- }
- return;
- }
- VOID
- DwRedrawInventory (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine redraws the player's current inventory.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- INT Index;
- INT Quantity;
- INT Row;
- SwClearRegion(ConsoleColorDarkBlue,
- ConsoleColorDefault,
- 47,
- 4,
- 24,
- DW_GOOD_COUNT);
- Row = 4;
- for (Index = 0; Index < DW_GOOD_COUNT; Index += 1) {
- Quantity = Context->Inventory[Index];
- if (Quantity == 0) {
- continue;
- }
- SwMoveCursor(stdout, 47, Row);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- DwGoodName(Index));
- SwMoveCursor(stdout, 47 + 18, Row);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorGray,
- "%6d",
- Quantity);
- Row += 1;
- }
- return;
- }
- VOID
- DwPresentNotification (
- PDW_CONTEXT Context,
- PSTR Notification
- )
- /*++
- Routine Description:
- This routine presents a notification to the user in the bottom area, and
- waits for them to press space.
- Arguments:
- Context - Supplies a pointer to the application context.
- Notification - Supplies an pointer to the notification. If NULL, then the
- lower screen isn't cleared, as it's assumed the notification is already
- set up.
- Return Value:
- None.
- --*/
- {
- if (Notification != NULL) {
- DwClearLowerRegion();
- SwMoveCursor(stdout, 1, 18);
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, Notification);
- }
- DwDrawBottomPrompt(DwString(DwsPressSpace));
- DwReadCharacterSet(Context, " ");
- return;
- }
- VOID
- DwDrawBottomPrompt (
- PSTR Prompt
- )
- /*++
- Routine Description:
- This routine prints a string centered in purple at the bottom of the
- screen. This routine assumes the bottom line is already clear.
- Arguments:
- Prompt - Supplies a pointer to the string containing the prompt to print.
- Return Value:
- None.
- --*/
- {
- UINTN Column;
- UINTN Length;
- Length = strlen(Prompt);
- if (Length >= 80) {
- Column = 0;
- } else {
- Column = 40 - (Length / 2);
- }
- SwMoveCursor(stdout, Column, 24);
- SwPrintInColor(ConsoleColorGray, ConsoleColorDarkMagenta, Prompt);
- return;
- }
- VOID
- DwDrawStat (
- PSTR Name,
- INT Row,
- INT Value,
- BOOL Money,
- CONSOLE_COLOR Foreground,
- CONSOLE_COLOR Background
- )
- /*++
- Routine Description:
- This routine redraws one of the statistics on the left pane.
- Arguments:
- Name - Supplies a pointer to the name of the statistic.
- Row - Supplies the starting row of the statistic.
- Value - Supplies the value of the stat.
- Money - Supplies a boolean indicating if this is a monetary value or not.
- Foreground - Supplies the text color to use.
- Background - Supplies the background color to use.
- Return Value:
- None.
- --*/
- {
- CHAR Line[21];
- CHAR ValueString[21];
- if (Money != FALSE) {
- DwFormatMoney(ValueString, sizeof(ValueString), Value);
- } else {
- snprintf(ValueString, sizeof(ValueString), "%d", Value);
- }
- snprintf(Line, sizeof(Line), "%s%*s", Name, 20 - strlen(Name), ValueString);
- SwMoveCursor(stdout, 9, Row);
- SwPrintInColor(Background, Foreground, Line);
- return;
- }
- VOID
- DwDrawLocation (
- PSTR Location
- )
- /*++
- Routine Description:
- This routine redraws the current location.
- Arguments:
- Location - Supplies the name of the location.
- Return Value:
- None.
- --*/
- {
- INT Column;
- INT Length;
- SwClearRegion(ConsoleColorDarkBlue, ConsoleColorGray, 33, 2, 13, 1);
- //
- // Center the text.
- //
- Length = strlen(Location);
- if (Length <= 14) {
- Column = 39 - (Length / 2);
- } else {
- Column = 33;
- }
- SwMoveCursor(stdout, Column, 2);
- SwPrintInColor(ConsoleColorDarkBlue, ConsoleColorWhite, Location);
- return;
- }
- VOID
- DwRedrawSpace (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine redraws the players remaining inventory capacity.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- None.
- --*/
- {
- SwMoveCursor(stdout, 73, 0);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkBlue,
- "%4d",
- Context->Space);
- return;
- }
- VOID
- DwFlashText (
- PDW_CONTEXT Context,
- PSTR String,
- INT XPosition,
- INT YPosition,
- CONSOLE_COLOR Background,
- CONSOLE_COLOR Foreground,
- CONSOLE_COLOR FlashForeground,
- BOOL Fast
- )
- /*++
- Routine Description:
- This routine flashes text for a little while, for an exciting visual
- experience.
- Arguments:
- Context - Supplies a pointer to the application context.
- String - Supplies a pointer to the string to flash.
- XPosition - Supplies the column to draw the text at.
- YPosition - Supplies the row to draw the text at.
- Background - Supplies the background color.
- Foreground - Supplies the initial and final foreground color.
- FlashForeground - Supplies the accent foreground color.
- Fast - Supplies a boolean indicating whether to flash fast or slow.
- Return Value:
- None.
- --*/
- {
- INT Count;
- CONSOLE_COLOR CurrentColor;
- INT Delay;
- INT Index;
- if (Fast != FALSE) {
- Delay = DW_FLASH_FAST_MICROSECONDS;
- } else {
- Delay = DW_FLASH_SLOW_MICROSECONDS;
- }
- Count = DwRandom(5, 7) | 1;
- for (Index = 0; Index < Count; Index += 1) {
- SwMoveCursor(stdout, XPosition, YPosition);
- if ((Index & 0x1) != 0) {
- CurrentColor = FlashForeground;
- } else {
- CurrentColor = Foreground;
- }
- SwPrintInColor(Background, CurrentColor, "%s", String);
- SwSleep(Delay);
- }
- return;
- }
- INT
- DwDisplayHighScores (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine displays the "high" scores. Oh yeah.
- Arguments:
- Context - Supplies a pointer to the player context.
- Return Value:
- 0 if the caller does not want to play again.
- 1 if the caller does want to play again (yay).
- -1 if the answer could not be read.
- --*/
- {
- CHAR Amount[16];
- INT Answer;
- CONSOLE_COLOR Color;
- struct tm *CurrentTime;
- PSTR Dead;
- PDW_HIGH_SCORE_ENTRY Entry;
- INT Index;
- CHAR Line[81];
- PSTR Name;
- INT PlayerValue;
- INT Result;
- INT Row;
- BOOL Save;
- DW_HIGH_SCORES Scores;
- time_t Time;
- Save = FALSE;
- DwLoadHighScores(Context, &Scores);
- //
- // If the player made the high score list, ask for their name and remember
- // to save the high scores list.
- //
- PlayerValue = Context->Cash + Context->Bank - Context->Debt;
- Entry = &(Scores.Entries[DW_HIGH_SCORE_COUNT - 1]);
- Name = (PSTR)(Entry->Name);
- if (((Entry->Flags & DW_HIGH_SCORE_VALID) == 0) ||
- (PlayerValue > Entry->Amount)) {
- DwClearLowerRegion();
- SwMoveCursor(stdout, 1, 18);
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- DwString(DwsMadeHighScores));
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorDarkMagenta,
- DwString(DwsNamePrompt));
- Result = DwReadString(Context, Name, DW_HIGH_SCORE_NAME_SIZE);
- if (Result != 0) {
- strncpy(Name, DwString(DwsAnonymous), DW_HIGH_SCORE_NAME_SIZE);
- }
- Save = TRUE;
- } else {
- strncpy(Name, DwString(DwsYou), DW_HIGH_SCORE_NAME_SIZE);
- }
- //
- // Add the remainder of the player's details, always to the last score.
- //
- Entry->Flags = DW_HIGH_SCORE_VALID | DW_HIGH_SCORE_YOU;
- if (Context->Health != 0) {
- Entry->Flags |= DW_HIGH_SCORE_ALIVE;
- }
- Entry->Amount = PlayerValue;
- Time = time(NULL);
- CurrentTime = localtime(&Time);
- if (CurrentTime != NULL) {
- Entry->Month = CurrentTime->tm_mon + 1;
- Entry->Day = CurrentTime->tm_mday;
- Entry->Year = CurrentTime->tm_year + 1900;
- }
- //
- // Sort the scores now.
- //
- qsort(&(Scores.Entries[0]),
- DW_HIGH_SCORE_COUNT,
- sizeof(DW_HIGH_SCORE_ENTRY),
- DwCompareHighScores);
- //
- // Print the high scores screen.
- //
- SwClearRegion(ConsoleColorDarkBlue, ConsoleColorDefault, 0, 0, 80, 25);
- SwMoveCursor(stdout, 28, 0);
- SwPrintInColor(ConsoleColorDarkBlue,
- ConsoleColorYellow,
- DwString(DwsHighScoresTitle));
- Row = 4;
- for (Index = 0; Index < DW_HIGH_SCORE_COUNT; Index += 1) {
- Entry = &(Scores.Entries[Index]);
- if ((Entry->Flags & DW_HIGH_SCORE_VALID) == 0) {
- continue;
- }
- DwFormatMoney(Amount, sizeof(Amount), Entry->Amount);
- Entry->Name[DW_HIGH_SCORE_NAME_SIZE - 1] = '\0';
- Dead = "";
- if ((Entry->Flags & DW_HIGH_SCORE_ALIVE) == 0) {
- Dead = DwString(DwsHighScoreDead);
- }
- snprintf(Line,
- sizeof(Line),
- DwString(DwsHighScoreFormat),
- Amount,
- Entry->Month,
- Entry->Day,
- Entry->Year,
- Entry->Name,
- Dead);
- Color = ConsoleColorGray;
- if ((Entry->Flags & DW_HIGH_SCORE_YOU) != 0) {
- Color = ConsoleColorWhite;
- Entry->Flags &= ~DW_HIGH_SCORE_YOU;
- }
- SwMoveCursor(stdout, 6, Row);
- SwPrintInColor(ConsoleColorDarkBlue, Color, "%s", Line);
- Row += 1;
- }
- //
- // Save the high scores file.
- //
- if (Save != FALSE) {
- Scores.Checksum = 0;
- Scores.Checksum = DwChecksum(&Scores, sizeof(DW_HIGH_SCORES));
- DwHighScoresFileIo(&Scores, FALSE);
- }
- //
- // Let's do it all again!
- //
- DwDrawBottomPrompt(DwString(DwsPlayAgain));
- Answer = DwReadYesNoAnswer(Context, NULL, NULL);
- return Answer;
- }
- VOID
- DwLoadHighScores (
- PDW_CONTEXT Context,
- PDW_HIGH_SCORES Scores
- )
- /*++
- Routine Description:
- This routine loads the high scores, or initializes a new set.
- Arguments:
- Context - Supplies a pointer to the player context.
- Scores - Supplies a pointer where the loaded stores will be returned.
- Return Value:
- None. If high scores could not be read, new ones will be initialized.
- --*/
- {
- ULONG Checksum;
- INT Result;
- //
- // Try to load the high scores and validate the CRC32.
- //
- Result = DwHighScoresFileIo(Scores, TRUE);
- if ((Result == 0) && (Scores->Magic == DW_HIGH_SCORE_MAGIC)) {
- Checksum = Scores->Checksum;
- Scores->Checksum = 0;
- if (DwChecksum(Scores, sizeof(DW_HIGH_SCORES)) == Checksum) {
- Scores->Checksum = Checksum;
- return;
- }
- }
- //
- // Either the scores didn't load or the CRC didn't match, so initialize a
- // new set.
- //
- memset(Scores, 0, sizeof(DW_HIGH_SCORES));
- Scores->Magic = DW_HIGH_SCORE_MAGIC;
- return;
- }
- INT
- DwHighScoresFileIo (
- PDW_HIGH_SCORES Scores,
- BOOL Load
- )
- /*++
- Routine Description:
- This routine attempts to load or save the high scores file.
- Arguments:
- Scores - Supplies a pointer to the high scores structure.
- Load - Supplies a boolean indicating whether to load (TRUE) or store
- (FALSE) the file.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PSTR Access;
- PUCHAR Bytes;
- FILE *File;
- PSTR Home;
- INT Index;
- UCHAR Pad;
- CHAR Path[256];
- ssize_t Size;
- Home = getenv("HOME");
- if (Home == NULL) {
- Home = ".";
- }
- snprintf(Path, sizeof(Path), "%s/.dwsco", Home);
- Access = "wb";
- if (Load != FALSE) {
- Access = "rb";
- }
- File = fopen(Path, Access);
- if (File == NULL) {
- return errno;
- }
- Bytes = (PUCHAR)Scores;
- if (Load != FALSE) {
- Size = fread(Scores, 1, sizeof(DW_HIGH_SCORES), File);
- //
- // When the stakes are this high it's important to have truly
- // bulletproof security.
- //
- Pad = 0x56;
- for (Index = 0; Index < sizeof(DW_HIGH_SCORES); Index += 1) {
- Bytes[Index] ^= Pad;
- Pad += 1;
- }
- } else {
- Pad = 0x56;
- for (Index = 0; Index < sizeof(DW_HIGH_SCORES); Index += 1) {
- Bytes[Index] ^= Pad;
- Pad += 1;
- }
- Size = fwrite(Scores, 1, sizeof(DW_HIGH_SCORES), File);
- }
- fclose(File);
- if (Size != sizeof(DW_HIGH_SCORES)) {
- if (errno == 0) {
- return -1;
- }
- return errno;
- }
- return 0;
- }
- int
- DwCompareHighScores (
- const void *LeftPointer,
- const void *RightPointer
- )
- /*++
- Routine Description:
- This routine compares two high score entries.
- Arguments:
- LeftPointer - Supplies the left high score pointer to compare.
- RightPointer - Supplies the right pointer to compare.
- Return Value:
- <0 if the left is less than the right.
- 0 if the left is equal to the right.
- >0 if the left is greater than the right.
- --*/
- {
- PDW_HIGH_SCORE_ENTRY Left;
- LONG LeftValue;
- PDW_HIGH_SCORE_ENTRY Right;
- LONG RightValue;
- Left = (PDW_HIGH_SCORE_ENTRY)LeftPointer;
- LeftValue = Left->Amount;
- Right = (PDW_HIGH_SCORE_ENTRY)RightPointer;
- RightValue = Right->Amount;
- //
- // First compare invalid entries.
- //
- if ((Left->Flags & DW_HIGH_SCORE_VALID) == 0) {
- LeftValue = -999999999;
- }
- if ((Right->Flags & DW_HIGH_SCORE_VALID) == 0) {
- RightValue = -999999999;
- }
- //
- // Higher scores should be first in the list.
- //
- if (LeftValue < RightValue) {
- return 1;
- } else if (LeftValue > RightValue) {
- return -1;
- }
- return 0;
- }
- VOID
- DwFormatMoney (
- PSTR String,
- UINTN StringSize,
- INT Value
- )
- /*++
- Routine Description:
- This routine prints a money value, with thousands separators.
- Arguments:
- String - Supplies a pointer to the output buffer.
- StringSize - Supplies the size of the output buffer string in bytes.
- Value - Supplies the value to print.
- Return Value:
- None.
- --*/
- {
- INT Billions;
- INT Millions;
- INT Ones;
- INT Thousands;
- if (Value < 0) {
- Value = -Value;
- *String = '-';
- String += 1;
- StringSize -= 1;
- }
- Ones = Value;
- Billions = Value / 1000000000;
- Ones = Value % 1000000000;
- Millions = Ones / 1000000;
- Ones = Ones % 1000000;
- Thousands = Ones / 1000;
- Ones = Ones % 1000;
- if (Billions != 0) {
- snprintf(String,
- StringSize,
- "$%d,%03d,%03d,%03d",
- Billions,
- Millions,
- Thousands,
- Ones);
- } else if (Millions != 0) {
- snprintf(String,
- StringSize,
- "$%d,%03d,%03d",
- Millions,
- Thousands,
- Ones);
- } else if (Thousands != 0) {
- snprintf(String, StringSize, "$%d,%03d", Thousands, Ones);
- } else {
- snprintf(String, StringSize, "$%d", Ones);
- }
- return;
- }
- INT
- DwReadCharacterSet (
- PDW_CONTEXT Context,
- PSTR Set
- )
- /*++
- Routine Description:
- This routine reads a character from a given permissible set.
- Arguments:
- Context - Supplies a pointer to the application context.
- Set - Supplies a pointer to a null terminated string containing the set of
- acceptable characters.
- Return Value:
- Returns the character received on success.
- -1 on read failure.
- --*/
- {
- INT Character;
- PSTR Current;
- while (TRUE) {
- Character = DwReadCharacter(Context);
- if (Character == -1) {
- break;
- }
- if (isupper(Character)) {
- Character = tolower(Character);
- }
- //
- // See if the character received was in the allowed set.
- //
- Current = Set;
- while (*Current != '\0') {
- if (*Current == Character) {
- return Character;
- }
- Current += 1;
- }
- }
- return Character;
- }
- INT
- DwReadQuantity (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine reads a numeric quantity in from standard input.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- Returns the numeric value read in on success.
- -1 on failure.
- --*/
- {
- CHAR Buffer[9];
- INT Character;
- INT Index;
- INT ScanIndex;
- INT Value;
- Index = 0;
- while (TRUE) {
- Character = DwReadCharacter(Context);
- if (Character == EOF) {
- return -1;
- }
- if (isdigit(Character)) {
- if (Index < 8) {
- Buffer[Index] = Character;
- Index += 1;
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- "%c",
- Character);
- }
- } else if ((Character == Context->Backspace) || (Character == '\b')) {
- if (Index > 0) {
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, "\b \b");
- Index -= 1;
- }
- } else if ((Character == '\r') || (Character == '\n')) {
- break;
- }
- }
- if (Index == 0) {
- return -1;
- }
- Value = 0;
- for (ScanIndex = 0; ScanIndex < Index; ScanIndex += 1) {
- Value = (Value * 10) + (Buffer[ScanIndex] - '0');
- }
- return Value;
- }
- INT
- DwReadString (
- PDW_CONTEXT Context,
- PSTR String,
- INT StringSize
- )
- /*++
- Routine Description:
- This routine reads a generic string from standard input.
- Arguments:
- Context - Supplies a pointer to the application context.
- String - Supplies a pointer where the string will be returned on success.
- StringSize - Supplies string buffer size.
- Return Value:
- 0 on success.
- -1 on failure.
- --*/
- {
- INT Character;
- INT Index;
- Index = 0;
- while (TRUE) {
- Character = DwReadCharacter(Context);
- if (Character == EOF) {
- return -1;
- }
- if ((Character == Context->Backspace) || (Character == '\b')) {
- if (Index > 0) {
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, "\b \b");
- Index -= 1;
- }
- } else if ((Character == '\r') || (Character == '\n')) {
- break;
- } else {
- if (Index < StringSize - 1) {
- String[Index] = Character;
- Index += 1;
- SwPrintInColor(ConsoleColorGray,
- ConsoleColorBlack,
- "%c",
- Character);
- }
- }
- }
- if (Index == 0) {
- return -1;
- }
- String[Index] = '\0';
- return 0;
- }
- INT
- DwReadYesNoAnswer (
- PDW_CONTEXT Context,
- PSTR Exposition,
- PSTR Prompt
- )
- /*++
- Routine Description:
- This routine reads a yes/no answer from the user.
- Arguments:
- Context - Supplies a pointer to the application context.
- Exposition - Supplies an optional pointer to a line of black text to put
- first. Most questions don't have this.
- Prompt - Supplies an optional pointer to the question to ask.
- Return Value:
- 0 if the user said no.
- 1 if the user said yes.
- -1 on failure.
- --*/
- {
- INT Answer;
- INT Row;
- if (Prompt != NULL) {
- DwClearLowerRegion();
- }
- Row = 18;
- if (Exposition != NULL) {
- SwMoveCursor(stdout, 1, Row);
- Row = 19;
- SwPrintInColor(ConsoleColorGray, ConsoleColorBlack, Exposition);
- }
- if (Prompt != NULL) {
- SwMoveCursor(stdout, 1, Row);
- SwPrintInColor(ConsoleColorGray, ConsoleColorDarkMagenta, Prompt);
- }
- Answer = DwReadCharacterSet(Context, "yn");
- if (Answer == EOF) {
- return Answer;
- }
- if (Answer == 'y') {
- return 1;
- }
- return 0;
- }
- INT
- DwReadCharacter (
- PDW_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine reads a key from standard in.
- Arguments:
- Context - Supplies a pointer to the application context.
- Return Value:
- Returns the character received on success.
- EOF on read failure or end of input.
- --*/
- {
- INT Character;
- Character = SwReadInputCharacter();
- if (Character == 0x3) {
- Context->ExitRequested = TRUE;
- return -1;
- }
- return Character;
- }
- INT
- DwRandom (
- INT Minimum,
- INT Maximum
- )
- /*++
- Routine Description:
- This routine gets a random value within the given range.
- Arguments:
- Minimum - Supplies the minimum random value.
- Maximum - Supplies the maximum random value, exclusive.
- Return Value:
- Returns a random value between the specified minimum and maximum.
- --*/
- {
- ssize_t BytesRead;
- INT Value;
- //
- // Prefer the random source if it exists.
- //
- if (DwRandomSource >= 0) {
- BytesRead = read(DwRandomSource, &Value, 2);
- if (BytesRead == sizeof(Value)) {
- return Minimum + (Value % (Maximum - Minimum));
- }
- }
- return Minimum + (rand() % (Maximum - Minimum));
- }
- ULONG
- DwChecksum (
- PVOID Buffer,
- ULONG Size
- )
- /*++
- Routine Description:
- This routine gets a checksum value for the high scores file.
- Arguments:
- Buffer - Supplies a pointer to the buffer to checksum.
- Size - Supplies the size in bytes of the checksum.
- Return Value:
- Returns the checksum of the file.
- --*/
- {
- PUCHAR Bytes;
- ULONG Sum;
- //
- // Borrow an algorithm from ELF: Sum = (Sum * 33) + Byte for each byte.
- //
- Bytes = Buffer;
- Sum = 0;
- while (Size != 0) {
- Sum = ((Sum << 5) + Sum) + *Bytes;
- Bytes += 1;
- Size -= 1;
- }
- return Sum;
- }
|