1 /**
2 *   Copyright: © 2012-2014 Anton Gushcha
3 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
4 *   Authors:  NCrashed <ncrashed@gmail.com>,
5 *             LeMarwin <lemarwin42@gmail.com>,
6 *             Nazgull09 <nazgull90@gmail.com>
7 */
8 module ant.world;
9 
10 import devol.world;
11 import ant.progtype;
12 import ant.operators;
13 import core.thread;
14 import core.time;
15 
16 import std.random;
17 import std.stdio;
18 import std.process;
19 import ant.app;
20 
21 import derelict.sdl2.sdl;
22 
23 class AntWorld: WorldAbstract
24 {
25 	void initialize()
26 	{	
27 		zeros();
28 		generateMap();
29 		print();
30 	}	
31 	static immutable int size = 18;	
32 	static int Food=25;
33 	
34 	const bool[size][size] getMap()
35 	{
36 		return map;
37 	}
38 	
39 	private:
40 	
41 	bool[size][size] map;
42 	
43 	public:
44 	
45 
46 	bool checkForFood(int x, int y)
47 	{
48 		if (x>=size || y>=size) return false;
49 		
50 		return map[x][y];
51 	}
52 	void removeFood(int x, int y)
53 	{
54 		map[x][y]=false;
55 	}
56 	
57 	void generateMap()
58 	{
59 		writeln("Generating map");
60 		Ant Grower = new Ant;
61 		
62 		Grower.x = size/2+uniform!"[]"(-1,1);
63 		Grower.y = size/2+uniform!"[]"(-1,1);
64 		
65 		Grower.Direction = cast(Ant.Faces)uniform!"[]"(cast(uint)Ant.Faces.min, cast(uint)Ant.Faces.max);
66 		
67 		int FC = 1;
68 		int breakCount = 0;
69 		
70 		writeln("Adding delegate");
71 		Grower.addCheat(delegate bool ()
72 		{
73 			final switch(Grower.Direction)
74 			{
75 			case Grower.Faces.NORTH:
76 				if(Grower.y>=2)
77 				return checkForFood(Grower.x,Grower.y-2)||checkForFood(Grower.x,Grower.y-1)
78 						||checkForFood(Grower.x-1,Grower.y-2)||checkForFood(Grower.x-1,Grower.y-1)
79 						||checkForFood(Grower.x+1,Grower.y-2)||checkForFood(Grower.x+1,Grower.y-1);
80 				break;
81 			case Grower.Faces.SOUTH:
82 				if(Grower.y<=size-2)
83 				return checkForFood(Grower.x,Grower.y+2)||checkForFood(Grower.x,Grower.y+1)
84 						||checkForFood(Grower.x-1,Grower.y+2)||checkForFood(Grower.x-1,Grower.y+1)
85 						||checkForFood(Grower.x+1,Grower.y+2)||checkForFood(Grower.x+1,Grower.y+1);
86 				break;
87 			case Grower.Faces.EAST:
88 				if(Grower.x<=size-2)
89 				return checkForFood(Grower.x+2,Grower.y)||checkForFood(Grower.x+1,Grower.y)
90 						||checkForFood(Grower.x+2,Grower.y-1)||checkForFood(Grower.x+1,Grower.y-1)
91 						||checkForFood(Grower.x+2,Grower.y+1)||checkForFood(Grower.x+1,Grower.y+1);
92 				break;
93 			case Grower.Faces.WEST:
94 				if(Grower.x>=2)
95 				return checkForFood(Grower.x-2,Grower.y)||checkForFood(Grower.x-1,Grower.y)
96 						||checkForFood(Grower.x-2,Grower.y-1)||checkForFood(Grower.x-1,Grower.y-1)
97 						||checkForFood(Grower.x-2,Grower.y+1)||checkForFood(Grower.x-1,Grower.y+1);
98 				break;
99 			}
100 			return false;
101 		});
102 		writeln("Placing food");
103 		auto flag = true;
104 		while(FC!=Food && breakCount < 100)
105 		{
106 			writeln("FC = ", FC);
107 			writeln("Food = ", Food);
108 			int c = uniform!"[]"(0,1);
109 			GoForward F = new GoForward;
110 			TurnLeft L = new TurnLeft;
111 			TurnRight R = new TurnRight;
112 			writeln("Choosing direction");
113 			if(c&&!Grower.MyCheat())
114 			{
115 				writeln("Forward");
116 				F.apply(Grower, null, this);
117 				
118 				int d = uniform!"[]"(0,1);
119 				writeln("Chance to place food: ", d);
120 				if ( Grower.x >= 1 && Grower.y  >= 1 && Grower.x <= size-1 && Grower.y <= size - 1 )
121 				{
122     				if((d||flag)&&!map[Grower.x][Grower.y])
123     				{
124     					writeln("Placing food");
125     					map[Grower.x][Grower.y] = true;
126     					FC++;
127     					flag = false;
128     				}
129     				else
130     				{
131     					flag = true;
132     				}
133 				}
134 			}
135 			else
136 			{
137 				writeln("Rotating");
138 				breakCount++;
139 				int d = uniform!"[]"(0,1);
140 				if(d)
141 				{
142 					writeln("Left");
143 					L.apply(Grower, null, this);
144 				}
145 				else
146 				{
147 					writeln("Right");
148 					R.apply(Grower,null,this);
149 				}
150 			}
151 			
152 
153 			
154 			void printGr()
155 			{
156 				writeln("Getting singleton");
157 				auto app = App.getSingleton();
158 				assert(app !is null);
159 				
160 				app.clear();
161 				draw(app, app.food, app.empty, app.wall);
162 				app.draw(app.ants[Grower.Direction], 32u*(Grower.x+1), 32u*(Grower.y+1), 32u, 32u);
163 				app.present();
164 			}
165 			
166 			printGr();
167 		}
168 	}
169 		void zeros()
170 		{
171 			foreach(ref line; map)
172 			{
173 				foreach(ref cell; line)
174 				{
175 					cell = false;
176 				}
177 			}
178 		}
179 	
180 	void print()
181 	{
182 		version(linux)
183 		{
184 			system("clear");
185 		}
186 		foreach( l; map )
187 		{
188 			foreach( c; l)
189 			{
190 				if (c)
191 					write("x");
192 				else
193 					write("-");
194 			}
195 			writeln();
196 		}
197 	}
198 	
199 	void draw(App app, SDL_Texture* food, SDL_Texture* empty, SDL_Texture* wall)
200 	{
201 		assert(food !is null);
202 		assert(empty !is null);
203 		
204 		foreach(uint j, l; map )
205 		{
206 			foreach(uint i, c; l)
207 			{
208 				if (c)
209 				{
210 					//writeln("drawing food at ", (j+1)*32u, " ", (i+1)*32u);
211 					app.draw(food, (j+1)*32u , (i+1)*32u, 32u, 32u);
212 				}
213 				else
214 				{	
215 					//writeln("drawing empty at ", (j+1)*32u, " ", (i+1)*32u);
216 					app.draw(empty, (j+1)*32u , (i+1)*32u, 32u, 32u);
217 				}
218 			}
219 		}		
220 		
221 		foreach(uint i; 0..map.length+2)
222 			app.draw(wall, i*32u, 0, 32u, 32u);
223 		foreach(uint i; 0..map.length+2)
224 			app.draw(wall, i*32u, (cast(uint)map.length+1)*32u, 32u, 32u);
225 		foreach(uint i; 0..map.length+2)
226 			app.draw(wall, 0, i*32u, 32u, 32u);				
227 		foreach(uint i; 0..map.length+2)
228 			app.draw(wall, (cast(uint)map.length+1)*32u, i*32u, 32u, 32u);	
229 	}
230 	
231 	}
232