//// PBEM Human-Human Diplomacy Mod for PBEM and Hotseat games: SLIC code v0.2a // created by: Wouter Snijders (aka Locutus) date: 2002-1-14 // last edited by: Wouter Snijders (aka Locutus) date: 2002-1-14 //// // Description: // As the title suggests, this code should make human-human diplomacy in PBEM // and Hotseat games. It's pretty complicated stuff, so only the Not So Faint Of // Heart will able to understand/edit the code. // // Note to fellow modmakers/SLIC coders: if you want to try to understand this // code (I'm not responsible for any braindamage or anything, don't say I didn't // warn you ;)) skip the user-defined functions until they are actually used in // the EventHandlers and various Messageboxes. Instead, focus on these things // first (but save the 'PBEM_CheckMessages' EventHandler and related functions // for when you're done with the rest of the code). This code is best viewed in // EditPlus or some other editor which displays at least 100-120 characters per // line (but even then it is highly recommended to have word wrap disabled). // // Format of the message that will be sent from one human player to another: // // "Dear {player[3].leader_name}, I, {player[4].leader_name} have a proposal for you. // {type[0]:offer}{proposal[0-5]}{comma[0-4]}{type[1]:offer} {moreOne} // {type[2]:request}{proposal[6-11]}{comma[6-10]}{type[3]:request} {moreTwo} // {type[4]:treaty}{proposal[12-17]}{comma[12-16]}{type[5]:treaty}, to improve our // relationship." //// You can only send 1 message per turn to every player, send more and the whole system is screwed up!!! //// // -> is this true? test it... // Still to be done (in order of precedence): // * test the composition of proposals by humans and the creation of a natural sentence by the code // * allow players to send proposals to an opponent of choice instead of a fixed one // * test if the store/retrieve/delete functions work properly // * make it possible to give treaties arguments (give gold -> how much?) // * implement the realization of treaties (give the gold, form the alliance, etc) //city_t PBEM_menuCity; //army_t PBEM_menuArmy; int_t PBEM_messageSent; // check if a message was already sent this turn (should eventually become array to check for every player combo) int_t PBEM_sender; // who sends the proposal int_t PBEM_receiver; // who receiver the proposal int_t PBEM_proposals[6]; // proposal clauses (proposals can consist of 6 clauses) int_t PBEM_proposalIndex; // proposal currently being processed (needed for sender) int_t PBEM_sentProposals[]; // queue with messages that have been sent (but not yet received) int_t PBEM_sentIndex; // length of message queue //int_t PBEM_goldAmount; // amount of gold to request/offer //int_t PBEM_diploUnit; // unit to request/offer //int_t PBEM_offerCity; // city to offer //int_t PBEM_requestCity; // city to request //int_t PBEM_tributeAmount; // amount of annual tribute to request/offer //int_t PBEM_pwAmount; // amount of PW to request/offer //int_t PBEM_pwtaxAmount; // amount of PW tax to request/offer // Compose a message from choices in interface/message queue and either show it to sender or receiver int_f PBEM_displayProposal(int_t bool) { int_t i; int_t totalCount; // total number of clauses int_t offerCount; // number of offer clauses int_t requestCount; // number of request clauses int_t treatyCount; // number of treaty clauses int_t proposal[18]; // locations of proposal clauses int_t comma[18]; // locations of ',' and 'and' int_t more[2]; // location of ','s and/or 'and's between types int_t type[6]; // locations of type announcements ('I request '...' from you') int_t senderOrReceiver; // should message be shown to sender or receiver? 0 = sender, 1 = receiver senderOrReceiver = bool; // init message by setting id numbers of strings SetString(0, ID_PBEM_MESSAGE_OFFER); SetString(1, ID_PBEM_MESSAGE_REQUEST1); SetString(2, ID_PBEM_MESSAGE_REQUEST2); SetString(3, ID_PBEM_MESSAGE_TREATY1); SetString(4, ID_PBEM_MESSAGE_TREATY2); SetString(5, ID_PBEM_MESSAGE_EMPTY); SetString(6, ID_PBEM_MESSAGE_COMMA); SetString(7, ID_PBEM_MESSAGE_AND); SetString(11, ID_PBEM_MESSAGE_GOLD); SetString(12, ID_PBEM_MESSAGE_OFFER_MAP); SetString(13, ID_PBEM_MESSAGE_ADVANCE); SetString(14, ID_PBEM_MESSAGE_UNIT); SetString(15, ID_PBEM_MESSAGE_OFFER_CITY); SetString(16, ID_PBEM_MESSAGE_TRIBUTE); SetString(17, ID_PBEM_MESSAGE_PW); SetString(18, ID_PBEM_MESSAGE_PW_TAX); SetString(31, ID_PBEM_MESSAGE_GOLD); SetString(32, ID_PBEM_MESSAGE_REQUEST_MAP); SetString(33, ID_PBEM_MESSAGE_ADVANCE); SetString(34, ID_PBEM_MESSAGE_UNIT); SetString(35, ID_PBEM_MESSAGE_REQUEST_CITY); SetString(36, ID_PBEM_MESSAGE_TRIBUTE); SetString(37, ID_PBEM_MESSAGE_PW); SetString(38, ID_PBEM_MESSAGE_PW_TAX); SetString(51, ID_PBEM_MESSAGE_CEASE_FIRE); SetString(52, ID_PBEM_MESSAGE_PEACE_TREATY); SetString(53, ID_PBEM_MESSAGE_TRADE_PACT); SetString(54, ID_PBEM_MESSAGE_RESEARCH_PACT); SetString(55, ID_PBEM_MESSAGE_MILITARY_PACT); SetString(56, ID_PBEM_MESSAGE_POLLUTION_PACT); SetString(57, ID_PBEM_MESSAGE_ALLIANCE); // clear message more[0] = 5; // 5 = ID_PBEM_MESSAGE_EMPTY more[1] = 5; for (i = 0; i < 18; i = i + 1) { proposal[i] = 5; comma[i] = 5; if (i < 6) { type[i] = 5; } } // compose message totalCount = 0; offerCount = 0; requestCount = 0; treatyCount = 0; for (i = 0; i < 6; i = i + 1) { if (PBEM_proposals[i] > 0) { // count total number of clauses totalCount = totalCount + 1; } if (PBEM_proposals[i] > 10 && PBEM_proposals[i] < 30) { // if proposal is offer proposal[i] = PBEM_proposals[i]; // "100 gold" (or city, or map, etc) if (offerCount > 0) { // if not first of this type comma[i - 1] = 7; // "100 gold *and* my map" if (offerCount > 1) { // if there was more than 1 other comma[i - 2] = 6; // "100 gold*,* my map and Bronze Working" } } offerCount = offerCount + 1; // count number of offers } elseif (PBEM_proposals[i] > 30 && PBEM_proposals[i] < 50) { // if proposal is request proposal[i + 6] = PBEM_proposals[i]; // "100 gold" if (requestCount > 0) { // if not first of this type comma[(i - 1) + 6] = 7; // "100 gold *and* your map" if (requestCount > 1) { // if there was more than 1 other comma[(i - 2) + 6] = 6; // "100 gold*,* your map and Bronze Working" } } requestCount = requestCount + 1; // count number of requests } elseif (PBEM_proposals[i] > 50 && PBEM_proposals[i] < 70) { // if proposal is treaty proposal[i + 12] = PBEM_proposals[i]; // "trade pact" if (treatyCount > 0) { // if not first of this type comma[(i - 1) + 12] = 7; // "trade pact *and* research pact" if (treatyCount > 1) { // if there was more than 1 other comma[(i - 2) + 12] = 6; // "trade pact*,* research pact and military pact" } } treatyCount = treatyCount + 1; // count number of treaties } elseif (PBEM_proposals[i] != 0) { Message(g.player, 'PBEM_InvalidMessage_M'); // there is a clause of unknown type: should never happen return 0; } } // finalize message by setting up type announcements if (treatyCount > 0) { // if there are treaties type[4] = 3; // "I wish to forge ..." type[5] = 4; // "... with you" if (requestCount > 0 && offerCount > 0) { // if there are treaties, requests and offers type[0] = 0; // "I offer ..." type[2] = 1; // "I request ..." type[3] = 2; // "... from you" more[0] = 6; // "I offer ...*,* I request ... from you and I wish to forge ... with you" more[1] = 7; // "I offer ..., I request ... from you *and* I wish to forge ... with you" } elseif (requestCount > 0) { // if there are treaties and requests type[2] = 1; // "I request ..." type[3] = 2; // "... from you" more[1] = 7; // "I request ... from you *and* I wish to forge ... with you" } elseif (offerCount > 0) { // if there are treaties and offers type[0] = 0; // "I offer ..." more[0] = 7; // "I offer ... *and* I wish to forge ... with you" } } elseif (requestCount > 0) { // if there are requests but no treaties type[2] = 1; // "I requests ..." type[3] = 2; // "... from you" if (offerCount > 0) { // if there are requests and offers but no treaties type[0] = 0; // "I offer ..." more[0] = 7; // "I offer ... *and* I request ... from you" } } elseif (offerCount > 0) { // if there are offers but no requests or treaties type[0] = 0; // "I offer ..." } else { Message(g.player, 'PBEM_InvalidMessage_M'); // there are no clauses: should never happen return 0; } // display message if (SenderOrReceiver) { Message(g.player, 'PBEM_MessageReceived_M'); } else { Message(g.player, 'PBEM_PreviewMessage_M'); } return 1; } // Send the proposal, i.e. store it in the queue void_f PBEM_sendProposal() { int_t i; PBEM_sentProposals[PBEM_sentIndex] = PBEM_receiver; // store receiver PBEM_sentIndex = PBEM_sentIndex + 1; PBEM_sentProposals[PBEM_sentIndex] = PBEM_sender; // store sender PBEM_sentIndex = PBEM_sentIndex + 1; for (i = 0; i < 6; i = i + 1) { // store all clauses PBEM_sentProposals[PBEM_sentIndex] = PBEM_proposals[i]; PBEM_sentIndex = PBEM_sentIndex + 1; } PBEM_sentProposals[PBEM_sentIndex] = -1; // mark end of proposal list PBEM_sentIndex = PBEM_sentIndex + 1; Message(PBEM_sender, 'PBEM_MessageSent_M'); // notify player that message was sent } // Remove the proposal from the queue after it has been processed void_f PBEM_removeProposal() { int_t i; int_t j; // location in last proposal int_t k; // find start of current proposal i = 0; while (!(PBEM_sentProposals[i] == -1 && PBEM_sentProposals[i + 1] == PBEM_receiver && PBEM_sentProposals[i + 2] == PBEM_sender)) { i = i + 1; // found it when there is a string [..., -1, receiver, sender, ...] } // find start of last proposal j = (PBEM_sentIndex - 2); // initial location in last proposal: last element before final '-1' while (PBEM_sentProposals[j] != -1) { j = j - 1; // found it when there is a '-1' } // if the current proposal is not the last proposal, overwrite current (now obsolete) proposal with last one if (i != j) { // first element to be overwritten is i + 1 because there is no need to overwrite the initial '-1' (which is the i-th element) for (k = 1; k < 8; k = k + 1) { // move: sender, receiver and 6 proposal clauses PBEM_sentProposals[i + k] = PBEM_sentProposals[j + k]; // do the overwrite-twist! } PBEM_sentIndex = j + 1; // resize the queue by cutting off at the start of the last proposal } // finally, simply cutt off the queue can at the start of last proposal PBEM_sentIndex = j + 1; // in reality the queue is still as long as before but the program does not and should not know this (SLIC doesn't have a real delete-from-array operation) } // Execute the proposals agreed upon by both players (i.e. actually give the gold, establish the alliance, etc) void_f PBEM_acceptProposal() { // not yet implemented } // Set up the mod at start of game HandleEvent(BeginTurn) 'PBEM_GameStart' post { int_t count; int_t i; count = 0; // first count the number of human players for (i = 0; i < 32; i = i + 1) { if (IsHumanPlayer(i)) { count = count + 1; } } // if more than one human, activate mod if (count > 1) { Message(g.player, 'PBEM_Activated_M'); } else { // DisableTrigger('PBEM_CityClick'); // DisableTrigger('PBEM_ArmyClick'); } // initialize proposal queue PBEM_sentProposals[0] = -1; // mark beginning of new entry PBEM_sentIndex = 1; // set initial size // do this only once, at the start of the game DisableTrigger('PBEM_GameStart'); } // Retrieve all messages for player from queue HandleEvent(BeginTurn) 'PBEM_CheckMessages' post { int_t next; // keep track of status of next element int_t i; int_t j; j = 0; i = 0; while (i < PBEM_sentIndex) { // cycle through entire queue if (next > 0) { // if proposal has been found if (next == 1 && PBEM_sentProposals[i] == g.player) { // this element is receiver and receiver is current player PBEM_receiver = g.player; // message is intended for this player next = 2; // next element is sender } elseif (next == 1) { // this element is receiver but receiver is not current player next = 0; // next element can be ignored unless it's a new proposal } elseif (next == 2) { // this element is sender PBEM_sender = PBEM_sentProposals[i]; // message comes from this player next = 3; // next element is proposal } elseif (next == 3) { // this element is a clause that is part of a proposal for this player if (PBEM_sentProposals[i] != -1) { // if not end of proposal PBEM_proposals[j] = PBEM_sentProposals[i]; // story clause (j is # of clause) j = j + 1; } else { // end of proposal, send it to player next = 1; // next element is receiver j = 0; // reset clauses for next proposal PBEM_displayProposal(PBEM_Sender, PBEM_Receiver, 1); } } } elseif (PBEM_sentProposals[i] == -1) { // if start of new proposal is found next = 1; // next element is receiver } i = i + 1; } PBEM_messageSent = 0; // you can send new messages again } // Enforce cease-fire between players as soon as they meet (to ensure consistency in the treaties elsewhere) HandleEvent(ContactMade) 'PBEM_EnforceCeaseFire' post { if (IsHumanPlayer(player[0]) && IsHumanPlayer(player[1])) { // can this be removed? does it affect AI-Human relationships in any way? // enforce cease fire // not yet implemented } } Trigger 'PBEM_test' on "ControlPanelWindow.ControlPanel.ShortcutPad.DiplomacyButton" when (1) { PBEM_sender = g.player; // current human player is sender PBEM_receiver = g.player + 1; // for now, simply send to next player player[3] = PBEM_receiver; // needed for message text player[4] = PBEM_sender; // needed for message text Message(g.player, 'PBEM_Start_M'); // start negotiations } // Display city menu on click. //HandleEvent(CityClicked) 'PBEM_CityClick' post { // if (city[0].owner != g.player) { // PBEM_menuCity = city[0]; // PBEM_opponent = PBEM_menuCity.owner; // Message(g.player, 'PBEM_CityMenu'); // } //} // Display army menu on click. //HandleEvent(ArmyClicked) 'PBEM_ArmyClick' post { // if (army[0].owner != g.player) { // PBEM_menuArmy = army[0]; // PBEM_opponent = PBEM_menuArmy.owner; // Message(g.player, 'PBEM_ArmyMenu'); // } //} // Message that indicates the mod has been activated Messagebox 'PBEM_Activated_M' { Show(); Title(ID_PBEM_ACTIVATED_TITLE); Text(ID_PBEM_ACTIVATED); Button(ID_PBEM_CLOSE_BUTTON) { // start playing? Kill(); } } // Menu displayed when a foreign city is clicked. //Messagebox 'PBEM_CityMenu' { // player[3] = PBEM_opponent; // Show(); // Title(ID_PBEM_CITY_MENU_TITLE); // Text(ID_PBEM_CITY_MENU); // Button(ID_PBEM_DIPLOMACY_BUTTON) { // Kill(); // if (IsHumanPlayer(PBEM_opponent)) { // Message(g.player, 'PBEM_Start_M'); // } else { // OpenDiplomacy(); // } // } // Wonder //} // take into account 'greatness' of city (based on size, happiness, wealth) and nation (ranks). // Menu displayed when a foreign army is clicked. //Messagebox 'PBEM_ArmyMenu' { // player[3] = PBEM_opponent; // Show(); // Title(ID_PBEM_ARMY_MENU_TITLE); // Text(ID_PBEM_ARMY_MENU); // Button(ID_PBEM_DIPLOMACY_BUTTON) { // if (IsHumanPlayer(PBEM_opponent)) { // Message(g.player, 'PBEM_Start_M'); // } else { // OpenDiplomacy(); // } // } // Button(ID_PBEM_LIBRARY_BUTTON) { // Kill(); // LibraryUnit(); // } //} // Start of Human-Human diplomacy interface, initialize stuff Messagebox 'PBEM_Start_M' { int_t i; player[3] = PBEM_receiver; // needed for message text PBEM_proposalIndex = 0; // first clause for (i = 0; i < 6; i = i + 1) { PBEM_proposals[i] = 0; // reset all clauses } Show(); Title(ID_PBEM_START_TITLE); Text(ID_PBEM_START); Button(ID_PBEM_NEXT_BUTTON) { // start actual negotiation? Kill(); Message(g.player, 'PBEM_Proposal_M'); } } // Choose the type of proposal that should be made: treaty, offer, request Messagebox 'PBEM_Proposal_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_PROPOSAL_TITLE); Text(ID_PBEM_PROPOSAL); Button(ID_PBEM_TREATY_BUTTON) { // suggest a treaty to opponent? Kill(); Message(g.player, 'PBEM_Treaty_M'); } Button(ID_PBEM_OFFER_BUTTON) { // offer something to opponent? Kill(); Message(g.player, 'PBEM_Offer1_M'); } Button(ID_PBEM_REQUEST_BUTTON) { // request something from opponent? Kill(); Message(g.player, 'PBEM_Request1_M'); } } // Send message now or add more clauses (if possible)? Messagebox 'PBEM_NextProposal_M' { player[3] = PBEM_receiver; // needed for message text Show(); if (PBEM_proposalIndex < 6) { // if more clauses can be added Title(ID_PBEM_NEXT_TITLE); Text(ID_PBEM_NEXT); // want more? } else { Title(ID_PBEM_FINAL_TITLE); Text(ID_PBEM_FINAL); // limit was reached } Button(ID_PBEM_VIEW_BUTTON) { // preview the message as it will be sent? Kill(); PBEM_displayProposal(0); } Button(ID_PBEM_SEND_BUTTON) { // send the message? Kill(); PBEM_sendProposal(); } if (PBEM_proposalIndex < 6) { // if more clauses can be added Button(ID_PBEM_ADD_BUTTON) { // add extra clause? PBEM_proposalIndex = PBEM_proposalIndex + 1; // init next clause Kill(); Message(g.player, 'PBEM_Proposal_M'); } } } // Choose what to treaty to suggest to opponent Messagebox 'PBEM_Treaty_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_TREATY_TITLE); Text(ID_PBEM_TREATY); if (!HasAgreement(PBEM_sender, PBEM_receiver, 32)) { // if no cease-fire exists between players Button(ID_PBEM_CEASE_FIRE_BUTTON) { // suggest cease-fire? Kill(); PBEM_proposals[PBEM_proposalIndex] = 51; Message(g.player, 'PBEM_NextProposal_M'); } } else { if (!HasAgreement(PBEM_sender, PBEM_receiver, 33)) { // if players aren't at peace with each other Button(ID_PBEM_PEACE_TREATY_BUTTON) { // suggest peace treaty? Kill(); PBEM_proposals[PBEM_proposalIndex] = 52; Message(g.player, 'PBEM_NextProposal_M'); } } else { // if peace treaty exists, more options become available if (!HasAgreement(PBEM_sender, PBEM_receiver, 34)) { // if players don't have trade pact with each other Button(ID_PBEM_TRADE_PACT_BUTTON) { Kill(); PBEM_proposals[PBEM_proposalIndex] = 53; Message(g.player, 'PBEM_NextProposal_M'); } } if (!HasAgreement(PBEM_sender, PBEM_receiver, 35)) { // if players don't have research pact with each other Button(ID_PBEM_RESEARCH_PACT_BUTTON) { Kill(); PBEM_proposals[PBEM_proposalIndex] = 54; Message(g.player, 'PBEM_NextProposal_M'); } } if (!HasAgreement(PBEM_sender, PBEM_receiver, 36)) { // if players don't have military pact with each other Button(ID_PBEM_MILITARY_PACT_BUTTON) { Kill(); PBEM_proposals[PBEM_proposalIndex] = 55; Message(g.player, 'PBEM_NextProposal_M'); } } // modern age requirement for pollution pack not yet implemented if (!HasAgreement(PBEM_sender, PBEM_receiver, 37)) { // if players don't have military pact with each other // Button(ID_PBEM_POLLUTION_PACT_BUTTON) { // Kill(); // PBEM_proposals[PBEM_proposalIndex] = 56; // Message(g.player, 'PBEM_NextProposal'); // } } // embassy requirement for alliance not yet implemented if (!HasAgreement(PBEM_sender, PBEM_receiver, 38)) { // if players aren't allies with each other Button(ID_PBEM_ALLIANCE_BUTTON) { Kill(); PBEM_proposals[PBEM_proposalIndex] = 57; Message(g.player, 'PBEM_NextProposal_M'); } } // bug: if all 5 post-peace treaties are allowed, there are 5 treaties for 4 buttons (pollution disabled to temporarily fix it) } } } // Choose what to offer to opponent (1) Messagebox 'PBEM_Offer1_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_OFFER_TITLE); Text(ID_PBEM_OFFER); Button(ID_PBEM_GOLD_BUTTON) { // offer gold? Kill(); PBEM_proposals[PBEM_proposalIndex] = 11; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_MAP_BUTTON) { // offer map? Kill(); PBEM_proposals[PBEM_proposalIndex] = 12; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_ADVANCE_BUTTON) { // offer advance? Kill(); PBEM_proposals[PBEM_proposalIndex] = 13; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_NEXT_BUTTON) { // show next set of choices? Kill(); Message(g.player, 'PBEM_Offer2_M'); } } // Choose what to offer to opponent (2) Messagebox 'PBEM_Offer2_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_OFFER_TITLE); Text(ID_PBEM_OFFER); Button(ID_PBEM_UNIT_BUTTON) { // offer unit? Kill(); PBEM_proposals[PBEM_proposalIndex] = 14; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_CITY_BUTTON) { // offer city? Kill(); PBEM_proposals[PBEM_proposalIndex] = 15; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_TRIBUTE_BUTTON) { // offer annual tribute? Kill(); PBEM_proposals[PBEM_proposalIndex] = 16; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_NEXT_BUTTON) { // show next set of choices? Kill(); Message(g.player, 'PBEM_Offer3_M'); } } // Choose what to offer to opponent (3) Messagebox 'PBEM_Offer3_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_OFFER_TITLE); Text(ID_PBEM_OFFER); Button(ID_PBEM_PW_BUTTON) { // offer pw? Kill(); PBEM_proposals[PBEM_proposalIndex] = 17; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_PW_TAX_BUTTON) { // offer annual pw tax? Kill(); PBEM_proposals[PBEM_proposalIndex] = 18; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_NEXT_BUTTON) { // show first set of choices again? Kill(); Message(g.player, 'PBEM_Offer1_M'); } } // Choose what to request from opponent (1) Messagebox 'PBEM_Request1_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_REQUEST_TITLE); Text(ID_PBEM_REQUEST); Button(ID_PBEM_GOLD_BUTTON) { // request gold? Kill(); PBEM_proposals[PBEM_proposalIndex] = 31; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_MAP_BUTTON) { // request map? Kill(); PBEM_proposals[PBEM_proposalIndex] = 32; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_ADVANCE_BUTTON) { // request advance? Kill(); PBEM_proposals[PBEM_proposalIndex] = 33; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_NEXT_BUTTON) { // show next set of choices? Kill(); Message(g.player, 'PBEM_Request2_M'); } } // Choose what to request from opponent (2) Messagebox 'PBEM_Request2_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_REQUEST_TITLE); Text(ID_PBEM_REQUEST); Button(ID_PBEM_UNIT_BUTTON) { // request unit? Kill(); PBEM_proposals[PBEM_proposalIndex] = 34; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_CITY_BUTTON) { // request city? Kill(); PBEM_proposals[PBEM_proposalIndex] = 35; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_TRIBUTE_BUTTON) { // request tribute? Kill(); PBEM_proposals[PBEM_proposalIndex] = 36; Message(g.player, 'PBEM_NextProposal_M'); } Button(ID_PBEM_NEXT_BUTTON) { // show next set of choices? Kill(); Message(g.player, 'PBEM_Request3_M'); } } // Choose what to request from opponent (3) Messagebox 'PBEM_Request3_M' { player[3] = PBEM_receiver; // needed for message text Show(); Title(ID_PBEM_REQUEST_TITLE); Text(ID_PBEM_REQUEST); Button(ID_PBEM_PW_BUTTON) { // request pw? Kill(); PBEM_proposals[PBEM_proposalIndex] = 37; Message(g.player, 'PBEM_NextProposal'); } Button(ID_PBEM_PW_TAX_BUTTON) { // request annual pw tax? Kill(); PBEM_proposals[PBEM_proposalIndex] = 38; Message(g.player, 'PBEM_NextProposal'); } Button(ID_PBEM_NEXT_BUTTON) { // show first set of choices again? Kill(); Message(g.player, 'PBEM_Request1_M'); } } // Error: somehow an invalid message was composed (should never happen) Alertbox 'PBEM_InvalidProposal_M' { player[3] = PBEM_receiver; // needed for message text Show(); Text(ID_PBEM_INVALID); Button(ID_PBEM_CLOSE_BUTTON) { Kill(); } } // Notify the sender that the message was sent Alertbox 'PBEM_MessageSent_M' { player[3] = PBEM_receiver; // needed for message text Show(); Text(ID_PBEM_MESSAGE_SENT); Button(ID_PBEM_CLOSE_BUTTON) { Kill(); } } // This is the preview message the sender gets to see Messagebox 'PBEM_PreviewMessage_M' { player[3] = PBEM_receiver; // needed for message text player[4] = PBEM_sender; // needed for message text Show(); Title(ID_PBEM_PREVIEW_MESSAGE_TITLE); Text(ID_PBEM_MESSAGE); Button(ID_PBEM_BACK_BUTTON) { // go back? Kill(); Message(g.player, 'PBEM_NextProposal_M'); } } // This is the actual message that the receiver gets Messagebox 'PBEM_MessageReceived_M' { player[3] = PBEM_receiver; // needed for message text player[4] = PBEM_sender; // needed for message text Show(); Title(ID_PBEM_MESSAGE_TITLE); Text(ID_PBEM_MESSAGE); Button(ID_PBEM_ACCEPT_BUTTON) { // accept the proposal? // PBEM_acceptProposal(); // PBEM_removeProposal(); Kill(); } Button(ID_PBEM_REJECT_BUTTON) { // reject the proposal? Message(PBEM_sender, 'PBEM_Rejected_M'); // PBEM_removeProposal(); Kill(); } Button(ID_PBEM_COUNTER_BUTTON) { // counter the proposal? Kill(); } } // bug: the player can simply ignore the message and not answer it; fix: make it an alterbox? // Notify the sender that the proposal was rejected Alertbox 'PBEM_Rejected_M' { player[3] = g.player; // needed for message text Show(); Text(ID_PBEM_PROPOSAL_REJECTED); }