1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859 |
- /*++
- 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) {
- do {
- BytesRead = read(DwRandomSource, &Value, 2);
- } while ((BytesRead < 0) && (errno == EINTR));
- 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;
- }
|