;##################LEMONADE STAND####################### ;Coded by: Art Coates and Ben Morris ;C335 ;Updated April 20, 2005 ;####################################################### Extrn GetDec:Far, PutDec:Far, PutDec:Far, PutStrng:Far, NewLine:Far ; #include "iostream.h" Data Segment ;######Game variables################# Day dw 1 GlassesSold dw ? PriceperGlass dw ? Income dw ? Expenses dw ? GlassesMade dw ? AdvertisingMade dw ? AdvertisingCost dw ? Profit dw ? Assets dw ? CurrentAssets dw 200 ;starting amount DaystoPlay dw ? WeatherCond dw ? CostPerGlass dw ? ;######inputforday function prompts###### OnDay db "On day: " ; length 8 LemonadeCost0 db "The cost to make lemonade is " ; length 29 LemonadeCost1 db " per glass." ; 11 ;######Random number function vars####### RAND_seed dw ? ;######prompts########################### Intro db "Welcome to Lemonade Stand" ; basic intro prompt 25 Instructions01 db ' Welcome to the wonderful world of Entrepreneurship! ' ; 80 Seperator1 db '* $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ * $ ' Instructions02 db 'You have chosen to run a lemonade stand from 1-30 days in an attempt to make a ' Instructions03 db 'little money. You must take into account your assests, advertising budget and ' Instructions04 db 'the current weather conditions in an attempt to make your stand profitable. ' Instructions05 db ' Good luck in your quest! ' DailyStatement db 'Lemonade stand Daily Statement:' ; daily statement 31 Date db 'On day: ' ; day output 8 Seperator db '******************************' ; seperator 30 Sales db 'Glasses sold: ' ; glasses sold 14 Priceprompt db 'Price per glass: ' ; price per glass 17 Production db 'Glasses made: ' ; glasses made 14 Advertsprompt db 'Signs made: ' ; signs made 12 Profitprompt db 'Profit: ' ; profit prompt 8 AssetsPrompt db 'Assets: ' ; asset prompt 8 GlassesPrompt db 'How many glasses of lemonade do you wish to make? ' ; length 50 AdvertisingPrompt0 db 'How many advertising signs do you wish to make at ' ; 50 AdvertisingPrompt1 db ' cents each? ' ; 13 LemonadePricePrompt db 'What price (in cents) do you wish to charge for lemonade? ' ; 56 DaysPrompt db 'Please enter the number of days to run the stand (1-30): ' ; 57 NumberOutOfRange db 'Number out of range, try again ' ; 32 CannotAfford db 'You cannot afford this many ' ; 32 OutOfMoney db 'Game Over - you are out of money' ; 32 ;########Weather report################## Weather0 db "Today's weather is: Hot and Humid " ; 35 Weather1 db "Today's weather is: Sunny " ; Weather2 db "Today's weather is: Fair " ; Weather3 db "Today's weather is: Cloudy and Cool" ; Weather4 db "Today's weather is: Raining " ; ;#######Glasses Sold##################### MaxPrice dw ? ;max price of lemondade for a given day MaxGlassesSold dw ? ;max number of glasses sold in one day GlassMul dw ? ;#######Game Graphics#################### logo01 db ' 888 888 ' ; 80 logo02 db ' 888 888 ' logo03 db ' 888 888 ' logo04 db ' 888 .d88b. 88888b.d88b. .d88b. 88888b. 8888b. .d88888 .d88b. ' logo05 db ' 888 d8P Y8b 888 "888 "88b d88""88b 888 "88b "88b d88" 888 d8P Y8b ' logo06 db ' 888 88888888 888 888 888 888 888 888 888 .d888888 888 888 88888888 ' logo07 db ' 888 Y8b. 888 888 888 Y88..88P 888 888 888 888 Y88b 888 Y8b. ' logo08 db ' 88888888 "Y8888 888 888 888 "Y88P" 888 888 "Y888888 "Y88888 "Y8888 ' logo09 db ' ' logo10 db ' ' logo11 db ' ' logo12 db ' .d8888b. 888 888 ' logo13 db ' d88P Y88b 888 888 ' logo14 db ' Y88b. 888 888 ' logo15 db ' "Y888b. 888888 8888b. 88888b. .d88888 ' logo16 db ' "Y88b. 888 "88b 888 "88b d88" 888 ' logo17 db ' "888 888 .d888888 888 888 888 888 ' logo18 db ' Y88b d88P Y88b. 888 888 888 888 Y88b 888 ' logo19 db ' "Y8888P" "Y888 "Y888888 888 888 "Y88888 ' logo20 db ' Press Enter to Continue... ' ;####Game Over########################### GameOver01 db " _____ ____ _ " ; 80 GameOver02 db " / ____| / __ \ | | " GameOver03 db " | | __ __ _ _ __ ___ ___ | | | |_ _____ _ __| | " GameOver04 db " | | |_ |/ _` | '_ ` _ \ / _ \ | | | \ \ / / _ \ '__| | " GameOver05 db " | |__| | (_| | | | | | | __/ | |__| |\ V / __/ | |_| " GameOver06 db " \_____|\__,_|_| |_| |_|\___| \____/ \_/ \___|_| (_) " GameOver07 db " Game Over! - Thank you for playing! " Data Ends Code Segment Assume Cs:Code, Ds:Data, Ss:Sseg ;#####Convert to Dollar################## ;takes 1 value converts it front cents ;to dollars ;Returns Whole # in Ax ;Cents # in DX @CentsToDollars Proc Near C, @CASH:WORD push bx xor dx,dx ;divided cash by 100 mov ax, @Cash ;creates the actual number cwd mov bx, 100 ;remainder is cents iDiv bx ;goes to DX pop bx @ctdif: cmp dx, 0 ;if dx < 0 jl @ctdthen jmp @ctdendif @ctdthen: ;then negate dx neg dx jmp @ctdendif @ctdendif: ret @CentsToDollars Endp ;#####random number generator############ ;gets a large number, a seed, and an upper limit ;seed is wiped out initially ;system time is used for seed ;answer is returned in Ax @RANDOMNUMBER Proc Near C, @high:word push bx push cx push dx xor ax, ax ;clear AX mov ah, 2Ch ;load 2Ch into ah int 21h ;load system time into registers mov RAND_seed, dx ;dh holds seconds, dl holds ms, move to seed mov bx, @high ;move high value into bx add bx, 1 ;add one mov ax, RAND_seed ;put random seed into Ax xor dx,dx ;clear dx cwd ;convert word to double div bx ;divide seed by high mov ax, dx ;move seed mod high into ax pop dx pop cx pop bx ret @RANDOMNUMBER ENDp ;####SetCostPerGlass#################### ;Generates a random number ;loads that number into costperglass ;####################################### @SetCostPerGlass Proc Near push ax invoke @RandomNumber,4 ;generate random 0-4 add ax,3 ;add 3 to it mov CostPerGlass,Ax ;load result into costperglass pop ax ret @SetCostPerGlass ENDp ;####SetAdvertisingCost################## ;generates a random number ;loads that number into advertising cost ;######################################## @SetAdvertisingCost Proc Near push ax invoke @RandomNumber,5 ;generate random 0-5 add ax,5 ;add 5 to the number mov AdvertisingCost,Ax ;move result into advertising cost pop ax ret @SetAdvertisingCost ENDp ;###########Post Daily info############# ;post the daily information ;####################################### @PostDailyInfo Proc Near push ax push cx Mov cx, 8 ;output onday prompt Lea Di, OnDay Call PutStrng mov Ax, Day ;show day call PutDec mov cx, 30 call NewLine lea di, Seperator ;load the separator call PutStrng call NewLine ;blank lines call NewLine pop cx pop ax ret @PostDailyInfo ENDp ;####ClearScreen######################### ;clears the screen with a loop ;puts @line # of new lines on the screen ;######################################## @cLEARSCREEN Proc Near C, @Lines:word push Bx mov Bx, @Lines ;bx = # of lines on the screen @CSfor: cmp bx, 0 ;for bx > 0 do ja @CSdo jmp @CSendfor @CSdo: call NewLine ;print new line dec Bx ;dec bx jmp @CSfor ;loop @CSendfor: pop Bx ret @CLEARSCREEN ENDp ;######outputs cents formated nicely##### ;outputs -3453 or 300 as $34.53 or $3.00 ;input is money in cents ;######################################## @OutputDollars Proc Near C, @Money:word push ax push bx push cx push dx invoke @CentsToDollars, @Money ;break money apart into ;dollars and cents push ax push dx xor ax, ax ;clears registers for xor dx, dx ;interrup call mov ah, 02h ;int 21h puts $ on the screen mov dl, 36 ;call 36 = $ int 21h pop dx pop ax @optif2: ; if money < 0 cmp @Money, 0 jl @optand2 jmp @optendif2 @optand2: ; AND cmp @Money, -100 ; money > -100 jg @optthen2 jmp @optendif2 @optthen2: push ax push dx ;clear registers xor ax, ax xor dx, dx mov ah, 02h ;use int21h again mov dl, 45 ;character 45 = - int 21h ;call int pop dx pop ax jmp @optendif2 @optendif2: call PutDec ;output whole $ push ax push dx xor ax, ax xor dx, dx mov ah, 02h ;int 21h again mov dl, 46 ;character 46 = . int 21h ;call int pop dx pop ax mov ax, dx ;move into ax, the decimal portion @optif: cmp ax, 10 ;if ax < 10 Jb @optthen jmp @optendif @optthen: ;this has to be added to keep a zero infront push ax ;of decimals < 10 or 9 would print out .9 instead mov ax, 0 ;of .09 call PutDec pop ax jmp @optendif @optendif: call PutDec ;output the decimal portion pop dx pop cx pop bx pop ax ret @outputdollars ENDp ;#########INPUT FOR DAY################## ;gets input for the day ;provides error handling for ;entering data also ;######################################## @InputForDay Proc Near C push ax push bx push cx push dx mov cx, 29 ;output the cost per glass lea di, LemonadeCost0 call PutStrng invoke @OutputDollars, CostPerGlass mov cx, 11 ;append perglass lea di, LemonadeCost1 call PutStrng call NewLine ;blank lines call NewLine mov cx, 7 ;output current assets lea di, AssetsPrompt call PutStrng invoke @OutputDollars, CurrentAssets call NewLine @if1: ;begin prompts for 3 values, loop to here call NewLine Mov cx, 50 ;prompt for how many glasses to make Lea di, GlassesPrompt Call PutStrng call GetDec ;get the value into ax mov GlassesMade, Ax ;load that into glassesmade call NewLine mul CostPerGlass ;multiply costperglass x # glasses mov Expenses, ax ;move result into expenses for below cmp ax, Currentassets ;if expenses > currentassets then jg @then1 jmp @endif1 @then1: mov cx, 32 lea di, CannotAfford ;show you can't afford message call PutStrng invoke @OutputDollars, ax ;show how much it would cost jmp @if1 ;jump to the top to reprompt @endif1: @if2: call NewLine mov cx, 50 lea di, AdvertisingPrompt0 ;show the cost of advertising call PutStrng mov ax,AdvertisingCost call PutDec mov cx, 13 lea di,AdvertisingPrompt1 ;append per sign call PutStrng call GetDec ;load the input into ax mov AdvertisingMade, ax ;move that into advertising made call NewLine mul AdvertisingCost ;multiply advertising cost x advertising made add ax, Expenses ;add expenses to the result cmp ax, CurrentAssets ;if the result is > currentassets then jg @then2 jmp @endif2 @then2: mov cx, 28 lea di, CannotAfford ;print you cant afford this call PutStrng invoke @OutputDollars, ax ;show how much it cost jmp @if2 ;jmp back to the top again @endif2: mov Cx, 58 lea Di, LemonadePricePrompt ;prompt for how much you want to charger /glass call PutStrng call GetDec ;load into ax mov PricePerGlass, ax ;move into priceperglass call NewLine pop dx pop cx pop bx pop ax ret @InputForDay endp ;#######Asset Statement################## ;finacial summary prints out ;important figures which show you ;where you stand in the game ;####################################### @AssetStatement Proc Near C push cx push ax mov ax,PricePerGlass ;priceperglass x glassessold = income mul GlassesSold ;move into income mov Income,ax mov ax,AdvertisingCost ;advertisingcost x advertisingmade = expenses mul AdvertisingMade mov Expenses,ax ;move into expenses mov ax,CostPerGlass ;costperglass x glassesmade + expenses = expenses mul GlassesMade add Expenses,ax ;add value to expeneses mov ax,Income ;income - expenses = profit sub ax,Expenses mov Profit,ax add ax,CurrentAssets ;add current assets to profit mov Assets,ax ;move result into assets mov Currentassets, Ax ;move result into currentassets invoke @clearscreen,25 ;clear the screen 25 times mov cx,31 lea di,dailystatement ;print daily statment call PutStrng mov cx,30 call NewLine lea di,seperator ;print the separator call PutStrng invoke @clearscreen,2 mov cx,8 lea di,date ;show the day call PutStrng mov ax,day call putdec call NewLine mov cx,12 lea di,advertsprompt ;show advertisingmade call PutStrng mov ax,AdvertisingMade call putdec call NewLine mov cx,14 lea di,production ;show glassesmade call PutStrng mov ax,GlassesMade call putdec call NewLine mov cx,17 lea di,priceprompt ;show priceperglass call PutStrng invoke @outputdollars,PriceperGlass call NewLine mov cx,14 lea di,sales ;show glassessold call PutStrng mov ax,GlassesSold call putdec call NewLine mov cx,8 lea di,profitprompt ;show profit call PutStrng invoke @outputdollars,Profit call NewLine lea di,assetsprompt call PutStrng ;show assets invoke @outputdollars,assets invoke @clearscreen,3 inc day ;add one to day pop cx pop ax ret @AssetStatement ENDp ;############promt for days######### ;prompts for the number of days to ;play the game ;################################### @PromptforDays proc near C push cx push ax @pfdfor: mov cx,57 ;shows the day prompt lea di,daysprompt call PutStrng ;input the number of days to play call getdec cmp ax,30 ;make sure that number isnt over 30 jg @pfdtryagain cmp ax,0 ;make sure it isnt over zero jle @pfdtryagain jmp @pfdendfor @pfdtryagain: mov cx,32 ;try again out of range message lea di,numberoutofrange call PutStrng call NewLine jmp @pfdfor @pfdendfor: mov DaystoPlay,ax ;load the value into daystoplay pop cx pop ax ret @promptforDays endp ;########Generate weather report######### ;Generates the weather report for the day @GenerateWeather Proc near C push ax push bx push cx push dx invoke @randomnumber, 4 ;generate a random number 0-4 Mov Cx, 35 @gswitch: ;case statment cmp ax, 0 je @gcase0 cmp ax, 1 je @gcase1 cmp ax, 2 je @gcase2 cmp ax, 3 je @gcase3 cmp ax, 4 je @gcase4 jmp @gdefault @gcase0: ;if number is zero Lea Di, weather0 ;weather is raining Call PutStrng Call NewLine mov weathercond, 0 jmp @gendswitch @gcase1: Lea Di, weather1 ;if number is 1 Call PutStrng ;weather is cloudy and cool Call NewLine mov weathercond, 1 jmp @gendswitch @gcase2: ;if number is 2 Lea Di, weather2 ;weather is fair Call PutStrng Call NewLine mov weathercond, 2 jmp @gendswitch @gcase3: ;if number is 3 Lea Di, weather3 ;weather is sunny Call PutStrng Call NewLine mov weathercond, 3 jmp @gendswitch @gcase4: ;if number 4 Lea Di, weather4 ;weather is hot and humid Call PutStrng Call NewLine mov weathercond, 4 jmp @gendswitch @gdefault: @gendswitch: call NewLine pop dx pop cx pop bx pop ax ret @generateweather endp ;#########Glasses Sold################### ;Figures the #of glasses sold ;Based on the weather, advertising ;and price charged. ;######################################## @glassessold Proc Near push ax push bx push cx push dx invoke @RandomNumber, 20 ;generate the max selling price mov MaxPrice, ax ;move into max selling variable mov ax, WeatherCond ;Adjust max price to reflect the weather ;switch changes max price to a percentage divider @mxswitch: cmp ax, 0 je @mxcase0 cmp ax, 1 je @mxcase1 cmp ax, 2 je @mxcase2 cmp ax, 3 je @mxcase3 cmp ax, 4 je @mxcase4 jmp @mxdefault @mxcase0: ;adjust the divider accordingly mov WeatherCond, 40 jmp @mxendswitch @mxcase1: mov WeatherCond, 20 jmp @mxendswitch @mxcase2: mov WeatherCond, 4 jmp @mxendswitch @mxcase3: mov WeatherCond, 2 jmp @mxendswitch @mxcase4: mov WeatherCond, 1 jmp @mxendswitch @mxdefault: @mxendswitch: mov Ax, MaxPrice mov Bx, WeatherCond ;conditions xor dx,dx ;Divide by weather condition add result to cwd ;max price idiv bx ;effect is a higher max price based on higher add MaxPrice, Ax ;weather condition invoke @RandomNumber,10 ;generate random number between 0-10 add Ax, 5 ;shifts the range to 5-15 mov MaxGlassesSold, Ax mov Bx, WeatherCond xor dx,dx ;Divide by weather condition add result to cwd ;maxglasses sold idiv bx ;effect is a higher max glasses sold based on higher add MaxGlassesSold, Ax ;weather condition mov ax, AdvertisingMade @adswitch: ;uses the number of advertising signs made here cmp ax, 5 ;arbitrary values making over 20 signs has no jl @adcase0 ;increase in sales cmp ax, 10 jl @adcase1 cmp ax, 15 jl @adcase2 cmp ax, 21 jl @adcase3 jmp @addefault @adcase0: ;loads the divider mov GlassMul, 15 jmp @adendswitch @adcase1: mov GlassMul, 8 jmp @adendswitch @adcase2: mov GlassMul, 3 jmp @adendswitch @adcase3: ;20 signs effectivly double your maxglassessold mov GlassMul, 1 jmp @adendswitch @addefault: @adendswitch: mov Ax, MaxGlassesSold ;further increase the max # of glasses sold by ;figure the multipier for Glasses based on advertising mov Bx, GlassMul ;using the advertising divider xor dx, dx cwd idiv bx ;divide by the number add MaxGlassesSold, Ax ;add it to maxglasses sold invoke @RandomNumber, 10 ; randomly add/subtract from glasses @adif: ;50/50 chance of loosing/gaining 1-5 glasses cmp ax, 5 jl @adthen jmp @adelse @adthen: invoke @RandomNumber, 5 ;add a random component from max glasses sold add MaxGlassesSold, ax @adelse: invoke @RandomNumber, 5 ;subtract a random component from max glasses sold sub MaxGlassesSold, ax @adendif: ;######################################## ;At this point your ideal max glasses sold and ideal maxprice is figured ;so if your price/glass = maxprice you're going to sell all your glasses up to ;maxglassessold ;######################################## mov cx, PricePerGlass @glif: cmp cx, MaxPrice ;compare the price/glass to max price jg @glthen ;if it's greater then glasses sold jmp @glendif ;will need to be reduced proportionally @glthen: mov Ax, PricePerGlass mov cx, MaxPrice xor dx, dx cwd div cx ;divide priceperglass by max price mov bx, ax mov ax, MaxGlassesSold xor dx, dx cwd div bx ;divide by divider mov MaxGlassesSold, ax ;replace the reduced maxglassessold with @aif: ;if divider > 3, or your price is 3x higher cmp bx, 3 ;than the maxprice, you sell zero jg @athen jmp @aendif @athen: mov MaxGlassesSold, 0 ;move zero into maxglassessold @aendif: ;the divided value @glendif: ;####END IF mov bx, MaxGlassesSold mov GlassesSold, bx ;populate glassessold with final number mov cx, GlassesMade ;load how many were made into Cx @gsif: cmp cx, GlassesSold ;if glasses made > glasses sold then jl @gsthen jmp @gsendif @gsthen: mov GlassesSold, cx ;glasses sold = glasses made jmp @gsendif @gsendif: call NewLine ;######################################## ;glassessold is ultimately the output of this function ;it is a global variable therefore the function is a void ;######################################## pop dx pop cx pop bx pop ax ret @glassessold endp ;#####PrintIntro######################### ;prints a ASCI graphical intro screen ;######################################## @PrintIntro Proc Near push cx invoke @ClearScreen, 25 ;clears the screen mov Cx, 25 lea Di, Intro ;show intro call PutStrng invoke @ClearScreen,2 mov cx,80 ;load each line of the ASCI ART lea di, logo01 ;graphic call PutStrng lea di, logo02 call PutStrng lea di, logo03 call PutStrng lea di, logo04 call PutStrng lea di, logo05 call PutStrng lea di, logo06 call PutStrng lea di, logo07 call PutStrng lea di, logo08 call PutStrng lea di, logo09 call PutStrng lea di, logo10 call PutStrng lea di, logo11 call PutStrng lea di, logo12 call PutStrng lea di, logo13 call PutStrng lea di, logo14 call PutStrng lea di, logo15 call PutStrng lea di, logo16 call PutStrng lea di, logo17 call PutStrng lea di, logo18 call PutStrng lea di, logo19 call PutStrng lea di, logo20 call PutStrng push ax call GetDec ;press enter pop ax pop cx ret @PrintIntro ENDp ;########print instructions######### ;shows the instructions how to play ;the game ;################################### @PrintInstructions Proc Near push cx invoke @ClearScreen, 25 ;clear the screen mov cx, 80 lea di, Instructions01 ;load each line of the instructions call PutStrng call NewLine lea di, Seperator1 call NewLine call PutStrng call NewLine lea di, Instructions02 call PutStrng lea di, Instructions03 call PutStrng lea di, Instructions04 call PutStrng call NewLine lea di, Seperator1 call PutStrng call NewLine lea di, Instructions05 call PutStrng Invoke @ClearScreen, 5 pop cx ret @PrintInstructions ENDp ;##########gameover############ ;shows the game over graphic ;############################## @GameOver Proc Near push cx mov cx,80 ;shows the game over graphic lea di, GameOver01 ;prints one line at a time call PutStrng lea di, GameOver02 call PutStrng lea di, GameOver03 call PutStrng lea di, GameOver04 call PutStrng lea di, GameOver05 call PutStrng lea di, GameOver06 call PutStrng lea di, GameOver07 call PutStrng pop cx ret @GameOver ENDp ;########### MAIN ################# ;################################## main Proc Far MOV AX,SEG DATA ;intialize registers MOV DS,AX MOV ES,AX invoke @PrintIntro ;invoke functions print intro invoke @PrintInstructions ;show the instructions invoke @PromptForDays ;prompt for # of days to play invoke @ClearScreen,25 ;clear the screen @for: ;for days to play > 0 cmp DaystoPlay,0 jg @do jmp @endfor @do: invoke @SetCostPerGlass ;generate a random glass cost invoke @SetAdvertisingCost ;generate a random advertising cost invoke @PostDailyInfo ;show the daily info invoke @GenerateWeather ;generate a weather report for the day invoke @InputForDay ;get input for the day invoke @GlassesSold ;do the calculations to get glasses sold invoke @AssetStatement ;show the result for the day mov Ax, CostPerGlass ;move into Ax costperglass @if: cmp CurrentAssets, ax ;if currentassets < costperglass jl @then jmp @endif @then: mov cx, 32 ;show you have ran out of money lea di, OutOfMoney call PutStrng call NewLine jmp @endfor ;jump to gameover @endif: dec DaysToPlay ;decrement the days to play jmp @for @endfor: invoke @GameOver ;show game over graphic mov ah, 4ch int 21h main ENDp Code Ends SSeg Segment STACK DB 254 dup(?) SSeg Ends End main