Skip to content

Instantly share code, notes, and snippets.

@JamesTryand
Last active December 19, 2015 21:39
Show Gist options
  • Select an option

  • Save JamesTryand/6021607 to your computer and use it in GitHub Desktop.

Select an option

Save JamesTryand/6021607 to your computer and use it in GitHub Desktop.
Abuse of yield to expose to the statemachine within it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
namespace BurgerMonkey
{
class Program
{
static void Main(string[] args)
{
var spotty = new BurgerMonkey();
spotty.ServeGimp();
spotty.FlipBurger();
spotty.ServeGimp();
spotty.ServeGimp();
spotty.HandFood();
spotty.FlipBurger();
spotty.FlipBurger();
spotty.HandFood();
spotty.HandFood();
Console.ReadLine();
}
}
public class BurgerMonkey
{
public readonly Action ServeGimp;
public readonly Action FlipBurger;
public readonly Action HandFood;
private Action Action;
private IEnumerator CurrentState;
public BurgerMonkey()
{
PrepareActions();
CurrentState = MoveState().GetEnumerator();
CurrentState.MoveNext();
}
#region This is where the magic happens ;-)
private void PrepareActions()
{
var type = GetType();
foreach (var field in type.GetFields(
BindingFlags.Public |
BindingFlags.Instance)
.Where(f => f.FieldType == typeof(Action)))
{
field.SetValue(this, BuildAction());
}
}
private Action BuildAction()
{
Action x = null;
x = () =>
{
Action = x;
CurrentState.MoveNext();
};
return x;
}
private void InAction(string excuse)
{
throw new InvalidOperationException(string.Format("Fucksake, {0} Broken", excuse));
}
#endregion
// This is where the work of the yeild state machine happens. it's a single statement that _should_
// ( if written correctly ) never complete, nor should it fall through to the other states (cases)
// while the external statemoves provide the stimulus to change state, it can (as demonstrated by the
// move to loungingAbout happen due to conditions of internal state).
// The requirement for goto's here is to allow the control flow WITHIN THIS ONE METHOD to occur.
// Note that as this is intended to be non-completing, the goto's only move within the scope of this method.
//
private IEnumerable MoveState()
{
loungingAbout:
Console.WriteLine("he just sits there");
yield return null;
if (Action == ServeGimp) { goto serveGimp; }
if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; }
InAction("idleness kills our hero");
flipBurger:
NumbersOf[The.BurgersNeedingToBeCooked] =
NumbersOf[The.BurgersNeedingToBeCooked] - 1;
Ready[AllThe.BurgersReady] = Ready[AllThe.BurgersReady] + 1;
Console.WriteLine("using a plasterers trowel he flips the burgers");
yield return null;
if (Action == ServeGimp) { goto serveGimp; }
if (Action == HandFood) { goto handFood; }
if (Action == FlipBurger) { goto flipBurger; }
if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; }
InAction("the burger landed on the floor and the 5 second rule was");
handFood:
NumbersOf[The.PeopleBeingWaitingToBeServed] =
NumbersOf[The.PeopleBeingWaitingToBeServed] - 1;
Ready.Keys.ToList().ForEach(thingy => Ready[thingy] = Ready[thingy] - 1);
yield return null;
if (Action == ServeGimp) { goto serveGimp; }
if (Action == FlipBurger) { goto flipBurger; }
if (Action == HandFood) { goto handFood; }
if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; }
InAction("our hero has a seizure from boredom");
serveGimp:
NumbersOf.Keys.ToList().ForEach(thingy => NumbersOf[thingy] = NumbersOf[thingy] + 1);
Console.WriteLine("blah blah blah? would you like fries with that");
yield return null;
if (Action == ServeGimp) { goto serveGimp; }
if (Action == HandFood) { goto handFood; }
if (Action == FlipBurger) { goto flipBurger; }
if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; }
InAction("falling on his face, his nose was");
}
private enum The { PeopleBeingWaitingToBeServed, BurgersNeedingToBeCooked };
private enum AllThe { PeopleBeingWaitingForFood, BurgersReady};
private Dictionary<The, int> NumbersOf = new Dictionary<The, int>() {
{ The.BurgersNeedingToBeCooked, 0 },
{ The.PeopleBeingWaitingToBeServed, 0 }
};
private Dictionary<AllThe, int> Ready = new Dictionary<AllThe, int>() {
{ AllThe.BurgersReady, 0 },
{ AllThe.PeopleBeingWaitingForFood, 0 }
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment