001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028 #include <sos/assert.h>
029 #include <sos/klibc.h>
030 #include <sos/thread.h>
031 #include <sos/ksynch.h>
032 #include <sos/kmalloc.h>
033 #include <drivers/x86_videomem.h>
034
035
036
037
038
039
040
041
042
043 #define MAP_X 76
044 #define MAP_Y 12
045 #define MAP_SIZE MAP_X * MAP_Y
046
047 #define MOUSE 0x01
048 #define CHEESE 0x02
049 #define OBSTACLE 0x04
050 #define INPUT 0x08
051 #define OUTPUT 0x10
052
053 #define OBSTACLE_COUNT 100
054 #define CHEESE_COUNT 650
055
056 #define MOUSE_FULL 0x01
057 #define MOUSE_EMPTY 0x02
058 #define CHEESE_FOUND 0x04
059 #define MOUSE_EXITED 0x08
060
061 #define MOUSE_SPEED_MAX 1000
062 #define MOUSE_SPEED_MIN 4
063
064 typedef unsigned int Color_t;
065
066 struct Point{
067 int X;
068 int Y;
069 };
070
071 typedef struct Point Point_t;
072
073 #define Set(Reg, Flag) Reg = (Reg | Flag)
074 #define Reset(Reg, Flag) Reg = (Reg &(~Flag))
075 #define IsSet(Reg, Flag) (Reg & Flag)
076
077
078
079
080
081 struct Element{
082 sos_ui32_t Type;
083 sos_ui32_t Status;
084 Color_t Color;
085 Point_t P;
086 struct sos_thread * ThreadID;
087 int Way;
088 };
089
090 typedef struct Element Element_t;
091
092
093
094
095 static void MouseCommander(void);
096 static void DrawMap(void);
097 static sos_ret_t CreateMap(void);
098 static sos_ret_t InitMapInput(Element_t * * pMap);
099 static sos_ret_t InitMapOutput(Element_t * * pMap);
100 static sos_ret_t ElementInit(Element_t * * pMap, unsigned int Type);
101 static void Mouse(unsigned long Param);
102 static void MouseMove(Point_t * P);
103 static Point_t ChoosePosition(Element_t * pMouse, int Positions[], int Count);
104 static int EvaluatePositions(Point_t Org, int Positions[], Point_t * Cheese);
105 static sos_bool_t IsCollision(Point_t Org, Point_t p, Point_t *Cheese);
106 static sos_bool_t AffectMovement(Point_t Org, Point_t p);
107 static void MouseCreator(void);
108 static sos_ret_t CreateMouse(void);
109
110
111
112
113
114 static Element_t * * pMap;
115 static struct sos_ksema SemMap;
116 static struct sos_ksema SemMouse;
117 static int MouseCount = 0;
118 static int CheeseCount = 0;
119 static int ObstacleCount = 0;
120 static int MouseSpeed = 100;
121
122
123
124
125 void DrawPixel(int x, int y, Color_t color)
126 {
127 sos_x86_videomem_putchar(y+3, x+2, color, 219);
128 }
129
130
131
132
133
134
135 void MouseSim(void)
136 {
137
138 SOS_ASSERT_FATAL(SOS_OK == sos_ksema_init(& SemMap, "SemMap", 1));
139
140
141 SOS_ASSERT_FATAL(SOS_OK == sos_ksema_init(& SemMouse, "SemMouse", 2));
142
143
144 SOS_ASSERT_FATAL(SOS_OK == CreateMap());
145
146
147 SOS_ASSERT_FATAL(sos_create_kernel_thread("MouseCreator",
148 (sos_kernel_thread_start_routine_t)MouseCreator,
149 0) != NULL);
150
151 }
152
153
154
155
156
157
158
159 static sos_ret_t CreateMap(void)
160 {
161 pMap = (Element_t * *)sos_kmalloc(MAP_SIZE * sizeof(Element_t *), 0);
162 if(pMap == NULL) return -SOS_ENOMEM;
163
164
165 memset(pMap, 0, MAP_SIZE * sizeof(Element_t *));
166
167
168 if(SOS_OK != InitMapInput(pMap))
169 {
170 return -SOS_EFATAL;
171 }
172
173
174 if(InitMapOutput(pMap) != SOS_OK)
175 {
176 return -SOS_EFATAL;
177 }
178
179
180 if(ElementInit(pMap, CHEESE) != SOS_OK)
181 {
182 return -SOS_EFATAL;
183 }
184
185
186 if(ElementInit(pMap, OBSTACLE) != SOS_OK)
187 {
188 return -SOS_EFATAL;
189 }
190
191 DrawMap();
192
193 return SOS_OK;
194 }
195
196
197
198
199
200
201 static void DrawMap(void)
202 {
203 unsigned int I;
204
205 for(I = 0; I < MAP_SIZE; I++)
206 {
207 if(pMap[I] != NULL)
208 {
209 DrawPixel(I % MAP_X, I/MAP_X, pMap[I]->Color);
210 }
211 else DrawPixel(I % MAP_X, I/MAP_X, SOS_X86_VIDEO_FG_BLACK);
212 }
213 sos_x86_videomem_printf(23, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
214 "Souris = %d; Fromages = %d; Obstacles = %d ",
215 MouseCount, CheeseCount, ObstacleCount);
216 }
217
218
219
220
221
222
223
224 static sos_ret_t InitMapInput(Element_t * * pMap)
225 {
226 Element_t * pElement;
227
228
229 pElement = (Element_t *)sos_kmalloc(sizeof(Element_t), 0);
230 if(pElement == NULL) return -SOS_ENOMEM;
231
232
233 pElement->Type = INPUT;
234 pElement->Status = 0;
235 pElement->Color = SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE;
236 pElement->P.X = 0;
237 pElement->P.Y = MAP_Y / 2;
238 pElement->ThreadID = 0;
239
240 pMap[(pElement->P.Y * MAP_X) + pElement->P.X] = pElement;
241
242 return SOS_OK;
243 }
244
245
246
247
248
249
250
251 static sos_ret_t InitMapOutput(Element_t * * pMap)
252 {
253 Element_t * pElement;
254
255
256 pElement = (Element_t *)sos_kmalloc(sizeof(Element_t), 0);
257 if(pElement == NULL) return -SOS_ENOMEM;
258
259
260 pElement->Type = OUTPUT;
261 pElement->Status = 0;
262 pElement->Color = SOS_X86_VIDEO_FG_LTBLUE;
263 pElement->P.X = MAP_X - 1;
264 pElement->P.Y = MAP_Y / 2;
265 pElement->ThreadID = 0;
266
267 pMap[(pElement->P.Y * MAP_X) + pElement->P.X] = pElement;
268
269 return SOS_OK;
270 }
271
272
273
274
275
276
277
278
279 static sos_ret_t ElementInit(Element_t * * pMap, unsigned int Type)
280 {
281 unsigned int I, J;
282 unsigned int Max;
283 Color_t Color;
284
285 if(Type == CHEESE)
286 {
287 Max = CHEESE_COUNT;
288 Color = SOS_X86_VIDEO_FG_YELLOW;
289 }
290 else if(Type == OBSTACLE)
291 {
292 Max = OBSTACLE_COUNT;
293 Color = SOS_X86_VIDEO_FG_GREEN;
294 }
295 else
296 {
297 return -SOS_EINVAL;
298 }
299
300 for(I = 0; I < Max; I++)
301 {
302 J = random();
303 J += random();
304 J %= MAP_SIZE;
305 if(pMap[J] == NULL)
306 {
307 pMap[J] = (Element_t *)sos_kmalloc(sizeof(Element_t),
308 0);
309 if(pMap[J] == NULL) return -SOS_ENOMEM;
310
311 pMap[J]->Type = Type;
312
313 if(Type == CHEESE)
314 {
315 CheeseCount++;
316 }
317 else if(Type == OBSTACLE)
318 {
319 ObstacleCount++;
320 }
321
322 pMap[J]->Color = Color;
323 pMap[J]->Status = 0;
324 pMap[J]->Color = Color;
325 pMap[J]->P.X = J % MAP_X;
326 pMap[J]->P.Y = J / MAP_X;
327 pMap[J]->ThreadID = 0;
328 }
329 }
330
331 return SOS_OK;
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345 static void Mouse(unsigned long Param)
346 {
347 Element_t * pMouse = (Element_t *)Param;
348 Point_t P;
349
350 SOS_ASSERT_FATAL(pMouse != NULL);
351
352
353 P = pMouse->P;
354 P = pMouse->P;
355
356 while(1)
357 {
358 int delay_ms;
359 struct sos_time delay;
360
361
362 sos_ksema_down(& SemMap, NULL);
363
364 MouseMove(&P);
365
366 sos_ksema_up(& SemMap);
367
368
369 if (IsSet(pMouse->Status, MOUSE_EXITED))
370
371 break;
372
373
374 delay_ms = MOUSE_SPEED_MIN + (random() % MouseSpeed);
375 delay.sec = delay_ms / 1000;
376 delay.nanosec = (delay_ms % 1000) * 1000000;
377 sos_thread_sleep(& delay);
378 }
379
380
381 sos_kfree((sos_vaddr_t)pMouse);
382 }
383
384
385
386
387
388
389
390
391 static void MouseMove(Point_t * P)
392 {
393 Point_t Org;
394 Point_t p;
395 Point_t Cheese;
396 int Positions[8];
397 int Count = 0;
398 Element_t * pMouse;
399
400 Org = *P;
401
402 pMouse = pMap[Org.X + (Org.Y * MAP_X)];
403
404 Count = EvaluatePositions(Org, Positions, &Cheese);
405
406 if(Count == 0) return;
407
408 p = Org;
409
410 if(IsSet(pMouse->Status, CHEESE_FOUND))
411 {
412 Reset(pMouse->Status, CHEESE_FOUND);
413 p = Cheese;
414 }
415 else
416 {
417 p = ChoosePosition(pMouse, Positions, Count);
418 }
419 if(AffectMovement(Org, p) == FALSE) return;
420
421 pMap[Org.X + (Org.Y * MAP_X)] = NULL;
422 pMap[p.X + (p.Y * MAP_X)] = pMouse;
423 pMouse->P = p;
424
425 DrawPixel(Org.X, Org.Y, SOS_X86_VIDEO_FG_BLACK);
426 DrawPixel(p.X, p.Y, pMouse->Color);
427 sos_x86_videomem_printf( 23,0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Souris = %d; Fromages = %d; Obstacles = %d ", MouseCount, CheeseCount, ObstacleCount);
428
429 *P = p;
430 }
431
432
433
434
435
436
437
438
439
440
441 static Point_t ChoosePosition(Element_t * pMouse, int Positions[], int Count)
442 {
443 int I, J;
444 Point_t p;
445
446 for(J = 0; J < Count; J++)
447 {
448 I = Positions[J];
449 if(I == pMouse->Way)
450 {
451 p = pMouse->P;
452 switch(I)
453 {
454 case 0:
455 p.Y++;
456 break;
457 case 1:
458 p.X++;
459 p.Y++;
460 break;
461 case 2:
462 p.X++;
463 break;
464 case 3:
465 p.Y--;
466 p.X++;
467 break;
468 case 4:
469 p.Y--;
470 break;
471 case 5:
472 p.Y--;
473 p.X--;
474 break;
475 case 6:
476 p.X--;
477 break;
478 case 7:
479 p.X--;
480 p.Y++;
481 break;
482 }
483 return p;
484 }
485 }
486
487 J = random() % Count;
488 I = Positions[J];
489 if(((I + 4) % 8) == pMouse->Way)
490 {
491 J = (J + 1) % Count;
492 I = Positions[J];
493 }
494
495 p = pMouse->P;
496 switch(I)
497 {
498 case 0:
499 p.Y++;
500 break;
501 case 1:
502 p.X++;
503 p.Y++;
504 break;
505 case 2:
506 p.X++;
507 break;
508 case 3:
509 p.Y--;
510 p.X++;
511 break;
512 case 4:
513 p.Y--;
514 break;
515 case 5:
516 p.Y--;
517 p.X--;
518 break;
519 case 6:
520 p.X--;
521 break;
522 case 7:
523 p.X--;
524 p.Y++;
525 break;
526 }
527
528 pMouse->Way = I;
529
530 return p;
531 }
532
533
534
535
536
537
538
539
540
541
542
543
544
545 static int EvaluatePositions(Point_t Org, int Positions[], Point_t * Cheese)
546 {
547 int I;
548 int Count = 0;
549 Point_t p;
550 Point_t CheesePos;
551
552 for(I = 0; I < 8; I++)
553 {
554 p = Org;
555 switch(I)
556 {
557 case 0:
558 p.Y++;
559 break;
560 case 1:
561 p.X++;
562 p.Y++;
563 break;
564 case 2:
565 p.X++;
566 break;
567 case 3:
568 p.Y--;
569 p.X++;
570 break;
571 case 4:
572 p.Y--;
573 break;
574 case 5:
575 p.Y--;
576 p.X--;
577 break;
578 case 6:
579 p.X--;
580 break;
581 case 7:
582 p.X--;
583 p.Y++;
584 break;
585 }
586
587 if(IsCollision(Org, p, &CheesePos) == FALSE)
588 {
589 Positions[Count] = I;
590 Count++;
591 }
592 }
593
594 *Cheese = CheesePos;
595
596 return Count;
597 }
598
599
600
601
602
603
604
605
606 static sos_bool_t AffectMovement(Point_t Org, Point_t p)
607 {
608 Element_t * pMouse = pMap[Org.X + (Org.Y * MAP_X)];
609 Element_t * pElement;
610
611 pElement = pMap[p.X + (p.Y * MAP_X)];
612
613
614 if(pElement == NULL) return TRUE;
615
616 switch(pElement->Type)
617 {
618 case CHEESE:
619
620 sos_kfree((sos_vaddr_t)pElement);
621 pMap[p.X + (p.Y * MAP_X)] = NULL;
622
623
624 Set(pMouse->Status, MOUSE_FULL);
625 Reset(pMouse->Status, MOUSE_EMPTY);
626 pMouse->Color = SOS_X86_VIDEO_FG_MAGENTA;
627 CheeseCount--;
628 return TRUE;
629 case OUTPUT:
630
631 pMap[Org.X + (Org.Y * MAP_X)] = NULL;
632 MouseCount--;
633 DrawPixel(Org.X, Org.Y, SOS_X86_VIDEO_FG_BLACK);
634 sos_x86_videomem_printf( 23,0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
635 "Souris = %d; Fromages = %d; Obstacles = %d ",
636 MouseCount, CheeseCount,
637 ObstacleCount);
638 Set(pMouse->Status, MOUSE_EXITED);
639 return FALSE;
640 default :
641 return FALSE;
642 }
643
644 return FALSE;
645 }
646
647
648
649
650
651
652
653
654
655
656 static sos_bool_t IsCollision(Point_t Org, Point_t p, Point_t *Cheese)
657 {
658 Element_t * pMouse = pMap[Org.X + (Org.Y * MAP_X)];
659 Element_t * pElement;
660
661
662 if((p.X < 0)||(p.Y < 0)) return TRUE;
663
664 if((p.Y >= MAP_Y)||(p.X >= MAP_X)) return TRUE;
665
666 pElement = pMap[p.X + (p.Y * MAP_X)];
667
668
669 if(pElement == NULL) return FALSE;
670
671
672 if(IsSet(pMouse->Status, CHEESE_FOUND)) return FALSE;
673
674 switch(pElement->Type)
675 {
676 case CHEESE:
677 if(IsSet(pMouse->Status, MOUSE_FULL)) return TRUE;
678
679 Set(pMouse->Status, CHEESE_FOUND);
680
681 (*Cheese).X = p.X;
682 (*Cheese).Y = p.Y;
683 break;
684 case INPUT:
685 if(IsSet(pMouse->Status, MOUSE_EMPTY)) return TRUE;
686
687 Set(pMouse->Status, MOUSE_EMPTY);
688 Reset(pMouse->Status, MOUSE_FULL);
689 pMouse->Color = SOS_X86_VIDEO_FG_LTRED;
690
691 sos_ksema_up(& SemMouse);
692 return TRUE;
693 case OUTPUT:
694 break;
695 default :
696 return TRUE;
697 }
698
699 return FALSE;
700 }
701
702
703
704
705 static void MouseCreator(void)
706 {
707 while(1)
708 {
709 sos_ksema_down(& SemMouse, NULL);
710 sos_ksema_down(& SemMap, NULL);
711 CreateMouse();
712 sos_ksema_up(& SemMap);
713 }
714 }
715
716
717
718
719
720
721
722 static sos_ret_t CreateMouse(void)
723 {
724 Element_t * pElement;
725 unsigned int I;
726
727 Point_t p;
728
729 for(I = 0; I < 8; I++)
730 {
731 p.X = 0;
732 p.Y = MAP_Y / 2;
733 switch(I)
734 {
735 case 0:
736 p.Y++;
737 break;
738 case 1:
739 p.X++;
740 p.Y++;
741 break;
742 case 2:
743 p.X++;
744 break;
745 case 3:
746 p.Y--;
747 p.X++;
748 break;
749 case 4:
750 p.Y--;
751 break;
752 case 5:
753 p.Y--;
754 p.X--;
755 break;
756 case 6:
757 p.X--;
758 break;
759 case 7:
760 p.X--;
761 p.Y++;
762 break;
763 }
764 if((p.X >= 0)&&(p.Y >= 0)&&(p.X < MAP_X)&&(p.Y < MAP_Y))
765 {
766 pElement = pMap[p.X + (p.Y * MAP_X)];
767 if(pElement == NULL)
768 {
769 pElement = (Element_t *)sos_kmalloc(sizeof(Element_t), 0);
770 if(pElement != NULL)
771 {
772 pElement->Type = MOUSE;
773 Set(pElement->Status, MOUSE_EMPTY);
774 pElement->Color = SOS_X86_VIDEO_FG_LTRED;
775 pElement->P = p;
776 pElement->Way = 0;
777 pElement->ThreadID
778 = sos_create_kernel_thread("Mouse",
779 (sos_kernel_thread_start_routine_t)Mouse,
780 pElement);
781 if(pElement->ThreadID == 0)
782 {
783 sos_kfree((sos_vaddr_t)pElement);
784 pElement = NULL;
785 return -SOS_ENOMEM;
786 }
787 pMap[p.X + (p.Y * MAP_X)] = pElement;
788 MouseCount++;
789
790 DrawPixel(p.X, p.Y, pElement->Color);
791 sos_x86_videomem_printf(23, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Souris = %d; Fromages = %d; Obstacles = %d ", MouseCount, CheeseCount, ObstacleCount);
792
793 return SOS_OK;
794 }
795 }
796 }
797 }
798 return -SOS_EBUSY;
799 }
800
801
802
803
804