├── EconomySim
├── EconomySim.suo
├── EconomySim
│ ├── Properties
│ │ ├── licenses.licx
│ │ ├── Settings.settings
│ │ ├── Settings.Designer.cs
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── EconomySim.csproj.user
│ ├── Good.cs
│ ├── Program.cs
│ ├── MarketReport.cs
│ ├── Offer.cs
│ ├── Economy.cs
│ ├── TradeBook.cs
│ ├── settings.txt
│ ├── InventoryData.cs
│ ├── Form1.cs
│ ├── History.cs
│ ├── MarketData.cs
│ ├── Agent.cs
│ ├── Form1.resx
│ ├── Form1.Designer.cs
│ ├── Quick.cs
│ ├── EconomySim.csproj
│ ├── Inventory.cs
│ ├── BasicAgent.cs
│ ├── MyEconomy.cs
│ ├── Logic.cs
│ └── Market.cs
└── EconomySim.sln
├── README.md
└── LICENSE
/EconomySim/EconomySim.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vibr8gKiwi/bazaarBot2/HEAD/EconomySim/EconomySim.suo
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Properties/licenses.licx:
--------------------------------------------------------------------------------
1 | DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v13.2, Version=13.2.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a
2 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bazaarBot2
2 | This is a C# port of bazaarBot by @larsiusprime with several modifications to fix issues I think existed. See this discussion for background:
3 |
4 | https://github.com/larsiusprime/bazaarBot/issues/17
5 |
6 |
7 | It should run but is somewhat incomplete compared to the original in its output, json processing, etc. If anyone wants to clean it up you have my thanks.
8 |
9 | Note that I changed the name to EconomySim because I'm always stumbling over the spelling of "bazaar."
10 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/EconomySim.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | publish\
5 |
6 |
7 |
8 |
9 |
10 | en-US
11 | false
12 |
13 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Good.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 |
9 | class Good
10 | {
11 | public String id = ""; //string id of good
12 | public double size = 1.0; //inventory size taken up
13 |
14 | public Good (String id_, double size_)
15 | {
16 | id = id_;
17 | size = size_;
18 | }
19 |
20 | public Good copy()
21 | {
22 | return new Good(id, size);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace EconomySim
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.EnableVisualStyles();
17 | Application.SetCompatibleTextRenderingDefault(false);
18 | Application.Run(new Form1());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/MarketReport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace EconomySim
8 | {
9 | class MarketReport
10 | {
11 | public String strListGood = "";
12 | public String strListGoodPrices= "";
13 | public String strListGoodTrades = "";
14 | public String strListGoodAsks = "";
15 | public String strListGoodBids = "";
16 |
17 | public String strListAgent = "";
18 | public String strListAgentCount = "";
19 | public String strListAgentMoney = "";
20 | public String strListAgentProfit = "";
21 |
22 | public List arrStrListInventory { get; set; }
23 |
24 |
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Offer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | class Offer
9 | {
10 | public String good; //the thing offered
11 | public double units; //how many units
12 | public double unit_price; //price per unit
13 | public int agent_id; //who offered this
14 |
15 | public Offer(int agent_id_=-1,String commodity_="",double units_=1.0,double unit_price_=1.0)
16 | {
17 | agent_id = agent_id_;
18 | good = commodity_;
19 | units = units_;
20 | unit_price = unit_price_;
21 | }
22 |
23 | public String toString()
24 | {
25 | return "("+agent_id + "): " + good + "x " + units + " @ " + unit_price;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EconomySim", "EconomySim\EconomySim.csproj", "{0AF795D6-768F-4E1E-957D-79F7F1F09747}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|x86 = Debug|x86
9 | Release|x86 = Release|x86
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {0AF795D6-768F-4E1E-957D-79F7F1F09747}.Debug|x86.ActiveCfg = Debug|x86
13 | {0AF795D6-768F-4E1E-957D-79F7F1F09747}.Debug|x86.Build.0 = Debug|x86
14 | {0AF795D6-768F-4E1E-957D-79F7F1F09747}.Release|x86.ActiveCfg = Release|x86
15 | {0AF795D6-768F-4E1E-957D-79F7F1F09747}.Release|x86.Build.0 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Economy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | class Economy : ISignalBankrupt
9 | {
10 | private List _markets;
11 |
12 | public Economy()
13 | {
14 | _markets = new List();
15 | }
16 |
17 | public void addMarket(Market m)
18 | {
19 | if (_markets.IndexOf(m) == -1)
20 | {
21 | _markets.Add(m);
22 | }
23 | }
24 |
25 | public Market getMarket(String name)
26 | {
27 | foreach (var m in _markets)
28 | {
29 | if (m.name == name) return m;
30 | }
31 | return null;
32 | }
33 |
34 | public void simulate(int rounds)
35 | {
36 | foreach (var m in _markets)
37 | {
38 | m.simulate(rounds);
39 | }
40 | }
41 |
42 |
43 | public virtual void signalBankrupt(Market m, BasicAgent a)
44 | {
45 | //no implemenation -- provide your own in a subclass
46 | }
47 |
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 David
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace EconomySim.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/TradeBook.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace EconomySim
8 | {
9 | class TradeBook
10 | {
11 | public Dictionary> bids;
12 | public Dictionary> asks;
13 |
14 | public DataTable dbook { get; set; }
15 |
16 | public TradeBook()
17 | {
18 | bids = new Dictionary>();
19 | asks = new Dictionary>();
20 | dbook = new DataTable("Book");
21 | dbook.Columns.Add(new DataColumn("bid"));
22 | dbook.Columns.Add(new DataColumn("ask"));
23 | dbook.Rows.Add(1.0,2.0);
24 | }
25 |
26 | public void register(String name)
27 | {
28 | asks[name] = new List();
29 | bids[name] = new List();
30 | }
31 |
32 | public bool bid(Offer offer)
33 | {
34 | if (!bids.ContainsKey(offer.good))
35 | return false;
36 |
37 | bids[offer.good].Add(offer);
38 | return true;
39 | }
40 |
41 | public bool ask(Offer offer)
42 | {
43 | if (!bids.ContainsKey(offer.good))
44 | return false;
45 |
46 | asks[offer.good].Add(offer);
47 | return true;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("EconomySim")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Hewlett-Packard Company")]
12 | [assembly: AssemblyProduct("EconomySim")]
13 | [assembly: AssemblyCopyright("Copyright © Hewlett-Packard Company 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("5548d7fc-307f-4a48-90ee-6f23cba4adaa")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/settings.txt:
--------------------------------------------------------------------------------
1 | {
2 | "start_conditions":{
3 | "agents":{
4 | "farmer":10,
5 | "miner":10,
6 | "woodcutter":10,
7 | "refiner":10,
8 | "blacksmith":10
9 | }
10 | },
11 | "goods":[
12 | {"id":"food" ,"size":"0.5"},
13 | {"id":"wood" ,"size":"1.0"},
14 | {"id":"ore" ,"size":"1.0"},
15 | {"id":"metal","size":"1.0"},
16 | {"id":"tools","size":"1.0"}
17 | ],
18 | "agents":[
19 | {
20 | "id":"farmer",
21 | "money":100,
22 | "inventory":{
23 | "start":{"food":0,"tools":1,"wood":0},
24 | "ideal":{"food":0,"tools":1,"wood":3},
25 | "max_size":20
26 | },
27 | "logic":"farmer"
28 | },
29 | {
30 | "id":"miner",
31 | "money":100,
32 | "inventory":{
33 | "start":{"food":1,"tools":1,"ore":0},
34 | "ideal":{"food":3,"tools":1,"ore":0},
35 | "max_size":20
36 | },
37 | "logic":"miner"
38 | },
39 | {
40 | "id":"refiner",
41 | "money":100,
42 | "inventory":{
43 | "start":{"food":1,"tools":1,"metal":0,"ore":0},
44 | "ideal":{"food":3,"tools":1,"metal":0,"ore":5},
45 | "max_size":20
46 | },
47 | "logic":"refiner"
48 | },
49 | {
50 | "id":"woodcutter",
51 | "money":100,
52 | "inventory":{
53 | "start":{"food":1,"tools":1,"wood":0},
54 | "ideal":{"food":3,"tools":1,"wood":0},
55 | "max_size":20
56 | },
57 | "logic":"woodcutter"
58 | },
59 | {
60 | "id":"blacksmith",
61 | "money":100,
62 | "inventory":{
63 | "start":{"food":1,"tools":0,"metal":0,"ore":0},
64 | "ideal":{"food":3,"tools":1,"metal":5,"ore":0},
65 | "max_size":20
66 | },
67 | "logic":"blacksmith"
68 | }
69 | ]
70 | }
--------------------------------------------------------------------------------
/EconomySim/EconomySim/InventoryData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 |
9 | /**
10 | */
11 | class InventoryData
12 | {
13 | public double maxSize;
14 | public Dictionary ideal;
15 | public Dictionary start;
16 | public Dictionary size;
17 |
18 | public InventoryData(double maxSize, Dictionaryideal, Dictionarystart, Dictionarysize)
19 | {
20 | this.maxSize = maxSize;
21 | this.ideal = ideal;
22 | this.start = start;
23 | this.size = size;
24 | if (this.size == null)
25 | {
26 | this.size = new Dictionary();
27 | foreach (KeyValuePair entry in start)
28 | {
29 | this.size[entry.Key] = 1;
30 | }
31 | }
32 | }
33 |
34 | public InventoryData(string data)
35 | {
36 | //var maxSize:Int = data.max_size;
37 | //var ideal = new Map();
38 | //var start = new Map();
39 | //var size = new Map();
40 |
41 | //var startArray = Reflect.fields(data.start);
42 | //if (startArray != null)
43 | //{
44 | // for (s in startArray)
45 | // {
46 | // start.set(s, cast Reflect.field(data.start, s));
47 | // size.set(s, 1); //initialize size of every item to 1 by default
48 | // }
49 | //}
50 | //var idealArray = Reflect.fields(data.ideal);
51 | //if (idealArray != null)
52 | //{
53 | // for (i in idealArray)
54 | // {
55 | // ideal.set(i, cast Reflect.field(data.ideal, i));
56 | // }
57 | //}
58 |
59 | //return new InventoryData(maxSize, ideal, start, size);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace EconomySim
11 | {
12 | public partial class Form1 : Form
13 | {
14 |
15 | private Economy economy;
16 | private Market market;
17 | // private MarketDisplay display;
18 | // private TextField txt_benchmark;
19 |
20 | public Form1()
21 | {
22 | InitializeComponent();
23 | }
24 |
25 | private void button1_Click(object sender, EventArgs e)
26 | {
27 | economy = new DoranAndParberryEconomy();
28 |
29 | market = economy.getMarket("default");
30 |
31 | dataGridView1.DataSource = market._agents;
32 | //dataGridView2.DataSource = market._book.dbook;
33 |
34 | }
35 |
36 | private void run(int rounds)
37 | {
38 | market.simulate(rounds);
39 | var res = market.get_marketReport(rounds);
40 | dataGridView1.Refresh();
41 | //dataGridView2.DataSource = res.arrStrListInventory;
42 | textBox1.Clear();
43 | textBox1.Text = res.strListGood.Replace("\n", " ") + Environment.NewLine;
44 | textBox1.Text += res.strListGoodPrices.Replace("\n", " ") + Environment.NewLine;
45 | textBox1.Text += res.strListGoodTrades.Replace("\n", " ") + Environment.NewLine;
46 | textBox1.Text += res.strListGoodBids.Replace("\n", " ") + Environment.NewLine;
47 | textBox1.Text += res.strListGoodAsks.Replace("\n", " ") + Environment.NewLine;
48 | //textBox1.Lines = res.arrStrListInventory.ToArray();
49 | //dataGridView1.DataSource = market._agents;
50 | }
51 |
52 | private void button2_Click(object sender, EventArgs e)
53 | {
54 | run(1);
55 | }
56 |
57 | private void button3_Click(object sender, EventArgs e)
58 | {
59 | run(20);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/History.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | enum EconNoun
9 | {
10 | Price,
11 | Ask,
12 | Bid,
13 | Trade,
14 | Profit
15 | }
16 |
17 | class HistoryLog
18 | {
19 | EconNoun type;
20 | Dictionary>log;
21 |
22 | public HistoryLog(EconNoun type)
23 | {
24 | this.type = type;
25 | log = new Dictionary>();
26 | }
27 |
28 | /**
29 | * Add a new entry to this log
30 | * @param name
31 | * @param amount
32 | */
33 | public void add(String name, double amount)
34 | {
35 | if (log.ContainsKey(name))
36 | {
37 | var list = log[name];
38 | list.Add(amount);
39 | }
40 | }
41 |
42 | /**
43 | * Register a new category list in this log
44 | * @param name
45 | */
46 | public void register(String name)
47 | {
48 | if (!log.ContainsKey(name))
49 | {
50 | log[name] = new List();
51 | }
52 | }
53 |
54 | /**
55 | * Returns the average amount of the given category, looking backwards over a specified range
56 | * @param name the category of thing
57 | * @param range how far to look back
58 | * @return
59 | */
60 | public double average(String name, int range)
61 | {
62 | if (log.ContainsKey(name))
63 | {
64 | var list = log[name];
65 | double amt = 0.0;
66 | var length = list.Count;
67 | if (length < range)
68 | {
69 | range = length;
70 | }
71 | for (int i=0; i goods;
11 | public ListagentTypes;
12 | public List agents;
13 |
14 | public MarketData(Listgoods, ListagentTypes, List agents)
15 | {
16 | this.goods = goods;
17 | this.agentTypes = agentTypes;
18 | this.agents = agents;
19 | }
20 |
21 | /**
22 | * Parse a market settings file to construct everything
23 | * @param data the JSON file definition for your Market
24 | * @param getAgent a function to create agents
25 | */
26 |
27 | public static MarketData fromJSON(string json, BasicAgent getAgent)
28 | {
29 | //var goods:Array = [];
30 |
31 | ////Create goods index
32 | //var jsonGoods:Array = json.goods;
33 | //for (g in jsonGoods)
34 | //{
35 | // goods.push(new Good(g.id, g.size));
36 | //}
37 |
38 | //var agentTypes:Array = [];
39 |
40 | ////Create agent classes
41 | //var jsonAgents:Array = json.agents;
42 |
43 | //for (a in jsonAgents)
44 | //{
45 | // var agentData:AgentData =
46 | // {
47 | // className:a.id,
48 | // money:a.money,
49 | // inventory:InventoryData.fromJson(a.inventory),
50 | // logicName:a.id,
51 | // logic:null
52 | // }
53 |
54 | // for (g in goods)
55 | // {
56 | // agentData.inventory.size.set(g.id, g.size);
57 | // }
58 |
59 | // agentTypes.push(agentData);
60 | //}
61 |
62 | ////Make the agent list
63 | //var agents:Array = [];
64 |
65 | ////Get start conditions
66 | //var startConditions:Dynamic = json.start_conditions;
67 | //var starts = Reflect.fields(startConditions.agents);
68 |
69 | //var agentIndex:Int = 0;
70 | ////Make given number of each agent type
71 |
72 | //for (classStr in starts)
73 | //{
74 | // var val:Int = Reflect.field(startConditions.agents, classStr);
75 | // var agentData = null;
76 | // for (i in 0...agentTypes.length) {
77 | // if (agentTypes[i].className == classStr)
78 | // {
79 | // agentData = agentTypes[i];
80 | // break;
81 | // }
82 | // }
83 |
84 | // for (i in 0...val)
85 | // {
86 | // var a:BasicAgent = getAgent(agentData);
87 | // a.id = agentIndex;
88 | // agentIndex++;
89 | // agents.push(a);
90 | // }
91 | //}
92 |
93 | //return new MarketData(goods, agentTypes, agents);
94 | return null;
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Agent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 |
9 | /**
10 | * An agent that performs the basic logic from the Doran & Parberry article
11 | * @author
12 | */
13 | class Agent : BasicAgent
14 | {
15 |
16 | public static double MIN_PRICE = 0.01; //lowest possible price
17 |
18 | public Agent(int id, AgentData data) : base(id,data)
19 | {
20 | }
21 |
22 |
23 | override public Offer createBid(Market bazaar, String good, double limit)
24 | {
25 | var bidPrice = 0;// determinePriceOf(good); bids are now made "at market", no price determination needed
26 | var ideal = determinePurchaseQuantity(bazaar, good);
27 |
28 | //can't buy more than limit
29 | double quantityToBuy = ideal > limit ? limit : ideal;
30 | if (quantityToBuy > 0)
31 | {
32 | return new Offer(id, good, quantityToBuy, bidPrice);
33 | }
34 | return null;
35 | }
36 |
37 | override public Offer createAsk(Market bazaar, String commodity_, double limit_)
38 | {
39 | var ask_price = _inventory.query_cost(commodity_) * 1.02; //asks are fair prices: costs + small profit
40 |
41 | var quantity_to_sell = _inventory.query(commodity_);//put asks out for all inventory
42 | nProduct = quantity_to_sell;
43 |
44 | if (quantity_to_sell > 0)
45 | {
46 | return new Offer(id, commodity_, quantity_to_sell, ask_price);
47 | }
48 | return null;
49 | }
50 |
51 | override public void generateOffers(Market bazaar, String commodity)
52 | {
53 | Offer offer;
54 | double surplus = _inventory.surplus(commodity);
55 | if (surplus >= 1)
56 | {
57 | offer = createAsk(bazaar, commodity, 1);
58 | if (offer != null)
59 | {
60 | bazaar.ask(offer);
61 | }
62 | }
63 | else
64 | {
65 | var shortage = _inventory.shortage(commodity);
66 | var space = _inventory.getEmptySpace();
67 | var unit_size = _inventory.getCapacityFor(commodity);
68 |
69 | if (shortage > 0 && space >= unit_size)
70 | {
71 | double limit = 0;
72 | if ((shortage * unit_size) <= space) //enough space for ideal order
73 | {
74 | limit = shortage;
75 | }
76 | else //not enough space for ideal order
77 | {
78 | limit = space; // Math.Floor(space / shortage);
79 | }
80 |
81 | if (limit > 0)
82 | {
83 | offer = createBid(bazaar, commodity, limit);
84 | if (offer != null)
85 | {
86 | bazaar.bid(offer);
87 | }
88 | }
89 | }
90 | }
91 | }
92 |
93 | override public void updatePriceModel(Market bazaar, String act, String good, bool success, double unitPrice= 0)
94 | {
95 | List observed_trades;
96 |
97 | if (success)
98 | {
99 | //Add this to my list of observed trades
100 | observed_trades = _observedTradingRange[good];
101 | observed_trades.Add(unitPrice);
102 | }
103 |
104 | var public_mean_price = bazaar.getAverageHistoricalPrice(good, 1);
105 |
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace EconomySim.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EconomySim.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to {
65 | /// "start_conditions":{
66 | /// "agents":{
67 | /// "farmer":10,
68 | /// "miner":10,
69 | /// "woodcutter":10,
70 | /// "refiner":10,
71 | /// "blacksmith":10
72 | /// }
73 | /// },
74 | /// "goods":[
75 | /// {"id":"food" ,"size":"0.5"},
76 | /// {"id":"wood" ,"size":"1.0"},
77 | /// {"id":"ore" ,"size":"1.0"},
78 | /// {"id":"metal","size":"1.0"},
79 | /// {"id":"tools","size":"1.0"}
80 | /// ],
81 | /// "agents":[
82 | /// {
83 | /// "id":"farmer",
84 | /// "money":100,
85 | /// "inventory":{
86 | /// "start":{"food":0,"tools":1,"wood":0},
87 | /// "ideal":{"food":0,"tools":1,"wood":3},
88 | /// "max_size":20
89 | /// },
90 | /// "logi [rest of string was truncated]";.
91 | ///
92 | public static string settings_json {
93 | get {
94 | return ResourceManager.GetString("settings_json", resourceCulture);
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace EconomySim
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.button1 = new System.Windows.Forms.Button();
32 | this.button2 = new System.Windows.Forms.Button();
33 | this.dataGridView1 = new System.Windows.Forms.DataGridView();
34 | this.dataGridView2 = new System.Windows.Forms.DataGridView();
35 | this.textBox1 = new System.Windows.Forms.TextBox();
36 | this.button3 = new System.Windows.Forms.Button();
37 | this.tbLog = new System.Windows.Forms.TextBox();
38 | ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
39 | ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit();
40 | this.SuspendLayout();
41 | //
42 | // button1
43 | //
44 | this.button1.Location = new System.Drawing.Point(12, 23);
45 | this.button1.Name = "button1";
46 | this.button1.Size = new System.Drawing.Size(75, 23);
47 | this.button1.TabIndex = 0;
48 | this.button1.Text = "Init";
49 | this.button1.UseVisualStyleBackColor = true;
50 | this.button1.Click += new System.EventHandler(this.button1_Click);
51 | //
52 | // button2
53 | //
54 | this.button2.Location = new System.Drawing.Point(12, 63);
55 | this.button2.Name = "button2";
56 | this.button2.Size = new System.Drawing.Size(42, 23);
57 | this.button2.TabIndex = 1;
58 | this.button2.Text = "Step";
59 | this.button2.UseVisualStyleBackColor = true;
60 | this.button2.Click += new System.EventHandler(this.button2_Click);
61 | //
62 | // dataGridView1
63 | //
64 | this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
65 | this.dataGridView1.Location = new System.Drawing.Point(0, 123);
66 | this.dataGridView1.Name = "dataGridView1";
67 | this.dataGridView1.Size = new System.Drawing.Size(604, 487);
68 | this.dataGridView1.TabIndex = 3;
69 | //
70 | // dataGridView2
71 | //
72 | this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
73 | this.dataGridView2.Location = new System.Drawing.Point(325, 123);
74 | this.dataGridView2.Name = "dataGridView2";
75 | this.dataGridView2.Size = new System.Drawing.Size(328, 487);
76 | this.dataGridView2.TabIndex = 4;
77 | //
78 | // textBox1
79 | //
80 | this.textBox1.Location = new System.Drawing.Point(130, 23);
81 | this.textBox1.Multiline = true;
82 | this.textBox1.Name = "textBox1";
83 | this.textBox1.Size = new System.Drawing.Size(512, 94);
84 | this.textBox1.TabIndex = 5;
85 | //
86 | // button3
87 | //
88 | this.button3.Location = new System.Drawing.Point(60, 63);
89 | this.button3.Name = "button3";
90 | this.button3.Size = new System.Drawing.Size(64, 23);
91 | this.button3.TabIndex = 6;
92 | this.button3.Text = "Step 20";
93 | this.button3.UseVisualStyleBackColor = true;
94 | this.button3.Click += new System.EventHandler(this.button3_Click);
95 | //
96 | // tbLog
97 | //
98 | this.tbLog.Location = new System.Drawing.Point(0, 616);
99 | this.tbLog.Multiline = true;
100 | this.tbLog.Name = "tbLog";
101 | this.tbLog.Size = new System.Drawing.Size(653, 80);
102 | this.tbLog.TabIndex = 7;
103 | //
104 | // Form1
105 | //
106 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
107 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
108 | this.ClientSize = new System.Drawing.Size(687, 697);
109 | this.Controls.Add(this.tbLog);
110 | this.Controls.Add(this.button3);
111 | this.Controls.Add(this.textBox1);
112 | this.Controls.Add(this.dataGridView1);
113 | this.Controls.Add(this.button2);
114 | this.Controls.Add(this.button1);
115 | this.Controls.Add(this.dataGridView2);
116 | this.Name = "Form1";
117 | this.Text = "Form1";
118 | ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
119 | ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();
120 | this.ResumeLayout(false);
121 | this.PerformLayout();
122 |
123 | }
124 |
125 | #endregion
126 |
127 | private System.Windows.Forms.Button button1;
128 | private System.Windows.Forms.Button button2;
129 | private System.Windows.Forms.DataGridView dataGridView1;
130 | private System.Windows.Forms.DataGridView dataGridView2;
131 | private System.Windows.Forms.TextBox textBox1;
132 | private System.Windows.Forms.Button button3;
133 | private System.Windows.Forms.TextBox tbLog;
134 | }
135 | }
136 |
137 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\settings.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
123 |
124 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Quick.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | class Quick
9 | {
10 | public static Random rnd = new Random();
11 |
12 |
13 | public static double avgf(double a, double b)
14 | {
15 | return (a + b) / 2;
16 | }
17 |
18 | public static double listAvgf(List list)
19 | {
20 | double avg=0;
21 | for (int j = 0; j < list.Count; j++)
22 | {
23 | avg += list[j];
24 | }
25 | avg /= list.Count;
26 | return avg;
27 | }
28 |
29 | public static double minArr(List a, int window)
30 | {
31 | double min = 99999999;//Math.POSITIVE_INFINITY;
32 | if (window > a.Count) window = a.Count;
33 | for (int i = 0; i < window-1; i++)
34 | {
35 | var f = a[a.Count-1 - i];
36 | if (f < min) { min = f; }
37 | }
38 |
39 | return min;
40 | }
41 |
42 | public static double maxArr(List a, int window)
43 | {
44 | double max = -9999999;///Math.NEGATIVE_INFINITY;
45 | if (window > a.Count) window = a.Count;
46 | for (int i = 0; i < window - 1; i++)
47 | {
48 | var f = a[a.Count - 1 - i];
49 | if (f > max) { max = f; }
50 | }
51 | return max;
52 | }
53 |
54 | /**
55 | * Turns a number into a string with the specified number of decimal points
56 | * @param num
57 | * @param decimals
58 | * @return
59 | */
60 | public static String numStr(double num, int decimals)
61 | {
62 | string s = string.Format("{0:N"+decimals.ToString()+"}", num);
63 | return s;
64 | }
65 | // num = Math.floor(num * tens) / tens;
66 | // var str:String = Std.string(num);
67 | // var split = str.split(".");
68 | // if (split.length == 2)
69 | // {
70 | // if (split[1].length < decimals)
71 | // {
72 | // var diff:Int = decimals - split[1].length;
73 | // for (i in 0...diff)
74 | // {
75 | // str += "0";
76 | // }
77 | // }
78 | // if (decimals > 0)
79 | // {
80 | // str = split[0] + "." + split[1].substr(0, decimals);
81 | // }
82 | // else
83 | // {
84 | // str = split[0];
85 | // }
86 | // }
87 | // else
88 | // {
89 | // if (decimals > 0)
90 | // {
91 | // str += ".";
92 | // for (i in 0...decimals)
93 | // {
94 | // str += "0";
95 | // }
96 | // }
97 | // }
98 | // return str;
99 | // }
100 |
101 | public static double positionInRange(double value, double min, double max, bool clamp = true)
102 | {
103 | value -= min;
104 | max -= min;
105 | min = 0;
106 | value = (value / (max - min));
107 | if (clamp) {
108 | if (value < 0) { value = 0; }
109 | if (value > 1) { value = 1; }
110 | }
111 | return value;
112 | }
113 |
114 | // public static inline function randomInteger(min:Int, max:Int):Int
115 | // {
116 | // return Std.int(Math.random() * cast(1 + max - min, Float)) + min;
117 | // }
118 |
119 | public static double randomRange(double a, double b)
120 | {
121 | double r = rnd.NextDouble();
122 | double min = a < b ? a : b;
123 | double max = a < b ? b : a;
124 | double range = max - min;
125 | return r * range + min;
126 | }
127 |
128 | public static List shuffle(Listlist)
129 | {
130 | /*
131 | To shuffle an array a of n elements (indices 0..n-1):
132 | for i from n − 1 downto 1 do
133 | j ← random integer with 0 ≤ j ≤ i
134 | exchange a[j] and a[i]
135 | */
136 | for (int i=0; i 1)
140 | {
141 | int j = rnd.Next(ii);
142 | var temp = list[j];
143 | list[j] = list[ii];
144 | list[ii] = temp;
145 | }
146 | }
147 | return list;
148 | }
149 |
150 | public static int sortAgentAlpha(BasicAgent a, BasicAgent b)
151 | {
152 | return String.Compare(a.className,b.className);
153 | }
154 |
155 | public static int sortAgentId(BasicAgent a, BasicAgent b)
156 | {
157 | if (a.id < b.id) return -1;
158 | if (a.id > b.id) return 1;
159 | return 0;
160 | }
161 |
162 | public static int sortOfferAcending(Offer a, Offer b)
163 | {
164 | if (a.unit_price < b.unit_price) return -1;
165 | if (a.unit_price > b.unit_price) return 1;
166 | return 0;
167 | }
168 | public static int sortOfferDecending(Offer a, Offer b)
169 | {
170 | if (a.unit_price > b.unit_price) return -1;
171 | if (a.unit_price < b.unit_price) return 1;
172 | return 0;
173 | }
174 |
175 |
176 | // public static function sortDecreasingPrice(a:Offer, b:Offer):Int
177 | // {
178 | // //Decreasing means: highest first
179 | // if (a.unit_price < b.unit_price) return 1;
180 | // if (a.unit_price > b.unit_price) return -1;
181 | // return 0;
182 | // }
183 |
184 | // public static function sortIncreasingPrice(a:Offer, b:Offer):Int
185 | // {
186 | // //Increasing means: lowest first
187 | // if (a.unit_price > b.unit_price) return 1;
188 | // if (a.unit_price < b.unit_price) return -1;
189 | // return 0;
190 | // }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/EconomySim.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {0AF795D6-768F-4E1E-957D-79F7F1F09747}
9 | WinExe
10 | Properties
11 | EconomySim
12 | EconomySim
13 | v4.0
14 | Client
15 | 512
16 | publish\
17 | true
18 | Disk
19 | false
20 | Foreground
21 | 7
22 | Days
23 | false
24 | false
25 | true
26 | 0
27 | 1.0.0.%2a
28 | false
29 | false
30 | true
31 |
32 |
33 | x86
34 | true
35 | full
36 | false
37 | bin\Debug\
38 | DEBUG;TRACE
39 | prompt
40 | 4
41 |
42 |
43 | x86
44 | pdbonly
45 | true
46 | bin\Release\
47 | TRACE
48 | prompt
49 | 4
50 |
51 |
52 |
53 | False
54 | ..\..\Json.NET\Newtonsoft.Json.dll
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | Form
73 |
74 |
75 | Form1.cs
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | Form1.cs
93 |
94 |
95 |
96 | PublicResXFileCodeGenerator
97 | Resources.Designer.cs
98 | Designer
99 |
100 |
101 | True
102 | Resources.resx
103 | True
104 |
105 |
106 | SettingsSingleFileGenerator
107 | Settings.Designer.cs
108 |
109 |
110 | True
111 | Settings.settings
112 | True
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | False
121 | Microsoft .NET Framework 4 Client Profile %28x86 and x64%29
122 | true
123 |
124 |
125 | False
126 | .NET Framework 3.5 SP1 Client Profile
127 | false
128 |
129 |
130 | False
131 | .NET Framework 3.5 SP1
132 | false
133 |
134 |
135 | False
136 | Windows Installer 3.1
137 | true
138 |
139 |
140 |
141 |
148 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Inventory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | class Inventory
9 | {
10 | public double maxSize = 0;
11 |
12 | //private static var _index:Map;
13 |
14 | private Dictionary_stuff; // key:commodity_id, val:amount, original_cost
15 | private Dictionary_ideal; // ideal counts for each thing
16 | private Dictionary_sizes; // how much space each thing takes up
17 |
18 |
19 | public Inventory()
20 | {
21 | _sizes = new Dictionary();
22 | _stuff = new Dictionary();
23 | _ideal = new Dictionary();
24 | maxSize = 0;
25 | }
26 |
27 | public void fromData(InventoryData data)
28 | {
29 | var sizes = new List();
30 | var amountsp = new List();
31 | foreach (string key in data.start.Keys)
32 | {
33 | sizes.Add(key);
34 | amountsp.Add(new Point(data.start[key],0));
35 | }
36 | setStuff(sizes, amountsp);
37 | sizes = new List();
38 | var amounts = new List();
39 | foreach (string key in data.size.Keys)
40 | {
41 | sizes.Add(key);
42 | amounts.Add(data.size[key]);
43 | }
44 | setSizes(sizes, amounts);
45 | sizes = new List();
46 | amounts = new List();
47 | foreach (string key in data.ideal.Keys)
48 | {
49 | sizes.Add(key);
50 | amounts.Add(data.ideal[key]);
51 | setIdeal(sizes, amounts);
52 | }
53 | maxSize = data.maxSize;
54 | }
55 |
56 | public Inventory copy()
57 | {
58 | var i = new Inventory();
59 | var stufff = new List();
60 | var stuffi = new List();
61 | var idealf = new List();
62 | var ideali = new List();
63 | var sizesf = new List();
64 | var sizesi = new List();
65 | foreach (string key in _stuff.Keys)
66 | {
67 | stufff.Add(_stuff[key]);
68 | stuffi.Add(key);
69 | }
70 | foreach (string key in _ideal.Keys)
71 | {
72 | idealf.Add(_ideal[key]);
73 | ideali.Add(key);
74 | }
75 | foreach (string key in _sizes.Keys)
76 | {
77 | sizesf.Add(_sizes[key]);
78 | sizesi.Add(key);
79 | }
80 | i.setStuff(stuffi, stufff);
81 | i.setIdeal(ideali, idealf);
82 | i.setSizes(sizesi, sizesf);
83 | i.maxSize = maxSize;
84 | return i;
85 | }
86 |
87 | public void destroy()
88 | {
89 | _stuff.Clear();
90 | _ideal.Clear();
91 | _sizes.Clear();
92 | _stuff = null;
93 | _ideal = null;
94 | _sizes = null;
95 | }
96 |
97 | /**
98 | * Set amounts of various commodities
99 | * @param stuff_
100 | * @param amounts_
101 | */
102 |
103 | public void setStuff(Liststuff, Listamounts)
104 | {
105 | for (int i=0; iideal, Listamounts)
118 | {
119 | for (int i=0; isizes, Listamounts)
126 | {
127 | for(int i=0; i 0)
204 | {
205 | if (amount.x <= 0)
206 | {
207 | result.x = delta;
208 | result.y = unit_cost;
209 | }
210 | else
211 | {
212 | result.y = (amount.x * amount.y + delta * unit_cost) / (amount.x + delta);
213 | result.x = amount.x + delta;
214 | }
215 | }
216 | else
217 | {
218 | result.x = amount.x + delta;
219 | result.y = amount.y; //just copy from old value?
220 | }
221 | }
222 | else
223 | {
224 | result.x = delta;
225 | result.y = unit_cost;
226 | }
227 |
228 | if (result.x < 0)
229 | {
230 | result.x = 0;
231 | result.y = 0;
232 | }
233 |
234 | _stuff[good] = result;
235 | return result.y; //return current unit cost
236 | }
237 |
238 | /**
239 | * Returns # of units above the desired inventory level, or 0 if @ or below
240 | * @param commodity_ string id of commodity
241 | * @return
242 | */
243 |
244 | public double surplus(string good)
245 | {
246 | var amt = query(good);
247 | double ideal = 0;
248 | if (_ideal.ContainsKey(good))
249 | ideal = _ideal[good];
250 | if (amt > ideal)
251 | {
252 | return (amt - ideal);
253 | }
254 | return 0;
255 | }
256 |
257 | /**
258 | * Returns # of units below the desired inventory level, or 0 if @ or above
259 | * @param commodity_
260 | * @return
261 | */
262 |
263 | public double shortage(string good)
264 | {
265 | if (!_stuff.ContainsKey(good))
266 | {
267 | return 0;
268 | }
269 | var amt = query(good);
270 | double ideal = 0;
271 | if (_ideal.ContainsKey(good))
272 | ideal = _ideal[good];
273 | if (amt < ideal)
274 | {
275 | return (ideal - amt);
276 | }
277 | return 0;
278 | }
279 |
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/BasicAgent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | /**
9 | * The most fundamental agent class, and has as little implementation as possible.
10 | * In most cases you should start by extending Agent instead of this.
11 | * @author larsiusprime
12 | */
13 |
14 | class AgentData {
15 | public string className { get; set;}
16 | public double money;
17 | public InventoryData inventory;
18 | public string logicName;
19 | public Logic logic;
20 | public int? lookBack;
21 |
22 | public AgentData(string className, double money, string logicName)
23 | {
24 | this.className = className;
25 | this.money = money;
26 | this.logicName = logicName;
27 | }
28 |
29 | }
30 |
31 | class Point
32 | {
33 | public double x;
34 | public double y;
35 | public Point(double x,double y)
36 | {
37 | this.x = x;
38 | this.y = y;
39 | }
40 | }
41 |
42 |
43 | class BasicAgent
44 | {
45 | public int id; //unique integer identifier
46 | public string className { get; set; } //string identifier, "famer", "woodcutter", etc.
47 | public double money { get; set; }
48 | public double Space { get { return _inventory.getEmptySpace(); } }
49 | public double nProduct { get; set; }
50 |
51 | //public var moneyLastRound(default, null):double;
52 | //public var profit(get, null):double;
53 | //public var inventorySpace(get, null):double;
54 | //public var inventoryFull(get, null):Bool;
55 | //public var destroyed(default, null):Bool;
56 | public bool destroyed; //dfs stub needed?
57 | public double moneyLastRound; //dfs stub needed?
58 | public double profit; //dfs stub needed?
59 |
60 | public double trackcosts;
61 |
62 | /********PRIVATE************/
63 |
64 | private Logic _logic;
65 | protected Inventory _inventory;
66 | protected Dictionary> _observedTradingRange;
67 | private double _profit = 0; //profit from last round
68 | private int _lookback = 15;
69 |
70 |
71 | public BasicAgent(int id, AgentData data)
72 | {
73 | this.id = id;
74 | className = data.className;
75 | money = data.money;
76 | _inventory = new Inventory();
77 | _inventory.fromData(data.inventory);
78 | _logic = data.logic;
79 |
80 | if (data.lookBack == null)
81 | {
82 | _lookback = 15;
83 | }
84 | else
85 | {
86 | _lookback = (int)data.lookBack;
87 | }
88 |
89 | _observedTradingRange = new Dictionary>();
90 |
91 | trackcosts = 0;
92 | }
93 |
94 | public void destroy()
95 | {
96 | destroyed = true;
97 | _inventory.destroy();
98 | foreach (string key in _observedTradingRange.Keys)
99 | {
100 | var list = _observedTradingRange[key];
101 | list.Clear();
102 | }
103 | _observedTradingRange.Clear();
104 | _observedTradingRange = null;
105 | _logic = null;
106 | }
107 |
108 | public void init(Market market)
109 | {
110 | var listGoods = market.getGoods_unsafe();//List
111 | foreach (string str in listGoods)
112 | {
113 | var trades = new List();
114 |
115 | var price = 2;// market.getAverageHistoricalPrice(str, _lookback);
116 | trades.Add(price * 1.0);
117 | trades.Add(price * 3.0); //push two fake trades to generate a range
118 |
119 | //set initial price belief & observed trading range
120 | _observedTradingRange[str]=trades;
121 | }
122 | }
123 |
124 | public void simulate(Market market)
125 | {
126 | _logic.perform(this, market);
127 | }
128 |
129 | public virtual void generateOffers(Market bazaar, string good)
130 | {
131 | //no implemenation -- provide your own in a subclass
132 | }
133 |
134 | public virtual void updatePriceModel(Market bazaar, String act, String good, bool success, double unitPrice = 0)
135 | {
136 | //no implementation -- provide your own in a subclass
137 | }
138 |
139 | public virtual Offer createBid(Market bazaar, String good, double limit)
140 | {
141 | //no implementation -- provide your own in a subclass
142 | return null;
143 | }
144 |
145 | public virtual Offer createAsk(Market bazaar, String commodity_, double limit_)
146 | {
147 | //no implementation -- provide your own in a subclass
148 | return null;
149 | }
150 |
151 | public double queryInventory(String good)
152 | {
153 | return _inventory.query(good);
154 | }
155 |
156 | public void produceInventory(String good, double delta)
157 | {
158 | if (trackcosts < 1) trackcosts = 1;
159 | double curunitcost = _inventory.change(good, delta, trackcosts / delta);
160 | trackcosts = 0;
161 | }
162 |
163 | public void consumeInventory(String good, double delta)
164 | {
165 | if (good == "money")
166 | {
167 | money += delta;
168 | if (delta < 0)
169 | trackcosts += (-delta);
170 | }
171 | else
172 | {
173 | double curunitcost = _inventory.change(good, delta, 0);
174 | if (delta < 0)
175 | trackcosts += (-delta) * curunitcost;
176 | }
177 | }
178 |
179 | public void changeInventory(String good, double delta, double unit_cost)
180 | {
181 | if (good == "money")
182 | {
183 | money += delta;
184 | }
185 | else
186 | {
187 | _inventory.change(good, delta, unit_cost);
188 | }
189 | }
190 |
191 | /********PRIVATE************/
192 |
193 |
194 | private double get_inventorySpace()
195 | {
196 | return _inventory.getEmptySpace();
197 | }
198 |
199 | public bool get_inventoryFull()
200 | {
201 | return _inventory.getEmptySpace() == 0;
202 | }
203 |
204 | public double get_profit()
205 | {
206 | return money - moneyLastRound;
207 | }
208 |
209 | protected double determineSaleQuantity(Market bazaar, String commodity_)
210 | {
211 | var mean = bazaar.getAverageHistoricalPrice(commodity_,_lookback); //double
212 | var trading_range = observeTradingRange(commodity_,10);//point
213 | if (trading_range != null && mean>0)
214 | {
215 | var favorability= Quick.positionInRange(mean, trading_range.x, trading_range.y);//double
216 | //position_in_range: high means price is at a high point
217 |
218 | double amount_to_sell = Math.Round(favorability * _inventory.surplus(commodity_)); //double
219 | amount_to_sell = _inventory.query(commodity_);
220 | if (amount_to_sell < 1)
221 | {
222 | amount_to_sell = 1;
223 | }
224 | return amount_to_sell;
225 | }
226 | return 0;
227 | }
228 |
229 | protected double determinePurchaseQuantity(Market bazaar, String commodity_)
230 | {
231 | var mean = bazaar.getAverageHistoricalPrice(commodity_,_lookback);//double
232 | var trading_range = observeTradingRange(commodity_,10); //Point
233 | if (trading_range != null)
234 | {
235 | var favorability = Quick.positionInRange(mean, trading_range.x, trading_range.y);//double
236 | favorability = 1 - favorability;
237 | //do 1 - favorability to see how close we are to the low end
238 |
239 | double amount_to_buy = Math.Round(favorability * _inventory.shortage(commodity_));//double
240 | if (amount_to_buy < 1)
241 | {
242 | amount_to_buy = 1;
243 | }
244 | return amount_to_buy;
245 | }
246 | return 0;
247 | }
248 |
249 | private Point observeTradingRange(String good, int window)
250 | {
251 | var a = _observedTradingRange[good]; //List
252 | var pt = new Point(Quick.minArr(a,window), Quick.maxArr(a,window));
253 | return pt;
254 | }
255 | }
256 |
257 | }
258 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/MyEconomy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.IO;
6 | using System.Reflection;
7 | using Newtonsoft.Json;
8 |
9 | namespace EconomySim
10 | {
11 | class DoranAndParberryEconomy : Economy
12 | {
13 |
14 | public DoranAndParberryEconomy()
15 | {
16 | var market = new Market("default",this);
17 |
18 | MarketData data = GetMarketData();
19 | market.init(data); // market.init(MarketData.fromJSON(Json.parse(Assets.getText("assets/settings.json")), getAgent));
20 | addMarket(market);
21 | }
22 |
23 | private MarketData GetMarketData()
24 | {
25 | List goods = new List();
26 | ListagentTypes = new List();
27 | List agents = new List();
28 |
29 | goods.Add(new Good("food", 0.5));
30 | goods.Add(new Good("wood", 1.0));
31 | goods.Add(new Good("ore", 1.0));
32 | goods.Add(new Good("metal", 1.0));
33 | goods.Add(new Good("tools", 1.0));
34 | goods.Add(new Good("work", 0.1));
35 |
36 | agentTypes.Add(new AgentData("farmer",100,"farmer"));
37 | agentTypes.Add(new AgentData("miner",100,"miner"));
38 | agentTypes.Add(new AgentData("refiner",100,"refiner"));
39 | agentTypes.Add(new AgentData("woodcutter",100,"woodcutter"));
40 | agentTypes.Add(new AgentData("blacksmith", 100, "blacksmith"));
41 | agentTypes.Add(new AgentData("worker", 10, "worker"));
42 |
43 | InventoryData ii;
44 | ii = new InventoryData(20, //farmer
45 | new Dictionary{{"food",0},{"tools",1},{"wood",3},{"work",3}},
46 | new Dictionary{{"food",1},{"tools",1},{"wood",0},{"work",0}},
47 | null
48 | );
49 | agentTypes[0].inventory = ii;
50 | ii = new InventoryData(20, //miner
51 | new Dictionary { { "food", 3 }, { "tools", 1 }, { "ore", 0 } },
52 | new Dictionary { { "food", 1 }, { "tools", 1 }, { "ore", 0 } },
53 | null
54 | );
55 | agentTypes[1].inventory = ii;
56 | ii = new InventoryData(20, //refiner
57 | new Dictionary { { "food", 3 }, { "tools", 1 }, { "ore", 5 } },
58 | new Dictionary { { "food", 1 }, { "tools", 1 }, { "ore", 0 } },
59 | null
60 | );
61 | agentTypes[2].inventory = ii;
62 | ii = new InventoryData(20, //woodcutter
63 | new Dictionary { { "food", 3 }, { "tools", 1 }, { "wood", 0 } },
64 | new Dictionary { { "food", 1 }, { "tools", 1 }, { "wood", 0 } },
65 | null
66 | );
67 | agentTypes[3].inventory = ii;
68 | ii = new InventoryData(20, //blacksmith
69 | new Dictionary { { "food", 3 }, { "tools", 1 }, { "metal", 5 }, { "ore", 0 } },
70 | new Dictionary { { "food", 1 }, { "tools", 0 }, { "metal", 0 }, { "ore", 0 } },
71 | null
72 | );
73 | agentTypes[4].inventory = ii;
74 | ii = new InventoryData(20, //worker
75 | new Dictionary { { "food", 3 } },
76 | new Dictionary { { "food", 1 } },
77 | null
78 | );
79 | agentTypes[5].inventory = ii;
80 |
81 |
82 | int idc = 0;
83 | for (int iagent = 0; iagent < agentTypes.Count; iagent++)
84 | {
85 | for (int i = 0; i < 5; i++)
86 | {
87 | agents.Add(getAgent(agentTypes[iagent]));
88 | agents[agents.Count - 1].id = idc++;
89 | }
90 | }
91 |
92 |
93 | MarketData data = new MarketData(goods, agentTypes, agents);
94 |
95 | return data;
96 |
97 | //var assembly = Assembly.GetExecutingAssembly();
98 | //var resourceName = "EconomySim.settings.txt";
99 |
100 | //string[] names = assembly.GetManifestResourceNames();
101 |
102 |
103 | //using (Stream stream = assembly.GetManifestResourceStream(resourceName))
104 | //using (StreamReader reader = new StreamReader(stream))
105 | //{
106 | // string result = reader.ReadToEnd();
107 | // MarketData data = JsonConvert.DeserializeObject(result);
108 | // return data;
109 | //}
110 | //return null;
111 | }
112 |
113 |
114 | public override void signalBankrupt(Market m, BasicAgent a)
115 | {
116 | replaceAgent(m, a);
117 | }
118 |
119 | private void replaceAgent(Market market, BasicAgent agent)
120 | {
121 | var bestClass = market.getMostProfitableAgentClass();
122 |
123 | //Special case to deal with very high demand-to-supply ratios
124 | //This will make them favor entering an underserved market over
125 | //Just picking the most profitable class
126 | var bestGood = market.getHottestGood();
127 |
128 | if (bestGood != "")
129 | {
130 | var bestGoodClass = getAgentClassThatMakesMost(bestGood);
131 | if (bestGoodClass != "")
132 | {
133 | bestClass = bestGoodClass;
134 | }
135 | }
136 |
137 | var newAgent = getAgent(market.getAgentClass(bestClass));
138 | market.replaceAgent(agent, newAgent);
139 | }
140 |
141 |
142 | /**
143 | * Get the average amount of a given good that a given agent class has
144 | * @param className
145 | * @param good
146 | * @return
147 | */
148 | /*
149 | public function getAgentClassAverageInventory(className:String, good:String):Float
150 | {
151 | var list = _agents.filter(function(a:BasicAgent):Bool { return a.className == className; } );
152 | var amount:Float = 0;
153 | for (agent in list)
154 | {
155 | amount += agent.queryInventory(good);
156 | }
157 | amount /= list.length;
158 | return amount;
159 | }
160 | */
161 |
162 | /**
163 | * Find the agent class that produces the most of a given good
164 | * @param good
165 | * @return
166 | */
167 | public String getAgentClassThatMakesMost(String good)
168 | {
169 | string res = "";
170 | if (good == "food" ) {res = "farmer"; }
171 | else if (good == "wood") { res = "woodcutter"; }
172 | else if (good == "ore") { res = "miner"; }
173 | else if (good == "metal") {res = "refiner"; }
174 | else if (good == "tools") { res = "blacksmith"; }
175 | else if (good == "work") { res = "worker"; }
176 | return res;
177 | }
178 |
179 | /**
180 | * Find the agent class that has the most of a given good
181 | * @param good
182 | * @return
183 | */
184 | /*
185 | public function getAgentClassWithMost(good:String):String
186 | {
187 | var amount:Float = 0;
188 | var bestAmount:Float = 0;
189 | var bestClass:String = "";
190 | for (key in _mapAgents.keys())
191 | {
192 | amount = getAverageInventory(key, good);
193 | if (amount > bestAmount)
194 | {
195 | bestAmount = amount;
196 | bestClass = key;
197 | }
198 | }
199 | return bestClass;
200 | }
201 | */
202 |
203 | //private BasicAgent getAgentScript(AgentData data)
204 | //{
205 | // data.logic = new LogicScript(data.logicName+".hs");
206 | // return new Agent(0, data);
207 | //}
208 |
209 | private BasicAgent getAgent(AgentData data)
210 | {
211 | data.logic = getLogic(data.logicName);
212 | return new Agent(0, data);
213 | }
214 |
215 | private Logic getLogic(String str)
216 | {
217 | switch (str)
218 | {
219 | case "blacksmith": return new LogicBlacksmith();
220 | case "farmer": return new LogicFarmer();
221 | case "miner": return new LogicMiner();
222 | case "refiner": return new LogicRefiner();
223 | case "woodcutter": return new LogicWoodcutter();
224 | case "worker": return new LogicWorker();
225 | }
226 | return null;
227 | }
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Logic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace EconomySim
7 | {
8 | class Logic
9 | {
10 | private bool init = false;
11 |
12 | //public function new(?data:Dynamic)
13 | //{
14 | // //no implemenation -- provide your own in a subclass
15 | //}
16 |
17 | /**
18 | * Perform this logic on the given agent
19 | * @param agent
20 | */
21 |
22 | public virtual void perform(BasicAgent agent, Market market)
23 | {
24 | //no implemenation -- provide your own in a subclass
25 | }
26 |
27 | protected void _produce(BasicAgent agent, String commodity, double amount, double chance = 1.0)
28 | {
29 | if (chance >= 1.0 || Quick.rnd.NextDouble() < chance)
30 | {
31 | agent.produceInventory(commodity, amount);
32 | }
33 | }
34 |
35 | protected void _consume(BasicAgent agent, String commodity, double amount, double chance = 1.0)
36 | {
37 | if (chance >= 1.0 || Quick.rnd.NextDouble() < chance)
38 | {
39 | //if (commodity == "money")
40 | //{
41 | // agent.changeInventory(comm
42 | // agent.money -= amount;
43 | //}
44 | //else
45 | //{
46 | agent.consumeInventory(commodity, -amount);
47 | //}
48 | }
49 | }
50 |
51 | }
52 |
53 | class LogicBlacksmith : Logic
54 | {
55 | override public void perform(BasicAgent agent, Market market)
56 | {
57 | var food = agent.queryInventory("food");
58 | var metal = agent.queryInventory("metal");
59 | var tools = agent.queryInventory("tools");
60 | var need_tools = tools < 4;
61 |
62 | var has_food = food >= 1;
63 | var has_metal = metal >= 1;
64 |
65 | //_consume(agent, "money", 0.5);//cost of living/business
66 | _consume(agent, "food", 1);//cost of living
67 |
68 | if (has_food && has_metal & need_tools)
69 | {
70 | //convert all metal into tools
71 | _consume(agent, "metal", metal);
72 | _produce(agent, "tools", metal);
73 | }
74 | else
75 | {
76 | //fined $2 for being idle
77 | //_consume(agent, "money", 2);
78 | if (!has_food && agent.get_inventoryFull())
79 | {
80 | //make_room_for(agent, "food", 2); stub todo needed?
81 | }
82 | }
83 | }
84 | }
85 |
86 | class LogicFarmer : Logic
87 | {
88 | override public void perform(BasicAgent agent, Market market)
89 | {
90 | var wood = agent.queryInventory("wood");
91 | var tools = agent.queryInventory("tools");
92 | var food = agent.queryInventory("food");
93 | var need_food = food < 10;
94 | var work = agent.queryInventory("work");
95 |
96 | var has_wood = wood >= 1;
97 | var has_tools = tools >= 1;
98 | var has_work = work >= 1;
99 |
100 | //_consume(agent, "money", 0.5);//cost of living/business
101 |
102 | if (need_food)
103 | {
104 | if (has_wood && has_tools && has_work)
105 | {
106 | //produce 4 food, consume 1 wood, break tools with 10% chance
107 | _consume(agent, "wood", 1, 1);
108 | _consume(agent, "tools", 1, 0.1);
109 | _consume(agent, "work", 1, 1);
110 | _produce(agent, "food", 6, 1);
111 | }
112 | else if (has_wood && !has_tools && has_work)
113 | {
114 | //produce 2 food, consume 1 wood
115 | _consume(agent, "wood", 1, 1);
116 | _consume(agent, "work", 1, 1);
117 | _produce(agent, "food", 3, 1);
118 | }
119 | else //no wood
120 | {
121 | //produce 1 food,
122 | _produce(agent, "food", 1, 1);
123 | }
124 | }
125 | else
126 | {
127 | //fined $2 for being idle
128 | //_consume(agent, "money", 2);
129 | }
130 | }
131 | }
132 |
133 |
134 | class LogicMiner : Logic
135 | {
136 | override public void perform(BasicAgent agent, Market market)
137 | {
138 | var food = agent.queryInventory("food");
139 | var tools = agent.queryInventory("tools");
140 | var ore = agent.queryInventory("ore");
141 | var need_ore = ore < 4;
142 |
143 | var has_food = food >= 1;
144 | var has_tools = tools >= 1;
145 |
146 | //_consume(agent, "money", 0.5);//cost of living/business
147 | _consume(agent, "food", 1);//cost of living
148 |
149 | if (has_food && need_ore)
150 | {
151 | if (has_tools)
152 | {
153 | //produce 4 ore, consume 1 food, break tools with 10% chance
154 | _consume(agent, "food", 1);
155 | _consume(agent, "tools", 1, 0.1);
156 | _produce(agent, "ore", 4);
157 | }
158 | else
159 | {
160 | //produce 2 ore, consume 1 food
161 | _consume(agent, "food", 1);
162 | _produce(agent, "ore", 2);
163 | }
164 | }
165 | else
166 | {
167 | //fined $2 for being idle
168 | //_consume(agent, "money", 2);
169 | if (!has_food && agent.get_inventoryFull())
170 | {
171 | //make_room_for(agent,"food",2);
172 | }
173 | }
174 | }
175 | }
176 |
177 | class LogicRefiner : Logic
178 | {
179 | override public void perform(BasicAgent agent, Market market)
180 | {
181 | var food = agent.queryInventory("food");
182 | var tools = agent.queryInventory("tools");
183 | var ore = agent.queryInventory("ore");
184 | if (ore > 4) ore = 4;
185 | var metal = agent.queryInventory("metal");
186 | var need_metal = metal < 4;
187 |
188 | var has_food = food >= 1;
189 | var has_tools = tools >= 1;
190 | var has_ore = ore >= 1;
191 |
192 | //_consume(agent, "money", 0.5);//cost of living/business
193 | _consume(agent, "food", 1);//cost of living
194 |
195 | if (has_food && has_ore && need_metal)
196 | {
197 | if (has_tools)
198 | {
199 | //convert all ore into metal, consume 1 food, break tools with 10% chance
200 | _consume(agent, "ore", ore);
201 | _consume(agent, "food", 1);
202 | _consume(agent, "tools", 1, 0.1);
203 | _produce(agent, "metal", ore);
204 | }
205 | else
206 | {
207 | //convert up to 2 ore into metal, consume 1 food
208 | var max = agent.queryInventory("ore");
209 | if (max > 2) { max = 2; }
210 | _consume(agent, "ore", max);
211 | _consume(agent, "food", 1);
212 | _produce(agent, "metal", max);
213 | }
214 | }
215 | else
216 | {
217 | //fined $2 for being idle
218 | //_consume(agent, "money", 2);
219 | if (!has_food && agent.get_inventoryFull())
220 | {
221 | //make_room_for(agent, "food", 2);
222 | }
223 | }
224 | }
225 | }
226 |
227 | class LogicWoodcutter : Logic
228 | {
229 | override public void perform(BasicAgent agent, Market market)
230 | {
231 | var food = agent.queryInventory("food");
232 | var tools = agent.queryInventory("tools");
233 | var wood = agent.queryInventory("wood");
234 | var need_wood = wood < 4;
235 |
236 | var has_food = food >= 1;
237 | var has_tools = tools >= 1;
238 |
239 | //_consume(agent, "money", 0.5);//cost of living/business
240 | _consume(agent, "food", 1);//cost of living
241 |
242 | if (has_food && need_wood)
243 | {
244 | if (has_tools)
245 | {
246 | //produce 2 wood, consume 1 food, break tools with 10% chance
247 | _consume(agent, "food", 1);
248 | _consume(agent, "tools", 1, 0.1);
249 | _produce(agent, "wood", 2);
250 | }
251 | else
252 | {
253 | //produce 1 wood, consume 1 food
254 | _consume(agent, "food", 1);
255 | _produce(agent, "wood", 1);
256 | }
257 | }
258 | else
259 | {
260 | //fined $2 for being idle
261 | //_consume(agent, "money", 2);
262 | if (!has_food && agent.get_inventoryFull())
263 | {
264 | //make_room_for(agent, "food", 2);
265 | }
266 | }
267 | }
268 | }
269 |
270 | class LogicWorker : Logic
271 | {
272 | override public void perform(BasicAgent agent, Market market)
273 | {
274 | var food = agent.queryInventory("food");
275 | var has_food = food >= 1;
276 | var work = agent.queryInventory("work");
277 | var need_work = work < 1;
278 |
279 | _consume(agent, "food", 1);
280 | //_consume(agent, "money", 0.5);//cost of living/business
281 |
282 | if (need_work)
283 | {
284 | _produce(agent, "work", 1);
285 | }
286 | }
287 | }
288 |
289 |
290 | }
291 |
--------------------------------------------------------------------------------
/EconomySim/EconomySim/Market.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Linq;
7 |
8 | namespace EconomySim
9 | {
10 | interface ISignalBankrupt
11 | {
12 | void signalBankrupt(Market m, BasicAgent agent);
13 | }
14 |
15 | class Market
16 | {
17 | public String name;
18 |
19 | /**Logs information about all economic activity in this market**/
20 | public History history;
21 |
22 | /**Signal fired when an agent's money reaches 0 or below**/
23 | public ISignalBankrupt signalBankrupt;
24 |
25 |
26 | /********PRIVATE*********/
27 |
28 | private int _roundNum = 0;
29 |
30 | private List _goodTypes; //list of string ids for all the legal commodities
31 | public BindingList _agents;
32 | public TradeBook _book;
33 | private Dictionary _mapAgents;
34 | private Dictionary _mapGoods;
35 |
36 |
37 | public Market(string name, ISignalBankrupt isb)
38 | {
39 | this.name = name;
40 |
41 | history = new History();
42 | _book = new TradeBook();
43 | _goodTypes = new List();
44 | _agents = new BindingList();
45 | _mapGoods = new Dictionary();
46 | _mapAgents = new Dictionary();
47 |
48 | signalBankrupt = isb;//new TypedSignalBasicAgent->Void>();
49 | }
50 |
51 | public void init(MarketData data)
52 | {
53 | fromData(data);
54 | }
55 |
56 | public int numTypesOfGood()
57 | {
58 | return _goodTypes.Count;
59 | }
60 |
61 | public int numAgents()
62 | {
63 | return _agents.Count;
64 | }
65 |
66 | public void replaceAgent(BasicAgent oldAgent, BasicAgent newAgent)
67 | {
68 | newAgent.id = oldAgent.id;
69 | _agents[oldAgent.id] = newAgent;
70 | oldAgent.destroy();
71 | newAgent.init(this);
72 | }
73 |
74 | //@:access(bazaarbot.agent.BasicAgent) //dfs stub ????
75 | public void simulate(int rounds)
76 | {
77 | for (int round=0; round();
95 | foreach (var agent in _agents)
96 | {
97 | if (agent.money <= 0) del.Add(agent);
98 | }
99 | while (del.Count > 0)
100 | {
101 | signalBankrupt.signalBankrupt(this, del[0]); //signalBankrupt.dispatch(this, agent);
102 | del.RemoveAt(0);
103 | }
104 | _roundNum++;
105 | }
106 | }
107 |
108 | public void ask(Offer offer)
109 | {
110 | _book.ask(offer);
111 | }
112 |
113 | public void bid(Offer offer)
114 | {
115 | _book.bid(offer);
116 | }
117 |
118 | /**
119 | * Returns the historical mean price of the given commodity over the last X rounds
120 | * @param commodity_ string id of commodity
121 | * @param range number of rounds to look back
122 | * @return
123 | */
124 |
125 | public double getAverageHistoricalPrice(String good, int range)
126 | {
127 | return history.prices.average(good, range);
128 | }
129 |
130 | /**
131 | * Get the good with the highest demand/supply ratio over time
132 | * @param minimum the minimum demand/supply ratio to consider an opportunity
133 | * @param range number of rounds to look back
134 | * @return
135 | */
136 |
137 | public String getHottestGood(double minimum = 1.5, int range = 10)
138 | {
139 | string best_market = "";
140 | double best_ratio = -99999;// Math.NEGATIVE_INFINITY;
141 | foreach (var good in _goodTypes)
142 | {
143 | var asks = history.asks.average(good, range);
144 | var bids = history.bids.average(good, range);
145 |
146 | double ratio = 0;
147 | if (asks == 0 && bids > 0)
148 | {
149 | //If there are NONE on the market we artificially create a fake supply of 1/2 a unit to avoid the
150 | //crazy bias that "infinite" demand can cause...
151 |
152 | asks = 0.5;
153 | }
154 |
155 | ratio = bids / asks;
156 |
157 | if (ratio > minimum && ratio > best_ratio)
158 | {
159 | best_ratio = ratio;
160 | best_market = good;
161 | }
162 | }
163 | return best_market;
164 | }
165 |
166 | /**
167 | * Returns the good that has the lowest average price over the given range of time
168 | * @param range how many rounds to look back
169 | * @param exclude goods to exclude
170 | * @return
171 | */
172 |
173 | public String getCheapestGood(int range, List exclude = null)
174 | {
175 | double best_price = -9999999;// Math.POSITIVE_INFINITY;
176 | string best_good = "";
177 | foreach (var g in _goodTypes)
178 | {
179 | if (exclude == null || !exclude.Contains(g))
180 | {
181 | double price = history.prices.average(g, range);
182 | if (price < best_price)
183 | {
184 | best_price = price;
185 | best_good = g;
186 | }
187 | }
188 | }
189 | return best_good;
190 | }
191 |
192 | /**
193 | * Returns the good that has the highest average price over the given range of time
194 | * @param range how many rounds to look back
195 | * @param exclude goods to exclude
196 | * @return
197 | */
198 |
199 | public String getDearestGood(int range, List exclude= null)
200 | {
201 | double best_price = 0;
202 | String best_good = "";
203 | foreach (var g in _goodTypes)
204 | {
205 | if (exclude == null || !exclude.Contains(g))
206 | {
207 | var price = history.prices.average(g, range);
208 | if (price > best_price)
209 | {
210 | best_price = price;
211 | best_good = g;
212 | }
213 | }
214 | }
215 | return best_good;
216 | }
217 |
218 | /**
219 | *
220 | * @param range
221 | * @return
222 | */
223 | public String getMostProfitableAgentClass(int range= 10)
224 | {
225 | double best = -999999;// Math.NEGATIVE_INFINITY;
226 | String bestClass="";
227 | foreach (var className in _mapAgents.Keys)
228 | {
229 | double val = history.profit.average(className, range);
230 | if (val > best)
231 | {
232 | bestClass = className;
233 | best = val;
234 | }
235 | }
236 | return bestClass;
237 | }
238 |
239 | public AgentData getAgentClass(String className)
240 | {
241 | return _mapAgents[className];
242 | }
243 |
244 | public List getAgentClassNames()
245 | {
246 | var agentData = new List ();
247 | foreach (var key in _mapAgents.Keys)
248 | {
249 | agentData.Add(key);
250 | }
251 | return agentData;
252 | }
253 |
254 | public List getGoods()
255 | {
256 | return new List(_goodTypes);
257 | }
258 |
259 | public List getGoods_unsafe()
260 | {
261 | return _goodTypes;
262 | }
263 |
264 | public Good getGoodEntry(String str)
265 | {
266 | if (_mapGoods.ContainsKey(str))
267 | {
268 | return _mapGoods[str].copy();
269 | }
270 | return null;
271 | }
272 |
273 | /********REPORT**********/
274 | public MarketReport get_marketReport(int rounds)
275 | {
276 | var mr = new MarketReport();
277 | mr.strListGood = "Commodities\n\n";
278 | mr.strListGoodPrices = "Price\n\n";
279 | mr.strListGoodTrades = "Trades\n\n";
280 | mr.strListGoodAsks = "Supply\n\n";
281 | mr.strListGoodBids = "Demand\n\n";
282 |
283 | mr.strListAgent = "Classes\n\n";
284 | mr.strListAgentCount = "Count\n\n";
285 | mr.strListAgentProfit = "Profit\n\n";
286 | mr.strListAgentMoney = "Money\n\n";
287 |
288 | mr.arrStrListInventory = new List();
289 |
290 | foreach (var commodity in _goodTypes)
291 | {
292 | mr.strListGood += commodity + "\n";
293 |
294 | var price = history.prices.average(commodity, rounds);
295 | mr.strListGoodPrices += Quick.numStr(price, 2) + "\n";
296 |
297 | var asks = history.asks.average(commodity, rounds);
298 | mr.strListGoodAsks += (int)(asks) + "\n";
299 |
300 | var bids = history.bids.average(commodity, rounds);
301 | mr.strListGoodBids += (int)(bids) + "\n";
302 |
303 | var trades = history.trades.average(commodity, rounds);
304 | mr.strListGoodTrades += (int)(trades) + "\n";
305 |
306 | mr.arrStrListInventory.Add(commodity + "\n\n");
307 | }
308 | foreach (var key in _mapAgents.Keys)
309 | {
310 | var inventory = new List();
311 | foreach (var str in _goodTypes)
312 | {
313 | inventory.Add(0);
314 | }
315 | mr.strListAgent += key + "\n";
316 | var profit = history.profit.average(key, rounds);
317 | mr.strListAgentProfit += Quick.numStr(profit, 2) + "\n";
318 |
319 | double test_profit = 0;
320 | var list = _agents; //var list = _agents.filter(function(a:BasicAgent):Bool { return a.className == key; } ); dfs stub wtf
321 | int count = 0;
322 | double money = 0;
323 |
324 | foreach (var a in list)
325 | {
326 | if (a.className==key)
327 | {
328 | count++;
329 | money += a.money;
330 | for (int lic=0; lic<_goodTypes.Count; lic++)
331 | {
332 | inventory[lic] += a.queryInventory(_goodTypes[lic]);
333 | }
334 | }
335 | }
336 |
337 | money /= count;
338 | for (int lic =0; lic<_goodTypes.Count; lic++)
339 | {
340 | inventory[lic] /= count;
341 | mr.arrStrListInventory[lic] += Quick.numStr(inventory[lic],1) + "\n";
342 | }
343 |
344 | mr.strListAgentCount += Quick.numStr(count, 0) + "\n";
345 | mr.strListAgentMoney += Quick.numStr(money, 0) + "\n";
346 | }
347 | return mr;
348 | }
349 |
350 | /********PRIVATE*********/
351 |
352 | private void fromData(MarketData data)
353 | {
354 | //Create commodity index
355 | foreach (var g in data.goods)
356 | {
357 | _goodTypes.Add(g.id);
358 | _mapGoods[g.id] = new Good(g.id, g.size);
359 |
360 | double v = 1.0;
361 | if (g.id == "metal") v = 2.0;
362 | if (g.id == "tools") v = 3.0;
363 |
364 | history.register(g.id);
365 | history.prices.add(g.id, v); //start the bidding at $1!
366 | history.asks.add(g.id, v); //start history charts with 1 fake buy/sell bid
367 | history.bids.add(g.id, v);
368 | history.trades.add(g.id, v);
369 |
370 | _book.register(g.id);
371 | }
372 |
373 | _mapAgents = new Dictionary();
374 |
375 | foreach (var aData in data.agentTypes)
376 | {
377 | _mapAgents[aData.className] = aData;
378 | history.profit.register(aData.className);
379 | }
380 |
381 | //Make the agent list
382 | _agents = new BindingList();
383 |
384 | var agentIndex = 0;
385 | foreach (var agent in data.agents)
386 | {
387 | agent.id = agentIndex;
388 | agent.init(this);
389 | _agents.Add(agent);
390 | agentIndex++;
391 | }
392 |
393 | }
394 |
395 | private void resolveOffers(String good= "")
396 | {
397 | var bids = _book.bids[good];
398 | var asks = _book.asks[good];
399 |
400 | bids = Quick.shuffle(bids);
401 | asks = Quick.shuffle(asks);
402 |
403 | //bids.Sort(Quick.sortOfferDecending); //highest buying price first
404 | asks.Sort(Quick.sortOfferAcending); //lowest selling price first
405 |
406 | int successfulTrades = 0; //# of successful trades this round
407 | double moneyTraded = 0; //amount of money traded this round
408 | double unitsTraded = 0; //amount of goods traded this round
409 | double avgPrice = 0; //avg clearing price this round
410 | double numAsks = 0;
411 | double numBids = 0;
412 |
413 | int failsafe = 0;
414 |
415 | for (int i=0; i 0 && asks.Count > 0) //while both books are non-empty
427 | {
428 | var buyer = bids[0];
429 | var seller = asks[0];
430 |
431 | var quantity_traded = (double)Math.Min(seller.units, buyer.units);
432 | var clearing_price = seller.unit_price; //Quick.avgf(seller.unit_price, buyer.unit_price);
433 |
434 | //if (buyer.unit_price < seller.unit_price)
435 | // break;
436 |
437 | if (quantity_traded > 0)
438 | {
439 | //transfer the goods for the agreed price
440 | seller.units -= quantity_traded;
441 | buyer.units -= quantity_traded;
442 |
443 | transferGood(good, quantity_traded, seller.agent_id, buyer.agent_id, clearing_price);
444 | transferMoney(quantity_traded * clearing_price, seller.agent_id, buyer.agent_id);
445 |
446 | //update agent price beliefs based on successful transaction
447 | var buyer_a = _agents[buyer.agent_id];
448 | var seller_a = _agents[seller.agent_id];
449 | buyer_a.updatePriceModel(this, "buy", good, true, clearing_price);
450 | seller_a.updatePriceModel(this, "sell", good, true, clearing_price);
451 |
452 | //log the stats
453 | moneyTraded += (quantity_traded * clearing_price);
454 | unitsTraded += quantity_traded;
455 | successfulTrades++;
456 | }
457 |
458 | if (seller.units == 0) //seller is out of offered good
459 | {
460 | asks.RemoveAt(0); //.splice(0, 1); //remove ask
461 | failsafe = 0;
462 | }
463 | if (buyer.units == 0) //buyer is out of offered good
464 | {
465 | bids.RemoveAt(0);//.splice(0, 1); //remove bid
466 | failsafe = 0;
467 | }
468 |
469 | failsafe++;
470 |
471 | if (failsafe > 1000)
472 | {
473 | Console.WriteLine("BOINK!");
474 | }
475 | }
476 |
477 | //reject all remaining offers,
478 | //update price belief models based on unsuccessful transaction
479 | while (bids.Count > 0)
480 | {
481 | var buyer = bids[0];
482 | var buyer_a = _agents[buyer.agent_id];
483 | buyer_a.updatePriceModel(this,"buy",good, false);
484 | bids.RemoveAt(0);//.splice(0, 1);
485 | }
486 | while (asks.Count > 0)
487 | {
488 | var seller = asks[0];
489 | var seller_a = _agents[seller.agent_id];
490 | seller_a.updatePriceModel(this,"sell",good, false);
491 | asks.RemoveAt(0);// splice(0, 1);
492 | }
493 |
494 | //update history
495 |
496 | history.asks.add(good, numAsks);
497 | history.bids.add(good, numBids);
498 | history.trades.add(good, unitsTraded);
499 |
500 | if (unitsTraded > 0)
501 | {
502 | avgPrice = moneyTraded / (double)unitsTraded;
503 | history.prices.add(good, avgPrice);
504 | }
505 | else
506 | {
507 | //special case: none were traded this round, use last round's average price
508 | history.prices.add(good, history.prices.average(good, 1));
509 | avgPrice = history.prices.average(good,1);
510 | }
511 |
512 | List ag = _agents.ToList();
513 | ag.Sort(Quick.sortAgentAlpha);
514 |
515 | String curr_class = "";
516 | String last_class = "";
517 | List list = null;
518 | double avg_profit = 0;
519 |
520 | for (int i=0;i(); //make a new list
532 | last_class = curr_class;
533 | }
534 | list.Add(a.get_profit()); //push profit onto list
535 | }
536 |
537 | //add the last class too
538 | history.profit.add(last_class, Quick.listAvgf(list));
539 |
540 | //sort by id so everything works again
541 | //_agents.Sort(Quick.sortAgentId);
542 |
543 | }
544 |
545 | private void transferGood(String good, double units, int seller_id, int buyer_id, double clearing_price)
546 | {
547 | var seller = _agents[seller_id];
548 | var buyer = _agents[buyer_id];
549 | seller.changeInventory(good, -units, 0);
550 | buyer.changeInventory(good, units, clearing_price);
551 | }
552 |
553 | private void transferMoney(double amount, int seller_id, int buyer_id)
554 | {
555 | var seller = _agents[seller_id];
556 | var buyer = _agents[buyer_id];
557 | seller.money += amount;
558 | buyer.money -= amount;
559 | }
560 |
561 | }
562 | }
563 |
--------------------------------------------------------------------------------