source: branches/AlphaChannel/AI Template/Project/Lib/DiplomacyBase.cs

Last change on this file was 191, checked in by chronos, 5 years ago
  • Added: AI Template directory with manual for development of custom AI from original game.
File size: 10.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using AI;
4
5namespace CevoAILib.Diplomacy
6{
7 interface ITradeItem
8 {
9 int Code { get; }
10 }
11
12 class ItemOfChoice : ITradeItem
13 {
14 public int Code { get { return Protocol.opChoose; } }
15 public ItemOfChoice() { }
16
17 public override string ToString()
18 {
19 return "ItemOfChoice";
20 }
21 }
22
23 class CopyOfMap : ITradeItem
24 {
25 public int Code { get { return Protocol.opMap; } }
26 public CopyOfMap() { }
27
28 public override string ToString()
29 {
30 return "CopyOfMap";
31 }
32 }
33
34 class CopyOfDossier : ITradeItem
35 {
36 public readonly Nation Nation;
37 public readonly int TurnOfReport;
38 public CopyOfDossier(Nation nation) { this.Nation = nation; this.TurnOfReport = 0; } // turn will be set by server
39 public CopyOfDossier(Nation nation, int turnOfReport) { this.Nation = nation; this.TurnOfReport = turnOfReport; }
40 public int Code { get { return Protocol.opCivilReport + (Nation.ID << 16) + TurnOfReport; } }
41
42 public override string ToString()
43 {
44 return string.Format("CopyOfDossier {0}", Nation);
45 }
46 }
47
48 class CopyOfMilitaryReport : ITradeItem
49 {
50 public readonly Nation Nation;
51 public readonly int TurnOfReport;
52 public CopyOfMilitaryReport(Nation nation) { this.Nation = nation; this.TurnOfReport = 0; } // turn will be set by server
53 public CopyOfMilitaryReport(Nation nation, int turnOfReport) { this.Nation = nation; this.TurnOfReport = turnOfReport; }
54 public int Code { get { return Protocol.opMilReport + (Nation.ID << 16) + TurnOfReport; } }
55
56 public override string ToString()
57 {
58 return string.Format("CopyOfMilitaryReport {0}", Nation);
59 }
60 }
61
62 class Payment : ITradeItem
63 {
64 public readonly int Amount;
65 public Payment(int amount) { this.Amount = amount; }
66 public int Code { get { return Protocol.opMoney + Amount; } }
67
68 public override string ToString()
69 {
70 return string.Format("Payment {0}", Amount);
71 }
72 }
73
74 class TeachAdvance : ITradeItem
75 {
76 public readonly Advance Advance;
77 public TeachAdvance(Advance advance) { this.Advance = advance; }
78 public int Code { get { return Protocol.opTech + (int)Advance; } }
79
80 public override string ToString()
81 {
82 return string.Format("TeachAdvance {0}", Advance);
83 }
84 }
85
86 class TeachAllAdvances : ITradeItem
87 {
88 public int Code { get { return Protocol.opAllTech; } }
89 public TeachAllAdvances() { }
90
91 public override string ToString()
92 {
93 return "TeachAllAdvances";
94 }
95 }
96
97 class TeachModel : ITradeItem
98 {
99 public readonly ModelBase Model;
100 readonly int indexInSharedMemory;
101 public TeachModel(Model model) { this.Model = model; indexInSharedMemory = model.IndexInSharedMemory; }
102 public TeachModel(ForeignModel model) { this.Model = model; indexInSharedMemory = model.IndexInNationsSharedMemory; }
103 public int Code { get { return Protocol.opModel + indexInSharedMemory; } }
104
105 public override string ToString()
106 {
107 return string.Format("TeachModel {0}", Model);
108 }
109 }
110
111 class TeachAllModels : ITradeItem
112 {
113 public int Code { get { return Protocol.opAllModel; } }
114 public TeachAllModels() { }
115
116 public override string ToString()
117 {
118 return "TeachAllModels";
119 }
120 }
121
122 class ColonyShipPartLot : ITradeItem
123 {
124 public readonly Building PartType;
125 public readonly int Number;
126 public ColonyShipPartLot(Building partType, int number) { this.PartType = partType; this.Number = number; }
127 public int Code { get { return Protocol.opShipParts + (((int)PartType - (int)Building.ColonyShipComponent) << 16) + Number; } }
128
129 public override string ToString()
130 {
131 return string.Format("{0} x{1}", PartType, Number);
132 }
133 }
134
135 class ChangeRelation : ITradeItem
136 {
137 public readonly Relation NewRelation;
138 public ChangeRelation(Relation newRelation) { this.NewRelation = newRelation; }
139 public int Code { get { return Protocol.opTreaty + (int)NewRelation - 1; } }
140
141 public override string ToString()
142 {
143 return string.Format("ChangeRelation {0}", NewRelation);
144 }
145 }
146
147 interface IStatement
148 {
149 int Command { get; }
150 }
151
152 class Notice : IStatement
153 {
154 public Notice() { }
155 public int Command { get { return Protocol.scDipNotice; } }
156
157 public override string ToString()
158 {
159 return "Notice";
160 }
161 }
162
163 class AcceptTrade : IStatement
164 {
165 public AcceptTrade() { }
166 public int Command { get { return Protocol.scDipAccept; } }
167
168 public override string ToString()
169 {
170 return "AcceptTrade";
171 }
172 }
173
174 class CancelTreaty : IStatement
175 {
176 public CancelTreaty() { }
177 public int Command { get { return Protocol.scDipCancelTreaty; } }
178
179 public override string ToString()
180 {
181 return "CancelTreaty";
182 }
183 }
184
185 class SuggestTrade : IStatement
186 {
187 public int Command { get { return Protocol.scDipOffer; } }
188
189 public readonly ITradeItem[] Offers;
190 public readonly ITradeItem[] Wants;
191
192 public SuggestTrade(ITradeItem[] offers, ITradeItem[] wants)
193 {
194 if (offers == null)
195 this.Offers = new ITradeItem[0];
196 else
197 this.Offers = offers;
198 if (wants == null)
199 this.Wants = new ITradeItem[0];
200 else
201 this.Wants = wants;
202 }
203
204 unsafe public void FillRawStream(int* rawStream)
205 {
206 rawStream[0] = Offers.Length;
207 for (int i = 0; i < Offers.Length; i++)
208 rawStream[2 + i] = Offers[i].Code;
209 rawStream[1] = Wants.Length;
210 for (int i = 0; i < Wants.Length; i++)
211 rawStream[2 + Offers.Length + i] = Wants[i].Code;
212 }
213
214 public override string ToString()
215 {
216 string offerString = "nothing";
217 if (Offers.Length > 0)
218 {
219 offerString = Offers[0].ToString();
220 for (int i = 1; i < Offers.Length; i++)
221 offerString += " + " + Offers[i].ToString();
222 }
223 string wantString = "nothing";
224 if (Wants.Length > 0)
225 {
226 wantString = Wants[0].ToString();
227 for (int i = 1; i < Wants.Length; i++)
228 wantString += " + " + Wants[i].ToString();
229 }
230 return "SuggestTrade " + offerString + " for " + wantString;
231 }
232 }
233
234 class SuggestEnd : SuggestTrade
235 {
236 public SuggestEnd() : base(null, null) { }
237
238 public override string ToString()
239 {
240 return "SuggestEnd";
241 }
242 }
243
244 class Break : IStatement
245 {
246 public Break() { }
247 public int Command { get { return Protocol.scDipBreak; } }
248
249 public override string ToString()
250 {
251 return "Break";
252 }
253 }
254
255 static class StatementFactory
256 {
257 static ITradeItem TradeItemFromCode(AEmpire empire, Nation source, int code)
258 {
259 switch (code & Protocol.opMask)
260 {
261 case Protocol.opChoose: return new ItemOfChoice();
262 case Protocol.opMap: return new CopyOfMap();
263 case Protocol.opCivilReport: return new CopyOfDossier(new Nation(empire, (code >> 16) & 0xFF), code & 0xFFFF);
264 case Protocol.opMilReport: return new CopyOfMilitaryReport(new Nation(empire, (code >> 16) & 0xFF), code & 0xFFFF);
265 case Protocol.opMoney: return new Payment(code & 0xFFFF);
266 case Protocol.opTech: return new TeachAdvance((Advance)(code & 0xFFFF));
267 case Protocol.opAllTech: return new TeachAllAdvances();
268 case Protocol.opAllModel: return new TeachAllModels();
269 case Protocol.opShipParts: return new ColonyShipPartLot((Building)((int)Building.ColonyShipComponent + (code >> 16) & 0xFF), code & 0xFFFF);
270 case Protocol.opTreaty: return new ChangeRelation((Relation)((code & 0xFFFF) + 1));
271
272 case Protocol.opModel:
273 {
274 if (source == empire.Us)
275 return new TeachModel(empire.Models[code & 0xFFFF]);
276 else
277 {
278 foreach (ForeignModel model in empire.ForeignModels)
279 {
280 if (model.Nation == source && model.IndexInNationsSharedMemory == (code & 0xFFFF))
281 return new TeachModel(model);
282 }
283 }
284 throw new Exception("Error in StatementFactory: Foreign model not found!");
285 }
286
287 default: throw new Exception("Error in StatementFactory: Not a valid trade item code!");
288 }
289 }
290
291 unsafe public static IStatement OpponentStatementFromCommand(AEmpire empire, Nation opponent, int command, int* rawStream)
292 {
293 switch (command)
294 {
295 case Protocol.scDipNotice: return new Notice();
296 case Protocol.scDipAccept: return new AcceptTrade();
297 case Protocol.scDipCancelTreaty: return new CancelTreaty();
298 case Protocol.scDipOffer:
299 {
300 if (rawStream[0] + rawStream[1] == 0)
301 return new SuggestEnd();
302 else
303 {
304 ITradeItem[] offers = new ITradeItem[rawStream[0]];
305 if (rawStream[0] > 0)
306 {
307 for (int i = 0; i < rawStream[0]; i++)
308 offers[i] = TradeItemFromCode(empire, opponent, rawStream[2 + i]);
309 }
310 ITradeItem[] wants = new ITradeItem[rawStream[1]];
311 if (rawStream[1] > 0)
312 {
313 for (int i = 0; i < rawStream[1]; i++)
314 wants[i] = TradeItemFromCode(empire, empire.Us, rawStream[2 + rawStream[0] + i]);
315 }
316 return new SuggestTrade(offers, wants);
317 }
318 }
319 case Protocol.scDipBreak: return new Break();
320 default: throw new Exception("Error in StatementFactory: Not a negotiation!");
321 }
322 }
323 }
324
325 struct ExchangeOfStatements
326 {
327 public IStatement OurStatement;
328 public IStatement OpponentResponse;
329
330 public ExchangeOfStatements(IStatement ourStatement, IStatement opponentResponse)
331 {
332 this.OurStatement = ourStatement;
333 this.OpponentResponse = opponentResponse;
334 }
335 }
336
337 sealed class Negotiation
338 {
339 AEmpire theEmpire;
340 public readonly Phase Situation;
341 public readonly Nation Opponent;
342 public readonly List<ExchangeOfStatements> History = new List<ExchangeOfStatements>(); // sorted from new to old, newest at index 0
343 IStatement ourNextStatement;
344 public IStatement OurNextStatement { get { return ourNextStatement; } }
345
346 public Negotiation(AEmpire empire, Phase negotiationSituation, Nation opponent)
347 {
348 this.theEmpire = empire;
349 this.Situation = negotiationSituation;
350 this.Opponent = opponent;
351 }
352
353 unsafe public PlayResult SetOurNextStatement(IStatement statement)
354 {
355 PlayResult result = PlayResult.Success;
356 if (statement is SuggestTrade)
357 {
358 if (((SuggestTrade)statement).Offers.Length > 2 || ((SuggestTrade)statement).Wants.Length > 2)
359 result = new PlayResult(PlayError.RulesViolation);
360
361 // check model owners
362 foreach (ITradeItem offer in ((SuggestTrade)statement).Offers)
363 {
364 if (offer is TeachModel && ((TeachModel)offer).Model.Nation != theEmpire.Us)
365 result = new PlayResult(PlayError.RulesViolation);
366 }
367 foreach (ITradeItem want in ((SuggestTrade)statement).Wants)
368 {
369 if (want is TeachModel && ((TeachModel)want).Model.Nation != Opponent)
370 result = new PlayResult(PlayError.RulesViolation);
371 }
372
373 if (result.OK)
374 {
375 fixed (int* tradeData = new int[14])
376 {
377 ((SuggestTrade)statement).FillRawStream(tradeData);
378 result = theEmpire.TestPlay(statement.Command, 0, tradeData);
379 }
380 }
381 }
382 else
383 result = theEmpire.TestPlay(statement.Command);
384 if (result.OK)
385 ourNextStatement = statement;
386 return result;
387 }
388 }
389}
Note: See TracBrowser for help on using the repository browser.