// --- Hardware definitions --------------------------------------------------#include "pswitch.nqh"PSWITCH(OUT_B, ps_claw, clawcode)#define DRIVE_L OUT_A#define DRIVE_R OUT_C#include "2wd.nqh"#define DROT_L SENSOR_2#define DROT_R SENSOR_3#define CLAWLS SENSOR_1// --- Misc ----------------------------------------------------#define ROTPOLL 12int ok_l, ok_r, opos_l, opos_r;#define DPower(pow) SetPower(DRIVE_L|DRIVE_R, pow)int holding_obj, mood, fchange;#define TIMER_LASTBUMP 0#define TIMER_SWAIT 1// --- Basic tasks ----------------------------------------------------task main () {  ps_claw = 1;  mood = 0;  SelectDisplay(DISPLAY_USER);  SetUserDisplay(mood, 0);  start stallwatch;  //repeat(4) {  //  MRight(90);  //  MForward(20);  //}  //stop main;  start drive;  start grab;  start noise;}task stallwatch () {  SetSensor(DROT_L, SENSOR_ROTATION);  SetSensor(DROT_R, SENSOR_ROTATION);  ok_l = 1;  ok_r = 1;  while (1) {    opos_l = DROT_L;    opos_r = DROT_R;    Wait(ROTPOLL);    ok_l = DROT_L - opos_l;    ok_r = DROT_R - opos_r;  }}task test () {  MForward(10);}void MForward(const int cm) {  int rots = cm * -46 / 15;  ClearSensor(DROT_L);  OnFwd(DRIVE_L + DRIVE_R);  until(DROT_L <= rots);  Off(DRIVE_L + DRIVE_R);}void MBackward(const int cm) {  int rots = cm * 46 / 15;  ClearSensor(DROT_L);  OnRev(DRIVE_L + DRIVE_R);  until(DROT_L >= rots);  Off(DRIVE_L + DRIVE_R);}void MLeft(const int deg) {  int rots = deg * 184 / 360;  ClearSensor(DROT_L);  SetDirection(DRIVE_R, OUT_FWD);  SetDirection(DRIVE_L, OUT_REV);  On(DRIVE_L + DRIVE_R);  until(DROT_L >= rots);  Off(DRIVE_L + DRIVE_R);}void MRight(const int deg) {  int rots = deg * 184 / 360;  ClearSensor(DROT_R);  SetDirection(DRIVE_L, OUT_FWD);  SetDirection(DRIVE_R, OUT_REV);  On(DRIVE_L + DRIVE_R);  until(DROT_R >= rots);  Off(DRIVE_L + DRIVE_R);}// --- Behaviors ----------------------------------------------------task drive () { while (1) {  int isright, lastb;  DPower(OUT_HALF);  DFwd();  Wait(30);  until(!ok_l || !ok_r);  PlaySound(SOUND_CLICK);  mood -= 2;  lastb = Timer(TIMER_LASTBUMP);  ClearTimer(TIMER_LASTBUMP);  DPower(OUT_FULL);  if (ok_l) isright = 1; else isright = 0;    DRev();  SWait(10);  if (isright) DLeft(); else DRight();  if (lastb < 50) SWait(25 - lastb / 2);             else SWait(1 + Random(10));}}void SWait(int time) {  ClearTimer(TIMER_SWAIT);  Wait(ROTPOLL);  while (Timer(TIMER_SWAIT) < time && ok_l && ok_r);  PlayTone(200, 2);}task grab () {  int threshold = CLAWLS + 10;  holding_obj = 0;  SetSensor(CLAWLS, SENSOR_LIGHT);  while (1) {    until (CLAWLS > 50 && !holding_obj);    PlaySound(SOUND_UP);    mood += 5;    stop drive; DStop();    DPower(OUT_FULL);    dograb();    start drive;    holding_obj = 1;    start release;  }}task release () {  Wait(500 + Random(500));  stop drive;  PlaySound(SOUND_DOWN);  dorelease();  mood -= 1;  holding_obj = 0;  DLeft();  Wait(30);  start drive;}void dograb () {  claw();  Wait(100);}void dorelease () {  claw();  DRev();  Wait(80);  DStop();}sub claw () {  clawcode();}task noise () { while (1) {  npause();  switch (Random(2)) {   case 0:    PlayTone(300 + fchange, 12);    PlayTone(350 + fchange, 12);    PlayTone(400 + fchange, 12);    PlayTone(340 + fchange, 12);    PlayTone(420 + fchange, 12);    PlayTone(280 + fchange, 12);    break;   case 1:    PlayTone(500 + fchange, 12);    PlayTone(400 + fchange, 12);    PlayTone(450 + fchange, 12);    PlayTone(350 + fchange, 12);    PlayTone(300 + fchange, 12);    PlayTone(200 + fchange, 12);    break;   case 2:    PlayTone(300 + fchange, 12);    PlayTone(350 + fchange, 12);    PlayTone(500 + fchange, 12);    PlayTone(400 + fchange, 12);    PlayTone(360 + fchange, 12);    PlayTone(320 + fchange, 12);    break;  }}}void npause () {  Wait(500);  if (mood > 0) mood--;  if (mood < 0) mood++;  if (mood > 5) mood = 5;  if (mood < -5) mood = -5;  fchange = mood * 80;}