Category : Pascal Source Code
Archive   : TPMONO.ZIP
Filename : MONOPOLY.PAS

 
Output of file : MONOPOLY.PAS contained in archive : TPMONO.ZIP
{ -------------------------------------------------------------- }
{ MONOPOLY }
{ By Richard Lovett }
{ 6649 Oak St. }
{ Kansas City, Mo. 64113 }
{ CIS #: 75425,666 }
{ Version 1.0 -- February 1987 }
{ }
{ Files required to compile: }
{ }
{ MONOPOLY.PAS This file }
{ TITLE.INC Draws title screen }
{ BOARD.INC Draws playing board }
{ WINDOW.INC Windowing procedures }
{ MONOPLY2.INC Misc. procedures }
{ ZGROUP.INC Community Chest and Chance procedures }
{ }
{ Needed to run: MONOPLY.DTA (data to initialize variables) }
{ }
{ See MONOPOLY.DOC for instructions on using the program }
{ -------------------------------------------------------------- }
program Monopoly;

CONST
arrow = #16;
housepic = #127;
hotelpic = 'ÜÜ';
TYPE
proptype = string[22];
Property_type = record
name : proptype; {name of square, 22 chars}
price : integer;
owner : byte;
houses_on : byte; {how many houses on it}
hotel : boolean; {true = property has hotel}
mortgageval : integer;
mortgaged : boolean;
base_rent : integer; {rent without houses or hotel}
house1rent : integer;
house2rent : integer;
house3rent : integer;
house4rent : integer;
hotel_rent : integer;
group : byte;
row : integer; {X-Y coordinates of first house}
col : integer; {to be built on this property }
END; {GROUPS ARE:
1. dark purple 7. green
2. light blue 8. dark blue
3. light purple 9. railroads
4. orange l0. utilities
5. red
6. yellow 0. other squares}
Player_type = record
name : string[11];
cash : integer;
location : byte; {what square player is on (1-40; GO=1}
jailed : boolean;
bankrupt : boolean;
escapetries : byte; {dice rolls to get out of jail}
END;

Card_type = record {Chance and Community Chest cards}
message : string[80];
moveto : string[2]; {#=square #, RR=railroad, UT=utility}
getmoney : integer; {what the card pays, if anything}
paymoney : integer; {what the $ penalty is, if any }
END;

diskdata = text;
rentflagtype = (regular,twice,tentimes);
string2 = string[2];

VAR
chance,
chest : array[1..16] of card_type;
player : array[1..4] of player_type;
square : array[1..40] of property_type;
parkingmoney : integer;
payparking : boolean;
datafile : diskdata;
gameover,
haltgame : boolean;
turn,
chancecounter,
chestcounter,
doubles,
current : byte; {the square the current player is on -- 1-40}
numplayers : integer;
rentflag : rentflagtype;
ansr : char;

procedure bigwindow; {the full screen}
BEGIN
window(1,1,80,25);
END;

procedure smallwindow; {area in center of playing board}
BEGIN
window(20,6,62,19);
END;

procedure showcash; {shows players' cash holdings on 25th line of screen}
{also shows cash on Free Parking, if applicable }
VAR
i : byte;
BEGIN
bigwindow;
for i := 0 to numplayers-1 do
BEGIN
gotoXY((20*i)+1,25);
if not player[i+1].bankrupt then
write(player[i+1].name,': $',player[i+1].cash:4)
else write(' '); {19 spaces}
if payparking then
BEGIN
gotoXY(73,21);
write('$',parkingmoney:4);
END;
END;
smallwindow;
END; {showcash}


{$I TITLE.INC}
{$I BOARD.INC}
{$I WINDOW.INC}
{$I MONOPLY2.INC}

function dispose(name: proptype; val: integer; groupnum: byte;
mortgaging: boolean; VAR buildingsale : integer): boolean;
{removes houses prior to mortgaging or selling}
VAR
housetotal : integer;
temp : real;
hoteltotal : integer;
i : byte;
BEGIN
housetotal := 0;
hoteltotal := 0;
dispose := false;
clrscr;
gotoXY(1,4);
if mortgaging then
BEGIN
writeln('Mortgaging ',name,' will net you $',val,'.');
writeln;
writeln('However, you must first sell buildings on that color group');
END
else writeln
('Before transferring, you must first sell buildings on that color group');
writeln('to the bank at the following prices (half of the original cost):');
writeln;
for i := 1 to 40 do
BEGIN
if square[i].group = groupnum then
BEGIN
if square[i].houses_on > 0 then
BEGIN
temp := cost_of_houses(groupnum);
writeln(square[i].name,':');
if square[i].houses_on = 1 then writeln(' 1 house at $',
round(temp/2))
else
writeln(' ',square[i].houses_on,' houses at $',
round(temp/2),' each');
housetotal := round(housetotal + (temp/2) *
square[i].houses_on);
END;
if square[i].hotel then
BEGIN
temp := (cost_of_houses(groupnum) * 5)/2;
writeln(square[i].name,':');
writeln(' 1 hotel at $',round(temp));
hoteltotal := round(hoteltotal + temp);
END;
END; {if square[i].group}
END; {for}
writeln;
write('The building sale will net you a total of $',housetotal + hoteltotal,
'. Okay (Y/N)? ');
read(kbd,ansr);
if upcase(ansr) = 'Y' then
BEGIN
for i := 1 to 40 do
BEGIN
if square[i].group = groupnum then
BEGIN
square[i].houses_on := 0;
square[i].hotel := false;
END;
END; {for}
dispose := true;
buildingsale := housetotal + hoteltotal;
END; {if upcase(ansr)=Y}
END; {dispose}

procedure mortgage(debt: integer);
VAR
i,
temp,
groupnum,
counter, total,
column, rowe : byte;
reply,result,
amountowed,
buildingsale : integer;
propnum : array [1..40] of byte;
sold, must_sell,
done : boolean;
ansr : char;
replystr : string[2];

BEGIN {mortgage}
initwin;
done := false;
buildingsale := 0;
openwin(' MORTGAGE A PROPERTY ',1,1,80,24);
amountowed := debt;
repeat
clrscr;
gotoXY(1,2);
counter := 0;
write('NON-MORTGAGED PROPERTIES YOU OWN: ');
reverse;
if debt > 0 then writeln(' Balance you need: $',amountowed,' ');
normal;
writeln;
rowe := 3;
for i := 1 to 40 do
BEGIN
if (square[i].owner = turn) and not square[i].mortgaged then
BEGIN
counter := counter + 1;
if not odd(counter) then column := 36
else
BEGIN
column := 1;
rowe := rowe + 1;
END;
gotoXY(column,rowe);
write(counter:2,'. ');
list_property(i); {print property name}
propnum[counter] := i;
END;
END; {for}
writeln;
rowe := whereY;
repeat
total := 0;
gotoXY(1,rowe+1);
write('Which property number (0 to exit)? ');
read(replystr);
val(replystr,reply,result);
until reply in [0..counter];
if reply > 0 then
BEGIN
clrscr;
gotoXY(3,1);
must_sell := false;
with square[propnum[reply]] do
BEGIN
temp := group;
for i := 1 to 40 do if (square[i].group = temp) and
(square[i].hotel or (square[i].houses_on > 0)) then
must_sell := true;
if must_sell then
BEGIN
sold := dispose(name, mortgageval, group, true,
buildingsale);
if sold then
BEGIN
player[turn].cash := player[turn].cash +
buildingsale;
amountowed := amountowed - buildingsale;
if amountowed < 0 then amountowed := 0;
writeln;
writeln;
write('Proceed to mortgage ',name,' (Y/N)? ');
read(kbd,ansr);
END; {if sold}
END; {if must_sell}
if must_sell and sold and (upcase(ansr)='Y') then
BEGIN
mortgaged := true;
player[turn].cash := player[turn].cash + mortgageval;
amountowed := amountowed - mortgageval;
if amountowed < 0 then amountowed := 0;
END;
if not must_sell then
BEGIN
writeln;
writeln('This will net you $',mortgageval);
writeln;
write('Proceed to mortgage ',name,' (Y/N)? ');
read(kbd,ansr);
if upcase(ansr)='Y' then
BEGIN
mortgaged := true;
player[turn].cash := player[turn].cash + mortgageval;
amountowed := amountowed - mortgageval;
if amountowed < 0 then amountowed := 0;
END;
END; {if not must_sell}
END; {with}
END; {if reply > 0}
until reply = 0;
closewin;
show_mortgages;
showcash;
gotoXY(5,14);
END; {mortgage}

procedure unmortgage;
VAR
counter, i,
column,
rowe : byte;
reply,
result : integer;
replystr : string[2];
propnum : array [1..40] of byte;
temp : real;
total : integer;
ch : char;
BEGIN
initwin;
openwin(' UNMORTGAGE A PROPERTY ',1,1,80,24);
repeat
clrscr;
gotoXY(1,2);
counter := 0;
writeln('MORTGAGED PROPERTIES YOU OWN:');
writeln;
rowe := 3;
for i := 1 to 40 do
BEGIN
if (square[i].owner = turn) and (square[i].mortgaged) then
BEGIN
counter := counter + 1;
if not odd(counter) then column := 36
else
BEGIN
column := 1;
rowe := rowe + 1;
END;
gotoXY(column,rowe);
write(counter:2,'. ');
list_property(i); {print property name}
propnum[counter] := i;
END;
END; {for}
writeln;
writeln;
repeat
write('Which property number (0 to exit)? ');
read(replystr);
val(replystr,reply,result);
until reply in [0..counter];
if reply <> 0 then with square[propnum[reply]] do
BEGIN
temp := mortgageval * 1.1;
total := round(temp);
if player[turn].cash < total then
BEGIN
writeln;
beep;
writeln('You don''t have enough money.');
delay(3000);
END
else
BEGIN
writeln;
write('The mortgage plus 10% will cost you $',total,
'. Okay (Y/N)? ');
read(kbd,ch);
if upcase(ch)='Y' then
BEGIN
mortgaged := false;
player[turn].cash := player[turn].cash - total;
END;
END; {else}
END; {if reply <> 0}
until reply = 0;
closewin;
bigwindow;
showcash;
show_mortgages;
smallwindow;
gotoXY(5,14);
END; {unmortgage}

function holdings_in_group (playernum, groupnum: byte): byte;
{determines how many properties in a group the player owns}
VAR
loop, count: byte;
BEGIN
count := 0;
for loop := 1 to 40 do if (square[loop].group = groupnum)
and (square[loop].owner = playernum) then count := count + 1;
holdings_in_group := count;
END;

function determine_rent: integer;
{if rentflag=regular, rent is computed normally. If rentflag=twice, pay
twice the normal rent. If rentflag=tentimes, pay 10 times roll of dice}
VAR
totalrent : integer;
grouptotal,
multiplier : byte;
BEGIN
with square[current] do
BEGIN
if owner = turn then
BEGIN
writeln ('You own this property.');
totalrent := 0;
END
else
BEGIN {you don't own it, so pay up}
grouptotal := holdings_in_group(owner,group);
if group in [1..8] then
BEGIN {it's residential property}
if (houses_on = 0) and not hotel then
BEGIN {property is unimproved}
if (grouptotal = 2) and (group in [1,8]) or
(grouptotal = 3) and (group in [2..7])
then
BEGIN
writeln('It''s an unimproved lot in a monopoly.');
writeln('The rent is doubled.');
totalrent := base_rent * 2
END
else totalrent := base_rent;
END;
if hotel then
BEGIN
writeln (' (The property has a hotel)');
totalrent := hotel_rent;
END;
if houses_on = 1 then
BEGIN
writeln(' (The property has 1 house)');
totalrent := house1rent;
END;
if houses_on = 2 then
BEGIN
writeln(' (The property has 2 houses)');
totalrent := house2rent;
END;
if houses_on = 3 then
BEGIN
writeln(' (The property has 3 houses)');
totalrent := house3rent;
END;
if houses_on = 4 then
BEGIN
writeln(' (The property has 4 houses)');
totalrent := house4rent;
END;
END {if group in 1..8}
else if group = 9 then
BEGIN {it's a railroad}
if grouptotal = 1 then totalrent := 25 else
if grouptotal = 2 then totalrent := 50 else
if grouptotal = 3 then totalrent := 100
else totalrent := 200;
if rentflag=twice then totalrent := totalrent * 2;
END {if group=9}
else
BEGIN {it's group 10, a utility}
if (grouptotal = 1) and (rentflag <> tentimes) then multiplier := 4
else multiplier := 10;
writeln(player[square[current].owner].name,' owns that property.');
write('Rent is ',multiplier,' times throw of dice.');
totalrent := multiplier * throwdice(true);
writeln('Rent = $',totalrent);
END; {group 10}
if group <> 10 then {it's residential, not utility}
writeln(player[owner].name,' owns that property. Rent is $',totalrent);
END; {you don't own it}
END; {with}
determine_rent := totalrent;
rentflag := regular;
END; {determine_rent}


{$I zgroup.inc}

procedure restore_board; forward;

procedure horsetrade (debt: boolean; VAR paid: boolean);
{Buy, sell, trade with opponent. If variable Debt is passed in false, this
transaction is not for the purpose of paying off a debt. In that case,
variable Paid will always return True. If there is a debt, Paid will be
true only if the debt is satisfied.}

LABEL
stop;
VAR
i, trader : byte;
transtype : integer;
ch : char;
entry : real;
result : integer;
entrystring : string[7];

procedure money_transaction;
VAR
choice : integer;
bucks : real;
money,
result : integer;
inputstring : string[7];
ch : char;
BEGIN
clrscr;
gotoXY(1,5);
writeln('The money will be paid:');
writeln;
writeln(' 1. By ',player[turn].name,' to ',player[trader].name);
writeln(' 2. By ',player[trader].name,' to ',player[turn].name);
writeln(' 0. Neither -- exit');
repeat
read(kbd,ch);
val(ch,choice,result);
until choice in [0..2];
writeln;
writeln;
if choice = 1 then
BEGIN
repeat
write('How much money goes to ',player[trader].name,'? $');
read(inputstring); {use string so nonnumeric entry won't crash it}
val(inputstring,bucks,result);
writeln;
money := round(bucks);
if money > player[turn].cash then
BEGIN
beep;
writeln('You don''t have that much.');
END; {if}
until money <= player[turn].cash;
player[trader].cash := player[trader].cash + money;
player[turn].cash := player[turn].cash - money;
END {if choice = 1}
else if choice = 2 then
BEGIN
repeat
write('How much money goes to ',player[turn].name,'? $');
read(inputstring);
val(inputstring,bucks,result);
writeln;
money := round(bucks);
if money > player[trader].cash then
BEGIN
beep;
writeln('You don''t have that much.');
END; {if}
until money <= player[trader].cash;
player[trader].cash := player[trader].cash - money;
player[turn].cash := player[turn].cash + money;
if debt then
BEGIN
write('Did that transaction satisfy ',player[turn].name,#39,
's debt (Y/N)? ');
read(kbd,ch);
writeln;
writeln;
writeln;
if upcase(ch) = 'Y' then paid := true;
END; {if debt}
END; {if choice = 2}

END; {money_transaction}

procedure property_transaction;
VAR
num,
counter,
playerfrom,
playerto,
rowe,
temp,
column, i : byte;
choice,
result,
reply,
buildingsale : integer;
person : string[11];
propnum : array [1..40] of byte;
yesno, ch : char;
replystr : string[2];
must_sell,
sold : boolean;
BEGIN
repeat
clrscr;
buildingsale := 0;
gotoXY(1,3);
writeln('PROPERTY TRANSACTION');
gotoXY(1,5);
writeln('The property will be transferred:');
writeln;
writeln(' 1. From ',player[turn].name,' to ',player[trader].name);
writeln(' 2. From ',player[trader].name,' to ',player[turn].name);
writeln(' 0. Neither -- exit');
repeat
read(kbd,ch);
val(ch,choice,result);
until choice in [0..2];
writeln;
writeln;
if choice = 0 then exit;
if choice = 1 then
BEGIN
playerfrom := turn;
playerto := trader;
END
else
BEGIN
playerfrom := trader;
playerto := turn;
END;
clrscr;
gotoXY(1,2);
counter := 0;
person := player[playerfrom].name;
for i := 1 to length(person) do person[i] := upcase(person[i]);
write('PROPERTIES OWNED BY ',person,':');
writeln;
rowe := 3;
for i := 1 to 40 do
BEGIN
if square[i].owner = playerfrom then
BEGIN
counter := counter + 1;
if not odd(counter) then column := 36
else
BEGIN
column := 1;
rowe := rowe + 1;
END;
gotoXY(column,rowe);
write(counter:2,'. ');
list_property(i); {print property name}
propnum[counter] := i;
END;
END; {for}
writeln;
rowe := whereY;
gotoXY(1,rowe+1);
write('Which property number (0 to exit)? ');
repeat
read(replystr);
val(replystr,reply,result);
until reply in [0..counter];
if reply = 0 then exit;
clrscr;
gotoXY(3,1);
must_sell := false;
with square[propnum[reply]] do
BEGIN
temp := group;
for i := 1 to 40 do if (square[i].group = temp) and
(square[i].hotel or (square[i].houses_on > 0)) then
must_sell := true;
if must_sell then
BEGIN
sold := dispose(' ',0,group,false,buildingsale);
if sold then
BEGIN
player[playerfrom].cash := player[playerfrom].cash
+ buildingsale;
num := propnum[reply];
square[num].owner := playerto;
writeln;
writeln;
if debt then
BEGIN
write('Did that transaction satisfy ',
player[turn].name,#39,'s debt (Y/N)? ');
read(kbd,ch);
writeln;
writeln;
if upcase(ch) = 'Y' then paid := true;
END; {if debt}
END; {if sold}
END {if must_sell}
else square[propnum[reply]].owner := playerto;
writeln;
writeln;
writeln('Okay, ',square[propnum[reply]].name,
' has been transferred to ',player[playerto].name,'.');
END; {with}
writeln;
write('Do you want to transfer any more property (Y/N)? ');
read(kbd,yesno);
until upcase(yesno) = 'N';
END; {property_transaction}

BEGIN {horsetrade}
if not debt then paid := true else paid := false;
initwin;
openwin(' HORSETRADE ',1,1,80,24);
gotoxy(1,3);
if numplayers > 2 then
BEGIN
writeln('Which player to horsetrade with (or 0 to exit)?');
for i := 1 to numplayers do
if (i <> turn) and not player[i].bankrupt
then writeln(' ',i,'. ',player[i].name);
write('--',arrow,' ');
repeat
read(kbd,ch);
val(ch,entry,result);
trader := round(entry);
until (trader <> turn) and (trader in [0..numplayers])
and not player[trader].bankrupt;
if trader = 0 then goto stop;
END
else if turn = 1 then trader := 2 else trader := 1;
writeln;
writeln;
writeln('What does this transaction involve?');
writeln(' 1. Money only');
writeln(' 2. Property only');
writeln(' 3. Both');
if debt and not paid then writeln(' 4. Declare debt paid');
writeln(' 0. None -- exit');
repeat
read(kbd,ch);
val(ch,transtype,result)
until transtype in [0..4];
case transtype of
0 : goto stop; {exit}
1 : money_transaction;
2 : property_transaction;
3 : BEGIN
money_transaction;
if debt and not paid or not debt then property_transaction;
END;
4 : if debt and not paid then
BEGIN
writeln;
write('The debt is satisfied, right (Y/N)? ');
read(ch);
if upcase(ch) = 'Y' then paid := true;
END; {if debt and not paid}
END; {case}
stop: {label}
closewin;
restore_board;
showcash;
smallwindow;
gotoXY(5,14);
END;

procedure go_bankrupt(playernum: byte; VAR debtpaid: boolean; payee: byte);
VAR
answer : char;
i, count : integer;
BEGIN
count := 0;
player_header;
gotoXY(4,7);
write('Bankruptcy--are you sure (Y/N)? ');
repeat
read (kbd,answer);
until upcase(answer) in ['Y','N'];
player[playernum].bankrupt := (upcase(answer) = 'Y');
if player[playernum].bankrupt then
BEGIN
gotoXY(4,9);
writeln ('Goodbye, ',player[playernum].name,'...');
delay(600);
play_dirge; {funeral march music}
delay(750);
for i := 1 to numplayers do
if player[i].bankrupt then count := count + 1;
if numplayers - count = 1 then gameover := true; {all but one player
is bankrupt}
debtpaid := true;
for i := 1 to 40 do
if square[i].owner = playernum then square[i].owner := payee;
if payee > 0 then
BEGIN
player[payee].cash := player[payee].cash +
player[playernum].cash;
player[playernum].cash := 0;
END;
END; {if player bankrupt}
END; {go_bankrupt}

procedure build; {buy houses or hotels}
LABEL
again, quit;
TYPE
temprecordtype = record
nam : string[22];
houses : byte;
hotl : boolean;
END;
VAR
temprecord : array [1..3] of temprecordtype;
i, loop, groupnum,
counter, total : byte;
column, rowe,
reply,
housecost, result,
howmany : integer;
propnum : array [1..40] of byte;
numhouses, holdings,
selected : byte;
which : string[22];
replystr : string[2];
ch : char;

function owns_all: boolean; {checks that player owns all properties
in the color group}
BEGIN
total := 0;
for i := 1 to 40 do
BEGIN
if (square[i].group = groupnum) and (square[i].owner = turn) then
BEGIN
total := total + 1;
with temprecord[total] do
BEGIN
nam := square[i].name;
if nam = which then selected := total;
houses := square[i].houses_on;
hotl := square[i].hotel;
END;
END; {if}
END; {for}
owns_all := ((total = 3) and (groupnum in [2..7]))
or ((total = 2) and (groupnum in [1,8]));
END; {owns_all}

function even_distribution: boolean;
VAR
uneven : boolean;
ch : char;
totl : byte;
BEGIN
even_distribution := true;
uneven := false;
writeln;
if groupnum in [2..7] then totl := 3 else totl := 2;
for i := 1 to totl do
BEGIN
if (temprecord[i].houses < temprecord[selected].houses)
and not temprecord[i].hotl then
BEGIN
beep;
writeln('You have to build on ',temprecord[i].nam,' first.');
uneven := true;
END; {if}
END; {for}
if uneven then
BEGIN
gotoXY(25,22);
write('PRESS A KEY TO CONTINUE');
read(kbd,ch);
even_distribution := false;
END;
END; {even_distribution}

procedure put_houses_on(number: byte);
BEGIN
closewin;
bigwindow;
with square[propnum[reply]] do
BEGIN
gotoXY(col,row);
if number = 5 then
BEGIN
write(' '); {5 spaces}
gotoXY(col+1,row);
write(hotelpic);
END
else
BEGIN
write(' ');
gotoXY(col,row);
reverse;
for i := 1 to number do write(housepic);
normal;
END;
END; {with}
END; {put_houses_on}


BEGIN {build}
initwin;
openwin(' BUY HOUSES OR HOTELS ',1,1,80,24);
again: {label}
repeat
clrscr;
gotoXY(1,2);
counter := 0;
writeln('RESIDENTIAL PROPERTIES YOU OWN:');
writeln;
rowe := 3;
for i := 1 to 40 do
BEGIN
if (square[i].owner = turn) and (square[i].group in [1..8]) then
BEGIN
counter := counter + 1;
if not odd(counter) then column := 36
else
BEGIN
column := 1;
rowe := rowe + 1;
END;
gotoXY(column,rowe);
write(counter:2,'. ');
list_property(i); {print property name}
propnum[counter] := i;
END;
END; {for}
writeln;
rowe := whereY;
repeat
total := 0;
gotoXY(1,rowe+1);
write('Which property number (0 to exit)? ');
read(replystr);
val(replystr,reply,result);
until reply in [0..counter];
if reply = 0 then
BEGIN
closewin;
goto quit;
END;
clrscr;
gotoXY(3,1);
groupnum := square[propnum[reply]].group;
which := square[propnum[reply]].name;
if not owns_all then
BEGIN
gotoXY(2,6);
writeln ('Sorry, you don''t own the whole group.');
delay(3000);
END;
if not even_distribution then goto again;
if square[propnum[reply]].mortgaged then
BEGIN
gotoXY(2,6);
writeln('Sorry, it''s mortgaged.');
delay(3000);
END;
if square[propnum[reply]].hotel then
BEGIN
gotoXY(2,6);
writeln('It already has a hotel.');
delay(3000);
END;
until owns_all and not square[propnum[reply]].mortgaged and
not square[propnum[reply]].hotel;
writeln;
with square[propnum[reply]] do
BEGIN
housecost := cost_of_houses(group);
if houses_on = 0
then writeln(name,' has no houses on it now. Five houses = hotel.')
else if houses_on = 1
then writeln(name,' has one house on it now. Five houses = hotel.')
else
writeln(name,' has ',houses_on,' houses on it now. Five houses = hotel.');
write('Houses cost $',housecost,' each. How many more (',5-houses_on,' max.)? ');
repeat
read(ch);
val(ch,howmany,result);
until howmany in [0..5];
if (howmany > 5 - houses_on) then goto again;
if howmany * housecost > player[turn].cash then
BEGIN
writeln;
beep;
writeln('You don''t have enough money.');
delay(3000);
goto again;
END
else
BEGIN
put_houses_on(howmany+houses_on); {show houses on playing board}
player[turn].cash := player[turn].cash - (howmany * housecost);
if houses_on + howmany <= 4 then houses_on := houses_on + howmany
else
BEGIN {it's a hotel}
houses_on := 0;
hotel := true;
END;
END; {else}
END; {with}
quit: {label}
showcash;
smallwindow;
gotoXY(5,14);
END; {build}



procedure review_holdings;
VAR
i : byte;
rowe,
column : byte;
ch : char;
BEGIN
initwin;
openwin(' PROPERTIES YOU OWN ',1,1,80,24);
clrscr;
writeln;
rowe := 1;
column := 2;
for i := 1 to 40 do
BEGIN
if square[i].owner = turn then
BEGIN
rowe := rowe + 1;
if rowe = 21 then
BEGIN
rowe := 2;
column := 36;

END;
gotoXY(column,rowe);
list_property(i);
END; {if square[i].owner}
END; {for}
gotoXY(28,22);
reverse; write(' PRESS A KEY TO CONTINUE '); normal;
read(kbd,ch);
closewin;
smallwindow;
gotoXY(5,14);
END;

procedure review_unsold;
VAR
i : byte;
rowe,
column : byte;
ch : char;
BEGIN
initwin;
openwin(' UNSOLD PROPERTIES ',1,1,80,24);
clrscr;
writeln;
rowe := 1;
column := 2;
for i := 1 to 40 do
BEGIN
if (square[i].owner = 0) and (square[i].group > 0) then
BEGIN
rowe := rowe + 1;
if rowe = 21 then
BEGIN
rowe := 2;
column := 36;
END;
gotoXY(column,rowe);
list_property(i);
END; {if square[i].owner}
END; {for}
gotoXY(28,22);
reverse; write(' PRESS A KEY TO CONTINUE '); normal;
read(kbd,ch);
closewin;
smallwindow;
gotoXY(5,14);
END;

procedure view_positions;
VAR
loop, Y : byte;
BEGIN
Y := 4;
clrscr;
for loop := 1 to numplayers do
BEGIN
gotoXY(2,Y);
writeln(player[loop].name,' is on ',
square[player[loop].location].name);
Y := Y + 2;
END;
awaitkeypress;
END;

procedure restore_board;
{updates pictures of houses, hotels & mortgages on playing board}
VAR
i, j : byte;
pic : string[5];
BEGIN
show_mortgages;
bigwindow;
for i := 1 to 40 do with square[i] do
BEGIN
if houses_on > 0 then
BEGIN
gotoXY(col,row);
reverse;
for j := 1 to houses_on do write(housepic);
normal;
for j := houses_on + 1 to 5 do write(' ');
END
else if hotel then
BEGIN
gotoXY(col,row);
write(hotelpic);
END;
END; {for}
END; {restore_board}

procedure sell_to_bank;
VAR
i,
loop,
rowe,
column,
max,
count : byte;
choice,
howmany,
result,
houseval : integer;
ch : char;
descrip,
choicestr : string[2];
propnum : array [1..40] of byte;

function evenly_sold: boolean;
VAR
even : boolean;
totl : byte;
BEGIN
evenly_sold := true;
even := true;
writeln;
for i := 1 to 40 do
BEGIN
if (square[i].group = square[propnum[choice]].group) then
BEGIN
if (square[i].houses_on > square[propnum[choice]].houses_on)
and not square[propnum[choice]].hotel
or (square[i].hotel and not square[propnum[choice]].hotel) then
BEGIN
beep;
writeln(' You have to sell buildings from ',
square[i].name, ' first.');
even := false;
END;
END; {if square[i].group}
END; {for}
if not even then
BEGIN
gotoXY(25,22);
write('PRESS A KEY TO CONTINUE');
read(kbd,ch);
evenly_sold := false;
END;
END; {evenly_sold}

BEGIN
initwin;
openwin(' SELL BUILDINGS TO THE BANK ',1,1,80,24);
repeat
clrscr;
writeln;
rowe := 1;
column := 2;
count := 0;
for i := 1 to 40 do
BEGIN
if (square[i].owner = turn) and ((square[i].houses_on > 0)
or (square[i].hotel)) then with square[i] do
BEGIN
count := count + 1;
propnum[count] := i;
case group of
1: descrip := 'dp';
2: descrip := 'lb';
3: descrip := 'lp';
4: descrip := 'or';
5: descrip := 'rd';
6: descrip := 'ye';
7: descrip := 'gr';
8: descrip := 'db';
9: descrip := 'rr';
10: descrip := 'ut';
END; {case}
rowe := rowe + 1;
if rowe = 21 then
BEGIN
rowe := 2;
column := 34;
END;
gotoXY(column,rowe);
write(count:2,'. ');
reverse;
write(descrip);
normal;
write(' ',name,' ');
reverse;
if hotel then write(hotelpic)
else for loop := 1 to houses_on do write(housepic);
normal;
END; {if square[i].owner}
END; {for}
gotoXY(7,rowe+2);
write('Sell buildings on which property (enter 0 to exit)? ');
repeat
read(choicestr);
val(choicestr,choice,result);
until choice in [0..count];
if choice > 0 then if evenly_sold then with square[propnum[choice]] do
BEGIN
clrscr;
gotoXY(1,10);
houseval := round(cost_of_houses(group)/2);
if hotel then
BEGIN
max := 5;
writeln('The hotel will bring $',houseval*5);
writeln('or you can sell houses at $',houseval,' each.');
END
else
BEGIN
max := houses_on;
writeln('Each house will bring $',houseval);
END;
writeln;
write('Sell how many houses (',max,' max.)? ');
repeat
read(choicestr);
val(choicestr,howmany,result);
until howmany in [0..max];
if howmany > 0 then
BEGIN
player[turn].cash := player[turn].cash + (howmany * houseval);
if hotel then
BEGIN
hotel := false;
houses_on := 5 - howmany;
END
else houses_on := houses_on - howmany;
END;
END; {if evenly_sold}
until choice = 0;
closewin;
restore_board;
showcash;
gotoXY(5,14);
END; {sell_to_bank}

procedure conduct_business; {buy/sell/trade with opponent,
erect houses/hotels}
LABEL
again;
VAR
choice : char;
dummyvar : boolean;
BEGIN
again: {label}
player_header;
gotoXY(5,3);
reverse; write('H'); normal; writeln('orsetrade with opponent');
gotoXY(5,4);
reverse; write('B'); normal; writeln('uy houses or hotels');
gotoXY(5,5);
reverse; write('L'); normal; writeln('iquidate houses or hotels');
gotoXY(5,6);
reverse; write('R'); normal; writeln('eview what you own');
gotoXY(5,7);
reverse; write('G'); normal; writeln('et list of unsold properties');
gotoXY(5,8);
reverse; write('M'); normal; writeln('ortgage');
gotoXY(5,9);
reverse; write('U'); normal; writeln('nmortgage');
gotoXY(5,10);
reverse; write('V'); normal; writeln('iew players'' positions');
gotoXY(5,11);
reverse; write('C'); normal; writeln('ontinue game');
gotoXY(5,12);
reverse; write('E'); normal; writeln('nd the game');
gotoXY(5,13);
reverse; write('S'); normal; writeln('ave game and quit');
repeat
read(kbd,choice);
case upcase(choice) of
'H' : horsetrade (false,dummyvar);
'B' : build;
'L' : sell_to_bank;
'R' : review_holdings;
'G' : review_unsold;
'M' : mortgage(0); {0 means there's no debt to be paid; player is
mortgaging voluntarily}
'U' : unmortgage;
'V' : BEGIN
view_positions;
goto again;
END;
'E' : haltgame := true;
'S' : savegame;
'C' : haltgame := false;
END; {case}
until upcase(choice) in ['C','E','S'];
smallwindow;
END; {conduct_business}


procedure determine_fate; forward;


procedure jail_escape;
VAR
choice,
answer : char;
dicetotal : byte;

procedure try_for_doubles;
BEGIN
gotoxy(1,5);
with player[turn] do
BEGIN {with}
if escapetries < 3 then
BEGIN
if escapetries = 0 then writeln('This is your first try.')
else if escapetries = 1 then writeln('This is your second try.')
else if escapetries = 2 then writeln('This is your last try.');
delay(2000);
player_header;
gotoXY(1,2);
dicetotal := throwdice(false);
if doubles > 0 then
BEGIN
writeln('You got doubles.');
escapetries := 0;
jailed := false;
location := location + dicetotal;
writeln('You''re on ',square[location].name);
determine_fate;
END
else
BEGIN
writeln('Sorry...no doubles.');
escapetries := escapetries + 1;
if not player[turn].bankrupt and not gameover and not haltgame
then
BEGIN
gotoXY(1,14);
write(' ');
reverse;
write(' Conduct other business (Y/N)? ');
normal;
read(kbd,answer);
if upcase(answer) = 'Y' then conduct_business;
END;
END;
END; {if escapetries < 3}
if (escapetries >= 3) and (cash > 49) then
BEGIN
player_header;
gotoXY(1,2);
writeln('You had to pay $50. You get to move now.');
cash := cash - 50;
jailed := false;
escapetries := 0;
delay(2000);
doubles := 0;
dicetotal := throwdice(false);
location := location + dicetotal;
writeln('You''re on ',square[location].name);
determine_fate;
END
else if escapetries >= 3 then
BEGIN
clrscr;
writeln;
writeln('You have to pay the $50 now.');
delay(2000);
player_in_trouble(turn,50,0);
jailed := false;
if not player[turn].bankrupt and not gameover and not haltgame
then
BEGIN
dicetotal := throwdice(false);
location := location + dicetotal;
writeln('You''re on ',square[location].name);
determine_fate;
END;
END; {if escapetries >=3}
END; {with}
END; {try_for_doubles}

BEGIN {jail_escape}
with player[turn] do
BEGIN {with}
player_header;
gotoXY(1,3);
writeln('You''re still in jail.');
if cash >49 then
BEGIN
repeat
gotoXY(1,4);
write('Throw ');
reverse;
write('D');
normal;
write('ice or ');
reverse;
write('P');
normal;
writeln('ay? ');
read(kbd,choice);
until upcase(choice) in ['P','D'];
if upcase(choice) = 'P' then
BEGIN
if cash < 50 then player_in_trouble(turn,50,0);
if gameover or haltgame or player[turn].bankrupt then exit;
cash := cash - 50;
showcash;
jailed := false;
escapetries := 0;
gotoXY(1,6);
writeln('Okay, you''re out of jail.');
writeln('You get to move now.');
delay(2000);
player_header;
gotoXY(1,2);
dicetotal := throwdice(false);
location := location + dicetotal;
writeln('You''re on ',square[location].name);
determine_fate;
END
else try_for_doubles;
END {if cash > 49}
else
BEGIN
writeln('You lack the $50 to get out.');
delay(2000);
try_for_doubles;
END;
END; {with}
END; {jail_escape}


procedure player_in_trouble;{playernum,debt, payee} {forward declared above}
{cash on hand is less than debt; determine action}
VAR
choice,
answer : char;
debtpaid: boolean;
BEGIN
debtpaid := false;
beep;
repeat
clrscr;
gotoXY(3,1);
writeln(player[playernum].name,', you need $',
debt-player[playernum].cash,'.');
gotoXY(3,2);
writeln('How will you raise the money?');
gotoXY(10,4);
reverse;
write('M');
normal;
writeln('ortgage property');
gotoXY(10,6);
reverse;
write('D');
normal;
writeln('eclare bankruptcy');
gotoXY(10,8);
reverse;
write('H');
normal;
writeln('orsetrade');
gotoXY(10,10);
reverse;
write('P');
normal;
writeln('ray for a miracle');
gotoXY(10,12);
reverse;
write('E');
normal;
writeln('nd the game');
repeat
read(kbd,choice);
until upcase(choice) in ['M','D','H','P','E'];
case upcase(choice) of
'M' : BEGIN {mortgage}
player[payee].cash := player[payee].cash
+ player[turn].cash; {player pays what he has as a start}
debt := debt - player[turn].cash;
player[turn].cash := 0;
mortgage(debt); {now go try to raise the balance owed}
{once program control returns here, player presumably has
some more cash}

if debt <= player[turn].cash then
BEGIN {debtor has more cash than the debt requires}
player[payee].cash := player[payee].cash + debt;
debtpaid := true;
player[turn].cash := player[turn].cash - debt;
END
else
BEGIN
player[payee].cash := player[payee].cash +
player[turn].cash; {give creditor whatever's on hand}
debt := debt - player[turn].cash;
player[turn].cash := 0;
debtpaid := false;
END;
showcash;
gotoXY(5,14);
END;
'D' : go_bankrupt(playernum,debtpaid,payee);
'H' : horsetrade(true,debtpaid);
'P' : BEGIN {pray for miracle}
clrscr;
delay(1000);
gotoXY(10,3);
writeln('... Rumble ...');
delay(2000);
gotoXY(13,6);
writeln('... Rumble. Rumble ...');
delay(2800);
gotoXY(10,8);
flash;
writeln('(God is thinking...)');
normal;
delay(3200);
gotoXY(10,10);
writeln('Sorry. No miracles today.');
delay(2500);
END;
'E' : gameover := true;
END; {case}
until player[turn].bankrupt or gameover or debtpaid;
player_header;
END;

procedure determine_fate;
{computes rent or penalty, prize or sale price, checks to make sure
player can pay any penalty, shows new totals on 25th line}
LABEL
again;
VAR
Y,
oldnum : byte;
amount_owed : integer;
answer : char;
BEGIN {determine_fate}
again: {label}
amount_owed := 0;
oldnum := current;
if square[current].group = 0 then zerogroup_action(amount_owed);
{pay tax, goto jail, draw card, etc.}
current := player[turn].location;
if (square[current].group = 0) and (oldnum <> current) then goto again;
{the card moved player to another square. Determine fate again}
with square[current] do
BEGIN
if not mortgaged then
BEGIN
if (owner = 0) and (group <> 0) then bank_sell_property(price) else
if (owner <> 0) and (group <> 0) then amount_owed := determine_rent;
{it's property, and somebody owns it}
if (player[turn].cash >= amount_owed) then
BEGIN {if current player owns this property, rent owed will be 0}
player[turn].cash := player[turn].cash - amount_owed;
player[owner].cash := player[owner].cash + amount_owed;
END
else if not player[turn].bankrupt then
BEGIN
gotoXY(1,10);
writeln('You don''t have enough money.');
delay(2000);
player_in_trouble(turn,amount_owed,square[current].owner);
END;
END {if not mortgaged}
else writeln('It''s mortgaged.');
END; {with}
Y := whereY;
showcash;
gotoXY(1,Y+1);
if not player[turn].jailed and not player[turn].bankrupt
and not gameover and not haltgame then
BEGIN
gotoXY(1,14);
write(' ');
reverse;
write(' Conduct other business (Y/N)? ');
normal;
read(kbd,answer);
if upcase(answer) = 'Y' then conduct_business;
END;
END; {determine_fate}


procedure showresults; {show final holdings of each player}
CONST
space = ' '; {20 spaces}
VAR
i, j,
propcount,
housecount,
hotelcount : byte;
propval,
houseval,
hotelval : integer;
BEGIN
bigwindow;
clrscr;
for i := 1 to numplayers do
BEGIN
propval := 0;
housecount := 0;
hotelcount := 0;
houseval := 0;
hotelval := 0;
propcount := 0;
for j := 1 to 40 do if square[j].owner = i then
with square[j] do
BEGIN
propval := propval + price;
propcount := propcount + 1;
if hotel then
BEGIN
hotelval := hotelval + (cost_of_houses(group) * 5);
hotelcount := hotelcount + 1;
END
else
BEGIN
houseval := houseval + (cost_of_houses(group)*houses_on);
housecount := housecount + houses_on;
END;
END; { 2nd for}
highlight;
writeln(space,player[i].name,' has:');
normal;
if propcount = 1 then writeln(space,' One property worth $',propval)
else if propcount > 1 then writeln
(space,' ',propcount,' properties worth $',propval);
if hotelcount = 1 then
writeln(space,' One hotel worth $',hotelval)
else if hotelcount > 1 then
writeln(space,' ',hotelcount,' hotels worth $',hotelval);
if housecount = 1 then
writeln(space,' One house worth $',houseval)
else if housecount > 1 then
writeln(space,' ',housecount,' houses worth $',houseval);
writeln(space,' Cash on hand $',player[i].cash);
writeln(space,' Total worth: $',propval+hotelval+houseval
+ player[i].cash);
END; {1st for}
END; {showresults}

BEGIN {------------------------- main loop ----------------------------}

show_title; {show opening title screen}

read(kbd,ansr); {does user want to load game in progress?}
clrscr;
if upcase(ansr) = 'Y' then
BEGIN
repeat
if not gameloaded then
BEGIN
gotoXY(30,14);
writeln('Insert proper disk and press RETURN');
gotoXY(30,15);
writeln('or press ESC to quit');
read(kbd,ansr);
if ansr = #27 then halt;
END;
until gameloaded;
draw_board;
restore_board;
showcash;
END
else
BEGIN
read_data; {initialize records}
getnames; {determine # of players, their names}
parkingmoney := 0; {fines accumulated on Free Parking, if used}
repeat
chancecounter := random(17); {increments each time Chance card drawn}
until chancecounter > 0;
repeat
chestcounter := random(17); { " " " Community Chest " }
until chestcounter > 0;
turn := 0;
draw_board;
showcash;
END;
gameover := false;
haltgame := false;
gotoXY(6,7);
reverse;
write(' Press a key to start the game ');
normal;
read(kbd,ansr);
repeat
repeat
turn := turn + 1;
doubles := 0;
if turn > numplayers then turn := 1;
if not player[turn].bankrupt and not player[turn].jailed then
BEGIN
current := moveplayer(turn); {moves player, tells where he landed}
determine_fate; {determines result of move}
END
else
if player[turn].jailed and not player[turn].bankrupt then
jail_escape;
while (doubles in [1..2]) and not player[turn].bankrupt
and not player[turn].jailed and not haltgame and not gameover do
BEGIN
clrscr;
gotoXY(1,7);
writeln('You got doubles. You get to move again.');
awaitkeypress;
current := moveplayer(turn);
determine_fate;
END; {while}
until haltgame or gameover;
if not gameover then
BEGIN
clrscr;
gotoXY(6,6);
write('End game -- are you sure (Y/N)? ');
read(ansr);
if upcase(ansr) = 'Y' then gameover := true else haltgame := false;
END;
until gameover;
bigwindow;
clrscr;
showresults;
END.




  3 Responses to “Category : Pascal Source Code
Archive   : TPMONO.ZIP
Filename : MONOPOLY.PAS

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/