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                 version(NoGraphicsOutput)
157                 {
158                     
159                 } else
160                 {
161     				//writeln("Getting singleton");
162     				auto app = App.getSingleton();
163     				assert(app !is null);
164     				
165     				app.clear();
166     				draw(app, app.food, app.empty, app.wall);
167     				app.draw(app.ants[Grower.Direction], 32u*(Grower.x+1), 32u*(Grower.y+1), 32u, 32u);
168     				app.present();
169 				}
170 			}
171 			
172 			printGr();
173 		}
174 	}
175 		void zeros()
176 		{
177 			foreach(ref line; map)
178 			{
179 				foreach(ref cell; line)
180 				{
181 					cell = false;
182 				}
183 			}
184 		}
185 	
186 	void print()
187 	{
188 //		version(linux)
189 //		{
190 //			system("clear");
191 //		}
192 //		foreach( l; map )
193 //		{
194 //			foreach( c; l)
195 //			{
196 //				if (c)
197 //					write("x");
198 //				else
199 //					write("-");
200 //			}
201 //			writeln();
202 //		}
203 	}
204 	
205 	void draw(App app, SDL_Texture* food, SDL_Texture* empty, SDL_Texture* wall)
206 	{
207         version(NoGraphicsOutput)
208         {
209             
210         } else
211         {
212     		assert(food !is null);
213     		assert(empty !is null);
214     		
215     		foreach(uint j, l; map )
216     		{
217     			foreach(uint i, c; l)
218     			{
219     				if (c)
220     				{
221     					//writeln("drawing food at ", (j+1)*32u, " ", (i+1)*32u);
222     					app.draw(food, (j+1)*32u , (i+1)*32u, 32u, 32u);
223     				}
224     				else
225     				{	
226     					//writeln("drawing empty at ", (j+1)*32u, " ", (i+1)*32u);
227     					app.draw(empty, (j+1)*32u , (i+1)*32u, 32u, 32u);
228     				}
229     			}
230     		}		
231     		
232     		foreach(uint i; 0..map.length+2)
233     			app.draw(wall, i*32u, 0, 32u, 32u);
234     		foreach(uint i; 0..map.length+2)
235     			app.draw(wall, i*32u, (cast(uint)map.length+1)*32u, 32u, 32u);
236     		foreach(uint i; 0..map.length+2)
237     			app.draw(wall, 0, i*32u, 32u, 32u);				
238     		foreach(uint i; 0..map.length+2)
239     			app.draw(wall, (cast(uint)map.length+1)*32u, i*32u, 32u, 32u);	
240 		}
241 	}
242 	
243 	}
244