! Puerto.inf - Inform port of the board game Puerto Rico
!       by J. Robinson Wheeler
!
! Release 1.0 - 25 December 2004
! Release 1.1 - 01 January 2005

Array buffer -> 60;  ! used for player input
Array parse -> 60;   ! used for player input

Property manned;
Property capacity;
Property inventory;
Property special;
Property cost;
Property VP;
Property man;
Property unman;

Global Governor = 0;

Global num_players = 0;
Global VP_tokens = 0;
Global colony_ship = 0;
Global colonist_supply = 0;

Class Player
 with
       board 0,
       colonists 0,
       corn_made 0,
       indigo_made 0,
       sugar_made 0,
       tobacco_made 0,
       coffee_made 0,
       VP 0,
       doubloons 0,
;
Class Player_Board
 with
       building_count 1,
       plantation_count 1,
       plant [ new_type i;
               if ( self.plantation_count >= 12 ) rfalse;      ! no more room

               if ( plantation_supply-->new_type == 0 ) rfalse;   ! none available

               i = Plantation.create( new_type );
               if ( i == 0 ) rfalse;

               move i to self;

               self.plantation_count++;
               plantation_supply-->new_type = plantation_supply-->new_type - 1;
               rtrue;
       ],
;

Attribute VP_flag;

Player P1
 with
       short_name "Player1",
       number 1,
       board P1_board,
;
Player_Board P1_board
 with
       short_name "Player1 board",
;

Player P2
 with
       short_name "Player2",
       number 2,
       board P2_board,
;
Player_Board P2_board
 with
       short_name "Player2 board",
;

Player P3
 with
       short_name "Player3",
       number 3,
       board P3_board,
;
Player_Board P3_board
 with
       short_name "Player3 board",
;

Player P4
 with
       short_name "Player4",
       number 4,
       board P4_board,
;
Player_Board P4_board
 with
       short_name "Player4 board",
;

Player P5
 with
       short_name "Player5",
       number 5,
       board P5_board,
;
Player_Board P5_board
 with
       short_name "Player5 board",
;

[ shortname thing;
       print (string) thing.short_name;
];

[ PrintPlayer playernum curplayer i the_ship;
       curplayer = GetPlayer( playernum );
       print "^", (shortname) curplayer, ":  ", curplayer.doubloons, "db  ";
       if ( curplayer.colonists > 0 ) {
               print "        ", curplayer.colonists, " extra colonist";
               if ( curplayer.colonists ~= 1 ) print "s";
       }
       if ( curplayer has VP_flag ) {
               print "     ", curplayer.VP, "VP";
       }
       print "^ Goods:          ";
       PrintGoods( curplayer );
       print "^ Buildings:      ";
       PrintBuildings( curplayer );
       print "^ Plantations:    ";
       PrintPlantations( curplayer );
       new_line;
       if ( curplayer has whrf ) {
               print " Cargo Fleet:    ";
               objectloop( i in curplayer.board ) {
                       if ( i ofclass Cargo_ship ) the_ship = i;
               }
               if ( i ~= 0 ) PrintShip( the_ship );
       }
       rtrue;
];

Constant CORN 0;
Constant INDIGO 1;
Constant SUGAR 2;
Constant TOBACCO 3;
Constant COFFEE 4;
Constant QUARRY 9;

Array plantation_supply --> 10 12 11 9 8;
Object Plantation_tiles;

Class Plantation(50)
 with
       short_name "Plantation",
       name,
       type 0,
       manned 0,
       capacity 1,
       man [; self.manned++; ],
       unman [; self.manned--; ],
       create[ new_type;
               self.type = new_type;
               switch( self.type ) {
                       CORN: self.short_name = "C( ) ";
                               self.name = 'c//';
                       INDIGO: self.short_name = "I( ) ";
                               self.name = 'i//';
                       SUGAR: self.short_name = "S( ) ";
                               self.name = 's//';
                       TOBACCO: self.short_name = "T( ) ";
                               self.name = 't//';
                       COFFEE: self.short_name = "K( ) ";
                               self.name = 'k//';
               }
       ],
;

Global quarry_supply = 8;

Class QuarryTile(8)
 class Plantation,
 with
       short_name "Q( )",
       type QUARRY,
       manned 0,
       create [;
               self.name = 'q//';
       ],
;

[ PlantationCount i count;
       for ( i=0 : i < 5 : i++ ) {
               count = count + plantation_supply-->i;
       }
       return( count );
];

[ PrintPlantationSupply noprintflag count;
       print "^  Plantation tiles remaining: ";

       count = PlantationCount();
       if ( count < 10 ) print " ";
       print count, "^";

       if ( noprintflag ) rfalse;

       print "      Quarry tiles remaining:  ", quarry_supply, "^";
       rtrue;
];

[ PrintPlantationName this;
       switch( this.type ) {
               CORN: print "C";
               INDIGO: print "I";
               SUGAR: print "S";
               TOBACCO: print "T";
               COFFEE: print "K";
               QUARRY: print "Q";
       }
       print "(";
       if ( this.manned ) print "*";
       else print " ";
       print ") ";
       rtrue;
];

[ PrintPlantations curplayer i j;
       objectloop( i in curplayer.board && i ofclass Plantation ) {
               j++;
               if ( j % 6 == 0 ) print "^                 ";
               PrintPlantationName( i );
       }
];

[ SetPlantationTiles stack choice i j remaining;
       switch( num_players ) {
               2: stack = 3;
               3: stack = 4;
               4: stack = 5;
               5: stack = 6;
       }

       while( child(Plantation_tiles) ~= nothing ) {
               i = child(Plantation_tiles);
               remove i;
       }

       for ( i=0: i < 5 : i++ ) {
               remaining = remaining + plantation_supply-->i;
       }
       if ( remaining == 0 ) {
               print "^No plantation tiles remaining^";
               rfalse;
       }
       if ( remaining < stack ) stack = remaining;

       for ( i=0: i < stack: i++ ) {
               choice = random(5) - 1;
               if ( plantation_supply-->choice == 0 ) {
                       while( plantation_supply-->choice == 0 ) {
                               choice = random(5) - 1;
                       }
               }
               j = Plantation.create( choice );
               if ( j ~= 0 ) {
                       move j to Plantation_tiles;
                       plantation_supply-->choice = plantation_supply-->choice - 1;
               }
       }

       remaining = 0;
       for ( i=0: i < 5 : i++ ) {
               remaining = remaining + plantation_supply-->i;
       }
       if ( remaining == 0 ) {
               print "^No plantation tiles remaining^";
               rfalse;
       }
       rtrue;
];

Constant PROSPECTOR 0;
Constant TRADER 1;
Constant SETTLER 2;
Constant BUILDER 3;
Constant MAYOR 4;
Constant CRAFTSMAN 5;
Constant CAPTAIN 6;

Constant VIOLET 14;
Constant LVIOLET 16;

Attribute ghal; ! Player has manned Guild Hall
Attribute smkt; ! Player has manned Small Market
Attribute hosp; ! Player has manned Hospice
Attribute fact; ! Player has manned Factory
Attribute resd; ! Player has manned Residence
Attribute haci; ! Player has manned Hacienda
Attribute offc; ! Player has manned Office
Attribute univ; ! Player has manned University
Attribute fort; ! Player has manned Fortress
Attribute chut; ! Player has manned Construction Hut
Attribute lmkt; ! Player has manned Large Market
Attribute harb; ! Player has manned Harbour
Attribute cust; ! Player has manned Customs House
Attribute swar; ! Player has manned Small Warehouse
Attribute lwar; ! Player has manned Large Warehouse
Attribute whrf; ! Player has manned Wharf
Attribute ctyh; ! Player has manned City Hall
Attribute general;

class Building
 with
       name,
       number,
       description,
       cost 1,
       VP 1,
       capacity 1,
       inventory 0,
       manned 0,
       man [; self.manned++; ],
       unman [; self.manned--; ],
       print_name [ i;
               print (string) self.short_name;
               for ( i=1 : i <= self.capacity : i++ ) {
                       print "(";
                       if ( i > self.manned ) print " ";
                       else print "*";
                       print ") ";
               }
       ],
;

Class ProductionBuilding
 class Building;

Class IndigoPlant
 class ProductionBuilding;

Class SugarMill
 class ProductionBuilding;

Class SmallIndigoPlant(4)
 class IndigoPlant,
 with
       create [; self.name = 'sind'; ],
       number 1,
       short_name "sInd",
       type INDIGO,
       cost 1,
       VP 1,
       description [;
               print " ------------------------------------^";
               print " | Small Indigo Plant [sInd]    1VP |^";
               print " | ( 1 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
;

Class LargeIndigoPlant(3)
 class IndigoPlant,
 with
       create [; self.name = 'lind'; ],
       number 2,
       short_name "LInd",
       type INDIGO,
       cost 3,
       VP 2,
       capacity 3,
       description [;
               print " ------------------------------------^";
               print " | Large Indigo Plant [LInd]    2VP |^";
               print " | ( 3 )(   )(   )                  |^";
               print " ------------------------------------^";
               rtrue;
       ],
;

Class TobaccoStorage(3)
 class ProductionBuilding,
 with
       create [; self.name = 'tbac'; ],
       number 3,
       short_name "Tbac",
       type TOBACCO,
       cost 5,
       VP 3,
       capacity 3,
       description [;
               print " ------------------------------------^";
               print " | Tobacco Storage [Tbac]       3VP |^";
               print " | ( 5 )(   )(   )                  |^";
               print " ------------------------------------^";
               rtrue;
       ],
;

Class SmallSugarMill(4)
 class SugarMill,
 with
       create [; self.name = 'ssug'; ],
       number 4,
       short_name "sSug",
       type SUGAR,
       cost 2,
       VP 1,
       description [;
               print " ------------------------------------^";
               print " | Small Sugar Mill [sSug]      1VP |^";
               print " | ( 2 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
;

Class LargeSugarMill(3)
 class SugarMill,
 with
       create [; self.name = 'lsug'; ],
       number 5,
       short_name "LSug",
       type SUGAR,
       cost 4,
       VP 2,
       capacity 3,
       description [;
               print " ------------------------------------^";
               print " | Large Sugar Mill [sSug]      2VP |^";
               print " | ( 4 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
;

Class CoffeeRoaster(3)
 class ProductionBuilding,
 with
       create [; self.name = 'krst'; ],
       number 6,
       short_name "Krst",
       type COFFEE,
       cost 6,
       VP 3,
       capacity 2,
       description [;
               print " ------------------------------------^";
               print " | Coffee Roaster [Krst]        3VP |^";
               print " | ( 6 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
;

Class GuildHall(1)
 class Building,
 with
       create [; self.name = 'ghal'; ],
       number 7,
       short_name "GHal",
       type LVIOLET,
       cost 10,
       VP 4,
       description [;
               print " ------------------------------------^";
               print " | Guild Hall [Ghal]            4VP |^";
               print " |      2 victory points for        |^";
               print " |      each large building         |^";
               print " |                                  |^";
               print " |      1 victory point for         |^";
               print " |      each small building         |^";
               print " |          (Game end)              |^";
               print " | ( 10 )                           |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer ghal; ],
       unman [ curplayer; self.manned--; give curplayer ~ghal; ],
       special [ curplayer extra i;
               extra = 0;
               objectloop( i in curplayer.board && i ofclass ProductionBuilding ) {
                       if ( i ofclass SmallIndigoPlant ) {
                               self.special_string( curplayer );
                               extra++;
                               print "   1 VP for owning Small Indigo Plant^";
                       }
                       if ( i ofclass LargeIndigoPlant ) {
                               self.special_string( curplayer );
                               extra = extra + 2;
                               print "   2 VP for owning Large Indigo Plant^";
                       }
                       if ( i ofclass SmallSugarMill ) {
                               self.special_string( curplayer );
                               extra++;
                               print "   1 VP for owning Small Sugar Mill^";
                       }
                       if ( i ofclass LargeSugarMill ) {
                               self.special_string( curplayer );
                               extra = extra + 2;
                               print "   2 VP for owning Large Sugar Mill^";
                       }
                       if ( i ofclass TobaccoStorage ) {
                               self.special_string( curplayer );
                               extra = extra + 2;
                               print "   2 VP for owning Tobacco Storage^";
                       }
                       if ( i ofclass CoffeeRoaster ) {
                               self.special_string( curplayer );
                               extra = extra + 2;
                               print "   2 VP for owning Coffee Roaster^";
                       }
               }
               if ( extra == 0 ) {
                       print "^ ", (shortname) curplayer, " has Guild Hall but receives 0 VP^";
               }
               curplayer.VP = curplayer.VP + extra;
       ],
       special_string [ curplayer;
               if ( self hasnt general ) {
                       give self general;
                       print "^ ", (shortname) curplayer, " has Guild Hall and receives:^";
               }
       ],
;

Class Market
 class Building;

Class SmallMarket(2)
 class Market,
 with
       create [; self.name = 'smkt'; ],
       number 8,
       short_name "sMkt",
       type VIOLET,
       cost 1,
       VP 1,
       description [;
               print " ------------------------------------^";
               print " | Small Market [sMkt]          1VP |^";
               print " |     +1 doubloon with sale        |^";
               print " |         (Trader phase)           |^";
               print " | ( 1 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer smkt; ],
       unman [ curplayer; self.manned--; give curplayer ~smkt; ],
;

Class Hospice(2)
 class Building,
 with
       create [; self.name = 'hosp'; ],
       number 9,
       short_name "Hosp",
       type VIOLET,
       cost 4,
       VP 2,
       description [;
               print " ------------------------------------^";
               print " | Hospice [Hosp]               2VP |^";
               print " |     +1 colonist for settling     |^";
               print " |         (Settler phase)          |^";
               print " | ( 4 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer hosp; ],
       unman [ curplayer; self.manned--; give curplayer ~hosp; ],
;

Class Factory(2)
 class Building,
 with
       create [; self.name = 'fact'; ],
       number 10,
       short_name "Fact",
       type VIOLET,
       cost 7,
       VP 3,
       description [;
               print " ------------------------------------^";
               print " | Factory [Fact]               3VP |^";
               print " |       +0/1/2/3/5 doubloons        |^";
               print " |         with production          |^";
               print " |        (Craftsman phase)         |^";
               print " | ( 7 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer fact; ],
       unman [ curplayer; self.manned--; give curplayer ~fact; ],
;

Class Residence(1)
 class Building,
 with
       create [; self.name = 'resd'; ],
       number 11,
       short_name "Resd",
       type LVIOLET,
       cost 10,
       VP 4,
       description [;
               print " ------------------------------------^";
               print " | Residence [Resd]             4VP |^";
               print " |         4 VP for <= 9            |^";
               print " |          5 VP for 10             |^";
               print " |          6 VP for 11             |^";
               print " |          7 VP for 12             |^";
               print " |     occupied island spaces       |^";
               print " |          (Game end)              |^";
               print " | ( 10 )                           |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer resd; ],
       unman [ curplayer; self.manned--; give curplayer ~resd; ],
       special [ curplayer extra i;
               print "^ ", (shortname) curplayer, " has Residence and receives:^";
               extra = 0;
               objectloop( i in curplayer.board && i ofclass Plantation ) {
                       extra++;
               }
               switch( extra ) {
                       0 to 9: curplayer.VP = curplayer.VP + 4;
                               print "   4 VP for owning ", extra, " Plantations^";
                       10: curplayer.VP = curplayer.VP + 5;
                               print "   5 VP for owning ", extra, " Plantations^";
                       11: curplayer.VP = curplayer.VP + 6;
                               print "   6 VP for owning ", extra, " Plantations^";
                       12: curplayer.VP = curplayer.VP + 7;
                               print "   7 VP for owning ", extra, " Plantations^";
               }
       ],
;

Class Hacienda(2)
 class Building,
 with
       create [; self.name = 'haci'; ],
       number 12,
       short_name "Haci",
       type VIOLET,
       cost 2,
       VP 1,
       description [;
               print " ------------------------------------^";
               print " | Hacienda [Haci]              1VP |^";
               print " |    +1 plantation from supply     |^";
               print " |         (Settler phase)          |^";
               print " | ( 2 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer haci; ],
       unman [ curplayer; self.manned--; give curplayer ~haci; ],
;

Class Office(2)
 class Building,
 with
       create [; self.name = 'offc'; ],
       number 13,
       short_name "Offc",
       type VIOLET,
       cost 5,
       VP 2,
       description [;
               print " ------------------------------------^";
               print " | Office [Offc]                2VP |^";
               print " |      Sell same kind of goods     |^";
               print " |          (Trader phase)          |^";
               print " | ( 5 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer offc; ],
       unman [ curplayer; self.manned--; give curplayer ~offc; ],
;

Class University(2)
 class Building,
 with
       create [; self.name = 'univ'; ],
       number 14,
       short_name "Univ",
       type VIOLET,
       cost 8,
       VP 3,
       description [;
               print " ------------------------------------^";
               print " | University [Univ]            3VP |^";
               print " |     +1 colonist for building     |^";
               print " |         (Builder phase)          |^";
               print " | ( 8 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer univ; ],
       unman [ curplayer; self.manned--; give curplayer ~univ; ],
;

Class Fortress(1)
 class Building,
 with
       create [; self.name = 'fort'; ],
       number 15,
       short_name "Fort",
       type LVIOLET,
       cost 10,
       VP 4,
       description [;
               print " ------------------------------------^";
               print " | Fortress [Fort]              4VP |^";
               print " |       1 victory point for        |^";
               print " |        every 3 colonists         |^";
               print " |           (Game end)             |^";
               print " | ( 10 )                           |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer fort; ],
       unman [ curplayer; self.manned--; give curplayer ~fort; ],
       special [ curplayer extra i;
               print "^ ", (shortname) curplayer, " has Fortress and receives:^";
               extra = 0;
               objectloop( i in curplayer.board ) {
                       extra = extra + i.manned;
               }
               i = extra + curplayer.colonists;
               extra = i / 3;
               print "   ", extra, " VP for having ", i, " colonists^";
               curplayer.VP = curplayer.VP + extra;
       ],
;

Class ConstructionHut(2)
 class Building,
 with
       create [; self.name = 'chut'; ],
       number 16,
       short_name "CHut",
       type VIOLET,
       cost 2,
       VP 1,
       description [;
               print " ------------------------------------^";
               print " | Construction Hut [CHut]      1VP |^";
               print " |        Quarry instead of         |^";
               print " |           plantation             |^";
               print " |         (Settler phase)          |^";
               print " | ( 2 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer chut; ],
       unman [ curplayer; self.manned--; give curplayer ~chut; ],
;

Class LargeMarket(2)
 class Market,
 with
       create [; self.name = 'lmkt'; ],
       number 17,
       short_name "LMkt",
       type VIOLET,
       cost 5,
       VP 2,
       description [;
               print " ------------------------------------^";
               print " | Large Market [LMkt]          2VP |^";
               print " |      +2 doubloons with sale       |^";
               print " |          (Trader phase)          |^";
               print " | ( 5 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer lmkt; ],
       unman [ curplayer; self.manned--; give curplayer ~lmkt; ],
;

Class Harbour(2)
 class Building,
 with
       create [; self.name = 'harb'; ],
       number 18,
       short_name "Harb",
       type VIOLET,
       cost 8,
       VP 3,
       description [;
               print " ------------------------------------^";
               print " | Harbour [Harb]               3VP |^";
               print " |   +1 victory point for delivery  |^";
               print " |         (Captain phase)          |^";
               print " | ( 8 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer harb; ],
       unman [ curplayer; self.manned--; give curplayer ~harb; ],
;

Class CustomsHouse(1)
 class Building,
 with
       create [; self.name = 'cust'; ],
       number 19,
       short_name "Cust",
       type LVIOLET,
       cost 10,
       VP 4,
       description [;
               print " ------------------------------------^";
               print " | Customs House [Cust]         4VP |^";
               print " |        1 victory point for       |^";
               print " |   every 4 victory point tokens   |^";
               print " |           (Game end)             |^";
               print " | ( 10 )                           |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer cust; ],
       unman [ curplayer; self.manned--; give curplayer ~cust; ],
       special [ curplayer extra;
               print "^ ", (shortname) curplayer, " has Customs House and receives:^";
               extra = curplayer.VP / 4;
               print "   ", extra, " VP for having ", curplayer.VP, " victory
                       point tokens^";
               curplayer.VP = curplayer.VP + extra;
       ],
;

Class Warehouse
 class Building;

Class SmallWarehouse(2)
 class Warehouse,
 with
       create [; self.name = 'swar'; ],
       number 20,
       short_name "sWar",
       type VIOLET,
       cost 3,
       VP 1,
       description [;
               print " ------------------------------------^";
               print " | Small Warehouse [sWar]       1VP |^";
               print " |       Store 1 kind of good       |^";
               print " |         (Captain phase)          |^";
               print " | ( 3 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer swar; ],
       unman [ curplayer; self.manned--; give curplayer ~swar; ],
;

Class LargeWarehouse(2)
 class Warehouse,
 with
       create [; self.name = 'lwar'; ],
       number 21,
       short_name "LWar",
       type VIOLET,
       cost 6,
       VP 2,
       description [;
               print " ------------------------------------^";
               print " | Large Warehouse [LWar]       2VP |^";
               print " |      Store 2 kinds of goods      |^";
               print " |          (Captain phase)         |^";
               print " | ( 6 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer lwar; ],
       unman [ curplayer; self.manned--; give curplayer ~lwar; ],
;

Class Wharf(2)
 class Building,
 with
       create [; self.name = 'whrf'; ],
       number 22,
       short_name "Whrf",
       type VIOLET,
       cost 9,
       VP 3,
       description [;
               print " ------------------------------------^";
               print " | Wharf [Whrf]                 3VP |^";
               print " |        Your own cargo ship       |^";
               print " |          (Captain phase)         |^";
               print " | ( 9 )                            |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer x;
               self.manned++;
               give curplayer whrf;
               x = Cargo_ship.create(256);
               Cargo_fleet.size++;
               x.number = Cargo_fleet.size;
               switch ( Cargo_fleet.size ) {
                       3: Cargo_fleet.ship3 = x;
                       4: Cargo_fleet.ship4 = x;
                       5: Cargo_fleet.ship5 = x;
               }
               move x to curplayer.board;

               switch ( curplayer.number ) {
                       1: x.short_name = "Player1's ship";
                       2: x.short_name = "Player2's ship";
                       3: x.short_name = "Player3's ship";
                       4: x.short_name = "Player4's ship";
                       5: x.short_name = "Player5's ship";
               }
               print "  ", (shortname) curplayer, " receives his own Cargo Ship with
                       unlimited capacity^";
       ],
       unman [ curplayer x;
               self.manned--;
               give curplayer ~whrf;
               print "^[Removing ", (shortname) self, " from board]^^";
               FlushCargoShip( self, 1 );
               x = Cargo_ship.destroy(x);
               Cargo_fleet.size--;
       ],
;

Class CityHall(1)
 class Building,
 with
       create [; self.name = 'ctyh'; ],
       number 23,
       short_name "CtyH",
       type LVIOLET,
       cost 10,
       VP 4,
       description [;
               print " ------------------------------------^";
               print " | City Hall [CtyH]             4VP |^";
               print " |       1 victory point for        |^";
               print " |      every violet building       |^";
               print " |           (Game end)             |^";
               print " | ( 10 )                           |^";
               print " ------------------------------------^";
               rtrue;
       ],
       man [ curplayer; self.manned++; give curplayer ctyh; ],
       unman [ curplayer; self.manned--; give curplayer ~ctyh; ],
       special [ curplayer extra i;
               print "^ ", (shortname) curplayer, " has City Hall and receives:^";
               extra = 0;
               objectloop( i in curplayer.board && i ofclass Building ) {
                       if ( i.type == VIOLET or LVIOLET ) extra++;
               }
               print "   ", extra, " VP for owning ", extra, " violet buildings^";
               curplayer.VP = curplayer.VP + extra;
       ],
;

Object building_supply;

[ PrintBuildings curplayer i j;
       objectloop( i in curplayer.board ) {
               if ( i ofclass Building ) {
                       j++;
                       i.print_name();
                       print "   ";
                       if ( j%4 == 0 ) print "^                 ";
               }
       }
];

[ QuarryDiscount bldgnum quarryflag maxdiscount;
       switch( bldgnum ) {
               1,4,8,12,16,20: maxdiscount = 1;
               2,5,9,13,17,21: maxdiscount = 2;
               3,6,10,14,18,22: maxdiscount = 3;
               7,11,15,19,23: maxdiscount = 4;
       }
       if ( quarryflag > maxdiscount )
               return( maxdiscount );
       return( quarryflag );
];

[ PrintBuildingSupply builderflag quarryflag bldgnum j k db;
       print "^Building tile supply: ^";
       for ( bldgnum = 1 : bldgnum < 24 : bldgnum++ ) {
               j = 0;
               print "   ";
               objectloop( k in building_supply && k.number == bldgnum ) {
                       j++;
                       if ( j == 1 ) {
                               db = k.cost;
                               print (string) k.short_name, "(";
                       }
               }
               if ( j ~= 0 ) {
                       db = db - builderflag - QuarryDiscount( bldgnum, quarryflag );
                       if ( db < 0 ) db = 0;
                       print j, ")-", db, "db";
               }
               else {
                       print "xxxx       ";
               }
               if ( bldgnum == 3 or 7 or 11 or 15 or 19 or 23 )
                       new_line;
       }
       if ( builderflag ) {
               if ( quarryflag ) {
                       print "^(Prices discounted for Builder + ";
                       if ( quarryflag == 1 ) print "Quarry";
                       else print quarryflag, " Quarries";
                       print ")^";
               }
               else
                       print "^(Prices discounted for Builder)^";
       }
       else if ( quarryflag ) {
               print "^(Prices discounted for owning ", quarryflag, " manned ";
               if ( quarryflag == 1 ) print "Quarry";
               else print " Quarries";
               print ")^";
       }
];

[ SetUpBuildingSupply i count newbuild;
       if ( num_players == 2 ) count = 2; else count = 4;
       for ( i=0: i < count : i++ ) {
               newbuild = SmallIndigoPlant.create();
               move newbuild to building_supply;
       }
       if ( num_players == 2 ) count = 2; else count = 3;
       for ( i=0: i < count: i++ ) {
               newbuild = LargeIndigoPlant.create();
               move newbuild to building_supply;
       }
       if ( num_players == 2 ) count = 2; else count = 3;
       for ( i=0: i < count: i++ ) {
               newbuild = TobaccoStorage.create();
               move newbuild to building_supply;
       }
       if ( num_players == 2 ) count = 2; else count = 4;
       for ( i=0: i < count : i++ ) {
               newbuild = SmallSugarMill.create();
               move newbuild to building_supply;
       }
       if ( num_players == 2 ) count = 2; else count = 3;
       for ( i=0: i < count: i++ ) {
               newbuild = LargeSugarMill.create();
               move newbuild to building_supply;
       }
       if ( num_players == 2 ) count = 2; else count = 3;
       for ( i=0: i < count: i++ ) {
               newbuild = CoffeeRoaster.create();
               move newbuild to building_supply;
       }

       if ( num_players == 2 ) count = 1; else count = 2;
       for ( i=0: i < count: i++ ) {
               newbuild = SmallMarket.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = Hacienda.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = ConstructionHut.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = SmallWarehouse.create();
               move newbuild to building_supply;
       }

       for ( i=0: i < count: i++ ) {
               newbuild = Hospice.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = Office.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = LargeMarket.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = LargeWarehouse.create();
               move newbuild to building_supply;
       }

       for ( i=0: i < count: i++ ) {
               newbuild = Factory.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = University.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = Harbour.create();
               move newbuild to building_supply;
       }
       for ( i=0: i < count: i++ ) {
               newbuild = Wharf.create();
               move newbuild to building_supply;
       }

       newbuild = GuildHall.create();
       move newbuild to building_supply;

       newbuild = Residence.create();
       move newbuild to building_supply;

       newbuild = Fortress.create();
       move newbuild to building_supply;

       newbuild = CustomsHouse.create();
       move newbuild to building_supply;

       newbuild = CityHall.create();
       move newbuild to building_supply;
];

Class Goods
 with
       name,
       type,
       value,
;

Class Corn_goods(10)
 class Goods,
 with
       create [; self.name = 'corn'; ],
       short_name "Corn",
       type CORN,
       value 0,
;
Class Indigo_goods(11)
 class Goods,
 with
       create [; self.name = 'indigo'; ],
       short_name "Indigo",
       type INDIGO,
       value 1,
;
Class Sugar_goods(11)
 class Goods,
 with
       create [; self.name = 'sugar'; ],
       short_name "Sugar",
       type SUGAR,
       value 2,
;
Class Tobacco_goods(9)
 class Goods,
 with
       create [; self.name = 'tobacco'; ],
       short_name "Tobacco",
       type TOBACCO,
       value 3,
;
Class Coffee_goods(9)
 class Goods,
 with
       create [; self.name = 'coffee'; ],
       short_name "Coffee",
       type COFFEE,
       value 4,
;

[ PrintGoods curplayer i j;
       objectloop( i in curplayer.board && i ofclass Goods ) {
               j++;
               if ( j > 1 ) {
                       if ( j % 5 == 0 ) print "^                 ";
                       else print " - ";
               }
               PrintCropType( i.type );
       }
       return( j );
];

Object Remove_From_Game;

Object Trading_post
 with
       capacity 4,
       inventory 0,
;

Constant EMPTY -1;

Class Cargo_ship(5)
 with
       short_name "Cargo ship",
       type EMPTY,
       number 0,
       capacity 0,
       inventory 0,
       create [ i;
               self.capacity = i;
       ],
;

Object Cargo_fleet
 with
       size,
       ship1,
       ship2,
       ship3,
       ship4,
       ship5,
;

[ WelcomeMsg;
       print "^Welcome to Puerto Rico^";
       print "Inform adaptation by J. Robinson Wheeler. Play testing by Storme Winfield.^";
       print "Release 1.1 / Serial number 20050101 / Inform v6.21^^";
       print "Type HELP at any prompt for full list of game commands (recommended)^";
];

! First, find out how many people are playing, and log them in, so to speak.
! Returns the number of players.
[ LoginPlayers input num;
       .select;
       print "^^How many players? (2-5) >";

       input = ReadInput();
       switch( input ) {
               '2//': num = 2;
               '3//': num = 3;
               '4//': num = 4;
               '5//': num = 5;
               'PRINT': jump select;
               default: print "^Please choose a number between 2 and 5."; jump select;
       }

       print "^^Starting ", num, "-Player game.^^^";
       return( num );
];

[ main;
       WelcomeMsg();
       num_players = LoginPlayers();
       Initialize();
       GameLoop();
       End_Game();
       quit;
];

! Initialize everything: players get their starting pieces. Plantation tokens
! are turned up randomly, based on the number of players. Colonist tokens are
! placed on the colony ship, based on the number of players.
[ Initialize x;
       SetUpBuildingSupply();
       PrintBuildingSupply();
       switch( num_players ) {
               2:
                       VP_tokens = 65;
                       P1.doubloons = 3;
                       P2.doubloons = 3;
                       quarry_supply = 5;
                       plantation_supply-->CORN = 7;
                       plantation_supply-->INDIGO = 9;
                       plantation_supply-->SUGAR = 8;
                       plantation_supply-->TOBACCO = 6;
                       plantation_supply-->COFFEE = 5;
                       P1.board.plant( INDIGO );
                       P2.board.plant( CORN );
                       SetPlantationTiles();

                       Cargo_fleet.size = 2;
                       x = Cargo_ship.create(4);
                       Cargo_fleet.ship1 = x;
                       x.short_name = "Cargo ship 1";
                       x.number = 1;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(6);
                       Cargo_fleet.ship2 = x;
                       x.short_name = "Cargo ship 2";
                       x.number = 2;
                       move x to Cargo_fleet;

                       colony_ship = 2;
                       colonist_supply = 40;
                       x = Corn_goods.create(); remove x;
                       x = Corn_goods.create(); remove x;
                       x = Indigo_goods.create(); remove x;
                       x = Indigo_goods.create(); remove x;
                       x = Sugar_goods.create(); remove x;
                       x = Sugar_goods.create(); remove x;
                       x = Tobacco_goods.create(); remove x;
                       x = Tobacco_goods.create(); remove x;
                       x = Coffee_goods.create(); remove x;
                       x = Coffee_goods.create(); remove x;
                       remove Prospector2_Card;
                       Role_Card_Deck.size = 7;
!                       2 of each production building, 1 of each violet building

               3:
                       VP_tokens = 75;
                       P1.doubloons = 2;
                       P2.doubloons = 2;
                       P3.doubloons = 2;
                       P1.board.plant( INDIGO );
                       P2.board.plant( INDIGO );
                       P3.board.plant( CORN );
                       SetPlantationTiles();

                       Cargo_fleet.size = 3;
                       x = Cargo_ship.create(4);
                       Cargo_fleet.ship1 = x;
                       x.short_name = "Cargo ship 1";
                       x.number = 1;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(5);
                       Cargo_fleet.ship2 = x;
                       x.short_name = "Cargo ship 2";
                       x.number = 2;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(6);
                       Cargo_fleet.ship3 = x;
                       x.short_name = "Cargo ship 3";
                       x.number = 3;
                       move x to Cargo_fleet;

                       colony_ship = 3;
                       colonist_supply = 55;
                       remove Prospector1_Card;
                       remove Prospector2_Card;
                       Role_Card_Deck.size = 6;

               4:
                       VP_tokens = 100;
                       P1.doubloons = 3;
                       P2.doubloons = 3;
                       P3.doubloons = 3;
                       P4.doubloons = 3;
                       P1.board.plant( INDIGO );
                       P2.board.plant( INDIGO );
                       P3.board.plant( CORN );
                       P4.board.plant( CORN );
                       SetPlantationTiles();

                       Cargo_fleet.size = 3;
                       x = Cargo_ship.create(5);
                       Cargo_fleet.ship1 = x;
                       x.short_name = "Cargo ship 1";
                       x.number = 1;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(6);
                       Cargo_fleet.ship2 = x;
                       x.short_name = "Cargo ship 2";
                       x.number = 2;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(7);
                       Cargo_fleet.ship3 = x;
                       x.short_name = "Cargo ship 3";
                       x.number = 3;
                       move x to Cargo_fleet;

                       colony_ship = 4;
                       colonist_supply = 75;
                       remove Prospector2_Card;
                       Role_Card_Deck.size = 7;

               5:
                       VP_tokens = 122;
                       P1.doubloons = 4;
                       P2.doubloons = 4;
                       P3.doubloons = 4;
                       P4.doubloons = 4;
                       P5.doubloons = 4;
                       P1.board.plant( INDIGO );
                       P2.board.plant( INDIGO );
                       P3.board.plant( INDIGO );
                       P4.board.plant( CORN );
                       P5.board.plant( CORN );
                       SetPlantationTiles();

                       Cargo_fleet.size = 3;
                       x = Cargo_ship.create(6);
                       Cargo_fleet.ship1 = x;
                       x.short_name = "Cargo ship 1";
                       x.number = 1;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(7);
                       Cargo_fleet.ship2 = x;
                       x.short_name = "Cargo ship 2";
                       x.number = 2;
                       move x to Cargo_fleet;

                       x = Cargo_ship.create(8);
                       Cargo_fleet.ship3 = x;
                       x.short_name = "Cargo ship 3";
                       x.number = 3;
                       move x to Cargo_fleet;

                       colony_ship = 5;
                       colonist_supply = 95;
       }
];

[ NextPlayer num;
       if ( num == num_players ) return 1;
       return(num + 1);
];

! Game Loop -
!
! 1) Assign a new Governor. If this is the first turn, do so randomly.
!    If not, move it to the next player in order.
! 2) A Role is chosen. The new Governor chooses first. Any doubloons on
!    the Role are claimed by the selecting player.
! 3) Players perform the actions according to this Role, in order,
!    starting with the Governor.
! 4) Check for End-of-Game conditions. If true, jump to step 7.
! 5) Repeat steps 2 through 4 for all players, in order, until each
!    player has chosen a Role for this turn. (In a 2-Player game, repeat
!    until each player has chosen 3 Roles, leaving 1 Role card unchosen
!    for the round.)
! 6) Allot 1 doubloon to each Role not chosen this turn. Loop back to step 1.
! 7) End of game: Tally victory points for all players and announce
!    the winner (or list all players, ranked by victory points).
[ GameLoop done curplayer;
       while ( done == 0 ) {
               Governor = NextPlayer(Governor);
               curplayer = GetPlayer(Governor);
               print "^The new Governor is ", (shortname) curplayer, "^";
               RoleLoop( Governor, 1 );
               done = CheckForEndGameState();
               if ( done == 0 ) RestoreRoleCards();
       }
       rtrue;
];

[ RestoreRoleCards i;
       ! Put doubloons on unpicked cards
       ! Put picked cards back in play
       print "^^Starting new turn.";
       print "^   Colonist supply = ", colonist_supply;
       print "^   VP token supply = ", VP_tokens, "^";
       print "^Restoring role cards, with doubloons on unpicked roles...^";
       objectloop( i in Role_Card_Deck ) {
               i.doubloons++;
               print "    ", (shortname) i, " now has ", i.doubloons, " doubloon";
               if ( i.doubloons ~= 1 ) print "s";
               new_line;
       }
       while ( child(Picked) ~= 0 ) {
               i = child(Picked);
               move i to Role_Card_Deck;
               if ( i.type == PROSPECTOR ) {
                       i.doubloons++;
                       print "    ", (shortname) i, " restored to ", i.doubloons, " doubloon^";
               }
               Picked.size--;
               Role_Card_Deck.size++;
       }
       rtrue;
];

[ PrintPlayerName this_player;
       switch( this_player ) {
               1: print (shortname) P1;
               2: print (shortname) P2;
               3: print (shortname) P3;
               4: print (shortname) P4;
               5: print (shortname) P5;
       }
];

[ GetPlayer playernum;
       switch( playernum ) {
               1: return( P1 );
               2: return( P2 );
               3: return( P3 );
               4: return( P4 );
               5: return( P5 );
       }
];

[ PrintRoleCardDeck i count;
       print "^", Role_Card_Deck.size, " Role cards left:^";
       objectloop( i in Role_Card_Deck ) {
               count++;
       }
       if ( count > 5 ) {
               count = 0;
               objectloop( i in Role_Card_Deck ) {
                       count++;
                       print "   ", (shortname) i;
                       if ( i.doubloons > 0 ) print "(", i.doubloons, ")";
                       if ( count == 4 ) new_line;
               }
       }
       else {
               objectloop( i in Role_Card_Deck ) {
                       print "   ", (shortname) i;
                       if ( i.doubloons > 0 ) print "(", i.doubloons, ")";
               }
       }
       new_line;
];

[ ChooseRole playernum curplayer new_role input p;
       curplayer = GetPlayer( playernum );

       .select;
       PrintRoleCardDeck();

       print "^", (shortname) curplayer, " choose a Role to play: > ";
       input = ReadInput( curplayer );
       switch( input ) {
               'prosp','props': if ( num_players == 2 || num_players == 4 ) {
                               new_role = Prospector1_Card;
                       }
                       else {
                               if ( Prospector1_Card in Role_Card_Deck &&
                                       Prospector2_Card in Role_Card_Deck ) {
                                       print "   Please select Prospector1 (PR1 or PROSP1) or
                                               Prospector2 (PR2 or PROSP2).^";
                                       jump select;
                               }
                               else {
                                       objectloop( p in Role_Card_Deck && p.doubloons > 0 ) {
                                               new_role = p;
                                       }
                               }
                       }
               'pr1', 'prosp1', 'props1': new_role = Prospector1_Card;
               't//', 'trade', 'trader' : new_role = Trader_Card;
               's//', 'set', 'settler' : new_role = Settler_Card;
               'b//', 'build', 'builder' : new_role = Builder_Card;
               'm//', 'mayor' : new_role = Mayor_Card;
               'cra', 'craft', 'craftsman' : new_role = Craftsman_Card;
               'cap', 'captain' : new_role = Captain_Card;
               'pr2', 'prosp2', 'props2': new_role = Prospector2_Card;
               'PRINT': new_line; jump select;
               default : print "Not a valid choice.^"; jump select;
       }

       print (shortname) curplayer, " selects the role of ", (shortname) new_role, "^";
       move new_role to Picked;
       Picked.size++;
       Role_Card_Deck.size--;
       if ( new_role.doubloons > 0 ) {
               curplayer.doubloons = curplayer.doubloons + new_role.doubloons;
               print "  ", (shortname) curplayer, " receives the ", new_role.doubloons, " doubloon";
               if ( new_role.doubloons ~= 1 ) print "s";
               print " from the ", (shortname) new_role, " card^";
               new_role.doubloons = 0;
       }
       return( new_role );
];

[ PlayRole new_role playernum curplayer;
       curplayer = GetPlayer( playernum );
       if ( new_role.type == PROSPECTOR ) {
               new_line; rtrue;
       }
       new_role.special( playernum, curplayer );
       new_line; rtrue;
];

! RoleLoop()
!  Play out the Role-turn for the passed-in roletype chosen by the Governor
!  for this turn, then cycle through the same for each player, stopping when
!  the player_ptr is once again on the Governor. At that point, return.
!  Or, in a 2-player game, cycle until each player has chosen 3 Roles and
!  only one Role card remains unchosen.
!
[ RoleLoop playernum flag new_role;
       if ( ~~flag ) {
               if ( num_players == 2 && Picked.size == 6 ) rtrue;
               if ( num_players > 2 && playernum == Governor ) rtrue;
       }
       new_role = ChooseRole( playernum );
       PlayRole( new_Role, playernum );
       RoleLoop( NextPlayer( playernum ) );
       rtrue;
];

[ CheckForEndGameState;
!       Are we out of colonists or VP? If not, rfalse. If so, rtrue;
       print "^^End of turn.^";
       MorePrompt();
       if ( colonist_supply <= 0 || VP_tokens <= 0 ) rtrue;
       rfalse;
];

Array winner_list --> 0 0 0 0 0;
Array winner_scores --> 0 0 0 0 0;

[ End_Game i curplayer g0 g1 k tie;
       print "^^**End of Game**^";
       for ( i=0 : i < num_players : i++ ) {
               curplayer = GetPlayer(i+1);
               PrintPlayer( curplayer.number );
               winner_list-->i = curplayer.number;
               winner_scores-->i = VPTally( curplayer );
       }
       SortHighToLow();
       if ( winner_scores-->0 == winner_scores-->1 ) {
               tie = 1;

               g0 = 0;
               curplayer = GetPlayer( winner_list-->0 );
               objectloop( i in curplayer.board && i ofclass Goods ) { g0++; }

               g1 = 0;
               curplayer = GetPlayer( winner_list-->1 );
               objectloop( i in curplayer.board && i ofclass Goods ) { g1++; }

               if ( g1 > g0 ) {
                       Swap( 0, 1 );
                       k = g0;
                       g0 = g1;
                       g1 = k;
               }
       }

       print "^^Final scores: ^^^";
       for ( i=0: i < num_players: i++ ) {
               PrintPlayerName( winner_list-->i );
               print ": ", winner_scores-->i, " VP";
               if ( tie ) {
                       switch( i ) {
                               0: print " + ", g0, " Goods";
                               1: print " + ", g1, " Goods";
                       }
               }
               new_line;
       }
       print "^^^^";
       MorePrompt();
];

[ VPTally curplayer score i;
!
! Victory Points for all players are tallied. Doubloons are converted
! into VP. Manned buildings have a VP worth. Players may have purchased
! special double-sized building cards during the game that affect their
! final tallies:
!
!   Guild Hall - 1 VP for each small building, 2 VP for each large building
!   Residence - VP are assigned for the number of occupied island spaces:
!               9 or fewer     4VP
!               10             5VP
!               11             6VP
!               12             7VP
!   Fortress - 1 VP for every colonist
!   Customs House - 1 VP for every 4 VP tokens
!   City Hall - 1 VP for each violet building card
!
       objectloop( i in curplayer.board && i ofclass CustomsHouse ) {
               if ( i.manned ) i.special( curplayer );
       }
       objectloop( i in curplayer.board && i ofclass GuildHall ) {
               if ( i.manned ) i.special( curplayer );
       }
       objectloop( i in curplayer.board && i ofclass Residence ) {
               if ( i.manned ) i.special( curplayer );
       }
       objectloop( i in curplayer.board && i ofclass Fortress ) {
               if ( i.manned ) i.special( curplayer );
       }
       objectloop( i in curplayer.board && i ofclass CityHall ) {
               if ( i.manned ) i.special( curplayer );
       }

       score = 0;
       objectloop( i in curplayer.board && i ofclass Building ) {
               score = score + i.VP;
       }
       if ( score > 0 )
               print "^ ", (shortname) curplayer, " receives ", score, " VP from
                       buildings owned^";

       print "^ ", (shortname) curplayer, " receives ", curplayer.doubloons, " VP for
               having ", curplayer.doubloons, " doubloon";
       if ( curplayer.doubloons ~= 1 ) print "s";
       new_line;

       score = score + curplayer.VP + curplayer.doubloons;
       curplayer.VP = score;

       print "^", (shortname) curplayer, " total: ", score, " VP^^";

       MorePrompt();

       return( score );
];

[ SortHighToLow i count;
       if ( i == num_players ) rtrue;

       for( count = (i+1) : count < num_players : count++ ) {
               if ( winner_scores-->i < winner_scores-->count )
                       Swap( i, count );
       }
       SortHighToLow( i+1 );
       rtrue;
];

[ Swap i j k;
       k = winner_list-->i;
       winner_list-->i = winner_list-->j;
       winner_list-->j = k;

       k = winner_scores-->i;
       winner_scores-->i = winner_scores-->j;
       winner_scores-->j = k;
];


! ******************************************************************** !

[ MorePrompt i;
       new_line;
       style reverse;
       print "More--";
       style roman;
       while ( i ~= 32 && i ~= 81 ) {
               @read_char 1 0 0 i;
       }
       if ( i == 81 ) { new_line; quit; }
       new_line;
       @erase_window 0;
       rtrue;
];

Class Role_Card
 with
       type 0,
       doubloons 0,
       special [; rtrue; ],
;

Object Picked
 with size 0,
;

Object Role_Card_Deck
 with size 8,
;

Role_Card -> Prospector1_Card
 with
       short_name "Prospector1",
       type PROSPECTOR,
       doubloons 1,
       special [ curplayer;
               curplayer.doubloons = curplayer.doubloons + self.doubloons;
               print (shortname) curplayer, " receives ", self.doubloons, " doubloon";
               if ( self.doubloons ~= 1 ) print "s";
               self.doubloons = 0;
               new_line; rtrue;
       ],
;

Role_Card -> Trader_Card
 with
       short_name "Trader",
       type TRADER,
       special [ playernum curplayer i;
               TradeGoods( curplayer, 1 );
               if ( Trading_post.inventory == Trading_post.capacity ) {
                       FlushTradingPost();
                       new_line; rtrue;
               }
               for ( i=1 : i < num_players : i++ ) {
                       print "^   Moving to next player^";
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       TradeGoods( curplayer );
                       if ( Trading_post.inventory == Trading_post.capacity ) {
                               FlushTradingPost();
                               new_line; rtrue;
                       }
               }
       ],
;

[ PrintTradingPostInv i j;
       print "^The Trading Post contains: ";
       objectloop( i in Trading_post ) {
               j++;
               if ( j > 1 ) print " - ";
               PrintCropType( i.type );
       }
       if ( j == 0 ) print "[none]";
       new_line;
];

[ TradeGoods curplayer traderflag marketflag input i j skip;
       if ( curplayer has smkt ) marketflag++;
       if ( curplayer has lmkt ) marketflag = marketflag + 2;
       if ( curplayer has offc ) marketflag++;

       .select;

       PrintTradingPostInv();
       print "   ", (shortname) curplayer, " has";
       j = 0;
       skip = -1;
       objectloop( i in curplayer.board && i ofclass Goods ) {
               if ( i.type ~= skip ) {
                       j++;
                       if ( j > 1 ) print " - ";
                       else print ": ";
                       PrintCropType( i.type );
                       skip = i.type;
               }
       }
       if ( j == 0 ) {
               print " no Goods to trade";
       }
       print "^^", (shortname) curplayer, " choose Goods to trade or 0 to pass >";

       input = ReadInput( curplayer );
       if ( input == '0//' ) {
               print (shortname) curplayer, " passes^";
               rtrue;
       }
       if ( input == 'PRINT' ) { new_line; jump select; }

       objectloop( i in curplayer.board && i ofclass Goods ) {
               if ( i.name == input ) {
                       if ( traderflag ) {
                               print "  ", (shortname) curplayer, " trades ";
                               PrintCropType( i.type );
                               TradeForCash( curplayer, i, traderflag, marketflag );
                               move i to Trading_post;
                               Trading_post.inventory++;
                               rfalse;
                       }
                       skip = 0;
                       objectloop( j in Trading_post ) {
                               if ( i.type == j.type ) skip = 1;
                       }
                       if ( skip == 0 ) {
                               print "  ", (shortname) curplayer, " trades ";
                               PrintCropType( i.type );
                               TradeForCash( curplayer, i, traderflag, marketflag );
                               move i to Trading_post;
                               Trading_post.inventory++;
                               rfalse;
                       }
                       else {
                               print "Trading Post already has ";
                               PrintCropType( i.type );
                               new_line; jump select;
                       }
               }
       }
       print "Not valid choice.^";
       jump select;
];

[ TradeForCash curplayer crop traderflag marketflag db;
       db = crop.value + traderflag + marketflag;
       curplayer.doubloons = curplayer.doubloons + db;
       print "^  ", (shortname) curplayer, " receives ", crop.value, " doubloon";
       if ( crop.value ~= 1 ) print "s";
       print " for the trade";

       if ( traderflag == 0 && marketflag == 0 ) {
               new_line; rtrue;
       }
       if ( traderflag ) {
               print " + 1 doubloon for Trader";
       }
       if ( marketflag ) {
               print " + ", marketflag, " doubloon";
               if ( marketflag ~= 1 ) print "s";
               print " for Markets";
       }
       print "^  ", (shortname) curplayer, " receives ", db, " doubloon";
       if ( db ~= 1 ) print "s";
       print " total^";
       rtrue;
];

[ FlushTradingPost i;
       while( child(Trading_post) ~= 0 ) {
               i = child(Trading_post);
               switch( i.type ) {
                       CORN: Corn_goods.destroy(i);
                       INDIGO: Indigo_goods.destroy(i);
                       SUGAR: Sugar_goods.destroy(i);
                       TOBACCO: Tobacco_goods.destroy(i);
                       COFFEE: Coffee_goods.destroy(i);
               }
       }
       Trading_post.inventory = 0;
       print "^Trading post is now full, and is cleared out.^";
       rtrue;
];

Role_Card -> Settler_Card
 with
       short_name "Settler",
       type SETTLER,
       special [ playernum curplayer i;
! Iterate through the players, each choosing a plantation from the stack or
! a quarry.
               ChoosePlantations( curplayer, 1 );
               for( i=1: i<num_players: i++ ) {
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       ChoosePlantations( curplayer );
               }
               SetPlantationTiles();
       ],
;

[ PrintPlantationStack quarryflag i j;
       print "^Plantation tiles currently available: ";
       objectloop( i in Plantation_tiles ) {
               j++;
               PrintPlantationName( i );
       }
       if ( quarryflag && quarry_supply > 0 ) {
               print "Q( ) ";
       }
       else {
               if ( j == 0 ) print "[none]";
       }
       new_line;
];

[ ChoosePlantations curplayer quarryflag haciendaflag i j q input choice;
       if ( curplayer has chut ) quarryflag = 1;
       if ( curplayer has haci ) haciendaflag = 1;

       .select;

       PrintPlantationStack( quarryflag );
       if ( quarryflag && quarry_supply > 0 ) {
               print (shortname) curplayer, " may choose a Quarry this turn^";
       }

       if ( child(Plantation_tiles) == 0 ) {
               print "^", (shortname) curplayer, " choose a plantation or 0 to pass: > ";
       }
       else {
               print "^", (shortname) curplayer, " choose a plantation: > ";
       }

       input = ReadInput( curplayer );

       if ( input == 'q//' ) {
               if ( quarryflag ) {
                       if ( quarry_supply > 0 ) {
                               q = QuarryTile.create();
                               if ( q ~= nothing ) {
                                       quarry_supply--;
                                       move q to curplayer.board;
                                       print (shortname) curplayer, " selects a Quarry^";
                                       if ( curplayer has hosp && colonist_supply > 0 ) {
                                               colonist_supply--;
                                               q.man( curplayer );
                                               print "  ", (shortname) curplayer, " receives 1 colonist
                                                       for Hospice^";
                                       }
                                       rtrue;
                               }
                               else {
                                       print "Can't create Quarry [BUG].^"; jump select;
                               }
                       }
                       else {
                               print "No quarries left.^"; jump select;
                       }
               }
               else {
                       print "Not a valid choice.^"; jump select;
               }
       }
       else {
               if ( input == '0//' ) {
                       if ( haciendaflag == 1 ) rtrue;
                       if ( child(Plantation_tiles) == 0 ) {
                               print "   Moving to next player^";
                               rtrue;
                       }
                       print "All players must choose a plantation^";
                       jump select;
               }
               if ( input == 'PRINT' ) { new_line; jump select; }

               j = 0;
               objectloop( i in Plantation_tiles ) {
                       if ( i.name == input )
                               j = i;
               }
               if ( j ~= 0 ) {
                       print (shortname) curplayer, " selects ";
                       PrintCropType(j.type);
                       print " plantation^";
                       move j to curplayer.board;
                       if ( curplayer has hosp && colonist_supply > 0 ) {
                               colonist_supply--;
                               j.man( curplayer );
                               print "  ", (shortname) curplayer, " receives 1 colonist
                               for Hospice^";
                       }
               }
               else {
                       print "Not a valid choice.^"; jump select;
               }

               if ( haciendaflag ) {
                       print "^  ", (shortname) curplayer, " has Hacienda and may draw a
                               second plantation from supply^";

                       PrintPlantationSupply( 1 );

                       .select2;
                       print "^", (shortname) curplayer, " type Y to draw a tile or 0 to pass: >";
                       input = ReadInput( curplayer );

                       switch( input ) {
                               '0//', 'n//', 'no' : print "   Moving to next player^"; rtrue;
                               'y//', 'yes':
                                       if ( PlantationCount() == 0 ) {
                                               print "No tiles left.    Moving to next player^";
                                               rtrue;
                                       }
                                       choice = random(5) - 1;
                                       if ( plantation_supply-->choice == 0 ) {
                                               while( plantation_supply-->choice == 0 ) {
                                                       choice = random(5) - 1;
                                               }
                                       }
                                       j = Plantation.create( choice );
                                       if ( j ~= 0 ) {
                                               print "^  ", (shortname) curplayer, " draws ";
                                               PrintCropType( j.type );
                                               print " plantation^";
                                               move j to curplayer.board;
                                               plantation_supply-->choice = plantation_supply-->choice - 1;
                                       }
                               'PRINT': new_line; jump select2;
                               default: print "Not valid input.^"; jump select2;
                       }
               }
       }
];

Role_Card -> Builder_Card
 with
       short_name "Builder",
       type BUILDER,
       special [ playernum curplayer i;
               ChooseBuildings( curplayer, 1 );
               for( i=1: i < num_players: i++ ) {
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       ChooseBuildings( curplayer );
               }
       ],
;

[ CountQuarries curplayer i count;
       objectloop( i in curplayer.board && i ofclass QuarryTile ) {
               if ( i.manned ) count++;
       }
       return( count );
];

[ ChooseBuildings curplayer builderflag quarryflag input i j k affordable;
       quarryflag = CountQuarries( curplayer );

       print "   Player has ", quarryflag, " manned ";
       if ( quarryflag == 1 ) print "Quarry^";
       else print "Quarries^";

       PrintBuildingSupply( builderflag, quarryflag );

       .select;

       PrintPlayer( curplayer.number );
       if ( curplayer.doubloons + builderflag + quarryflag == 0 ) {
               print "  ", (shortname) curplayer, " has 0 doubloons and cannot buy
                       any buildings this turn^";
               print "   Moving to next player^^";
               rtrue;
       }

       print "^", (shortname) curplayer, " choose a building to purchase: (L for list,
               0 to cancel) > ";
       input = ReadInput( curplayer, 1 );

       if ( input == 'l//' ) {
               PrintBuildingSupply( builderflag, quarryflag );
               new_line;
               jump select;
       }
       else if ( input == '0//' ) {
               print "  ", (shortname) curplayer, " chooses not to buy
                       any buildings this turn^";
               print "   Moving to next player^^";
               rtrue;
       }
       else if ( input == 'PRINT' ) {
               new_line; jump select;
       }
       else {
               j = 0;
               objectloop( i in building_supply ) {
                       if ( i.name == input ) {
                               objectloop( k in curplayer.board && k ofclass Building ) {
                                       if ( k.name == i.name ) {
                                               print "^   You can't buy more than one of the same
                                               type of building.^";
                                               jump select;
                                       }
                               }
                               j = i;
                       }
               }
               if ( j ~= 0 ) {
                       affordable = curplayer.doubloons + builderflag + QuarryDiscount( j.number, quarryflag );
                       if ( j.cost > affordable ) {
                               print "You can't afford that selection. ";
                               jump select;
                       }
                       print (shortname) curplayer, " selects ", (shortname) j, "^";
                       move j to curplayer.board;
                       curplayer.doubloons = affordable - j.cost;

                       if ( builderflag ~= 0 ) builderflag = 0;   ! one use only

                       if ( curplayer has univ && colonist_supply > 0 ) {
                               colonist_supply--;
                               j.man( curplayer );
                               print "  ", (shortname) curplayer, " receives 1 colonist for
                                       University^";
                       }
                       print "^   Moving to next player^^";
                       rtrue;
               }
               else {
                       print "Not a valid choice.^"; jump select;
               }
       }
];

[ CountUnmannedBuildings curplayer i count;
       objectloop( i in curplayer.board && i ofclass Building ) {
               if ( i.manned < i.capacity )
                       count = count + ( i.capacity - i.manned );
       }
       return( count );
];

Role_Card -> Mayor_Card
 with
       short_name "Mayor",
       type MAYOR,
       special [ playernum curplayer the_mayor i;
! Iterate through the number of tokens on the colony ship, giving one
! to each player, looping until it's done.
               the_mayor = curplayer;
               curplayer.colonists++;
               print "    ", (shortname) curplayer, " gets 1 colonist from the ship^";
               for ( i=1 : i < colony_ship : i++ ) {
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       curplayer.colonists++;
                       print "    ", (shortname) curplayer, " gets 1 colonist from the ship^";
               }
               colony_ship = 0;

! The player who chose the Mayor gets an extra colonist from the supply.
               if ( colonist_supply > 0 ) {
                       colonist_supply--;
                       the_mayor.colonists++;
                       print "  ", (shortname) the_mayor, " receives 1 extra colonist for
                               choosing Mayor^";
               }

! Players now take turns placing their colonists on unmanned tiles on their boards.
               playernum = the_mayor.number;
               curplayer = GetPlayer( playernum );
               PlaceColonists( curplayer );
               for ( i=1: i < num_players : i++ ) {
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       PlaceColonists( curplayer );
               }

! The ship is then refilled from the supply, one for each player, and then
! one more for each unmanned building space on the table, whichever is greater.
!
               RefillColonyShip();
               rtrue;
       ],
;

[ CountUnmannedPlantations curplayer i count;
       objectloop( i in curplayer.board && i ofclass Plantation ) {
               if ( i.manned == 0 )
                       count++;
       }
       return( count );
];

[ CountUnmannedSpaces curplayer count;
       count = CountUnmannedPlantations(curplayer) + CountUnmannedBuildings(curplayer);
       return( count );
];

[ PrintUnmannedSpaces curplayer count;
       PrintPlayer( curplayer.number );
       count = CountUnmannedSpaces( curplayer );
       if ( count == 0 ) {
               print "^ ", (shortname) curplayer, " has no available places^";
               rfalse;
       }
       rtrue;
];

[ PrintCropType croptype;
       switch( croptype ) {
               CORN: print "Corn";
               INDIGO: print "Indigo";
               SUGAR: print "Sugar";
               TOBACCO: print "Tobacco";
               COFFEE: print "Coffee";
               QUARRY: print "Quarry";
               EMPTY: print "empty";
       }
];

[ PlaceColonists curplayer i j input;
       .select;

       print "^  ", (shortname) curplayer, " has ", curplayer.colonists, " unplaced colonist";
       if ( curplayer.colonists ~= 1 ) print "s";
       print " left^";

       i = PrintUnmannedSpaces( curplayer );
       new_line;
       if ( i == 0 || curplayer.colonists == 0 ) {
               print (shortname) curplayer, " type M to move a colonist or
                       0 to pass: > ";
       }
       else {
               print (shortname) curplayer, " choose where to place a colonist or
               M to move: > ";
       }
       input = ReadInput( curplayer, 1 );
       if ( input == '0//' ) {
               print "Skipping to next player.^";
               rtrue;
       }
       if ( input == 'PRINT' ) { new_line; jump select; }
       if ( input == 'm//' ) {
               MoveColonists( curplayer );
               jump select;
       }
       if ( curplayer.colonists == 0 ) {
               jump select;
       }
       j = 0;
       objectloop( i in curplayer.board && j == 0 ) {
               if ( i.name == input && ( i.manned < i.capacity ) ) {
                       print (shortname) curplayer, " places 1 colonist on ";
                       if ( i ofclass Plantation ) {
                               PrintCropType(i.type);
                               if ( i.type ~= QUARRY )
                                       print " plantation";
                               new_line;
                       }
                       else {
                               print (shortname) i; new_line;
                       }
                       i.man( curplayer );
                       curplayer.colonists--;
                       j = 1;
               }
       }
       if ( j == 0 ) {
               if ( input == 'PRINT' ) new_line;
               else print "Not valid input.^";
               jump select;
       }

       new_line;
       jump select;
];

[ MoveColonists curplayer input whence thence i;
       .select;

       PrintPlayer( curplayer.number );

       print "^Choose where to move a colonist from: >";
       input = ReadInput( curplayer, 1 );
       if ( input == '0//' ) {
               print "Movement cancelled.^";
               rtrue;
       }
       if ( input == 'PRINT' ) { new_line; jump select; }

       objectloop( i in curplayer.board && ( i ofclass Plantation or Building ) ) {
               if ( ( i.name == input ) && i.manned )
                       whence = i;
       }
       if ( whence == 0 ) {
               print "Not valid choice.^";
               jump select;
       }

       .select2;

       print "^Choose where to move this colonist to: >";
       input = ReadInput( curplayer, 1 );

       if ( input == '0//' ) {
               print "Movement cancelled.^";
               rtrue;
       }
       if ( input == 'PRINT' ) { new_line; jump select; }

       objectloop( i in curplayer.board && ( i ofclass Plantation or Building ) ) {
               if ( ( i.name == input ) && ( i.manned < i.capacity ) )
                       thence = i;
       }
       if ( thence == 0 ) {
               print "Not valid choice.^";
               jump select2;
       }

       whence.unman( curplayer );
       thence.man( curplayer );
       print "Colonist moved from ";
       if ( whence ofclass Plantation ) {
               PrintCropType( whence.type );
               print " to ";
       }
       else
               print (shortname) whence;
       print " to ", (shortname) thence, "^";
       rtrue;
];

[ RefillColonyShip i;
       for ( i=0 : i < num_players : i++ ) {
               if ( colonist_supply > 0 ) {
                       colonist_supply--;
                       colony_ship++;
               }
       }
       i = CountUnmannedBuildings(P1) + CountUnmannedBuildings(P2) + CountUnmannedBuildings(P3)
               + CountUnmannedBuildings(P4) + CountUnmannedBuildings(P5);

       print "^  Number of unmanned buildings is ", i, "^";
       if ( i > num_players ) {
               i = i - num_players;
               if ( colonist_supply < i ) {
                       print "^  Colonist supply only has ", colonist_supply;
                       if ( colonist_supply == 1 ) print " colonist ";
                       else print " colonists ";
                       print " remaining^";
                       i = colonist_supply;
               }
               colonist_supply = colonist_supply - i;
               colony_ship = colony_ship + i;
       }
       print "  Colony Ship refilled with ", colony_ship;
       if ( colony_ship == 1 ) print " colonist^";
       else print " colonists^";

       if ( colonist_supply == 0 )
               print "^Colonist supply is now exhausted. Game will end this turn.^";
       else print "  Colonist Supply down to: ", colonist_supply, "^";
];

Role_Card -> Craftsman_Card
 with
       short_name "Craftsman",
       type CRAFTSMAN,
       special [ playernum curplayer i;
               ProduceGoods( curplayer );
               if ( child(curplayer) ~= 0 )
                       CraftsmanChoice( curplayer );
               StoreGoods( curplayer );
               for ( i=1 : i < num_players : i++ ) {
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       ProduceGoods( curplayer );
                       StoreGoods( curplayer );
               }
               new_line; rtrue;
       ],
;

[ StoreGoods curplayer i factorycount bonus;
       while( child(curplayer) ~= nothing ) {
               i = child(curplayer);
               move i to curplayer.board;
       }

       if ( curplayer has fact ) {
               factorycount = curplayer.corn_made + curplayer.indigo_made +
                       curplayer.sugar_made + curplayer.tobacco_made + curplayer.coffee_made;
               switch( factorycount ) {
                       1: bonus = 0;
                       2: bonus = 1;
                       3: bonus = 2;
                       4: bonus = 3;
                       5: bonus = 5;
               }
               if ( bonus > 0 ) {
                       curplayer.doubloons = curplayer.doubloons + bonus;
                       print "  ", (shortname) curplayer, " produced ", factorycount, " types
                               of goods and receives ", bonus, " doubloon";
                       if ( bonus ~= 1 ) print "s";
                       print " for Factory^";
               }
       }
       curplayer.corn_made = 0;
       curplayer.indigo_made = 0;
       curplayer.sugar_made = 0;
       curplayer.tobacco_made = 0;
       curplayer.coffee_made = 0;
];

[ CraftsmanChoice curplayer input i j bonus;
       i = curplayer.corn_made + curplayer.indigo_made + curplayer.sugar_made +
               curplayer.tobacco_made + curplayer.coffee_made;

       if ( i == 0 ) rfalse;
       if ( i == 1 ) {
               objectloop ( i in curplayer ) {
                       j = i.type;
               }
               switch( j ) {
                       CORN: bonus = Corn_goods.create();
                       INDIGO: bonus = Indigo_goods.create();
                       SUGAR: bonus = Sugar_goods.create();
                       TOBACCO: bonus = Tobacco_goods.create();
                       COFFEE: bonus = Coffee_goods.create();
               }
               if ( bonus ~= nothing ) {
                       print "    ", (shortname) curplayer, " receives 1 extra ", (PrintCropType) j,
                       " for choosing Craftsman^";
                       move bonus to curplayer;
               }
               else {
                       print (shortname) curplayer, " cannot receive bonus production good,
                               because there are no ", (PrintCropType) j, " tokens left^";
               }
               rtrue;
       }

       .select;

       new_line;
       print (shortname) curplayer, " may now choose 1 extra production good: ";
       if ( curplayer.corn_made ) { PrintCropType( CORN ); print " - "; }
       if ( curplayer.indigo_made ) { PrintCropType( INDIGO ); print " - "; }
       if ( curplayer.sugar_made ) { PrintCropType( SUGAR ); print " - "; }
       if ( curplayer.tobacco_made ) { PrintCropType( TOBACCO ); print " - "; }
       if ( curplayer.coffee_made ) { PrintCropType( COFFEE ); }
       print " >";

       input = ReadInput( curplayer );

       if ( input == '0//' ) rtrue;
       if ( input == 'PRINT' ) { new_line; jump select; }

       j = 0;
       objectloop( i in curplayer && j == 0 ) {
               if ( i.name == input )
                       j = i;
       }
       if ( j ~= 0 ) {
               switch( j.type ) {
                       CORN: bonus = Corn_goods.create();
                       INDIGO: bonus = Indigo_goods.create();
                       SUGAR: bonus = Sugar_goods.create();
                       TOBACCO: bonus = Tobacco_goods.create();
                       COFFEE: bonus = Coffee_goods.create();
               }
               if ( bonus ~= nothing ) {
                       print (shortname) curplayer, " chooses 1 extra ", (PrintCropType) j.type, "^";
                       move bonus to curplayer;
               }
               else {
                       print "There are no ", (PrintCropType) j, " tokens left. Please
                               select again or 0 to cancel.^";
                       jump select;
               }
       }
       else {
               print "Not valid input.^";
               jump select;
       }
];

[ ProduceGoods curplayer i j prodmanned prodcapacity newgood;
       print "    ", (shortname) curplayer, " produces ";

! Produce CORN
       j = 0;
       objectloop( i in curplayer.board && i ofclass Plantation && i.type == CORN ) {
               if ( i.manned ) {
                       newgood = Corn_goods.create();
                       if ( newgood ~= nothing ) {
                               j++;
                               move newgood to curplayer;
                       }
               }
       }
       if ( j > 0 ) {
               print j, " Corn";
               curplayer.corn_made = 1;
       }

! Produce INDIGO
       j = 0;
       prodmanned = 0;
       prodcapacity = 0;
       objectloop( i in curplayer.board && i ofclass Plantation && i.type == INDIGO ) {
               if ( i.manned )
                       prodmanned = prodmanned + i.manned;
       }
       objectloop( i in curplayer.board && i ofclass IndigoPlant ) {
               prodcapacity = prodcapacity + i.manned;
       }
       if ( prodmanned > 0 && prodcapacity > 0 ) {
               if ( prodcapacity > prodmanned )
                       prodcapacity = prodmanned;

               for ( i=0: i < prodcapacity : i++ ) {
                       newgood = Indigo_goods.create();
                       if ( newgood ~= nothing ) {
                               j++;
                               move newgood to curplayer;
                       }
               }
       }
       if ( j > 0 ) {
               i = curplayer.corn_made + curplayer.indigo_made + curplayer.sugar_made +
                       curplayer.tobacco_made + curplayer.coffee_made;
               if ( i ~= 0 ) print " - ";
               print j, " Indigo";
               curplayer.indigo_made = 1;
       }

! Produce SUGAR
       j = 0;
       prodmanned = 0;
       prodcapacity = 0;
       objectloop( i in curplayer.board && i ofclass Plantation && i.type == SUGAR ) {
               if ( i.manned )
                       prodmanned = prodmanned + i.manned;
       }
       objectloop( i in curplayer.board && i ofclass SugarMill ) {
               prodcapacity = prodcapacity + i.manned;
       }
       if ( prodmanned > 0 && prodcapacity > 0 ) {
               if ( prodcapacity > prodmanned )
                       prodcapacity = prodmanned;

               for ( i=0: i < prodcapacity : i++ ) {
                       newgood = Sugar_goods.create();
                       if ( newgood ~= nothing ) {
                               j++;
                               move newgood to curplayer;
                       }
               }
       }
       if ( j > 0 ) {
               i = curplayer.corn_made + curplayer.indigo_made + curplayer.sugar_made +
                       curplayer.tobacco_made + curplayer.coffee_made;
               if ( i ~= 0 ) print " - ";
               print j, " Sugar";
               curplayer.sugar_made = 1;
       }

! Produce TOBACCO
       j = 0;
       prodmanned = 0;
       prodcapacity = 0;
       objectloop( i in curplayer.board && i ofclass Plantation && i.type == TOBACCO ) {
               if ( i.manned )
                       prodmanned = prodmanned + i.manned;
       }
       objectloop( i in curplayer.board && i ofclass TobaccoStorage ) {
               prodcapacity = prodcapacity + i.manned;
       }
       if ( prodmanned > 0 && prodcapacity > 0 ) {
               if ( prodcapacity > prodmanned )
                       prodcapacity = prodmanned;

               for ( i=0: i < prodcapacity : i++ ) {
                       newgood = Tobacco_goods.create();
                       if ( newgood ~= nothing ) {
                               j++;
                               move newgood to curplayer;
                       }
               }
       }
       if ( j > 0 ) {
               i = curplayer.corn_made + curplayer.indigo_made + curplayer.sugar_made +
                       curplayer.tobacco_made + curplayer.coffee_made;
               if ( i ~= 0 ) print " - ";
               print j, " Tobacco";
               curplayer.tobacco_made = 1;
       }

! Produce COFFEE
       j = 0;
       prodmanned = 0;
       prodcapacity = 0;
       objectloop( i in curplayer.board && i ofclass Plantation && i.type == COFFEE ) {
               if ( i.manned )
                       prodmanned = prodmanned + i.manned;
       }
       objectloop( i in curplayer.board && i ofclass CoffeeRoaster ) {
               prodcapacity = prodcapacity + i.manned;
       }
       if ( prodmanned > 0 && prodcapacity > 0 ) {
               if ( prodcapacity > prodmanned )
                       prodcapacity = prodmanned;

               for ( i=0: i < prodcapacity : i++ ) {
                       newgood = Coffee_goods.create();
                       if ( newgood ~= nothing ) {
                               j++;
                               move newgood to curplayer;
                       }
               }
       }
       if ( j > 0 ) {
               i = curplayer.corn_made + curplayer.indigo_made + curplayer.sugar_made +
                       curplayer.tobacco_made + curplayer.coffee_made;
               if ( i ~= 0 ) print " - ";
               print j, " Coffee";
               curplayer.coffee_made = 1;
       }

       if ( child(curplayer) == 0 )
               print "nothing this turn";

       new_line; rtrue;
];

Role_Card -> Captain_Card
 with
       short_name "Captain",
       type CAPTAIN,
       special [ playernum curplayer the_captain captainflag done i j;
               the_captain = curplayer;
               while ( done < num_players ) {
                       if ( curplayer == the_captain ) captainflag = 1;
                       done = done + ShipGoods( curplayer, captainflag );
                       playernum = NextPlayer( playernum );
                       curplayer = GetPlayer( playernum );
                       captainflag = 0;
               }
               new_line;
               for ( i=1 : i <= Cargo_fleet.size : i++ ) {
                       if ( Ship(i).inventory == Ship(i).capacity ) {
                               FlushCargoShip( Ship(i) );
                       }
               }
               for ( i=0 : i < num_players : i++ ) {
                       curplayer = GetPlayer(i+1);
                       give curplayer ~general;
                       if ( curplayer has whrf ) {
                               objectloop( j in curplayer.board && j ofclass Cargo_ship ) {
                                       FlushCargoShip( j );
                               }
                       }
               }
               RotGoods( the_captain );
       ],
;

[ PrintFleet curplayer wharfflag the_ship i count;
       print "^Current Cargo fleet:^";

       if ( num_players == 2 ) count = 2;
       else count = 3;

       for ( i=1 : i <= count : i++ ) {
               the_ship = Ship(i);
               print "(", i, ") ";
               PrintShip(the_ship);
       }
       if ( wharfflag ) {
               the_ship = 0;
               objectloop( i in curplayer.board && i ofclass Cargo_ship ) {
                       the_ship = i;
               }
               if ( the_ship ~= 0 ) {
                       print "(", count + 1, ") ";
                       PrintShip( the_ship );
                       new_line;
               }
       }
];

[ PrintShip the_ship i j;
       print (shortname) the_ship, ": (";
       PrintCropType( the_ship.type );
       print ") ";

       if ( the_ship in Cargo_fleet ) {
               j = the_ship.capacity - the_ship.inventory;

               for ( i=0 : i < the_ship.inventory : i++ ) {
                       print "[*]";
               }
               for ( i=0 : i < j : i++ ) {
                       print "[ ]";
               }
       }
       else {
               if ( the_ship.inventory < 9 )
                       j = 8 - the_ship.inventory;

               for ( i=0 : i < the_ship.inventory : i++ ) {
                       print "[*]";
               }
               if ( j > 0 ) {
                       for ( i=0 : i < j : i++ ) {
                               print "[ ]";
                       }
                       print "  (Unlimited)";
               }
       }
       new_line;
];

[ PlayerCanShipGoods curplayer i the_ship ccount scount icount tcount kcount;
       objectloop( i in curplayer.board && i ofclass Goods ) {
               switch( i.type ) {
                       CORN: ccount = 1;
                       SUGAR: scount = 1;
                       INDIGO: icount = 1;
                       TOBACCO: tcount = 1;
                       COFFEE: kcount = 1;
               }
       }
       for ( i = 1 : i <= Cargo_Fleet.size : i++ ) {
               the_ship = Ship( i );
               if ( ccount && CheckShippable( curplayer, the_ship, CORN ) ) {
!                       print "^   ", (PrintCroptype) CORN, " is shippable on ",
!                       (shortname) the_ship, ". PlayerCanShipGoods = true.^";
                       rtrue;
               }
               if ( scount && CheckShippable( curplayer, the_ship, SUGAR ) ) {
!                       print "^   ", (PrintCroptype) SUGAR, " is shippable on ",
!                       (shortname) the_ship, ". PlayerCanShipGoods = true.^";
                       rtrue;
               }
               if ( icount && CheckShippable( curplayer, the_ship, INDIGO ) )  {
!                       print "^   ", (PrintCroptype) INDIGO, " is shippable on ",
!                       (shortname) the_ship, ". PlayerCanShipGoods = true.^";
                       rtrue;
               }
               if ( tcount && CheckShippable( curplayer, the_ship, TOBACCO ) )  {
!                       print "^   ", (PrintCroptype) TOBACCO, " is shippable on ",
!                       (shortname) the_ship, ". PlayerCanShipGoods = true.^";
                       rtrue;
               }
               if ( kcount && CheckShippable( curplayer, the_ship, COFFEE ) )  {
!                       print "^   ", (PrintCroptype) COFFEE, " is shippable on ",
!                       (shortname) the_ship, ". PlayerCanShipGoods = true.^";
                       rtrue;
               }
       }
       rfalse;
];

[ CheckShippable curplayer the_ship croptype whrf_ship i j;
       if ( the_ship.capacity == the_ship.inventory ) {
!               print "^", (PrintCroptype) croptype, " is not shippable because ",
!                       (shortname) the_ship, " is full.^";
               rfalse;
       }
       if ( the_ship.type == croptype ) {
               if ( the_ship in Cargo_fleet ) {
!                       print "^", (PrintCroptype) croptype, " is shippable on ",
!                       (shortname) the_ship, ", which is shipping ", (PrintCropType) croptype, ".^";
                       rtrue;
               }
               if ( the_ship in curplayer.board && curplayer has whrf ) {
!                       print "^", (PrintCroptype) croptype, " is shippable on Wharf ship ",
!                       (shortname) the_ship, ", which is shipping ", (PrintCropType) croptype, ".^";
                       rtrue;
               }
               else {
!                       print "^", (PrintCroptype) croptype, " isn't shippable on ",
!                       (shortname) the_ship, ", because ", (shortname) curplayer, " does
!                       not own that Wharf ship.^";
                       rfalse;
               }
       }
       if ( the_ship.type == EMPTY ) {
               if ( the_ship in Cargo_fleet ) {
                       objectloop( i in Cargo_fleet && i.type == croptype ) {
                               j = 1;
                       }
                       if ( j ) {
                               if ( curplayer has whrf ) {
                                       objectloop( i in curplayer.board && i ofclass Cargo_ship ) {
                                               whrf_ship = i;
                                       }
                                       if ( whrf_ship.type == EMPTY ) {
!                                               print "^", (PrintCroptype) croptype, " is not shippable
!                                               on ", (shortname) the_ship, " because another ship is
!                                               already shipping ", (PrintCropType) croptype, ", but it
!                                               can be shipped on Wharf ship ", (shortname) whrf_ship,
!                                               ", which is empty.^";
                                               rtrue;
                                       }
                                       if ( whrf_ship.type == croptype &&
                                               whrf_ship.capacity < whrf_ship.inventory ) {
!                                               print "^", (PrintCroptype) croptype, " is shippable on
!                                               Wharf ship ", (shortname) whrf_ship, ", which is
!                                               shipping ", (PrintCropType) croptype, ".^";
                                               rtrue;
                                       }
!                                       print "^", (PrintCroptype) croptype, " isn't shippable on ",
!                                       (shortname) the_ship, ", which is empty, because another ship
!                                       is already shipping ", (PrintCropType) croptype, " and Wharf
!                                       ship is full or shipping the wrong crop type.^";
                                       rfalse;
                               }
!                               print "^", (PrintCroptype) croptype, " isn't shippable on ",
!                               (shortname) the_ship, ", which is empty, because another ship
!                               is already shipping ", (PrintCropType) croptype, ".^";
                               rfalse;
                       }
!                       print "^", (PrintCroptype) croptype, " is shippable on ",
!                       (shortname) the_ship, ", which is empty.^";
                       rtrue;
               }
               if ( the_ship in curplayer.board && curplayer has whrf ) {
!                       print "^", (PrintCroptype) croptype, " is shippable on Wharf ship ",
!                       (shortname) the_ship, ", which is empty.^";
                       rtrue;
               }
               else {
!                       print "^", (PrintCroptype) croptype, " isn't shippable on ",
!                       (shortname) the_ship, ", which is empty, because another ship
!                       is already shipping ", (PrintCropType) croptype, " and ",
!                       (shortname) curplayer, " has no Wharf ship.^";
                       rfalse;
               }
       }
!       print "^", (PrintCroptype) croptype, " isn't shippable on ",
!       (shortname) the_ship, ", because it is shipping ",
!       (PrintCropType) the_ship.type, ".^";
       rfalse;
];

[ ShipGoods curplayer captainflag harbourflag wharfflag i j input award;
       if ( curplayer has whrf ) wharfflag = 1;
       if ( curplayer has harb ) harbourflag = 1;

       .select;

       PrintFleet( curplayer, wharfflag );
       print "   ", (shortname) curplayer, " has ";
       j = PrintGoods( curplayer );
       if ( j == 0 ) {
               print "no Goods to ship";
               if ( curplayer has general ) {
                       print "^   Moving to next player^";
                       rfalse;
               }
       }

       print "^^", (shortname) curplayer, " choose Goods to ship or 0 to pass >";

       input = ReadInput( curplayer );
       if ( input == '0//' ) {
               if ( PlayerCanShipGoods( curplayer ) ) {
                       print "^   ", (shortname) curplayer, " must ship all Goods possible^";
                       print "   Please select again^";
                       jump select;
               }
               print "   ", (shortname) curplayer, " passes^";
               print "   Moving to next player^";
               if ( curplayer has general ) rfalse;
               give curplayer general;
               rtrue;
       }
       if ( input == 'PRINT' ) { new_line; jump select; }

       objectloop( i in curplayer.board && i ofclass Goods ) {
               if ( i.name == input ) {
                       award = LoadCargo( curplayer, i.type, wharfflag );
                       if ( award > 0 ) {
                               print "   ", (shortname) curplayer, " receives ", award, "VP";
                               if ( captainflag || harbourflag ) {
                                       award = award + captainflag + harbourflag;
                                       if ( captainflag ) {
                                               print " + 1VP for Captain";
                                       }
                                       if ( harbourflag ) {
                                               print " + 1VP for Harbour";
                                       }
                                       print "^for a total of ", award, "VP";
                               }
                               curplayer.VP = curplayer.VP + award;
                               VP_tokens = VP_tokens - award;
                               new_line; rfalse;
                       }
                       else {
                               jump select;
                       }
               }
       }
       print "Not valid input.^";
       jump select;
];

[ LoadCargo curplayer croptype wharfflag i j the_ship input award;
       for ( i = 1 : i <= Cargo_fleet.size : i++ ) {
               the_ship = Ship(i);
               j = j + CheckShippable( curplayer, the_ship, croptype );
       }
       if ( j == 0 ) {
               print "^   ", (shortname) curplayer, " cannot ship ",
               (PrintCropType) croptype, " at this time. Please select
               again.^";
               rfalse;
       }
       else {
               i = 0;
               j = 0;
               the_ship = 0;
       }

       .select;

       print "^Load ";
       PrintCropType( croptype );
       print " onto which ship (1-";

       if ( num_players == 2 ) print 2 + wharfflag;
       else print 3 + wharfflag;

       print ")? (L for list)>";
       input = ReadInput( curplayer );
       if ( input == 'PRINT' ) { new_line; jump select; }
       switch( input ) {
               'l//', 'list': PrintFleet( curplayer, wharfflag ); jump select;
               '0//': print "Cancelling. Choose again.^"; rfalse;
               '1//': the_ship = Ship(1);
               '2//': the_ship = Ship(2);
               '3//': if ( num_players > 2 ) { the_ship = Ship(3); }
                       else {
                               if ( wharfflag == 0 ) {
                                       print "Not valid choice.^"; jump select;
                               }
                               objectloop( i in curplayer.board && i ofclass Cargo_ship ) {
                                       the_ship = i;
                               }
                       }
               '4//': if ( num_players == 2 || wharfflag == 0 ) {
                               print "Not valid choice.^"; jump select;
                       }
                       objectloop( i in curplayer.board && i ofclass Cargo_ship ) {
                               the_ship = i;
                       }
               default: print "Not valid choice.^"; jump select;
       }
       if ( the_ship.type == croptype ) {
               if ( the_ship.capacity == the_ship.inventory ) {
                       print (shortname) the_ship, " is full. Choose a different ship
                               or 0 to cancel.^";
                       jump select;
               }
               award = PutCargoAboard( curplayer, croptype, the_ship );
               return( award );
       }
       else if ( the_ship.type == EMPTY ) {
               if ( the_ship in Cargo_fleet ) {
                       objectloop( i in Cargo_fleet && i.type == croptype ) {
                               j = i;
                       }
                       if ( j ~= 0 ) {
                               print "^You can't have two ships with the same cargo.^";
                               print (shortname) j, " is already shipping ";
                               PrintCropType( croptype );
                               print ". Choose again.^";
                               jump select;
                       }
               }
               award = PutCargoAboard( curplayer, croptype, the_ship );
               return( award );
       }
       else {
               print (shortname) the_ship, " is shipping ";
               PrintCropType( croptype );
               print ". Try again or 0 to cancel and choose a different type of Goods.^";
               jump select;
       }
];

[ PutCargoAboard curplayer croptype the_ship count i j cargo num;
       num = 0;
       count = the_ship.capacity - the_ship.inventory;
       if ( the_ship.type == EMPTY ) the_ship.type = croptype;
       for ( i=0: i < count: i++ ) {
               cargo = 0;
               objectloop( j in curplayer.board && j ofclass Goods ) {
                       if ( j.type == croptype ) {
                               cargo = j;
                       }
               }
               if ( cargo ~= 0 ) {
                       move cargo to the_ship;
                       the_ship.inventory++;
                       num++;
               }
       }
       print "^   ", (shortname) curplayer, " loads ", num, " ";
       PrintCropType( croptype );
       print " onto ", (shortname) the_ship, "^";
       return( num );
];

[ FlushCargoShip the_ship noprintflag i;
       if ( noprintflag == 0 ) {
               print (shortname) the_ship;
               if ( the_ship.capacity == the_ship.inventory )
                       print " is now full, and";
               print " sails off with its cargo^";
       }
       while( child(the_ship) ~= 0 ) {
               i = child(the_ship);
               switch( i.type ) {
                       CORN: Corn_goods.destroy(i);
                       INDIGO: Indigo_goods.destroy(i);
                       SUGAR: Sugar_goods.destroy(i);
                       TOBACCO: Tobacco_goods.destroy(i);
                       COFFEE: Coffee_goods.destroy(i);
               }
       }
       the_ship.inventory = 0;
       the_ship.type = EMPTY;
       rtrue;
];

[ RotGoods curplayer playernum i;
       print "^Captain phase is over. All goods not shipped or stored must be
               reduced to 1.^";

       playernum = curplayer.number;
       SaveGoods( curplayer );
       for ( i=1: i < num_players : i++ ) {
               playernum = NextPlayer( playernum );
               curplayer = GetPlayer( playernum );
               SaveGoods( curplayer );
       }
];

[ CountCropTypes curplayer i ccount scount icount tcount kcount;
       objectloop( i in curplayer.board && i ofclass Goods ) {
               switch( i.type ) {
                       CORN: ccount = 1;
                       SUGAR: scount = 1;
                       INDIGO: icount = 1;
                       TOBACCO: tcount = 1;
                       COFFEE: kcount = 1;
               }
       }
       return( ccount + scount + icount + tcount + kcount );
];

[ SaveGoods curplayer warehouseflag i j input croptypecount count;
       if ( curplayer has swar ) warehouseflag++;
       if ( curplayer has lwar ) warehouseflag = warehouseflag + 2;

       .select;

       if ( warehouseflag ) {
               print "^   ", (shortname) curplayer, " has ";
               if ( curplayer has swar && curplayer has lwar ) {
                       print "Small Warehouse and Large Warehouse, and may store
                               up to 3 kinds of Goods";
               }
               else if ( curplayer has lwar ) {
                       print "Large Warehouse and may store up to 2 kinds of Goods";
               }
               else {
                       print "Small Warehouse and may store 1 kind of Good";
               }
       }
       print "^   ", (shortname) curplayer, " has ";
       j = PrintGoods( curplayer );
       if ( j == 0 ) {
               print "no Goods left^";
               print "   Moving to next player^";
               rtrue;
       }
       if ( j == 1 ) {
               print " only, which is stored^";
               print "   Moving to next player^^";
               rtrue;
       }

       croptypecount = CountCropTypes( curplayer );
       if ( croptypecount <= warehouseflag ) {
               print "^   ", (shortname) curplayer, " stores all Goods^";
               print "   Moving to next player^";
               rtrue;
       }
       new_line;

       if ( warehouseflag == 0 ) {
               print "   ", (shortname) curplayer, " will only be able to save 1 token
                       of 1 type of Good^";
       }

       if ( count == 0 ) {
               count = warehouseflag + 1;
!               if ( warehouseflag > 0 ) count = warehouseflag;
!               else count = 1;
       }

       .select2;

       new_line;
       if ( count == 0 ) {
               RecycleGoods( curplayer );
               rtrue;
       }
       if ( warehouseflag )
               print (shortname) curplayer, " choose Goods to store (L for list)>";
       else
               print (shortname) curplayer, " choose 1 Good to save (L for list)>";

       input = ReadInput( curplayer );
       if ( input == '0//' ) {
               print "You must make a selection.^";
               jump select2;
       }
       if ( input == 'PRINT' ) { new_line; jump select2; }
       if ( input == 'l//' or 'list' ) {
               print "^   ", (shortname) curplayer, " has ";
               PrintGoods( curplayer );
               new_line;
               jump select2;
       }

       j = 0;
       objectloop( i in curplayer.board && i ofclass Goods ) {
               if ( i.name == input ) {
                       j = i;
               }
       }
       if ( j ~= 0 ) {
               if ( warehouseflag == 0  ) {
                       RecycleGoods( curplayer, j.type, 1 );
                       rtrue;
               }
               WarehouseGoods( curplayer, j.type );
               warehouseflag--;
               count--;
               jump select2;
       }
       print "Not valid choice.^";
       jump select2;
];

[ RecycleGoods curplayer croptype saveoneflag i storage croptypecount;
       while( child(curplayer.board) ~= 0 ) {
               i = child(curplayer.board);
               move i to curplayer;
       }

       while( child(curplayer) ~= 0 ) {
               i = child(curplayer);
               if ( i ofclass Goods ) {
                       switch( i.type ) {
                               CORN: Corn_goods.destroy(i);
                               INDIGO: Indigo_goods.destroy(i);
                               SUGAR: Sugar_goods.destroy(i);
                               TOBACCO: Tobacco_goods.destroy(i);
                               COFFEE: Coffee_goods.destroy(i);
                       }
               }
               else
                       move i to curplayer.board;
       }
       if ( saveoneflag ) {
               switch( croptype ) {
                       CORN: i = Corn_goods.create();
                       INDIGO: i = Indigo_goods.create();
                       SUGAR: i = Sugar_goods.create();
                       TOBACCO: i = Tobacco_goods.create();
                       COFFEE: i = Coffee_goods.create();
               }
               move i to curplayer.board;
       }
       objectloop( storage in curplayer.board && storage ofclass Warehouse ) {
               while( child(storage) ~= 0 ) {
                       i = child(storage);
                       move i to curplayer.board;
               }
       }
       croptypecount = CountCropTypes( curplayer );
       if ( croptypecount ~= 0 ) {
               print "   ", (shortname) curplayer, " saves ";
               PrintGoods( curplayer );
               new_line;
       }
       print (shortname) curplayer, " loses all remaining unstored Goods^";
       new_line; rtrue;
];

[ WarehouseGoods curplayer croptype storage i;
       objectloop( i in curplayer.board && i ofclass Warehouse ) {
               storage = i;
       }
       if ( storage == nothing ) {
               print "Couldn't find warehouse!^";
               rfalse;
       }
       while( child(curplayer.board) ~= 0 ) {
               i = child(curplayer.board);
               move i to curplayer;
       }

       while( child(curplayer) ~= 0 ) {
               i = child(curplayer);
               if ( i ofclass Goods && i.type == croptype )
                       move i to storage;
               else
                       move i to curplayer.board;
       }
       print (shortname) curplayer, " stores ";
       PrintCropType( croptype );
       print " in Warehouse";
       new_line;
       rtrue;
];

[ Ship which;
       switch( which ) {
               1: return( Cargo_fleet.ship1 );
               2: return( Cargo_fleet.ship2 );
               3: return( Cargo_fleet.ship3 );
               4: return( Cargo_fleet.ship4 );
               5: return( Cargo_fleet.ship5 );
       }
];

Role_Card -> Prospector2_Card
 with
       short_name "Prospector2",
       type PROSPECTOR,
       doubloons 1,
       special [ curplayer;
               curplayer.doubloons = curplayer.doubloons + self.doubloons;
               print (shortname) curplayer, " receives ", self.doubloons, " doubloon";
               if ( self.doubloons ~= 1 ) print "s";
               self.doubloons = 0;
               new_line; rtrue;
       ],
;

[ ReadInput curplayer builderflag quarryflag wharfflag i input;
       buffer->0 = 60;
       parse->0 = 2;
       read buffer parse;
       switch ( parse->1 ) {
               1: input = parse-->1;
               2:      if ( parse-->1 == 'x//' ) {
                               input = parse-->3;
                       }
                       else input = 'notUnderstood';
               default: input = 'notUnderstood';
       }
       switch( parse-->1 ) {
               'p1': if ( curplayer == 0 ) {
                               print "Option not available until game begins.^";
                       }
                       else {
                               PrintPlayer(1);
                       }
                       input = 'PRINT';
               'p2': if ( curplayer == 0 ) {
                               print "Option not available until game begins.^";
                       }
                       else {
                               PrintPlayer(2);
                       }
                       input = 'PRINT';
               'p3': if ( curplayer == 0 ) {
                               print "Option not available until game begins.^";
                       }
                       else {
                               if ( num_players > 2 ) PrintPlayer(3);
                               else print "^No such player^";
                       }
                       input = 'PRINT';
               'p4': if ( curplayer == 0 ) {
                               print "Option not available until game begins.^";
                       }
                       else {
                               if ( num_players > 3 ) PrintPlayer(4);
                               else print "^No such player^";
                       }
                       input = 'PRINT';
               'p5': if ( curplayer == 0 ) {
                               print "Option not available until game begins.^";
                       }
                       else {
                               if ( num_players > 4 ) PrintPlayer(5);
                               else print "^No such player^";
                       }
                       input = 'PRINT';
               'quit', 'quity': new_line; quit;
               '?//', 'help': PrintHelp(); input = 'PRINT';
               'blort': Blort(); print "^Blorted.^"; input = 'PRINT';
               'fleeb': Fleeb(); input = 'PRINT';
               'printvp': VP_cheat(); input = 'PRINT';
               'endgame': End_game(); quit;
               'x//': switch( input ) {
                               'captain':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               if ( curplayer has whrf ) wharfflag = 1;
                                               PrintFleet( curplayer, wharfflag );
                                       }
                                       input = 'PRINT';
                               'trader':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               PrintTradingPostInv();
                                       }
                                       input = 'PRINT';
                               'builder':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               quarryflag = CountQuarries( curplayer );
                                               PrintBuildingSupply( builderflag, quarryflag );
                                       }
                                       input = 'PRINT';
                               'settler':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               PrintPlantationSupply();
                                               PrintPlantationStack();
                                       }
                                       input = 'PRINT';
                               'pr1':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               print "^Prospector1 has ", Prospector1_card.doubloons,
                                                       " doubloon";
                                               if ( Prospector1_card.doubloons ~= 1 ) print "s";
                                               new_line;
                                       }
                                       input = 'PRINT';
                               'pr2':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               print "^Prospector2 has ", Prospector2_card.doubloons,
                                                       " doubloon";
                                               if ( Prospector2_card.doubloons ~= 1 ) print "s";
                                               new_line;
                                       }
                                       input = 'PRINT';
                               'mayor':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               print "^   Colonist supply = ", colonist_supply;
                                               print "^   Colony ship has ", colony_ship, " colonist";
                                               if ( colony_ship ~= 1 ) print "s";
                                               print " aboard^";
                                       }
                                       input = 'PRINT';
                               'craftsman':
                                       if ( curplayer == 0 ) {
                                               print "Option not available until game begins.^";
                                       }
                                       else {
                                               print "^Goods tokens remaining for production:^^";
                                               i = Corn_goods.remaining();
                                               print "    Corn: ";
                                               if ( i < 10 ) print " ";
                                               print i, " remaining^";
                                               i = Indigo_goods.remaining();
                                               print "  Indigo: ";
                                               if ( i < 10 ) print " ";
                                               print i, " remaining^";
                                               i = Sugar_goods.remaining();
                                               print "   Sugar: ";
                                               if ( i < 10 ) print " ";
                                               print i, " remaining^";
                                               i = Tobacco_goods.remaining();
                                               print " Tobacco: ";
                                               if ( i < 10 ) print " ";
                                               print i, " remaining^";
                                               i = Coffee_goods.remaining();
                                               print "  Coffee: ";
                                               if ( i < 10 ) print " ";
                                               print i, " remaining^";
                                       }
                                       input = 'PRINT';
                               default:
                                       objectloop( i ofclass Building ) {
                                               if ( i.name == parse-->3 ) {
                                                       i.description();
                                                       input = 'PRINT';
                                                       return( input );
                                               }
                                       }
                                       input = 'notUnderstood';
                       }
       }
       return( input );
];

[ PrintHelp;
       print "^Commands at any prompt:^";
       print "  x [Role]    -  Print stats relevant to Role card (Mayor, Settler, etc)^";
       print "  x [bldg]    -  Print Building tile info (sMkt, Haci, CtyH, etc)^";
       print "  p[num]      -  Print Player data (p1, p2, ... p5)^";
       print "  0           -  Cancel or pass turn, when applicable^";
       print "  quit        -  Quit game^";
       print "  ?, help     -  This menu^";
       print "^Type ~pr1~ or ~pr2~ to choose Prospector1 or Prospector2 cards during
               Role selection.^";
       print "^Type ~printvp~ to toggle printing of accumulated VP tokens when
               viewing Player data. (Default is OFF.)^";
];

[ Blort x i;
       objectloop( i in building_supply && i ofclass Wharf ) {
               x = i;
       }
       if ( x ~= 0 ) {
               move x to P1.board;
               x.man(P1);
       }
       objectloop( i in building_supply && i ofclass Wharf ) {
               x = i;
       }
       if ( x ~= 0 ) {
               move x to P2.board;
               x.man(P2);
       }
       objectloop( i in building_supply && i ofclass LargeWarehouse ) {
               x = i;
       }
       if ( x ~= 0 ) {
               move x to P3.board;
               x.manned = 1;
               x.man(P3);
       }
       objectloop( i in building_supply && i ofclass CoffeeRoaster ) {
               x = i;
       }
       if ( x ~= 0 ) {
               move x to P1.board;
               x.manned = 1;
               x.man(P1);
       }
       objectloop( i in building_supply && i ofclass SmallWarehouse ) {
               x = i;
       }
       if ( x ~= 0 ) {
               move x to P3.board;
               x.manned = 1;
               x.man(P3);
       }
       objectloop( i in building_supply && i ofclass SmallWarehouse ) {
               x = i;
       }
       if ( x ~= 0 ) {
               move x to P4.board;
               x.manned = 1;
               x.man(P4);
       }
       x = QuarryTile.create();
       quarry_supply--;
       x.manned = 1;
       move x to P1.board;
       x = QuarryTile.create();
       quarry_supply--;
       x.manned = 1;
       move x to P1.board;
       x = QuarryTile.create();
       quarry_supply--;
       x.manned = 1;
       move x to P1.board;
       x = Corn_goods.create();
       move x to P1.board;
       x = Corn_goods.create();
       move x to P1.board;
       x = Corn_goods.create();
       move x to P2.board;
       x = Corn_goods.create();
       move x to P2.board;
       x = Corn_goods.create();
       move x to P3.board;
       x = Corn_goods.create();
       move x to P3.board;
       x = Corn_goods.create();
       move x to P3.board;
       x = Corn_goods.create();
       move x to P4.board;
       x = Corn_goods.create();
       move x to P5.board;
       x = Indigo_goods.create();
       move x to P1.board;
       x = Indigo_goods.create();
       move x to P2.board;
       x = Indigo_goods.create();
       move x to P3.board;
       x = Indigo_goods.create();
       move x to P4.board;
       x = Indigo_goods.create();
       move x to P5.board;
       x = Indigo_goods.create();
       move x to P5.board;
       x = Sugar_goods.create();
       move x to P1.board;
       x = Sugar_goods.create();
       move x to P2.board;
       x = Sugar_goods.create();
       move x to P3.board;
       x = Sugar_goods.create();
       move x to P3.board;
       x = Sugar_goods.create();
       move x to P3.board;
       x = Sugar_goods.create();
       move x to P4.board;
       x = Sugar_goods.create();
       move x to P5.board;
       x = Tobacco_goods.create();
       move x to P1.board;
       x = Tobacco_goods.create();
       move x to P3.board;
       x = Tobacco_goods.create();
       move x to P4.board;
       x = Tobacco_goods.create();
       move x to P4.board;
       x = Coffee_goods.create();
       move x to P1.board;
       x = Coffee_goods.create();
       move x to P2.board;
       x = Coffee_goods.create();
       move x to P3.board;
       x = Coffee_goods.create();
       move x to P4.board;
       x = Coffee_goods.create();
       move x to P4.board;
       x = Coffee_goods.create();
       move x to P4.board;
       x = Coffee_goods.create();
       move x to P5.board;
       P1.VP = 10;
       P2.VP = 11;
       P3.VP = 12;
       P4.VP = 13;
       P5.VP = 14;
       P1.doubloons = 50;
       P2.doubloons = 12;
       P3.doubloons = 22;
       P4.doubloons = 14;
       P5.doubloons = 39;
       P1.colonists = 11;
       P2.colonists = 15;
       P3.colonists = 12;
       P4.colonists = 9;
       P5.colonists = 4;
       P2.board.plant(CORN);
       P2.board.plant(INDIGO);
       P2.board.plant(INDIGO);
       P2.board.plant(CORN);
       P2.board.plant(SUGAR);
       P2.board.plant(COFFEE);
       P2.board.plant(TOBACCO);
       P2.board.plant(COFFEE);
       P2.board.plant(TOBACCO);
       P2.board.plant(CORN);
];

[ VP_cheat i;
       if ( P1 has vp_flag ) {
               for ( i=0 : i < num_players : i++ ) {
                       switch( i+1 ) {
                               1: give P1 ~vp_flag;
                               2: give P2 ~vp_flag;
                               3: give P3 ~vp_flag;
                               4: give P4 ~vp_flag;
                               5: give P5 ~vp_flag;
                       }
               }
               print "^VP printing now OFF.^";
               rtrue;
       }
       for ( i=0 : i < num_players : i++ ) {
               switch( i+1 ) {
                       1: give P1 vp_flag;
                       2: give P2 vp_flag;
                       3: give P3 vp_flag;
                       4: give P4 vp_flag;
                       5: give P5 vp_flag;
               }
       }
       print "^VP printing now ON.^";
       rtrue;
];

[ Fleeb;
       SetPlantationTiles();
       PrintPlantationSupply();
       PrintPlantationStack();
       new_line;
       rtrue;
];


!EOF