/* micromouse action algorithm simulator Hirotaka JOE Ohkubo 2001 is based on : # Map Editor for Micro Mouse # (c) Copyright 1996, T.Yasui # 1996/05/03 V0.0a Test Version */ /* coodination 0 1 2 3 4 5 .. x 0 S W 1 | 2 S ---+-\ N . | . E _ bit 0 of Map[x][y] y | bit 1 of Map[x][y] */ /* POORSOdialog msg : message shown in dialog callback : callbackfunction name of C++ in case OK */ extern Tcl_Interp interp; void POORSOdialog(char *msg,char *callback) { #pragma tcl interp msg callback global msg callback fname proc SOdialogOK {} { global callback fname ; destroy .sodialog ; if {[string length $fname]} { ceval $callback (\"$fname\") ; } ; } # SOdialogOK toplevel .sodialog ; label .sodialog.label -text $msg ; entry .sodialog.entry -relief sunken -textvariable fname ; pack .sodialog.label .sodialog.entry -side left -padx 1m -pady 1m ; bind .sodialog.entry SOdialogOK ; grab set .sodialog ; #pragma endtcl } // POORSOdialog /* readopendialog ext : extension msg : message shown in dialog callback : callback function name of C++ in case OK clicked */ void readopendialog(char *ext, char *msg, char *callback) { #pragma tcl interp ext msg callback global ext msg callback proc doCancel {} { destroy .rodialog ; } proc doOK {filename} { global callback ; destroy .rodialog ; if {[string length $filename]} { ceval $callback (\"$filename\") ; } ; } proc setpwd {} { .rodialog.dir config -text [pwd] } proc clickOn {file} { if [regexp "/$" $file] { cd $file; setpwd; listfiles $ext; return } ; if [string compare ".." $file] { # set filename $file ; return } ; cd .. ; setpwd ; listfiles } proc listfiles {} { global ext ; .rodialog.filebox.files delete 0 end ; .rodialog.filebox.files insert end \.\. ; foreach i [lsort [glob */ *$ext]] { .rodialog.filebox.files insert end $i } } toplevel .rodialog wm title .rodialog "Open File" label .rodialog.msg -text $msg label .rodialog.dir frame .rodialog.filebox frame .rodialog.buttons pack .rodialog.msg .rodialog.dir .rodialog.filebox .rodialog.buttons setpwd listbox .rodialog.filebox.files -yscrollcommand ".rodialog.filebox.scroll set" pack .rodialog.filebox.files -side left scrollbar .rodialog.filebox.scroll -command ".rodialog.filebox.files yview" pack .rodialog.filebox.scroll -side left -fill y listfiles button .rodialog.buttons.ok -text "OK" -command {doOK [selection get]} button .rodialog.buttons.cancel -text "Cancel" -command doCancel pack .rodialog.buttons.ok .rodialog.buttons.cancel -side left bind .rodialog.filebox.files {clickOn [selection get]} bind .rodialog.filebox.files {doOK [selection get]} raise .rodialog #pragma endtcl } static int Map[17][17]; static int WallIdNS[17][17]; static int WallIdEW[17][17]; void initMapArray() { int x,y; for (x=0;x<=16;x++) { for (y=0;y<=16;y++) { Map[x][y] = 0; } } for (x=1;x<=15;x++) { Map[x][0] = 1; Map[x][16] = 1; Map[0][x] = 2; Map[16][x] = 2; } Map[0][0] = 3; Map[0][16] = 1; Map[16][0] = 2; Map[16][16] = 0; } //initMapArray int readMap(int x, int y) { return Map[x][y]; } // it seems that "ceval" cannot read array directly. void writeMap(int x, int y, int v) { Map[x][y] = v; } void setWallIdNS(int x, int y, int id) { WallIdNS[x][y] = id; } void setWallIdEW(int x, int y, int id) { WallIdEW[x][y] = id; } int readWallIdNS(int x, int y) { return WallIdNS[x][y]; } int readWallIdEW(int x, int y) { return WallIdEW[x][y]; } void LoadMap() { readopendialog(".map","Select Map File:","LoadMapCB"); } // LoadMap void LoadMapCB(char *filename) { initMapArray(); #pragma tcl interp filename LoadFile $filename ; #pragma endtcl } // LoadMapCallback void ExportTextCB(char *filename) { FILE *file; char *title; int x,y; #pragma tcl interp title global title ; set title [.base.p.title cget -text] ; #pragma endtcl file = fopen(filename,"w"); fprintf(file,"Title = %s\n",title); fputs(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n",file); for (y=0;y<=16;y++) { fputs(" ",file); for (x=0;x<=16;x++) { fputc('+',file); if (Map[x][y] & 1) { fputc('-',file); } else { fputc(' ',file); } } fputs(" \n",file); if (y != 16) { fprintf(file,"%2d",y); for (x=0;x<=16;x++) { if (Map[x][y] & 2) { fputc('|',file); } else { fputc(' ',file); } if (x == 0 && y == 0) { fputc('S',file); } else if ((x==7||x==8)&&(y==7||y==8)) { fputc('G',file); } else { fputc(' ',file); } } } fputc('\n',file); } fclose(file); } // ExportTextCB void SaveMapCB(char *filename) { FILE *file; char *title; int x,y; #pragma tcl interp title global title ; set title [.base.p.title cget -text] ; #pragma endtcl file = fopen(filename,"w"); fprintf(file,"; %s\n",title); for (y=0;y<=15;y++) { for (x=0;x<=15;x++) { fprintf(file,"%1d",Map[x][y]); } fputc('\n',file); } fclose(file); } // SaveMapCB // for Simulation char userprog[256]; enum Action { Step, TurnLeft, TurnRight, TurnBack, End }; void LoadProgram() { readopendialog(".c","Select Mouse:","LoadProgramCB"); } // LoadProgram void LoadProgramCB(char *filename) { if (userprog[0] != '\0') { G__unloadfile(userprog); } strcpy(userprog,filename); G__loadfile(userprog); ResetSimulation(); } // LoadProgramCallback void ReloadProgram() { G__unloadfile(userprog); G__loadfile(userprog); ResetSimulation(); } void ResetSimulation() { theMouseStatus.InitMouse(); MouseInit(); } void SaveLogCB(char *filename) { FILE *file; char *data; #pragma tcl interp data global data ; set data [.base.p.m.message get "0.0" end] ; #pragma endtcl file = fopen(filename,"w"); fputs(data,file); fclose(file); } // SaveLogCB class MouseStatus { int x,y,dir ; int step,walk,turn,uturn; void ShowMouse(); int rotx(int dx, int dy); int roty(int dx, int dy); public: int ready; void InitMouse(); int sense(int dir); void doAction(); void Bring2Start(); } ; void MouseStatus::InitMouse () { x = 0; y = 0; dir = 0; ready = 1; step = 0; walk = 0; turn = 0; uturn = 0; ShowMouse(); } int MouseStatus::rotx(int dx, int dy) { switch (dir) { case 0: return dx; case 1: return dy; case 2: return -dx; case 3: return -dy; } } int MouseStatus::roty(int dx, int dy) { switch (dir) { case 0: return dy; case 1: return dx; case 2: return -dy; case 3: return -dx; } } void MouseStatus::ShowMouse() { char msg[256], *msgp; int x1,y1,x2,y2,x3,y3; sprintf(msg,"%d steps\n%d walks\n%d turns\n%d Uturn",step,walk,turn,uturn); msgp = msg; #pragma tcl interp msgp global msgp ; .base.p.st config -state normal ; .base.p.st delete "0.0" end ; .base.p.st insert end $msgp mytag ; .base.p.st tag configure mytag -justify right ; .base.p.st config -state disabled ; #pragma endtcl int xc = 27+25*x; int yc = 27+25*y; x1 = xc+rotx( 7, 0); y1 = yc+roty( 7, 0); x2 = xc+rotx(-6, 5); y2 = yc+roty(-6, 5); x3 = xc+rotx(-6,-5); y3 = yc+roty(-6,-5); #pragma tcl interp x1 y1 x2 y2 x3 y3 global x1 y1 x2 y2 x3 y3 ; .base.c delete mouse ; .base.c create polygon $x1 $y1 $x2 $y2 $x3 $y3 -fill Blue -outline black -tags mouse ; #pragma endtcl } int senseForward() { return theMouseStatus.sense(0); } int senseLeft() { return theMouseStatus.sense(-1); } int senseRight() { return theMouseStatus.sense(1); } int MouseStatus::sense(int d) { int direction = (dir+d+4) % 4; switch (direction) { case 0: return Map[x+1][y] & 2 ; case 1: return Map[x][y+1] & 1 ; case 2: return Map[x ][y] & 2 ; case 3: return Map[x ][y] & 1 ; } } void MousePuts(char *msg); void MouseStatus::doAction() { char msg[30], *msgp; if (!ready) { return; } Action res = MousedoAction(); step++; sprintf(msg,"%3d: ",step); msgp = msg; MousePuts(msg); switch (res) { case Step: walk++; if (sense(0)) { MousePuts("Step...Crash!!!\n"); ready = 0; break; } MousePuts("Step\n"); switch (dir) { case 0: x++; break; case 1: y++; break; case 2: x--; break; case 3: y--; break; } ShowMouse(); break; case TurnLeft: MousePuts("Left\n"); dir = (dir + 3) % 4; turn++; ShowMouse(); break; case TurnRight: MousePuts("Right\n"); dir = (dir + 1) % 4; turn++; ShowMouse(); break; case TurnBack: MousePuts("U-Turn\n"); dir = (dir + 2) % 4; uturn++; ShowMouse(); break; case End: MousePuts("End\n"); ready = 0; break; } } void MouseStatus::Bring2Start() { x = 0; y = 0; dir = 0; ready = 1; MouseBring2Start(); ShowMouse(); } MouseStatus theMouseStatus; main() { userprog[0]='\0'; #pragma tcl interp # constant set x_base 15 set y_base 15 set delta 25 proc ClickWall {id x y b} { set m [ceval "readMap" ($x,$y) ] ; if {$m & $b} { .base.c itemconfigure $id -fill ""; } else { .base.c itemconfigure $id -fill black; } ; set m [expr $m ^ $b]; ceval "writeMap" ($x,$y,$m) ; } # ClickWall proc DrawPoles {} { global x_base y_base delta ; set limit [expr $x_base + $delta * 16] ; for {set x [expr $x_base-2]} {$x < $limit} {set x [expr $x+$delta]} { for {set y [expr $y_base-2]} {$y < $limit} {set y [expr $y+$delta]} { .base.c create oval $x $y [expr $x+4] [expr $y+4] -outline black -fill red ; } ; } ; } # DrawPoles proc DrawWalls {} { global x_base y_base delta ; for {set x 0} {$x <=16} {incr x} { for {set y 0} {$y <=16} {incr y} { set x1 [expr $x_base+$x*$delta] ; set y1 [expr $y_base+$y*$delta] ; if {$x != 16} { set id [.base.c create line [expr $x1+4] $y1 [expr $x1+20] $y1 -width 3 ]; if { ($y != 0) && ($y != 16) } { .base.c bind $id