import java.util.Random;

/**
 * Subclass to handle events when creating a new game. -- Rev. 2021 June 2
 * Use this to update GameEngine-generated code (unused methods omitted)
 *
 * Set DevLev=0/1/2 to test different code levels re RipTime/RipMore.htm
 *
 * Look for the comment "// added code *" ...
 */
public class Rips extends GameEvent {              // 2020 November 14
  JavaGame myGame = null; // soon: reference to the GameEngine
  GameWgt myRips = null; // reference to the game board widget
  /// ($) Begin generated class variables (do not modify) ($..)
    GameWgt Announce = null, HumanS = null, CompuS = null, CompuW = null,
      HumanX = null, HumanR = null, HumanW = null;
  /// (..$) End generated class variables ($) (do not modify this line)

  int RipPhase = 0, Hscore = 0, Cscore = 0; // added code *..
  Random rn = new Random();
                                                   final int DevLev = 2;
  GameWgt ColorW = null;
  public static final boolean GoodRip = false, Logging = false;

  public String toString() {return "(Rips)";} //~toString            // (Rips)

 /**
  * (Generated code only) GameList returns a text descriptor of widgets.
  */
  public String GameList(JavaGame whom) {                            // (Rips)
    String info = super.GameList(whom), data
    /// <$> Begin generated widget list (do not modify) <$..>
      = "1 1029 0 0 250 444 0x66FF66 0 0 4  2 0 0 0  '[List of item lists]"
      + " in win {Rips}'\n2 5 0 0 250 444 -1 0 1 9  4 5 6 11 16 21 26 0 0"
      + " '[Sprite list]' #3\n3 3 0 0 12 12 0x0 4 0 0 '[Font B]'\n"
      + "4 4 40 40 32 300 0 -66 2 0 'Rock-Paper-Scissors, click icon to begin"
      + "...' {Announce}\n5 4 80 80 32 40 0 -66 2 0 '0  You' {HumanS}\n"
      + "6 4 80 288 32 40 0 -66 2 0 'Me   0' {CompuS}\n"
      + "7 2 0 0 32 32 0xFFFFFF 0 11 0 'RPS tool paper icon' [QxPi]\n"
      + "8 2 0 0 32 32 0x666666 0 11 0 'RPS tool rock icon' [QxRi]\n"
      + "9 2 0 0 32 32 0 0 11 0 'RPS tool scissors icon' [QxSi]\n"
      + "10 2 0 0 32 32 0xDDDDDD 0 11 0 'RPS tool cloud icon' [QxQi]\n"
      + "11 262 160 288 32 32 -1 0 2 4 7 8 9 10 (Qw) {CompuW}\n"
      + "12 2 0 0 32 32 0xFFFFFF 0 16 0 'RPS tool paper icon' [QxPi]\n"
      + "13 2 0 0 32 32 0x666666 0 16 0 'RPS tool rock icon' [QxRi]\n"
      + "14 2 0 0 32 32 0 0 16 0 'RPS tool scissors icon' [QxSi]\n"
      + "15 2 0 0 32 32 0xDDDDDD 0 16 0 'RPS tool cloud icon' [QxQi]\n"
      + "16 1030 160 120 32 32 -1 0 2 4 12 13 14 15 (Qs) {HumanX}\n"
      + "17 2 0 0 32 32 0xFFFFFF 0 21 0 'RPS tool paper icon' [QxPi]\n"
      + "18 2 0 0 32 32 0x666666 0 21 0 'RPS tool rock icon' [QxRi]\n"
      + "19 2 0 0 32 32 0 0 21 0 'RPS tool scissors icon' [QxSi]\n"
      + "20 2 0 0 32 32 0xDDDDDD 0 21 0 'RPS tool cloud icon' [QxQi]\n"
      + "21 1030 160 40 32 32 -1 0 2 4 17 18 19 20 (Qr) {HumanR}\n"
      + "22 2 0 0 32 32 0xFFFFFF 0 26 0 'RPS tool paper icon' [QxPi]\n"
      + "23 2 0 0 32 32 0x666666 0 26 0 'RPS tool rock icon' [QxRi]\n"
      + "24 2 0 0 32 32 0 0 26 0 'RPS tool scissors icon' [QxSi]\n"
      + "25 2 0 0 32 32 0xDDDDDD 0 26 0 'RPS tool cloud icon' [QxQi]\n"
      + "26 1286 160 80 32 32 -1 0 2 4 22 23 24 25 (Qq) {HumanW}\n"
      + "";
    /// <..$> End generated widget list <$> (do not modify this line)
    myGame = whom; // save a local reference to the GameEngine
    return data;} //~GameList

 /**
  * My RPS scoring code
  */
  public void RipScore(int hum, int com) { // added code *..
    int dLev = DevLev&15, tmp;
    String msg = "";
    if (Logging) System.out.println("(RipSco) H=" + hum + " C=" + com);
    if (myGame == null) return;
    if (Announce==null) return;
    if (hum<1) hum = 1;
    if (hum>3) hum = 3;
    if (com<1) com = 1;
    if (com>3) com = 3;
    aFrameNum = 30;
    tmp = myGame. ChoseRPS(CompuW,com);
    if (hum==com) { // tie..
      if (hum<3) tmp = myGame. ChoseRPS(HumanX,0);
      if (hum != 2) tmp = myGame. ChoseRPS(HumanR,0);
      if (hum>1) tmp = myGame. ChoseRPS(HumanW,0);
      tmp = Announce.PutTextLn("No score, click to go again");
      RipPhase = 20;
      ColorW = null;
      return;} //~if
    tmp = myGame. ChoseRPS(HumanX,0)
        + myGame. ChoseRPS(HumanR,0)
        + myGame. ChoseRPS(HumanW,hum);
    switch (hum*3+com-4) {
      case 1: // H=1(P), C=2(R)
      case 3: // H=2(R), C=1(P)
        msg = "Paper covers rock";
        break;
      case 2: // H=1(P), C=3(S)
      case 6: // H=3(S), C=1(P)
        msg = "Scissors cuts paper";
        if (com==3) com = 0;
        if (hum==3) hum = 0;
        break;
      case 5: // H=2(R), C=3(S)
      case 7: // H=3(S), C=2(R)
        msg = "Rock breaks scissors";
        break;} //~switch
    if (StrLength(msg)>0)
      tmp = Announce.PutTextLn(msg);
    if (hum<com) { // human won this round..
      Hscore++;
      if (HumanS != null) tmp = HumanS.PutTextLn("" + Hscore + "  You");
      if (dLev>1) ColorW = CompuW;
      RipPhase = 20;} //~if
    else if (hum>com) { // computer won this round..
      Cscore++;
      if (CompuS != null) tmp = CompuS.PutTextLn("Me  " + Cscore);
      if (dLev>1) ColorW = HumanW;
      RipPhase = 20;} //~if    // we have a loser to animate..
    if (myGame != null) if (ColorW != null) {
      tmp = DevLev&0x3FF0;
      if (tmp==0) tmp = 0x8F0;
      else if (tmp<256) tmp = tmp|0x800;
      tmp = myGame. ChoseRPS(ColorW,tmp+0xC) // start anim'n
          + myGame. ChoseRPS(ColorW,0xFFFF00);} //~if // yellow
    } //~RipScore

 /**
  * My RPS transaction code: 0: idle, 1/2/3/4: click, -1: start
  */
  public void DoStateEvt(int whom) { // added code *..
    int dLev = DevLev&15, tmp = 0, why = 0;
    String msg = "";
    if (Logging) System.out.println("(TomRip) " + RipPhase + " + " + whom
        + " t=" + aFrameNum);
    if (whom<0) { // (re)startup..
      if (dLev>0) if (whom+4>0) {
        if (HumanS != null) tmp = HumanS.PutTextLn("0  You");
        if (CompuS != null) tmp = CompuS.PutTextLn("Me   0");
        Hscore = 0;
        Cscore = 0;} //~if
      RipPhase = 0;
      if (myGame == null) return;
      if (Announce==null) return;
      tmp = Announce.PutTextLn("Rock-Paper-Scissors (Oops)");
      if (dLev>0) {
        if (HumanW != null) {
          HumanW.SetInfo(0); // restore velo+posn in case anim=moved
          HumanW.SetPosn(160,80);
          tmp = myGame. ChoseRPS(HumanW,7);} //~if // why = 0
        else why--;
        if (CompuW != null) {
          tmp = myGame. ChoseRPS(CompuW,7);
          CompuW.SetInfo(0); // restore velo+posn in case anim=moved
          CompuW.SetPosn(160,288);} //~if
        else why--;
        if (why<0) return;
        tmp = myGame. ChoseRPS(HumanX,3)
            + myGame. ChoseRPS(HumanR,2)
            + myGame. ChoseRPS(HumanW,1);
        aFrameNum = 0;} //~if
      tmp = Announce.PutTextLn("Rock-Paper-Scissors, click to begin...");
      ColorW = null;} //~if
    else switch (RipPhase+whom) {
      case 1:  case 2:  case 3:  case 4: // starting click..
        tmp = myGame. ChoseRPS(HumanX,3)
            + myGame. ChoseRPS(HumanR,2)
            + myGame. ChoseRPS(HumanW,1);
        msg = "Synchronize:  One...";
        aFrameNum = 0;
        RipPhase = 5;
        break;
      case 5: // next timing event
        tmp = aFrameNum%3 +1;
        if (dLev>0) tmp = myGame. ChoseRPS(CompuW,tmp);
        if (aFrameNum<10) break; // wait one full second, then...
        msg = "Synchronize:  One...  Two...";
        RipPhase = 10;
        why = RipPhase;
        break;
      case 10: // next timing event (in second second)
        tmp = aFrameNum%3 +1;
        if (dLev>0) tmp = myGame. ChoseRPS(CompuW,tmp);
        if (aFrameNum<20) break; // wait another full second, then...
        msg = "Synchronize:  One...  Two...  Three...";
        RipPhase = 15;
        why = RipPhase;
        break;
      case 15: // during (and after) the third second..
        tmp = aFrameNum%3 +1;
        if (dLev>0) tmp = myGame. ChoseRPS(CompuW,tmp);
        if (aFrameNum<50) break;
        DoStateEvt(-3); // give up and start over
        why = -3;
        break;
      case 20: // hold the result for three+ seconds more..
        tmp = (DevLev>>16)&255;
        if (tmp==0) tmp = 99;
        if (aFrameNum<tmp) {
          if (dLev<2) break;
          if (ColorW==null) break;
          tmp = (DevLev>>24)&255;
          if (tmp>0) {
            dLev = (DevLev>>8)&31;
            if ((dLev&~8)==0) dLev = 2;
            else if (dLev<16) dLev = 16/dLev;
              else dLev = 1;} //~if
          else tmp = 75;
          if (aFrameNum==tmp) // set color red-gray after one second..
            tmp = myGame. ChoseRPS(ColorW,0xCC9933);
          else if (aFrameNum==tmp+dLev)
            tmp = myGame. ChoseRPS(ColorW,0xAA7755);
          else if (aFrameNum==tmp+dLev+dLev)
            tmp = myGame. ChoseRPS(ColorW,0xCCAA88);
          else if (aFrameNum==tmp+dLev*3) { // last visible frame..
            tmp = myGame. ChoseRPS(ColorW,4); // hide all but cloud
            tmp = myGame. ChoseRPS(ColorW,0x42C); // last frame slower
            tmp = myGame. ChoseRPS(ColorW,0xDDDDDD);} //~if
          break;} //~if
        DoStateEvt(-4); // timed out, restart
        why = -4;
        break;
      case 9:  case 14: // human clicked somewhere else, start over
        DoStateEvt(-2);
        break;
      case 6:  case 11:  case 16: // human played paper..
      case 7:  case 12:  case 17: // human played rock..
      case 8:  case 13:  case 18: // human played scissors..
      case 19: // test case, human wins (DevLev=0 only, else ignore it)
        if (aFrameNum<18) { // they played early,
          if (dLev==0) break; // (ignore it)
          tmp = whom-1; // ..so I get to see before I choose
          why--;} //~if // why = 3
        else if (rn == null) tmp = whom+1; // (can't, so I lose this one)
        else {
          tmp = rn.nextInt(3)+1;
          if (dLev>1) tmp = myGame. ChoseRPS(CompuW,-1)&3;
          why++;} //~else // why = 5
        if (tmp==0) tmp = 3;
        else if (tmp>3) tmp = 1;
          else why = why+4; // = 3/4/5/6 (normal)
        if (whom==4) {
          if (dLev>0) break; // (ignore it)
          whom = tmp-1;
          if (whom==0) whom = 3;} //~if
        if (dLev==0) {
          tmp = myGame. ChoseRPS(CompuW,tmp);
          if (whom !=3)
            tmp = myGame. ChoseRPS(HumanX,0); // hide the scissors
          if (whom !=2)
            tmp = myGame. ChoseRPS(HumanR,0); // hide the rock
          if (whom !=1)
            tmp = myGame. ChoseRPS(HumanW,0); // hide the paper
          msg = "...";
          RipPhase = 20;} //~if
        else RipScore(whom,tmp); // also sets RipPhase
        // if (Logging) System.out.println("===> " + RipPhase + " " + why);
        aFrameNum = 55; // stabilize the time reference
        break;
      case 24: // got any click, just start the next round...
      case 21:  case 22:  case 23:
        aFrameNum = 0; // start GameEngine's frame counter
        msg = "Synchronize:  One...";
        RipPhase = 5; // go to next state
        tmp = myGame. ChoseRPS(HumanR,2); // show the rock
        tmp = myGame. ChoseRPS(HumanW,1); // show the paper
        tmp = myGame. ChoseRPS(HumanX,3); // show the scissors
        tmp = myGame. ChoseRPS(CompuW,7); // show all 3 for computer
        break;} //~switch
    if (StrLength(msg)>0)
      tmp = Announce.PutTextLn(msg);
    if (Logging) if ((whom>0) || (why !=0))
      System.out.println("===> " + RipPhase + " " + why);} //~DoStateEvt // added code *

 /**
  * (Partly generated code).
  */
  public void StartUp() {                                            // (Rips)
    if (myGame != null) myRips = myGame.FindListWgt("{Rips}");
    /// [$] Begin generated StartUp code (do not modify) [$..]
    if (myGame==null) return;
    Announce = myGame.FindListWgt("{Announce}");
    HumanS = myGame.FindListWgt("{HumanS}");
    CompuS = myGame.FindListWgt("{CompuS}");
    CompuW = myGame.FindListWgt("{CompuW}");
    HumanX = myGame.FindListWgt("{HumanX}");
    HumanR = myGame.FindListWgt("{HumanR}");
    HumanW = myGame.FindListWgt("{HumanW}");
    if (CompuW != null) myGame.LoadRPSpix(CompuW,7);
    if (HumanX != null) myGame.LoadRPSpix(HumanX,3);
    if (HumanR != null) myGame.LoadRPSpix(HumanR,2);
    if (HumanW != null) myGame.LoadRPSpix(HumanW,1);
    /// [..$] End generated StartUp code [$] (do not modify this line)
    DoStateEvt(-1);} //~StartUp // added code *

 /**
  * DoOften is called once each frame to do whatever.
  */
  public void DoOften() {                                            // (Rips)
    DoStateEvt(0);} //~DoOften // added code *

 /**
  * ClickEvt is called for a widget when the user clicks on it.
  */
  public boolean ClickEvt(GameWgt whom, int vert, int horz) {        // (Rips)
    if (super.ClickEvt(whom,vert,horz)) return true; // added code *..

      if (whom==HumanX) DoStateEvt(3); // scissor
      else if (whom==HumanR) DoStateEvt(2); // rock
      else if (whom==HumanW) DoStateEvt(1); // paper
        else DoStateEvt(4); // anything else
    return false;} //~ClickEvt // (or true: nobody else cares)

 /**
  * Collided is called once for each Collidable ("Bump") Sprite widget.
  */
  public boolean Collided(GameWgt whom, GameWgt hitt) {              // (Rips)
    if (RipPhase<32) return false; // added code *
    DoStateEvt(1); // same as click
    return true;} //~Collided // return true to stop looking

 /**
  * This is the main() you start your game in.
  * DO NOT MODIFY THIS CODE.
  */
  public static void main() { // (in Rips)
    JavaGame whom = new JavaGame();
    GameEvent evh = new Rips();
    String title = "Rips", data = "";
    int tall = 0, wide = 0, colo = 0x0;
    if (whom != null) if (evh != null) {
      data = evh.GameList(whom);
      tall = JavaGame.SafeParseInt(JavaGame.NthItemOf(' ',5,data));
      wide = JavaGame.SafeParseInt(JavaGame.NthItemOf(' ',6,data));
      colo = JavaGame.SafeParseInt(JavaGame.NthItemOf(' ',7,data));
      whom.StartGame(tall,wide,colo,title,evh);
      if (false) whom.LogAlWgts("[main] ");}
    if (Logging)
      System.out.println("{main} " + tall + "x" + wide + " '" + title + "'");}

  public Rips() {
    if (Logging) System.out.println("(new Rips)");}} //~Rips // (RG)
